diff --git a/.changelog/config.toml b/.changelog/config.toml index de0fee50c2f..7d52c95188f 100644 --- a/.changelog/config.toml +++ b/.changelog/config.toml @@ -1 +1,17 @@ -project_url = 'https://github.com/cometbft/cometbft' +project_url = 'https://github.com/cometbft/cometbft' + +sort_releases_by = [ + "date", + "version" +] +release_date_formats = [ + # "*December 1, 2023* + "*%B %d, %Y*", + # "*Dec 1, 2023* + "*%b %d, %Y*", + # "2023-12-01" (ISO format) + "%F", +] + +[change_set_sections] +sort_entries_by = "entry-text" diff --git a/.changelog/unreleased/breaking-changes/1010-mempool-interface.md b/.changelog/unreleased/breaking-changes/1010-mempool-interface.md new file mode 100644 index 00000000000..a81edaef562 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1010-mempool-interface.md @@ -0,0 +1,4 @@ +`[mempool]` Change the signature of `CheckTx` in the `Mempool` interface to +`CheckTx(tx types.Tx) (*abcicli.ReqRes, error)`. Also, add new method +`SetTxRemovedCallback`. +([\#1010](https://github.com/cometbft/cometbft/issues/1010)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1096-state-store-adr101-methods.md b/.changelog/unreleased/breaking-changes/1096-state-store-adr101-methods.md new file mode 100644 index 00000000000..2c1d317b776 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1096-state-store-adr101-methods.md @@ -0,0 +1,3 @@ +- `[state]` The `state.Store` interface has been expanded + to accommodate the data pull companion API of ADR 101 + ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1141-abci-advanced-proxy.md b/.changelog/unreleased/breaking-changes/1141-abci-advanced-proxy.md new file mode 100644 index 00000000000..659094e507e --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1141-abci-advanced-proxy.md @@ -0,0 +1,3 @@ +- `[proxy]` Expand `ClientCreator` interface to allow + for per-"connection" control of client creation + ([\#1141](https://github.com/cometbft/cometbft/pull/1141)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1146-mempool-remove-ids.md b/.changelog/unreleased/breaking-changes/1146-mempool-remove-ids.md new file mode 100644 index 00000000000..647536c21d8 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1146-mempool-remove-ids.md @@ -0,0 +1,3 @@ +- `[mempool]` Remove `mempoolIDs` for internally storing peer ids as `p2p.ID` + instead of `uint16`. + ([\#1146](https://github.com/cometbft/cometbft/pull/1146)) diff --git a/.changelog/unreleased/breaking-changes/1170-rm-replay-cmds.md b/.changelog/unreleased/breaking-changes/1170-rm-replay-cmds.md new file mode 100644 index 00000000000..9a3082fca6d --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1170-rm-replay-cmds.md @@ -0,0 +1,4 @@ +- `[cmd]` Remove `replay` and `replay-console` subcommands + and corresponding consensus file replay code, such as + `consensus.RunReplayFile`, and `consensus.State.ReplayFile` + ([\#1170](https://github.com/cometbft/cometbft/pull/1170)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1176-blockindexer-pruning.md b/.changelog/unreleased/breaking-changes/1176-blockindexer-pruning.md new file mode 100644 index 00000000000..d2456229424 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1176-blockindexer-pruning.md @@ -0,0 +1,2 @@ +- `[state/indexer/block]` BlockIndexer now has additional method `Prune`, `GetRetainHeight`, `SetRetainHeight` ([\#1176](https://github.com/cometbft/cometbft/pull/1176)) +- `[state/txindex]` TxIndexer now has additional methods: `Prune`, `GetRetainHeight`, `SetRetainHeight` ([\#1176](https://github.com/cometbft/cometbft/pull/1176)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1287-genesis-doc-hash-from-file.md b/.changelog/unreleased/breaking-changes/1287-genesis-doc-hash-from-file.md new file mode 100644 index 00000000000..10900495ea4 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1287-genesis-doc-hash-from-file.md @@ -0,0 +1,3 @@ +- `[node]` Change the signature of `GenesisDocProvider` to + return the checksum of JSON content alongside the parsed genesis data + ([\#1287](https://github.com/cometbft/cometbft/issues/1287)). diff --git a/.changelog/unreleased/breaking-changes/1324-load-state-from-gen-file-api.md b/.changelog/unreleased/breaking-changes/1324-load-state-from-gen-file-api.md new file mode 100644 index 00000000000..3c2a52438d3 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1324-load-state-from-gen-file-api.md @@ -0,0 +1,3 @@ +- `[node]` Go-API breaking: Change the signature of `LoadStateFromDBOrGenesisDocProvider` + to accept an optional operator provided hash of the genesis file + ([\#1324](https://github.com/cometbft/cometbft/pull/1324)). diff --git a/.changelog/unreleased/breaking-changes/1411-bump-p2p-version.md b/.changelog/unreleased/breaking-changes/1411-bump-p2p-version.md new file mode 100644 index 00000000000..9569c50a835 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1411-bump-p2p-version.md @@ -0,0 +1,2 @@ +- `[version]` Bumped the P2P version from 8 to 9, as this release contains new P2P messages. + ([\#1411](https://github.com/cometbft/cometbft/pull/1411)) diff --git a/.changelog/unreleased/breaking-changes/1412-rpc-hardcode-websocket.md b/.changelog/unreleased/breaking-changes/1412-rpc-hardcode-websocket.md new file mode 100644 index 00000000000..038f750ede9 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1412-rpc-hardcode-websocket.md @@ -0,0 +1,3 @@ +- `[rpc/client]` Hard-code the `/websocket` endpoint path such that it is + no longer configurable, removing the related client constructor parameter + ([\#1412](https://github.com/cometbft/cometbft/pull/1412)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-blocksync-internalize.md b/.changelog/unreleased/breaking-changes/1485-blocksync-internalize.md new file mode 100644 index 00000000000..a169fac2331 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-blocksync-internalize.md @@ -0,0 +1,2 @@ +- `[blocksync]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-consensus-internalize.md b/.changelog/unreleased/breaking-changes/1485-consensus-internalize.md new file mode 100644 index 00000000000..2739ee8807a --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-consensus-internalize.md @@ -0,0 +1,2 @@ +- `[consensus]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-evidence-internalize.md b/.changelog/unreleased/breaking-changes/1485-evidence-internalize.md new file mode 100644 index 00000000000..067496e1cb2 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-evidence-internalize.md @@ -0,0 +1,2 @@ +- `[evidence]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-inspect-internalize.md b/.changelog/unreleased/breaking-changes/1485-inspect-internalize.md new file mode 100644 index 00000000000..8766b337581 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-inspect-internalize.md @@ -0,0 +1,2 @@ +- `[inspect]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-autofile-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-autofile-internalize.md new file mode 100644 index 00000000000..3fabffd6caf --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-autofile-internalize.md @@ -0,0 +1,2 @@ +- `[libs/autofile]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-bits-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-bits-internalize.md new file mode 100644 index 00000000000..4eb86f8a2ad --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-bits-internalize.md @@ -0,0 +1,2 @@ +- `[libs/bits]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-clist-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-clist-internalize.md new file mode 100644 index 00000000000..1fa31ff7399 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-clist-internalize.md @@ -0,0 +1,2 @@ +- `[libs/clist]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-cmap-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-cmap-internalize.md new file mode 100644 index 00000000000..6b4533b3a7b --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-cmap-internalize.md @@ -0,0 +1,2 @@ +- `[libs/cmap]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-events-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-events-internalize.md new file mode 100644 index 00000000000..378d64198bb --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-events-internalize.md @@ -0,0 +1,2 @@ +- `[libs/events]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-fail-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-fail-internalize.md new file mode 100644 index 00000000000..7684f8007b4 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-fail-internalize.md @@ -0,0 +1,2 @@ +- `[libs/fail]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-flowrate-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-flowrate-internalize.md new file mode 100644 index 00000000000..a6f6d2701cc --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-flowrate-internalize.md @@ -0,0 +1,2 @@ +- `[libs/flowrate]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-net-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-net-internalize.md new file mode 100644 index 00000000000..5dd0922bb10 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-net-internalize.md @@ -0,0 +1,2 @@ +- `[libs/net]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-os-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-os-internalize.md new file mode 100644 index 00000000000..2f3f7adc9b7 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-os-internalize.md @@ -0,0 +1,2 @@ +- `[libs/os]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-progressbar-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-progressbar-internalize.md new file mode 100644 index 00000000000..5b28d72807b --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-progressbar-internalize.md @@ -0,0 +1,2 @@ +- `[libs/progressbar]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-protoio-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-protoio-internalize.md new file mode 100644 index 00000000000..a45c852dcad --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-protoio-internalize.md @@ -0,0 +1,2 @@ +- `[libs/protoio]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-pubsub-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-pubsub-internalize.md new file mode 100644 index 00000000000..27ed0ea0d28 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-pubsub-internalize.md @@ -0,0 +1,2 @@ +- `[libs/pubsub]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-rand-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-rand-internalize.md new file mode 100644 index 00000000000..0eb7fa5e956 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-rand-internalize.md @@ -0,0 +1,2 @@ +- `[libs/rand]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-service-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-service-internalize.md new file mode 100644 index 00000000000..11733884718 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-service-internalize.md @@ -0,0 +1,2 @@ +- `[libs/service]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-strings-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-strings-internalize.md new file mode 100644 index 00000000000..93e8409df29 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-strings-internalize.md @@ -0,0 +1,2 @@ +- `[libs/strings]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-sync-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-sync-internalize.md new file mode 100644 index 00000000000..fe6497de0c1 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-sync-internalize.md @@ -0,0 +1,2 @@ +- `[libs/sync]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-tempfile-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-tempfile-internalize.md new file mode 100644 index 00000000000..7d36a9d2e1f --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-tempfile-internalize.md @@ -0,0 +1,2 @@ +- `[libs/tempfile]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libs-timer-internalize.md b/.changelog/unreleased/breaking-changes/1485-libs-timer-internalize.md new file mode 100644 index 00000000000..1cdaae8c7f4 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libs-timer-internalize.md @@ -0,0 +1,2 @@ +- `[libs/timer]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-libsasync-internalize.md b/.changelog/unreleased/breaking-changes/1485-libsasync-internalize.md new file mode 100644 index 00000000000..460bea88794 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-libsasync-internalize.md @@ -0,0 +1,2 @@ +- `[libs/async]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-state-internalize.md b/.changelog/unreleased/breaking-changes/1485-state-internalize.md new file mode 100644 index 00000000000..7c03d56efa8 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-state-internalize.md @@ -0,0 +1,2 @@ +- `[state]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-statesync-internalize.md b/.changelog/unreleased/breaking-changes/1485-statesync-internalize.md new file mode 100644 index 00000000000..a599b88f4e2 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-statesync-internalize.md @@ -0,0 +1,2 @@ +- `[statesync]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1485-store-internalize.md b/.changelog/unreleased/breaking-changes/1485-store-internalize.md new file mode 100644 index 00000000000..c343840e55d --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1485-store-internalize.md @@ -0,0 +1,2 @@ +- `[store]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1533-proto-renames-fix-buf-lints.md b/.changelog/unreleased/breaking-changes/1533-proto-renames-fix-buf-lints.md new file mode 100644 index 00000000000..af5d622ef78 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1533-proto-renames-fix-buf-lints.md @@ -0,0 +1,10 @@ +- `[abci]` Renamed the alias types for gRPC requests, responses, and service + instances to follow the naming changes in the proto-derived + `api/cometbft/abci/v1` package + ([\#1533](https://github.com/cometbft/cometbft/pull/1533)): + * The prefixed naming pattern `RequestFoo`, `ReponseFoo` changed to + suffixed `FooRequest`, `FooResponse`. + * Each method gets its own unique request and response type to allow for + independent evolution with backward compatibility. + * `ABCIClient` renamed to `ABCIServiceClient`. + * `ABCIServer` renamed to `ABCIServiceServer`. diff --git a/.changelog/unreleased/breaking-changes/1556-return-meta-with-load-block.md b/.changelog/unreleased/breaking-changes/1556-return-meta-with-load-block.md new file mode 100644 index 00000000000..a21aaeec1d6 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1556-return-meta-with-load-block.md @@ -0,0 +1,2 @@ +- `[store]` Make the `LoadBlock` method also return block metadata + ([\#1556](https://github.com/cometbft/cometbft/issues/1556)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1561-standalone-api-go-mod.md b/.changelog/unreleased/breaking-changes/1561-standalone-api-go-mod.md new file mode 100644 index 00000000000..eff21a95cb2 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1561-standalone-api-go-mod.md @@ -0,0 +1,2 @@ +- Made `/api` a standalone Go module with its own `go.mod` + ([\#1561](https://github.com/cometbft/cometbft/issues/1561)) diff --git a/.changelog/unreleased/breaking-changes/1621-rename-version-variables.md b/.changelog/unreleased/breaking-changes/1621-rename-version-variables.md new file mode 100644 index 00000000000..f53dbbd5b24 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1621-rename-version-variables.md @@ -0,0 +1,2 @@ +- `[comet]` Version variables, in `version/version.go`, have been renamed to reflect the CometBFT rebranding. + ([cometbft/cometbft\#1621](https://github.com/cometbft/cometbft/pull/1621)) diff --git a/.changelog/unreleased/breaking-changes/1972-store-prune-abci-responses.md b/.changelog/unreleased/breaking-changes/1972-store-prune-abci-responses.md new file mode 100644 index 00000000000..525cac96d4a --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1972-store-prune-abci-responses.md @@ -0,0 +1 @@ +- `[state/store]` go-API breaking change in `PruneABCIResponses`: added parameter to force compaction. ([\#1972](https://github.com/cometbft/cometbft/pull/1972)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/1972-store-pruning-api-breaking.md b/.changelog/unreleased/breaking-changes/1972-store-pruning-api-breaking.md new file mode 100644 index 00000000000..25fbb8fd6be --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1972-store-pruning-api-breaking.md @@ -0,0 +1 @@ +- `[state/store]` go-API breaking change in `PruneStates`: added parameter to pass the number of pruned states and return pruned entries in current pruning iteration. ([\#1972](https://github.com/cometbft/cometbft/pull/1972)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/211-deprecate-tmhome.md b/.changelog/unreleased/breaking-changes/211-deprecate-tmhome.md deleted file mode 100644 index 547fc4e2d54..00000000000 --- a/.changelog/unreleased/breaking-changes/211-deprecate-tmhome.md +++ /dev/null @@ -1,2 +0,0 @@ -- 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/unreleased/breaking-changes/2230-rfc-106-remove-get-latest-block.md b/.changelog/unreleased/breaking-changes/2230-rfc-106-remove-get-latest-block.md new file mode 100644 index 00000000000..6ef28211995 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/2230-rfc-106-remove-get-latest-block.md @@ -0,0 +1,12 @@ +- `[proto]` Remove stateful block data retrieval methods from the + data companion gRPC API as per + [RFC 106](https://github.com/cometbft/cometbft/blob/main/docs/references/rfc/rfc-106-separate-stateful-methods.md) + ([\#2230](https://github.com/cometbft/cometbft/issues/2230)): + * `GetLatest` from `cometbft.services.block.v1.BlockService`; + * `GetLatestBlockResults` from `cometbft.services.block_results.v1.BlockResultsService`. +- `[rpc/grpc]` Remove support for stateful block data retrieval methods from the + data companion APIs as per [RFC 106](https://github.com/cometbft/cometbft/blob/main/docs/references/rfc/rfc-106-separate-stateful-methods.md) + * `GetLatestBlock` method removed from the `BlockServiceClient` interface. + * `GetLatestBlockResults` method removed from the `BlockResultServiceClient` interface. + * `GetLatest` endpoint is no longer served by `BlockServiceServer` instances. + * `GetLatestBlockResults` endpoint is no longer served by `BlockResultServiceServer` instances. diff --git a/.changelog/unreleased/breaking-changes/2246-p2p-peerset.md b/.changelog/unreleased/breaking-changes/2246-p2p-peerset.md new file mode 100644 index 00000000000..657f9124552 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/2246-p2p-peerset.md @@ -0,0 +1,3 @@ +- `[p2p]` Rename `IPeerSet#List` to `Copy`, add `Random`, `ForEach` methods. + Rename `PeerSet#List` to `Copy`, add `Random`, `ForEach` methods. + ([\#2246](https://github.com/cometbft/cometbft/pull/2246)) diff --git a/.changelog/unreleased/breaking-changes/2322-removes-abci-params.md b/.changelog/unreleased/breaking-changes/2322-removes-abci-params.md new file mode 100644 index 00000000000..c985704dce9 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/2322-removes-abci-params.md @@ -0,0 +1,3 @@ +- `[abci]` Deprecates `ABCIParams` field of `ConsensusParam` and + introduces replacement in `FeatureParams` to enable Vote Extensions. + ([\#2322](https://github.com/cometbft/cometbft/pull/2322)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/2397-move-median-time.md b/.changelog/unreleased/breaking-changes/2397-move-median-time.md new file mode 100644 index 00000000000..aab1f75bf64 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/2397-move-median-time.md @@ -0,0 +1,3 @@ +- `[internal/state]` Moved function `MedianTime` to package `types`, + and made it a method of `Commit` so it can be used by external packages. + ([\#2397](https://github.com/cometbft/cometbft/pull/2397)) diff --git a/.changelog/unreleased/breaking-changes/260-remove-priority-mempool.md b/.changelog/unreleased/breaking-changes/260-remove-priority-mempool.md deleted file mode 100644 index 5800158653e..00000000000 --- a/.changelog/unreleased/breaking-changes/260-remove-priority-mempool.md +++ /dev/null @@ -1,6 +0,0 @@ -- [mempool] Remove priority mempool. - ([\#260](https://github.com/cometbft/cometbft/issues/260)) -- [config] Remove `Version` field from `MempoolConfig`. - ([\#260](https://github.com/cometbft/cometbft/issues/260)) -- [protobuf] Remove fields `sender`, `priority`, and `mempool_error` from - `ResponseCheckTx`. ([\#260](https://github.com/cometbft/cometbft/issues/260)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/2692-privval-sign-bytes.md b/.changelog/unreleased/breaking-changes/2692-privval-sign-bytes.md new file mode 100644 index 00000000000..9b18f37e02f --- /dev/null +++ b/.changelog/unreleased/breaking-changes/2692-privval-sign-bytes.md @@ -0,0 +1,2 @@ +- `[privval]` allow privval to sign arbitrary bytes + ([\#2692](https://github.com/cometbft/cometbft/pull/2692)) diff --git a/.changelog/unreleased/breaking-changes/2786-remove-cleveldb-boltdb.md b/.changelog/unreleased/breaking-changes/2786-remove-cleveldb-boltdb.md new file mode 100644 index 00000000000..664cd78232e --- /dev/null +++ b/.changelog/unreleased/breaking-changes/2786-remove-cleveldb-boltdb.md @@ -0,0 +1 @@ +- Remove `cleveldb` and `boltdb` ([\2786](https://github.com/cometbft/cometbft/pull/2786)) diff --git a/.changelog/unreleased/breaking-changes/385-update-to-go1.20.md b/.changelog/unreleased/breaking-changes/385-update-to-go1.20.md deleted file mode 100644 index 5e9ea3386ac..00000000000 --- a/.changelog/unreleased/breaking-changes/385-update-to-go1.20.md +++ /dev/null @@ -1,2 +0,0 @@ -- 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/unreleased/breaking-changes/495-proto-version-packages.md b/.changelog/unreleased/breaking-changes/495-proto-version-packages.md new file mode 100644 index 00000000000..144c0c8a579 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/495-proto-version-packages.md @@ -0,0 +1,10 @@ +- `[proto]` Renamed the packages from `tendermint.*` to `cometbft.*` + and introduced versioned packages to distinguish between proto definitions + released in 0.34.x, 0.37.x, 0.38.x, and 1.0.x versions. + Prior to the 1.0 release, the versioned packages are suffixed with + `.v1beta1`, `.v1beta2`, and so on; all definitions describing the protocols + as per the 1.0.0 release are in packages suffixed with `.v1`. + Relocated generated Go code into a new `api` folder and changed the import + paths accordingly. + ([\#495](https://github.com/cometbft/cometbft/pull/495) + [\#1504](https://github.com/cometbft/cometbft/issues/1504)) diff --git a/.changelog/unreleased/breaking-changes/558-tm10011-B.md b/.changelog/unreleased/breaking-changes/558-tm10011-B.md new file mode 100644 index 00000000000..be3c8802c5c --- /dev/null +++ b/.changelog/unreleased/breaking-changes/558-tm10011-B.md @@ -0,0 +1,2 @@ +- `[crypto/merkle]` The public `Proof.ComputeRootHash` function has been deleted. + ([\#558](https://github.com/cometbft/cometbft/issues/558)) diff --git a/.changelog/unreleased/breaking-changes/6498-signerharness-set-home-dir.md b/.changelog/unreleased/breaking-changes/6498-signerharness-set-home-dir.md deleted file mode 100644 index 19beb3c9b38..00000000000 --- a/.changelog/unreleased/breaking-changes/6498-signerharness-set-home-dir.md +++ /dev/null @@ -1,2 +0,0 @@ -- `[tools/tm-signer-harness]` Set OS home dir to instead of the hardcoded PATH. - ([\#6498](https://github.com/tendermint/tendermint/pull/6498)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/650-rm-grpc-broadcast-api.md b/.changelog/unreleased/breaking-changes/650-rm-grpc-broadcast-api.md new file mode 100644 index 00000000000..f1465a6909f --- /dev/null +++ b/.changelog/unreleased/breaking-changes/650-rm-grpc-broadcast-api.md @@ -0,0 +1,2 @@ +- `[rpc/grpc]` Remove the deprecated gRPC broadcast API + ([\#650](https://github.com/cometbft/cometbft/issues/650)) \ No newline at end of file diff --git a/.changelog/unreleased/breaking-changes/736+-proto-renaming.md b/.changelog/unreleased/breaking-changes/736+-proto-renaming.md new file mode 100644 index 00000000000..782acf6ebe7 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/736+-proto-renaming.md @@ -0,0 +1,28 @@ +- `[proto]` The names in the `cometbft.abci.v1` versioned proto package + are changed to satisfy the + [buf guidelines](https://buf.build/docs/best-practices/style-guide/) + ([#736](https://github.com/cometbft/cometbft/issues/736), + [#1504](https://github.com/cometbft/cometbft/issues/1504), + [#1530](https://github.com/cometbft/cometbft/issues/1530)): + * Names of request and response types used in gRPC changed by making + `Request`/`Response` the suffix instead of the prefix, e.g. + `RequestCheckTx` ⭢ `CheckTxRequest`. + * The `Request` and `Response` multiplex messages are redefined accordingly. + * `CheckTxType` values renamed with the `CHECK_TX_TYPE_` prefix. + * `MisbehaviorType` values renamed with the `MISBEHAVIOR_TYPE_` prefix. + * `Result` enum formerly nested in `ResponseOfferSnapshot` replaced with the package-level + `OfferSnapshotResult`, its values named with the + `OFFER_SNAPSHOT_RESULT_` prefix. + * `Result` enum formerly nested in `ResponseApplyShapshotChunk` replaced with the package-level + `ApplySnapshotChunkResult`, its values named with the + `APPLY_SNAPSHOT_CHUNK_RESULT_` prefix. + * `Status` enum formerly nested in `ResponseProcessProposal` replaced with the package-level + `ProcessProposalStatus`, its values named with the + `PROCESS_PROPOSAL_STATUS_` prefix. + * `Status` enum formerly nested in `ResponseVerifyVoteExtension` replaced with the package-level + `VerifyVoteExtensionStatus`, its values named with the + `VERIFY_VOTE_EXTENSION_STATUS_` prefix. + * New definition of `Misbehavior` using the changed `MisbehaviorType`. + * The gRPC service is renamed `ABCIService` and defined using the types listed above. +- `[proto]` In the `cometbft.state.v1` package, the definition for `ABCIResponsesInfo` + is changed, renaming `response_finalize_block` field to `finalize_block`. diff --git a/.changelog/unreleased/breaking-changes/736-proto-enum-rename.md b/.changelog/unreleased/breaking-changes/736-proto-enum-rename.md new file mode 100644 index 00000000000..892902110bd --- /dev/null +++ b/.changelog/unreleased/breaking-changes/736-proto-enum-rename.md @@ -0,0 +1,7 @@ +- `[abci]` Changed the proto-derived enum type and constant aliases to the + buf-recommended naming conventions adopted in the `abci/v1` proto package. + For example, `ResponseProcessProposal_ACCEPT` is renamed to `PROCESS_PROPOSAL_STATUS_ACCEPT` + ([\#736](https://github.com/cometbft/cometbft/issues/736)). +- `[abci]` The `Type` enum field is now required to be set to a value other + than the default `CHECK_TX_TYPE_UNKNOWN` for a valid `CheckTxRequest` + ([\#736](https://github.com/cometbft/cometbft/issues/736)). diff --git a/.changelog/unreleased/breaking-changes/785-reject-incoming-txs-while-catching-up.md b/.changelog/unreleased/breaking-changes/785-reject-incoming-txs-while-catching-up.md new file mode 100644 index 00000000000..e545f97c704 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/785-reject-incoming-txs-while-catching-up.md @@ -0,0 +1,7 @@ +- `[rpc]` The endpoints `broadcast_tx_*` now return an error when the node is + performing block sync or state sync. + ([\#785](https://github.com/cometbft/cometbft/issues/785)) +- `[mempool]` When the node is performing block sync or state sync, the mempool + reactor now discards incoming transactions from peers, and does not propagate + transactions to peers. + ([\#785](https://github.com/cometbft/cometbft/issues/785)) diff --git a/.changelog/unreleased/breaking-changes/857-handshake-api-ctx.md b/.changelog/unreleased/breaking-changes/857-handshake-api-ctx.md new file mode 100644 index 00000000000..6fe01558506 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/857-handshake-api-ctx.md @@ -0,0 +1,2 @@ +- `[consensus]` `Handshaker.Handshake` now requires `context.Context` ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) +- `[node]` `NewNode` now requires `context.Context` as the first parameter ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) diff --git a/.changelog/unreleased/bug-fixes/0000-asa-2024-001-fix-validate.md b/.changelog/unreleased/bug-fixes/0000-asa-2024-001-fix-validate.md new file mode 100644 index 00000000000..e1ddae9c141 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/0000-asa-2024-001-fix-validate.md @@ -0,0 +1,2 @@ +`[consensus]` Fix for "Validation of `VoteExtensionsEnableHeight` can cause chain halt" + ([ASA-2024-001](https://github.com/cometbft/cometbft/security/advisories/GHSA-qr8r-m495-7hc4)) diff --git a/.changelog/unreleased/bug-fixes/1175-consensus-prevote-improve-logic.md b/.changelog/unreleased/bug-fixes/1175-consensus-prevote-improve-logic.md new file mode 100644 index 00000000000..67afa08deed --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1175-consensus-prevote-improve-logic.md @@ -0,0 +1,3 @@ +- `[consensus]` Consensus now prevotes `nil` when the proposed value does not + match the value the local validator has locked on + ([\#1203](https://github.com/cometbft/cometbft/pull/1203)) diff --git a/.changelog/unreleased/bug-fixes/1175-consensus-remove-unlock-behavior.md b/.changelog/unreleased/bug-fixes/1175-consensus-remove-unlock-behavior.md new file mode 100644 index 00000000000..644fa34ee35 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1175-consensus-remove-unlock-behavior.md @@ -0,0 +1,2 @@ +- `[consensus]` Remove logic to unlock block on +2/3 prevote for nil + ([\#1175](https://github.com/cometbft/cometbft/pull/1175): @BrendanChou) diff --git a/.changelog/unreleased/bug-fixes/1529-indexer-respect-height-params-on-query.md b/.changelog/unreleased/bug-fixes/1529-indexer-respect-height-params-on-query.md new file mode 100644 index 00000000000..d12f3eda536 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1529-indexer-respect-height-params-on-query.md @@ -0,0 +1,2 @@ +- `[state/indexer]` Respect both height params while querying for events + ([\#1529](https://github.com/cometbft/cometbft/pull/1529)) diff --git a/.changelog/unreleased/bug-fixes/1616-pruning-dont-prune-state-when-no-blocks-pruned.md b/.changelog/unreleased/bug-fixes/1616-pruning-dont-prune-state-when-no-blocks-pruned.md new file mode 100644 index 00000000000..81de0a48e62 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1616-pruning-dont-prune-state-when-no-blocks-pruned.md @@ -0,0 +1,2 @@ +- `[state/pruning]` When no blocks are pruned, do not attempt to prune statestore + ([\#1616](https://github.com/cometbft/cometbft/pull/1616)) diff --git a/.changelog/unreleased/bug-fixes/1687-consensus-fix-block-validation.md b/.changelog/unreleased/bug-fixes/1687-consensus-fix-block-validation.md new file mode 100644 index 00000000000..778f0b538b4 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1687-consensus-fix-block-validation.md @@ -0,0 +1,3 @@ +- `[mempool]` The calculation method of tx size returned by calling proxyapp should be consistent with that of mempool + ([\#1687](https://github.com/cometbft/cometbft/pull/1687)) + diff --git a/.changelog/unreleased/bug-fixes/1749-light-client-attack-verify-all-sigs.md b/.changelog/unreleased/bug-fixes/1749-light-client-attack-verify-all-sigs.md new file mode 100644 index 00000000000..1115c4d195a --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1749-light-client-attack-verify-all-sigs.md @@ -0,0 +1,4 @@ +- `[evidence]` When `VerifyCommitLight` & `VerifyCommitLightTrusting` are called as part + of evidence verification, all signatures present in the evidence must be verified + ([\#1749](https://github.com/cometbft/cometbft/pull/1749)) + diff --git a/.changelog/unreleased/bug-fixes/1825-false-on-nil-key.md b/.changelog/unreleased/bug-fixes/1825-false-on-nil-key.md new file mode 100644 index 00000000000..dcd466a39e7 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1825-false-on-nil-key.md @@ -0,0 +1,3 @@ +- `[crypto]` `SupportsBatchVerifier` returns false + if public key is nil instead of dereferencing nil. + ([\#1825](https://github.com/cometbft/cometbft/pull/1825)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/1879-blocksync-wait-for-pool-routine.md b/.changelog/unreleased/bug-fixes/1879-blocksync-wait-for-pool-routine.md new file mode 100644 index 00000000000..e4122368287 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1879-blocksync-wait-for-pool-routine.md @@ -0,0 +1,2 @@ +- `[blocksync]` wait for `poolRoutine` to stop in `(*Reactor).OnStop` + ([\#1879](https://github.com/cometbft/cometbft/pull/1879)) diff --git a/.changelog/unreleased/bug-fixes/2010-p2p-pex-shutdown.md b/.changelog/unreleased/bug-fixes/2010-p2p-pex-shutdown.md new file mode 100644 index 00000000000..e913d7b2371 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/2010-p2p-pex-shutdown.md @@ -0,0 +1 @@ +- `[p2p/pex]` gracefully shutdown Reactor ([\#2010](https://github.com/cometbft/cometbft/pull/2010)) diff --git a/.changelog/unreleased/bug-fixes/2047-privval-retry-accepting-conn.md b/.changelog/unreleased/bug-fixes/2047-privval-retry-accepting-conn.md new file mode 100644 index 00000000000..45260721c8b --- /dev/null +++ b/.changelog/unreleased/bug-fixes/2047-privval-retry-accepting-conn.md @@ -0,0 +1 @@ +- `[privval]` Retry accepting a connection ([\#2047](https://github.com/cometbft/cometbft/pull/2047)) diff --git a/.changelog/unreleased/bug-fixes/2136-fix-state-rollback.md b/.changelog/unreleased/bug-fixes/2136-fix-state-rollback.md new file mode 100644 index 00000000000..55cbfe51ed4 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/2136-fix-state-rollback.md @@ -0,0 +1,2 @@ +- `[state]` Fix rollback to a specific height + ([\#2136](https://github.com/cometbft/cometbft/pull/2136)) diff --git a/.changelog/unreleased/bug-fixes/2774-bitarray-unmarshal-json.md b/.changelog/unreleased/bug-fixes/2774-bitarray-unmarshal-json.md new file mode 100644 index 00000000000..1c51af49d26 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/2774-bitarray-unmarshal-json.md @@ -0,0 +1,2 @@ +- [`bits`] prevent `BitArray.UnmarshalJSON` from crashing on 0 bits + ([\#2774](https://github.com/cometbft/cometbft/pull/2774)) diff --git a/.changelog/unreleased/bug-fixes/386-quick-fix-needproofblock.md b/.changelog/unreleased/bug-fixes/386-quick-fix-needproofblock.md deleted file mode 100644 index 2180086ce97..00000000000 --- a/.changelog/unreleased/bug-fixes/386-quick-fix-needproofblock.md +++ /dev/null @@ -1,2 +0,0 @@ -- `[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/unreleased/bug-fixes/4-busy-loop-send-block-part.md b/.changelog/unreleased/bug-fixes/4-busy-loop-send-block-part.md deleted file mode 100644 index 59bda2afc3e..00000000000 --- a/.changelog/unreleased/bug-fixes/4-busy-loop-send-block-part.md +++ /dev/null @@ -1,2 +0,0 @@ -- `[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/unreleased/bug-fixes/642-clist-mempool-data-races.md b/.changelog/unreleased/bug-fixes/642-clist-mempool-data-races.md new file mode 100644 index 00000000000..037bbc9550f --- /dev/null +++ b/.changelog/unreleased/bug-fixes/642-clist-mempool-data-races.md @@ -0,0 +1,2 @@ +- `[mempool]` Fix data races in `CListMempool` by making atomic the types of `height`, `txsBytes`, and + `notifiedTxsAvailable`. ([\#642](https://github.com/cometbft/cometbft/pull/642)) diff --git a/.changelog/unreleased/dependencies/1725-cometbft-db.md b/.changelog/unreleased/dependencies/1725-cometbft-db.md new file mode 100644 index 00000000000..ed74be7ce1d --- /dev/null +++ b/.changelog/unreleased/dependencies/1725-cometbft-db.md @@ -0,0 +1,2 @@ +- Bump cometbft-db to v0.9.0, providing support for RocksDB v8 + ([\#1725](https://github.com/cometbft/cometbft/pull/1725)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1094-grpc-block-service-cfg.md b/.changelog/unreleased/features/1094-grpc-block-service-cfg.md new file mode 100644 index 00000000000..f0892b3a149 --- /dev/null +++ b/.changelog/unreleased/features/1094-grpc-block-service-cfg.md @@ -0,0 +1,2 @@ +- `[config]` Add `[grpc.block_service]` section to configure gRPC `BlockService` + ([\#1094](https://github.com/cometbft/cometbft/issues/1094)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1094-grpc-block-service.md b/.changelog/unreleased/features/1094-grpc-block-service.md new file mode 100644 index 00000000000..543e1d6d1ef --- /dev/null +++ b/.changelog/unreleased/features/1094-grpc-block-service.md @@ -0,0 +1,3 @@ +- `[grpc]` Add `BlockService` with client to facilitate fetching of blocks and + streaming of the latest committed block height + ([\#1094](https://github.com/cometbft/cometbft/issues/1094)) diff --git a/.changelog/unreleased/features/1095-grpc-block-results-service-cfg.md b/.changelog/unreleased/features/1095-grpc-block-results-service-cfg.md new file mode 100644 index 00000000000..bc3d18f3e08 --- /dev/null +++ b/.changelog/unreleased/features/1095-grpc-block-results-service-cfg.md @@ -0,0 +1,2 @@ +- `[config]` Add `[grpc.block_results_service]` gRPC configuration `BlockResultsService` + ([\#1095](https://github.com/cometbft/cometbft/issues/1095)) diff --git a/.changelog/unreleased/features/1095-grpc-block-results-service.md b/.changelog/unreleased/features/1095-grpc-block-results-service.md new file mode 100644 index 00000000000..51c6713ebf4 --- /dev/null +++ b/.changelog/unreleased/features/1095-grpc-block-results-service.md @@ -0,0 +1,3 @@ +- `[grpc]` Add `BlockResultsService` with client to fetch BlockResults + for a given height, or latest. + ([\#1095](https://github.com/cometbft/cometbft/issues/1095)) diff --git a/.changelog/unreleased/features/1097-pruning-service.md b/.changelog/unreleased/features/1097-pruning-service.md new file mode 100644 index 00000000000..47882ff8b25 --- /dev/null +++ b/.changelog/unreleased/features/1097-pruning-service.md @@ -0,0 +1,23 @@ +- `[proto]` Add definitions and generated code for + [ADR-101](./docs/architecture/adr-101-data-companion-pull-api.md) + `PruningService` in the `cometbft.services.pruning.v1` proto package + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[rpc/grpc]` Add privileged gRPC server and client facilities, in + `server/privileged` and `client/privileged` packages respectively, to + enable a separate API server within the node which serves trusted clients + without authentication and should never be exposed to public internet + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[rpc/grpc]` Add a pruning service adding on the privileged gRPC server API to + give an [ADR-101](./docs/architecture/adr-101-data-companion-pull-api.md) data + companion control over block data retained by the node. The + `WithPruningService` option method in `server/privileged` is provided to + configure the pruning service + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[rpc/grpc]` Add `PruningServiceClient` interface + for the gRPC client in `client/privileged` along with a configuration option + to enable it + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[config]` Add `[grpc.privileged]` section to configure the privileged + gRPC server for the node, and `[grpc.privileged.pruning_service]` section + to control the pruning service + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). diff --git a/.changelog/unreleased/features/1234-pruning-metrics.md b/.changelog/unreleased/features/1234-pruning-metrics.md new file mode 100644 index 00000000000..0afcd759550 --- /dev/null +++ b/.changelog/unreleased/features/1234-pruning-metrics.md @@ -0,0 +1,2 @@ +- `[metrics]` Add metrics to monitor pruning and current available data in stores: `PruningServiceBlockRetainHeight`, `PruningServiceBlockResultsRetainHeight`, `ApplicationBlockRetainHeight`, `BlockStoreBaseHeight`, `ABCIResultsBaseHeight`. + ([\#1234](https://github.com/cometbft/cometbft/pull/1234)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1327-grpc-pruning-indexer.md b/.changelog/unreleased/features/1327-grpc-pruning-indexer.md new file mode 100644 index 00000000000..c07d7bafb32 --- /dev/null +++ b/.changelog/unreleased/features/1327-grpc-pruning-indexer.md @@ -0,0 +1,2 @@ +`[rpc/grpc]` Add gRPC endpoint for pruning the block and transaction indexes +([\#1327](https://github.com/cometbft/cometbft/pull/1327)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1334-metrics-for-index-pruning.md b/.changelog/unreleased/features/1334-metrics-for-index-pruning.md new file mode 100644 index 00000000000..92129c1ba64 --- /dev/null +++ b/.changelog/unreleased/features/1334-metrics-for-index-pruning.md @@ -0,0 +1,2 @@ +- `[state]` Add TxIndexer and BlockIndexer pruning metrics + ([\#1334](https://github.com/cometbft/cometbft/issues/1334)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1512-metric-mempool-size-bytes.md b/.changelog/unreleased/features/1512-metric-mempool-size-bytes.md new file mode 100644 index 00000000000..b935dc40842 --- /dev/null +++ b/.changelog/unreleased/features/1512-metric-mempool-size-bytes.md @@ -0,0 +1,2 @@ +- `[metrics]` Add metric for mempool size in bytes `SizeBytes`. + ([\#1512](https://github.com/cometbft/cometbft/pull/1512)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1643-nop-mempool.md b/.changelog/unreleased/features/1643-nop-mempool.md new file mode 100644 index 00000000000..e12ec43fc1a --- /dev/null +++ b/.changelog/unreleased/features/1643-nop-mempool.md @@ -0,0 +1,17 @@ +- `[mempool]` Add `nop` mempool ([\#1643](https://github.com/cometbft/cometbft/pull/1643)) + + If you want to use it, change mempool's `type` to `nop`: + + ```toml + [mempool] + + # The type of mempool for this node to use. + # + # Possible types: + # - "flood" : concurrent linked list mempool with flooding gossip protocol + # (default) + # - "nop" : nop-mempool (short for no operation; the ABCI app is responsible + # for storing, disseminating and proposing txs). "create_empty_blocks=false" + # is not supported. + type = "nop" + ``` \ No newline at end of file diff --git a/.changelog/unreleased/features/1972-compaction-config.md b/.changelog/unreleased/features/1972-compaction-config.md new file mode 100644 index 00000000000..62718f13194 --- /dev/null +++ b/.changelog/unreleased/features/1972-compaction-config.md @@ -0,0 +1 @@ +- `[config]` Add configuration parameters to tweak forced compaction. ([\#1972](https://github.com/cometbft/cometbft/pull/1972)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1972-force-compaction-on-pruning.md b/.changelog/unreleased/features/1972-force-compaction-on-pruning.md new file mode 100644 index 00000000000..abe1cbcfc58 --- /dev/null +++ b/.changelog/unreleased/features/1972-force-compaction-on-pruning.md @@ -0,0 +1 @@ +- `[store]` When pruning force compaction of the database. ([\#1972](https://github.com/cometbft/cometbft/pull/1972)) \ No newline at end of file diff --git a/.changelog/unreleased/features/1974-statestore-metrics.md b/.changelog/unreleased/features/1974-statestore-metrics.md new file mode 100644 index 00000000000..02fb8b9e100 --- /dev/null +++ b/.changelog/unreleased/features/1974-statestore-metrics.md @@ -0,0 +1 @@ +- `[metrics]` Added metrics to monitor state store access. ([\#1974](https://github.com/cometbft/cometbft/pull/1974)) diff --git a/.changelog/unreleased/features/1974-store-metrics.md b/.changelog/unreleased/features/1974-store-metrics.md new file mode 100644 index 00000000000..fdd14fc8ce1 --- /dev/null +++ b/.changelog/unreleased/features/1974-store-metrics.md @@ -0,0 +1 @@ +- `[metrics]` Added metrics to monitor block store access. ([\#1974](https://github.com/cometbft/cometbft/pull/1974)) diff --git a/.changelog/unreleased/features/2056-remove-unused-param.md b/.changelog/unreleased/features/2056-remove-unused-param.md new file mode 100644 index 00000000000..41ae1287891 --- /dev/null +++ b/.changelog/unreleased/features/2056-remove-unused-param.md @@ -0,0 +1,2 @@ +`[config]` Removed unused `[mempool.max_batch_bytes]` mempool parameter + ([\#2056](https://github.com/cometbft/cometbft/pull/2056/)) diff --git a/.changelog/unreleased/features/2107-localnet-monitoring.md b/.changelog/unreleased/features/2107-localnet-monitoring.md new file mode 100644 index 00000000000..64bd2ee912c --- /dev/null +++ b/.changelog/unreleased/features/2107-localnet-monitoring.md @@ -0,0 +1 @@ +- `[test]` Added monitoring tools and dashboards for local testing with `localnet`. ([\#2107](https://github.com/cometbft/cometbft/issues/2107)) diff --git a/.changelog/unreleased/features/2132-cometbft-db.md b/.changelog/unreleased/features/2132-cometbft-db.md new file mode 100644 index 00000000000..379b03a0c06 --- /dev/null +++ b/.changelog/unreleased/features/2132-cometbft-db.md @@ -0,0 +1,2 @@ +- Add [`pebbledb`](https://github.com/cockroachdb/pebble). To use, build with + `pebbledb` tag (`go build -tags pebbledb`) ([\#2132](https://github.com/cometbft/cometbft/pull/2132/)) diff --git a/.changelog/unreleased/features/2327-evidence-support-for-ordercode.md b/.changelog/unreleased/features/2327-evidence-support-for-ordercode.md new file mode 100644 index 00000000000..a4177cfee79 --- /dev/null +++ b/.changelog/unreleased/features/2327-evidence-support-for-ordercode.md @@ -0,0 +1 @@ +- [evidence/store] Added support for a different DB key representation within the evidence store ([\#2327](https://github.com/cometbft/cometbft/pull/2327/)) diff --git a/.changelog/unreleased/features/2327-lightdb-support-for-ordercode.md b/.changelog/unreleased/features/2327-lightdb-support-for-ordercode.md new file mode 100644 index 00000000000..3b40dbfa2fc --- /dev/null +++ b/.changelog/unreleased/features/2327-lightdb-support-for-ordercode.md @@ -0,0 +1 @@ +- [light/store] Added support for a different DB key representation within the light block store ([\#2327](https://github.com/cometbft/cometbft/pull/2327/)) diff --git a/.changelog/unreleased/features/2327-store-db-layout-config.md b/.changelog/unreleased/features/2327-store-db-layout-config.md new file mode 100644 index 00000000000..d0b99baf846 --- /dev/null +++ b/.changelog/unreleased/features/2327-store-db-layout-config.md @@ -0,0 +1,3 @@ +- `[config]` Added `[storage.experimental_db_key_layout]` storage parameter, set to "v2" + for order preserving representation +([\#2327](https://github.com/cometbft/cometbft/pull/2327/)) diff --git a/.changelog/unreleased/features/2327-store-support-for-ordercode.md b/.changelog/unreleased/features/2327-store-support-for-ordercode.md new file mode 100644 index 00000000000..aec7c4d1d2f --- /dev/null +++ b/.changelog/unreleased/features/2327-store-support-for-ordercode.md @@ -0,0 +1 @@ +- [store] Added support for a different DB key representation to state and block store ([\#2327](https://github.com/cometbft/cometbft/pull/2327/)) diff --git a/.changelog/unreleased/features/2362-e2e-block-max-bytes.md b/.changelog/unreleased/features/2362-e2e-block-max-bytes.md new file mode 100644 index 00000000000..a3b007c3f96 --- /dev/null +++ b/.changelog/unreleased/features/2362-e2e-block-max-bytes.md @@ -0,0 +1,2 @@ +- `[e2e]` Add `block_max_bytes` option to the manifest file. + ([\#2362](https://github.com/cometbft/cometbft/pull/2362)) \ No newline at end of file diff --git a/.changelog/unreleased/features/2433-e2e-testnet-dir.md b/.changelog/unreleased/features/2433-e2e-testnet-dir.md new file mode 100644 index 00000000000..33050d20ca2 --- /dev/null +++ b/.changelog/unreleased/features/2433-e2e-testnet-dir.md @@ -0,0 +1,2 @@ +- `[e2e]` Add new `--testnet-dir` parameter to set a custom directory for the generated testnet files. + ([\#2433](https://github.com/cometbft/cometbft/pull/2433)) \ No newline at end of file diff --git a/.changelog/unreleased/features/2596-storage-report.md b/.changelog/unreleased/features/2596-storage-report.md new file mode 100644 index 00000000000..27fc6d95a8f --- /dev/null +++ b/.changelog/unreleased/features/2596-storage-report.md @@ -0,0 +1 @@ +- `[docs]` Add report on storage improvements and findings. ([\#2569](https://github.com/cometbft/cometbft/pull/2569)) \ No newline at end of file diff --git a/.changelog/unreleased/features/2756-mempool-max-txs-bytes.md b/.changelog/unreleased/features/2756-mempool-max-txs-bytes.md new file mode 100644 index 00000000000..97ab4d1271a --- /dev/null +++ b/.changelog/unreleased/features/2756-mempool-max-txs-bytes.md @@ -0,0 +1,2 @@ +- `[config]` Update the default value of `mempool.max_txs_bytes` to 64 MiB. + ([\#2756](https://github.com/cometbft/cometbft/issues/2756)) diff --git a/.changelog/unreleased/features/2765-bls12-381-curve.md b/.changelog/unreleased/features/2765-bls12-381-curve.md new file mode 100644 index 00000000000..4e73808a59c --- /dev/null +++ b/.changelog/unreleased/features/2765-bls12-381-curve.md @@ -0,0 +1,2 @@ +- `[crypto]` Add support for BLS12-381 keys. Use `bls12381` build flag to enable + it ([\#2765](https://github.com/cometbft/cometbft/pull/2765)) diff --git a/.changelog/unreleased/features/7354-synchrony-field.md b/.changelog/unreleased/features/7354-synchrony-field.md new file mode 100644 index 00000000000..94505049768 --- /dev/null +++ b/.changelog/unreleased/features/7354-synchrony-field.md @@ -0,0 +1,3 @@ +- `[consensus]` add a new `synchrony` field to the `ConsensusParameter` struct + for controlling the parameters of the proposer-based timestamp algorithm. (@williambanfield) + ([tendermint/tendermint\#7354](https://github.com/tendermint/tendermint/pull/7354)) diff --git a/.changelog/unreleased/features/7376-wait-for-previous-block-time.md b/.changelog/unreleased/features/7376-wait-for-previous-block-time.md new file mode 100644 index 00000000000..b7a101fbcef --- /dev/null +++ b/.changelog/unreleased/features/7376-wait-for-previous-block-time.md @@ -0,0 +1,4 @@ +- `[consensus]` Update the proposal logic per the Propose-based timestamps specification + so that the proposer will wait for the previous block time to occur + before proposing the next block. (@williambanfield) + ([tendermint/tendermint\#7376](https://github.com/tendermint/tendermint/pull/7376)) diff --git a/.changelog/unreleased/features/7382-new-ts-validation.md b/.changelog/unreleased/features/7382-new-ts-validation.md new file mode 100644 index 00000000000..ea7c6e01780 --- /dev/null +++ b/.changelog/unreleased/features/7382-new-ts-validation.md @@ -0,0 +1,3 @@ +- `[consensus]` Update block validation to no longer require the block timestamp + to be the median of the timestamps of the previous commit. (@anca) + ([tendermint/tendermint\#7382](https://github.com/tendermint/tendermint/pull/7382)) diff --git a/.changelog/unreleased/features/7391-use-pbts-for-proposal-ts.md b/.changelog/unreleased/features/7391-use-pbts-for-proposal-ts.md new file mode 100644 index 00000000000..3ed67673809 --- /dev/null +++ b/.changelog/unreleased/features/7391-use-pbts-for-proposal-ts.md @@ -0,0 +1,4 @@ +- `[consensus]` Use the proposed block timestamp as the proposal timestamp. + Update the block validation logic to ensure that the proposed block's timestamp + matches the timestamp in the proposal message. (@williambanfield) + ([tendermint/tendermint\#7391](https://github.com/tendermint/tendermint/pull/7391)) diff --git a/.changelog/unreleased/features/7415-prevote-nil-non-timely.md b/.changelog/unreleased/features/7415-prevote-nil-non-timely.md new file mode 100644 index 00000000000..3677b12514b --- /dev/null +++ b/.changelog/unreleased/features/7415-prevote-nil-non-timely.md @@ -0,0 +1,4 @@ +- `[consensus]` Update proposal validation logic to Prevote nil + if a proposal does not meet the conditions for Timeliness + per the proposer-based timestamp specification. (@anca) + ([tendermint/tendermint\#7415](https://github.com/tendermint/tendermint/pull/7415)) diff --git a/.changelog/unreleased/features/7711-fix-first-height.md b/.changelog/unreleased/features/7711-fix-first-height.md new file mode 100644 index 00000000000..2652371261b --- /dev/null +++ b/.changelog/unreleased/features/7711-fix-first-height.md @@ -0,0 +1,3 @@ +- `[consensus]` Use the proposer timestamp for the first height instead of the genesis time. + Chains will still start consensus at the genesis time. (@anca) + ([tendermint/tendermint\#7711](https://github.com/tendermint/tendermint/pull/7711)) diff --git a/.changelog/unreleased/features/816-config-grpc-version-service.md b/.changelog/unreleased/features/816-config-grpc-version-service.md new file mode 100644 index 00000000000..89bfd74ab26 --- /dev/null +++ b/.changelog/unreleased/features/816-config-grpc-version-service.md @@ -0,0 +1,2 @@ +- `[config]` Added `[grpc.version_service]` section for configuring the gRPC version service. + ([\#816](https://github.com/cometbft/cometbft/issues/816)) diff --git a/.changelog/unreleased/features/816-config-grpc.md b/.changelog/unreleased/features/816-config-grpc.md new file mode 100644 index 00000000000..3bb38abfa37 --- /dev/null +++ b/.changelog/unreleased/features/816-config-grpc.md @@ -0,0 +1,2 @@ +- `[config]` Added `[grpc]` section to configure the gRPC server. + ([\#816](https://github.com/cometbft/cometbft/issues/816)) diff --git a/.changelog/unreleased/features/816-grpc-client.md b/.changelog/unreleased/features/816-grpc-client.md new file mode 100644 index 00000000000..e1511882bf0 --- /dev/null +++ b/.changelog/unreleased/features/816-grpc-client.md @@ -0,0 +1,2 @@ +- `[rpc/grpc]` Add gRPC client with support for version service + ([\#816](https://github.com/cometbft/cometbft/issues/816)) \ No newline at end of file diff --git a/.changelog/unreleased/features/816-grpc-server.md b/.changelog/unreleased/features/816-grpc-server.md new file mode 100644 index 00000000000..eba1d7fccda --- /dev/null +++ b/.changelog/unreleased/features/816-grpc-server.md @@ -0,0 +1,3 @@ +- `[rpc/grpc]` Add gRPC server to the node, configurable + via a new `[grpc]` section in the configuration file + ([\#816](https://github.com/cometbft/cometbft/issues/816)) \ No newline at end of file diff --git a/.changelog/unreleased/features/816-grpc-version-service.md b/.changelog/unreleased/features/816-grpc-version-service.md new file mode 100644 index 00000000000..0d3ca50c6f5 --- /dev/null +++ b/.changelog/unreleased/features/816-grpc-version-service.md @@ -0,0 +1,3 @@ +- `[rpc/grpc]` Add gRPC version service to allow clients to + establish the software and protocol versions of the node + ([\#816](https://github.com/cometbft/cometbft/issues/816)) \ No newline at end of file diff --git a/.changelog/unreleased/features/9680-config-introduce-bootstrappeers.md b/.changelog/unreleased/features/9680-config-introduce-bootstrappeers.md deleted file mode 100644 index 538429f3a24..00000000000 --- a/.changelog/unreleased/features/9680-config-introduce-bootstrappeers.md +++ /dev/null @@ -1,3 +0,0 @@ -- `[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)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1017-remove-genesis-persistence-in-state-db.md b/.changelog/unreleased/improvements/1017-remove-genesis-persistence-in-state-db.md new file mode 100644 index 00000000000..13917825084 --- /dev/null +++ b/.changelog/unreleased/improvements/1017-remove-genesis-persistence-in-state-db.md @@ -0,0 +1,3 @@ +- `[node]` Remove genesis persistence in state db, replaced by a hash + ([cometbft/cometbft\#1017](https://github.com/cometbft/cometbft/pull/1017), + [cometbft/cometbft\#1295](https://github.com/cometbft/cometbft/pull/1295)) diff --git a/.changelog/unreleased/improvements/1022-log-invalid-vote-extension.md b/.changelog/unreleased/improvements/1022-log-invalid-vote-extension.md new file mode 100644 index 00000000000..8e015ae41f8 --- /dev/null +++ b/.changelog/unreleased/improvements/1022-log-invalid-vote-extension.md @@ -0,0 +1,2 @@ +- `[consensus]` Log vote validation failures at info level + ([\#1022](https://github.com/cometbft/cometbft/pull/1022)) diff --git a/.changelog/unreleased/improvements/1096-config-pruner.md b/.changelog/unreleased/improvements/1096-config-pruner.md new file mode 100644 index 00000000000..045a4364999 --- /dev/null +++ b/.changelog/unreleased/improvements/1096-config-pruner.md @@ -0,0 +1,3 @@ +- `[config]` Added `[storage.pruning]` and `[storage.pruning.data_companion]` + sections to facilitate background pruning and data companion (ADR 101) + operations ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1096-node-pruner.md b/.changelog/unreleased/improvements/1096-node-pruner.md new file mode 100644 index 00000000000..ba9f412fc97 --- /dev/null +++ b/.changelog/unreleased/improvements/1096-node-pruner.md @@ -0,0 +1,3 @@ +- `[node]` The `node.Node` struct now manages a + `state.Pruner` service to facilitate background pruning + ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1096-state-abcires-pruning.md b/.changelog/unreleased/improvements/1096-state-abcires-pruning.md new file mode 100644 index 00000000000..efb451b1df2 --- /dev/null +++ b/.changelog/unreleased/improvements/1096-state-abcires-pruning.md @@ -0,0 +1,2 @@ +- `[state]` ABCI response pruning has been added for use by the data companion + ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1096-state-background-pruning.md b/.changelog/unreleased/improvements/1096-state-background-pruning.md new file mode 100644 index 00000000000..7c6fd662147 --- /dev/null +++ b/.changelog/unreleased/improvements/1096-state-background-pruning.md @@ -0,0 +1,2 @@ +- `[state]` Block pruning has been moved from the block executor into a + background process ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1141-abci-consensus-syncd-proxy.md b/.changelog/unreleased/improvements/1141-abci-consensus-syncd-proxy.md new file mode 100644 index 00000000000..a2e8c09ce69 --- /dev/null +++ b/.changelog/unreleased/improvements/1141-abci-consensus-syncd-proxy.md @@ -0,0 +1,4 @@ +- `[abci/client]` Add consensus-synchronized local client creator, + which only imposes a mutex on the consensus "connection", leaving + the concurrency of all other "connections" up to the application + ([\#1141](https://github.com/cometbft/cometbft/pull/1141)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1141-abci-unsync-proxy.md b/.changelog/unreleased/improvements/1141-abci-unsync-proxy.md new file mode 100644 index 00000000000..4937c2f9c14 --- /dev/null +++ b/.changelog/unreleased/improvements/1141-abci-unsync-proxy.md @@ -0,0 +1,3 @@ +- `[abci/client]` Add fully unsynchronized local client creator, which + imposes no mutexes on the application, leaving all handling of concurrency up + to the application ([\#1141](https://github.com/cometbft/cometbft/pull/1141)) diff --git a/.changelog/unreleased/improvements/1230-consensus-process-proposal-once.md b/.changelog/unreleased/improvements/1230-consensus-process-proposal-once.md new file mode 100644 index 00000000000..a06acfc27b8 --- /dev/null +++ b/.changelog/unreleased/improvements/1230-consensus-process-proposal-once.md @@ -0,0 +1,3 @@ +- `[consensus]` When prevoting, avoid calling PropocessProposal when we know the + proposal was already validated by correct nodes. + ([\#1230](https://github.com/cometbft/cometbft/pull/1230)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1297-remove-genesis-from-db-upgrade.md b/.changelog/unreleased/improvements/1297-remove-genesis-from-db-upgrade.md new file mode 100644 index 00000000000..e7772829b3b --- /dev/null +++ b/.changelog/unreleased/improvements/1297-remove-genesis-from-db-upgrade.md @@ -0,0 +1,2 @@ +- `[node]` On upgrade, after [\#1296](https://github.com/cometbft/cometbft/pull/1296), delete the genesis file existing in the DB. + ([cometbft/cometbft\#1297](https://github.com/cometbft/cometbft/pull/1297) diff --git a/.changelog/unreleased/improvements/1324-cli-genesis-hash-checked-on-load.md b/.changelog/unreleased/improvements/1324-cli-genesis-hash-checked-on-load.md new file mode 100644 index 00000000000..27ae4d9cce8 --- /dev/null +++ b/.changelog/unreleased/improvements/1324-cli-genesis-hash-checked-on-load.md @@ -0,0 +1,3 @@ +- `[cli/node]` The genesis hash provided with the `--genesis-hash` is now + forwarded to the node, instead of reading the file. + ([\#1324](https://github.com/cometbft/cometbft/pull/1324)). \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1324-config-genesis-hash.md b/.changelog/unreleased/improvements/1324-config-genesis-hash.md new file mode 100644 index 00000000000..eb42c70fec4 --- /dev/null +++ b/.changelog/unreleased/improvements/1324-config-genesis-hash.md @@ -0,0 +1,3 @@ +`[config]` Added `genesis_hash` storage parameter, which when set it is checked + on node startup + ([\#1324](https://github.com/cometbft/cometbft/pull/1324/)) diff --git a/.changelog/unreleased/improvements/136-remove-tm-signer-harness.md b/.changelog/unreleased/improvements/136-remove-tm-signer-harness.md deleted file mode 100644 index 6eb6c2158c2..00000000000 --- a/.changelog/unreleased/improvements/136-remove-tm-signer-harness.md +++ /dev/null @@ -1,2 +0,0 @@ -- `[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/unreleased/improvements/1412-rpc-versioning.md b/.changelog/unreleased/improvements/1412-rpc-versioning.md new file mode 100644 index 00000000000..e809d20ea45 --- /dev/null +++ b/.changelog/unreleased/improvements/1412-rpc-versioning.md @@ -0,0 +1,3 @@ +- `[rpc]` The RPC API is now versioned, with all existing endpoints accessible + via `/v1/*` as well as `/*` + ([\#1412](https://github.com/cometbft/cometbft/pull/1412)) diff --git a/.changelog/unreleased/improvements/1518-reduce-default-maxbytes_increase_maxgas.md b/.changelog/unreleased/improvements/1518-reduce-default-maxbytes_increase_maxgas.md new file mode 100644 index 00000000000..85b84c65cf0 --- /dev/null +++ b/.changelog/unreleased/improvements/1518-reduce-default-maxbytes_increase_maxgas.md @@ -0,0 +1,2 @@ +- `[consensus]` Reduce the default MaxBytes to 4MB and increase MaxGas to 10 million + ([\#1518](https://github.com/cometbft/cometbft/pull/1518)) diff --git a/.changelog/unreleased/improvements/1558-experimental-gossip-limiting.md b/.changelog/unreleased/improvements/1558-experimental-gossip-limiting.md new file mode 100644 index 00000000000..58fc6c6f863 --- /dev/null +++ b/.changelog/unreleased/improvements/1558-experimental-gossip-limiting.md @@ -0,0 +1,9 @@ +- `[mempool]` Add experimental feature to limit the number of persistent peers and non-persistent + peers to which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and + `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to + which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) diff --git a/.changelog/unreleased/improvements/1559-e2e-latency-emulation.md b/.changelog/unreleased/improvements/1559-e2e-latency-emulation.md new file mode 100644 index 00000000000..02e8d0a0355 --- /dev/null +++ b/.changelog/unreleased/improvements/1559-e2e-latency-emulation.md @@ -0,0 +1,2 @@ +- `[e2e]` Allow latency emulation between nodes. + ([\#1559](https://github.com/cometbft/cometbft/pull/1559)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1560-e2e-latency-emulation.md b/.changelog/unreleased/improvements/1560-e2e-latency-emulation.md new file mode 100644 index 00000000000..77dc608db3a --- /dev/null +++ b/.changelog/unreleased/improvements/1560-e2e-latency-emulation.md @@ -0,0 +1,2 @@ +- `[e2e]` Allow latency emulation between nodes. + ([\#1560](https://github.com/cometbft/cometbft/pull/1560)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1579-e2e-disable-pex-reactor.md b/.changelog/unreleased/improvements/1579-e2e-disable-pex-reactor.md new file mode 100644 index 00000000000..069026a41e6 --- /dev/null +++ b/.changelog/unreleased/improvements/1579-e2e-disable-pex-reactor.md @@ -0,0 +1,2 @@ +- `[e2e]` Allow disabling the PEX reactor on all nodes in the testnet + ([\#1579](https://github.com/cometbft/cometbft/pull/1579)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1594-export-makehttpdialer.md b/.changelog/unreleased/improvements/1594-export-makehttpdialer.md new file mode 100644 index 00000000000..dfd1cd81021 --- /dev/null +++ b/.changelog/unreleased/improvements/1594-export-makehttpdialer.md @@ -0,0 +1,2 @@ +- `[rpc]` Export `MakeHTTPDialer` to allow HTTP client constructors more flexibility. + ([\#1594](https://github.com/cometbft/cometbft/pull/1594)) diff --git a/.changelog/unreleased/improvements/169-tx_index-pruning.md b/.changelog/unreleased/improvements/169-tx_index-pruning.md new file mode 100644 index 00000000000..957462f6889 --- /dev/null +++ b/.changelog/unreleased/improvements/169-tx_index-pruning.md @@ -0,0 +1,2 @@ +- `[state/indexer]` Add transaction and block index pruning + ([\#1176](https://github.com/cometbft/cometbft/pull/1176)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/1715-validate-validator-address.md b/.changelog/unreleased/improvements/1715-validate-validator-address.md new file mode 100644 index 00000000000..ec7f2c7da6a --- /dev/null +++ b/.changelog/unreleased/improvements/1715-validate-validator-address.md @@ -0,0 +1 @@ +- `[types]` Validate `Validator#Address` in `ValidateBasic` ([\#1715](https://github.com/cometbft/cometbft/pull/1715)) diff --git a/.changelog/unreleased/improvements/1730-increase-abci-socket-message-size-limit.md b/.changelog/unreleased/improvements/1730-increase-abci-socket-message-size-limit.md new file mode 100644 index 00000000000..5246eb57f08 --- /dev/null +++ b/.changelog/unreleased/improvements/1730-increase-abci-socket-message-size-limit.md @@ -0,0 +1 @@ +- `[abci]` Increase ABCI socket message size limit to 2GB ([\#1730](https://github.com/cometbft/cometbft/pull/1730): @troykessler) diff --git a/.changelog/unreleased/improvements/1735-batch-save-state.md b/.changelog/unreleased/improvements/1735-batch-save-state.md new file mode 100644 index 00000000000..721380f6041 --- /dev/null +++ b/.changelog/unreleased/improvements/1735-batch-save-state.md @@ -0,0 +1 @@ +- `[state]` Save the state using a single DB batch ([\#1735](https://github.com/cometbft/cometbft/pull/1735)) diff --git a/.changelog/unreleased/improvements/1755-batch-save-block.md b/.changelog/unreleased/improvements/1755-batch-save-block.md new file mode 100644 index 00000000000..22f15cdb423 --- /dev/null +++ b/.changelog/unreleased/improvements/1755-batch-save-block.md @@ -0,0 +1,2 @@ +- `[store]` Save block using a single DB batch if block is less than 640kB, otherwise each block part is saved individually + ([\#1755](https://github.com/cometbft/cometbft/pull/1755)) diff --git a/.changelog/unreleased/improvements/1900-httpproxy-from-env.md b/.changelog/unreleased/improvements/1900-httpproxy-from-env.md new file mode 100644 index 00000000000..fd654ef7ba0 --- /dev/null +++ b/.changelog/unreleased/improvements/1900-httpproxy-from-env.md @@ -0,0 +1,2 @@ +- `[rpc]` Support setting proxy from env to `DefaultHttpClient`. + ([\#1900](https://github.com/cometbft/cometbft/pull/1900)) diff --git a/.changelog/unreleased/improvements/1901-export-p2p-package-errors.md b/.changelog/unreleased/improvements/1901-export-p2p-package-errors.md new file mode 100644 index 00000000000..97dae672c8d --- /dev/null +++ b/.changelog/unreleased/improvements/1901-export-p2p-package-errors.md @@ -0,0 +1 @@ +- `[p2p]` Export p2p package errors ([\#1901](https://github.com/cometbft/cometbft/pull/1901)) (contributes to [\#1140](https://github.com/cometbft/cometbft/issues/1140)) diff --git a/.changelog/unreleased/improvements/1902-rpc-default-port.md b/.changelog/unreleased/improvements/1902-rpc-default-port.md new file mode 100644 index 00000000000..b321bed5394 --- /dev/null +++ b/.changelog/unreleased/improvements/1902-rpc-default-port.md @@ -0,0 +1 @@ +- `[rpc]` Use default port for HTTP(S) URLs when there is no explicit port ([\#1903](https://github.com/cometbft/cometbft/pull/1903)) diff --git a/.changelog/unreleased/improvements/1904-export-light-package-errors.md b/.changelog/unreleased/improvements/1904-export-light-package-errors.md new file mode 100644 index 00000000000..654a7a32d54 --- /dev/null +++ b/.changelog/unreleased/improvements/1904-export-light-package-errors.md @@ -0,0 +1 @@ +- `[light]` Export light package errors ([\#1904](https://github.com/cometbft/cometbft/pull/1904)) (contributes to [\#1140](https://github.com/cometbft/cometbft/issues/1140)) diff --git a/.changelog/unreleased/improvements/1921-crypto-merkle-innerHash.md b/.changelog/unreleased/improvements/1921-crypto-merkle-innerHash.md new file mode 100644 index 00000000000..d3c9dac2cba --- /dev/null +++ b/.changelog/unreleased/improvements/1921-crypto-merkle-innerHash.md @@ -0,0 +1 @@ +- `[crypto/merkle]` faster calculation of hashes ([#1921](https://github.com/cometbft/cometbft/pull/1921)) diff --git a/.changelog/unreleased/improvements/1958-disable-linting.md b/.changelog/unreleased/improvements/1958-disable-linting.md new file mode 100644 index 00000000000..b744fb7fe53 --- /dev/null +++ b/.changelog/unreleased/improvements/1958-disable-linting.md @@ -0,0 +1 @@ +- Removed undesired linting from `Makefile` and added dependency check for `codespell`. diff --git a/.changelog/unreleased/improvements/2016-blocksync-avoid-double-calling-block-from-proto.md b/.changelog/unreleased/improvements/2016-blocksync-avoid-double-calling-block-from-proto.md new file mode 100644 index 00000000000..7251221be18 --- /dev/null +++ b/.changelog/unreleased/improvements/2016-blocksync-avoid-double-calling-block-from-proto.md @@ -0,0 +1,2 @@ +- `[blocksync]` Avoid double-calling `types.BlockFromProto` for performance + reasons ([\#2016](https://github.com/cometbft/cometbft/pull/2016)) diff --git a/.changelog/unreleased/improvements/2017-state-avoid-double-saving-finalize-block-response.md b/.changelog/unreleased/improvements/2017-state-avoid-double-saving-finalize-block-response.md new file mode 100644 index 00000000000..e5df5a0dd1e --- /dev/null +++ b/.changelog/unreleased/improvements/2017-state-avoid-double-saving-finalize-block-response.md @@ -0,0 +1,2 @@ +- `[state]` avoid double-saving `FinalizeBlockResponse` for performance reasons + ([\#2017](https://github.com/cometbft/cometbft/pull/2017)) diff --git a/.changelog/unreleased/improvements/2065-e2e-vote-ext-activation.md b/.changelog/unreleased/improvements/2065-e2e-vote-ext-activation.md new file mode 100644 index 00000000000..9ced3a5da72 --- /dev/null +++ b/.changelog/unreleased/improvements/2065-e2e-vote-ext-activation.md @@ -0,0 +1,5 @@ +- `[e2e]` Add manifest option `VoteExtensionsUpdateHeight` to test + vote extension activation via `InitChain` and `FinalizeBlock`. + Also, extend the manifest generator to produce different values + of this new option + ([\#2065](https://github.com/cometbft/cometbft/pull/2065)) diff --git a/.changelog/unreleased/improvements/2093-metric-chain-size-bytes.md b/.changelog/unreleased/improvements/2093-metric-chain-size-bytes.md new file mode 100644 index 00000000000..afba958e3b7 --- /dev/null +++ b/.changelog/unreleased/improvements/2093-metric-chain-size-bytes.md @@ -0,0 +1,2 @@ +- `[consensus]` Add `chain_size_bytes` metric for measuring the size of the blockchain in bytes + ([\#2093](https://github.com/cometbft/cometbft/pull/2093)) diff --git a/.changelog/unreleased/improvements/2094-e2e-load-max-txs.md b/.changelog/unreleased/improvements/2094-e2e-load-max-txs.md new file mode 100644 index 00000000000..31ca79cfe3b --- /dev/null +++ b/.changelog/unreleased/improvements/2094-e2e-load-max-txs.md @@ -0,0 +1,2 @@ +- `[e2e]` Add manifest option `load_max_txs` to limit the number of transactions generated by the + `load` command. ([\#2094](https://github.com/cometbft/cometbft/pull/2094)) diff --git a/.changelog/unreleased/improvements/2142-psql-optimization.md b/.changelog/unreleased/improvements/2142-psql-optimization.md new file mode 100644 index 00000000000..9add9ed6d7a --- /dev/null +++ b/.changelog/unreleased/improvements/2142-psql-optimization.md @@ -0,0 +1,2 @@ +- Optimized the PSQL indexer + ([\#2142](https://github.com/cometbft/cometbft/pull/2142)) thanks to external contributor @k0marov ! diff --git a/.changelog/unreleased/improvements/2192-e2e-make-fast.md b/.changelog/unreleased/improvements/2192-e2e-make-fast.md new file mode 100644 index 00000000000..308918c2d5f --- /dev/null +++ b/.changelog/unreleased/improvements/2192-e2e-make-fast.md @@ -0,0 +1,2 @@ +- `[e2e]` Add new targets `fast` and `clean` to Makefile. + ([\#2192](https://github.com/cometbft/cometbft/pull/2192)) diff --git a/.changelog/unreleased/improvements/2200-export-rpc-packager-errors.md b/.changelog/unreleased/improvements/2200-export-rpc-packager-errors.md new file mode 100644 index 00000000000..b549dc3e783 --- /dev/null +++ b/.changelog/unreleased/improvements/2200-export-rpc-packager-errors.md @@ -0,0 +1 @@ +- `[rpc]` Export RPC package errors ([\#2200](https://github.com/cometbft/cometbft/pull/2200)) (contributes to [\#1140](https://github.com/cometbft/cometbft/issues/1140)) diff --git a/.changelog/unreleased/improvements/2246-make-peerset-remove-more-efficient.md b/.changelog/unreleased/improvements/2246-make-peerset-remove-more-efficient.md new file mode 100644 index 00000000000..793d7eb99fc --- /dev/null +++ b/.changelog/unreleased/improvements/2246-make-peerset-remove-more-efficient.md @@ -0,0 +1 @@ +- `[p2p]` make `PeerSet.Remove` more efficient (Author: @odeke-em) [\#2246](https://github.com/cometbft/cometbft/pull/2246) diff --git a/.changelog/unreleased/improvements/2328-e2e-log-sent-txs b/.changelog/unreleased/improvements/2328-e2e-log-sent-txs new file mode 100644 index 00000000000..e1b69899f40 --- /dev/null +++ b/.changelog/unreleased/improvements/2328-e2e-log-sent-txs @@ -0,0 +1,2 @@ +- `[e2e]` Log the number of transactions that were sent successfully or failed. + ([\#2328](https://github.com/cometbft/cometbft/pull/2328)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/2434-jsonrpc-websocket-basic-auth.md b/.changelog/unreleased/improvements/2434-jsonrpc-websocket-basic-auth.md new file mode 100644 index 00000000000..e4db7c06c7d --- /dev/null +++ b/.changelog/unreleased/improvements/2434-jsonrpc-websocket-basic-auth.md @@ -0,0 +1 @@ +- `[jsonrpc]` enable HTTP basic auth in websocket client ([#2434](https://github.com/cometbft/cometbft/pull/2434)) diff --git a/.changelog/unreleased/improvements/2453-e2e-add-clock-skew.md b/.changelog/unreleased/improvements/2453-e2e-add-clock-skew.md new file mode 100644 index 00000000000..5f4e294430c --- /dev/null +++ b/.changelog/unreleased/improvements/2453-e2e-add-clock-skew.md @@ -0,0 +1,3 @@ +- `[e2e]` Introduce the possibility in the manifest for some nodes + to run in a preconfigured clock skew. + ([\#2453](https://github.com/cometbft/cometbft/pull/2453)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/2467-decrease-n-of-requested-blocks.md b/.changelog/unreleased/improvements/2467-decrease-n-of-requested-blocks.md new file mode 100644 index 00000000000..3b5ea17ce5a --- /dev/null +++ b/.changelog/unreleased/improvements/2467-decrease-n-of-requested-blocks.md @@ -0,0 +1,3 @@ +- `[blocksync]` make the max number of downloaded blocks dynamic. + Previously it was a const 600. Now it's `peersCount * maxPendingRequestsPerPeer (20)` + [\#2467](https://github.com/cometbft/cometbft/pull/2467) diff --git a/.changelog/unreleased/improvements/2475-blocksync-2nd-request.md b/.changelog/unreleased/improvements/2475-blocksync-2nd-request.md new file mode 100644 index 00000000000..67614a8e35f --- /dev/null +++ b/.changelog/unreleased/improvements/2475-blocksync-2nd-request.md @@ -0,0 +1,3 @@ +- `[blocksync]` Request a block from peer B if we are approaching pool's height + (less than 50 blocks) and the current peer A is slow in sending us the + block [\#2475](https://github.com/cometbft/cometbft/pull/2475) diff --git a/.changelog/unreleased/improvements/2475-blocksync-no-block-response.md b/.changelog/unreleased/improvements/2475-blocksync-no-block-response.md new file mode 100644 index 00000000000..d01b3679866 --- /dev/null +++ b/.changelog/unreleased/improvements/2475-blocksync-no-block-response.md @@ -0,0 +1,3 @@ +- `[blocksync]` Request the block N from peer B immediately after getting + `NoBlockResponse` from peer A + [\#2475](https://github.com/cometbft/cometbft/pull/2475) diff --git a/.changelog/unreleased/improvements/2475-blocksync-sort-peers.md b/.changelog/unreleased/improvements/2475-blocksync-sort-peers.md new file mode 100644 index 00000000000..5c544401ba6 --- /dev/null +++ b/.changelog/unreleased/improvements/2475-blocksync-sort-peers.md @@ -0,0 +1,2 @@ +- `[blocksync]` Sort peers by download rate (the fastest peer is picked first) + [\#2475](https://github.com/cometbft/cometbft/pull/2475) diff --git a/.changelog/unreleased/improvements/2496-privval-ext-signature.md b/.changelog/unreleased/improvements/2496-privval-ext-signature.md new file mode 100644 index 00000000000..d23573f3f7f --- /dev/null +++ b/.changelog/unreleased/improvements/2496-privval-ext-signature.md @@ -0,0 +1,4 @@ +- `[privval]` DO NOT require extension signature from privval if vote + extensions are disabled. Remote signers can skip signing the extension if + `skip_extension_signing` flag in `SignVoteRequest` is true. + [\#2496](https://github.com/cometbft/cometbft/pull/2496) diff --git a/.changelog/unreleased/improvements/2522-privval-skip-extension-signing.md b/.changelog/unreleased/improvements/2522-privval-skip-extension-signing.md new file mode 100644 index 00000000000..86965e98ab0 --- /dev/null +++ b/.changelog/unreleased/improvements/2522-privval-skip-extension-signing.md @@ -0,0 +1,5 @@ +- `[proto]` Add `skip_extension_signing` field to the `SignVoteRequest` message + in `cometbft.privval.v1` ([\#2522](https://github.com/cometbft/cometbft/pull/2522)). + The `cometbft.privval.v1beta2` package is added to capture the protocol as it was + released in CometBFT 0.38.x + ([\#2529](https://github.com/cometbft/cometbft/pull/2529)). diff --git a/.changelog/unreleased/improvements/2788-move-ws-info-log-to-debug b/.changelog/unreleased/improvements/2788-move-ws-info-log-to-debug new file mode 100644 index 00000000000..7e5012e823d --- /dev/null +++ b/.changelog/unreleased/improvements/2788-move-ws-info-log-to-debug @@ -0,0 +1 @@ +Move the websockets info log for successful replies to debug. diff --git a/.changelog/unreleased/improvements/56-rpc-cache-rpc-responses.md b/.changelog/unreleased/improvements/56-rpc-cache-rpc-responses.md deleted file mode 100644 index 344b3df93b9..00000000000 --- a/.changelog/unreleased/improvements/56-rpc-cache-rpc-responses.md +++ /dev/null @@ -1,2 +0,0 @@ -- `[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/unreleased/improvements/634-mempool-metric-times-tx-was-received.md b/.changelog/unreleased/improvements/634-mempool-metric-times-tx-was-received.md new file mode 100644 index 00000000000..0de610b5ea6 --- /dev/null +++ b/.changelog/unreleased/improvements/634-mempool-metric-times-tx-was-received.md @@ -0,0 +1,2 @@ +- `[mempool]` Add a metric (a counter) to measure whether a tx was received more than once. + ([\#634](https://github.com/cometbft/cometbft/pull/634)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/658-adr-102-rpc-companion.md b/.changelog/unreleased/improvements/658-adr-102-rpc-companion.md new file mode 100644 index 00000000000..d75828fa662 --- /dev/null +++ b/.changelog/unreleased/improvements/658-adr-102-rpc-companion.md @@ -0,0 +1,2 @@ +- `[docs/references]` Added ADR-102: RPC Companion. + ([\#658](https://github.com/cometbft/cometbft/pull/658)) diff --git a/.changelog/unreleased/improvements/896-consensus-metric-duplicates.md b/.changelog/unreleased/improvements/896-consensus-metric-duplicates.md new file mode 100644 index 00000000000..5661da834a9 --- /dev/null +++ b/.changelog/unreleased/improvements/896-consensus-metric-duplicates.md @@ -0,0 +1,2 @@ +- `[consensus]` New metrics (counters) to track duplicate votes and block parts. + ([\#896](https://github.com/cometbft/cometbft/pull/896)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/904-gossip-sleep-had-block-part.md b/.changelog/unreleased/improvements/904-gossip-sleep-had-block-part.md new file mode 100644 index 00000000000..2374ea82fd7 --- /dev/null +++ b/.changelog/unreleased/improvements/904-gossip-sleep-had-block-part.md @@ -0,0 +1,6 @@ +- `[consensus]` Optimize vote and block part gossip with new message `HasProposalBlockPartMessage`, + which is similar to `HasVoteMessage`; and random sleep in the loop broadcasting those messages. + The sleep can be configured with new config `peer_gossip_intraloop_sleep_duration`, which is set to 0 + by default as this is experimental. + Our scale tests show substantial bandwidth improvement with a value of 50 ms. + ([\#904](https://github.com/cometbft/cometbft/pull/904)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/955-lightclient-spec.md b/.changelog/unreleased/improvements/955-lightclient-spec.md new file mode 100644 index 00000000000..24680c39dc4 --- /dev/null +++ b/.changelog/unreleased/improvements/955-lightclient-spec.md @@ -0,0 +1 @@ +- Update Apalache type annotations in the light client spec ([#955](https://github.com/cometbft/cometbft/pull/955)) diff --git a/.changelog/unreleased/improvements/9650-rpc-cache-rpc-responses.md b/.changelog/unreleased/improvements/9650-rpc-cache-rpc-responses.md deleted file mode 100644 index 3b6b5034726..00000000000 --- a/.changelog/unreleased/improvements/9650-rpc-cache-rpc-responses.md +++ /dev/null @@ -1,2 +0,0 @@ -- `[rpc]` Enable caching of RPC responses - ([\#9650](https://github.com/tendermint/tendermint/pull/9650)) \ No newline at end of file diff --git a/.changelog/unreleased/minimum-go-version/1244-bump-go-version.md b/.changelog/unreleased/minimum-go-version/1244-bump-go-version.md new file mode 100644 index 00000000000..e04bb31d4e3 --- /dev/null +++ b/.changelog/unreleased/minimum-go-version/1244-bump-go-version.md @@ -0,0 +1,2 @@ +- Bump minimum Go version to v1.21 + ([\#1244](https://github.com/cometbft/cometbft/pull/1244)) \ No newline at end of file diff --git a/.changelog/v0.34.28/breaking-changes/558-tm10011.md b/.changelog/v0.34.28/breaking-changes/558-tm10011.md new file mode 100644 index 00000000000..d1b9fca4aba --- /dev/null +++ b/.changelog/v0.34.28/breaking-changes/558-tm10011.md @@ -0,0 +1,2 @@ +- `[crypto/merkle]` Do not allow verification of Merkle Proofs against empty trees (`nil` root). `Proof.ComputeRootHash` now panics when it encounters an error, but `Proof.Verify` does not panic + ([\#558](https://github.com/cometbft/cometbft/issues/558)) diff --git a/.changelog/unreleased/bug-fixes/496-error-on-applyblock-should-panic.md b/.changelog/v0.34.28/bug-fixes/496-error-on-applyblock-should-panic.md similarity index 100% rename from .changelog/unreleased/bug-fixes/496-error-on-applyblock-should-panic.md rename to .changelog/v0.34.28/bug-fixes/496-error-on-applyblock-should-panic.md diff --git a/.changelog/unreleased/bug-fixes/524-rename-peerstate-tojson.md b/.changelog/v0.34.28/bug-fixes/524-rename-peerstate-tojson.md similarity index 100% rename from .changelog/unreleased/bug-fixes/524-rename-peerstate-tojson.md rename to .changelog/v0.34.28/bug-fixes/524-rename-peerstate-tojson.md diff --git a/.changelog/v0.34.28/bug-fixes/575-fix-light-client-panic.md b/.changelog/v0.34.28/bug-fixes/575-fix-light-client-panic.md new file mode 100644 index 00000000000..0ec55b923fb --- /dev/null +++ b/.changelog/v0.34.28/bug-fixes/575-fix-light-client-panic.md @@ -0,0 +1,6 @@ +- `[light]` Fixed an edge case where a light client would panic when attempting + to query a node that (1) has started from a non-zero height and (2) does + not yet have any data. The light client will now, correctly, not panic + _and_ keep the node in its list of providers in the same way it would if + it queried a node starting from height zero that does not yet have data + ([\#575](https://github.com/cometbft/cometbft/issues/575)) \ No newline at end of file diff --git a/.changelog/v0.34.28/improvements/475-upgrade-go-schnorrkel.md b/.changelog/v0.34.28/improvements/475-upgrade-go-schnorrkel.md new file mode 100644 index 00000000000..bdaf96c14cf --- /dev/null +++ b/.changelog/v0.34.28/improvements/475-upgrade-go-schnorrkel.md @@ -0,0 +1 @@ +- `[crypto/sr25519]` Upgrade to go-schnorrkel@v1.0.0 ([\#475](https://github.com/cometbft/cometbft/issues/475)) diff --git a/.changelog/v0.34.28/improvements/638-json-rpc-error-message.md b/.changelog/v0.34.28/improvements/638-json-rpc-error-message.md new file mode 100644 index 00000000000..6922091fd25 --- /dev/null +++ b/.changelog/v0.34.28/improvements/638-json-rpc-error-message.md @@ -0,0 +1,3 @@ +- `[jsonrpc/client]` Improve the error message for client errors stemming from + bad HTTP responses. + ([cometbft/cometbft\#638](https://github.com/cometbft/cometbft/pull/638)) diff --git a/.changelog/v0.34.28/summary.md b/.changelog/v0.34.28/summary.md new file mode 100644 index 00000000000..ba3efa9d79e --- /dev/null +++ b/.changelog/v0.34.28/summary.md @@ -0,0 +1,6 @@ +*April 26, 2023* + +This release fixes several bugs, and has had to introduce one small Go +API-breaking change in the `crypto/merkle` package in order to address what +could be a security issue for some users who directly and explicitly make use of +that code. diff --git a/.changelog/v0.34.29/bug-fixes/771-kvindexer-parsing-big-ints.md b/.changelog/v0.34.29/bug-fixes/771-kvindexer-parsing-big-ints.md new file mode 100644 index 00000000000..4a0000db6d3 --- /dev/null +++ b/.changelog/v0.34.29/bug-fixes/771-kvindexer-parsing-big-ints.md @@ -0,0 +1,2 @@ +- `[state/kvindex]` Querying event attributes that are bigger than int64 is now + enabled. ([\#771](https://github.com/cometbft/cometbft/pull/771)) diff --git a/.changelog/v0.34.29/bug-fixes/771-pubsub-parsing-big-ints.md b/.changelog/v0.34.29/bug-fixes/771-pubsub-parsing-big-ints.md new file mode 100644 index 00000000000..fc5f25a90ff --- /dev/null +++ b/.changelog/v0.34.29/bug-fixes/771-pubsub-parsing-big-ints.md @@ -0,0 +1,4 @@ +- `[pubsub]` Pubsub queries are now able to parse big integers (larger than + int64). Very big floats are also properly parsed into very big integers + instead of being truncated to int64. + ([\#771](https://github.com/cometbft/cometbft/pull/771)) diff --git a/.changelog/v0.34.29/improvements/654-rpc-rm-response-data-logs.md b/.changelog/v0.34.29/improvements/654-rpc-rm-response-data-logs.md new file mode 100644 index 00000000000..3fddfee8e71 --- /dev/null +++ b/.changelog/v0.34.29/improvements/654-rpc-rm-response-data-logs.md @@ -0,0 +1,3 @@ +- `[rpc]` Remove response data from response failure logs in order + to prevent large quantities of log data from being produced + ([\#654](https://github.com/cometbft/cometbft/issues/654)) \ No newline at end of file diff --git a/.changelog/v0.34.29/security-fixes/788-rpc-client-pw.md b/.changelog/v0.34.29/security-fixes/788-rpc-client-pw.md new file mode 100644 index 00000000000..430b7b5ac4b --- /dev/null +++ b/.changelog/v0.34.29/security-fixes/788-rpc-client-pw.md @@ -0,0 +1,3 @@ +- `[rpc/jsonrpc/client]` **Low severity** - Prevent RPC + client credentials from being inadvertently dumped to logs + ([\#788](https://github.com/cometbft/cometbft/pull/788)) diff --git a/.changelog/v0.34.29/security-fixes/794-cli-debug-kill-unsafe-cast.md b/.changelog/v0.34.29/security-fixes/794-cli-debug-kill-unsafe-cast.md new file mode 100644 index 00000000000..782eccd9d58 --- /dev/null +++ b/.changelog/v0.34.29/security-fixes/794-cli-debug-kill-unsafe-cast.md @@ -0,0 +1,2 @@ +- `[cmd/cometbft/commands/debug/kill]` **Low severity** - Fix unsafe int cast in + `debug kill` command ([\#794](https://github.com/cometbft/cometbft/pull/794)) diff --git a/.changelog/v0.34.29/security-fixes/865-fix-peerstate-marshaljson.md b/.changelog/v0.34.29/security-fixes/865-fix-peerstate-marshaljson.md new file mode 100644 index 00000000000..fdd9172c209 --- /dev/null +++ b/.changelog/v0.34.29/security-fixes/865-fix-peerstate-marshaljson.md @@ -0,0 +1,3 @@ +- `[consensus]` **Low severity** - Avoid recursive call after rename to + `(*PeerState).MarshalJSON` + ([\#863](https://github.com/cometbft/cometbft/pull/863)) diff --git a/.changelog/v0.34.29/security-fixes/890-mempool-fix-cache.md b/.changelog/v0.34.29/security-fixes/890-mempool-fix-cache.md new file mode 100644 index 00000000000..bad30efc7ab --- /dev/null +++ b/.changelog/v0.34.29/security-fixes/890-mempool-fix-cache.md @@ -0,0 +1,3 @@ +- `[mempool/clist_mempool]` **Low severity** - Prevent a transaction from + appearing twice in the mempool + ([\#890](https://github.com/cometbft/cometbft/pull/890): @otrack) diff --git a/.changelog/v0.34.29/summary.md b/.changelog/v0.34.29/summary.md new file mode 100644 index 00000000000..7ecb2739409 --- /dev/null +++ b/.changelog/v0.34.29/summary.md @@ -0,0 +1,4 @@ +*June 14, 2023* + +Provides several minor bug fixes, as well as fixes for several low-severity +security issues. diff --git a/.changelog/v0.34.30/build/1351-bump-go-120.md b/.changelog/v0.34.30/build/1351-bump-go-120.md new file mode 100644 index 00000000000..12091e3b614 --- /dev/null +++ b/.changelog/v0.34.30/build/1351-bump-go-120.md @@ -0,0 +1,2 @@ +- Bump Go version used to v1.20 since v1.19 has reached EOL + ([\#1351](https://github.com/cometbft/cometbft/pull/1351)) \ No newline at end of file diff --git a/.changelog/v0.34.30/features/1512-metric-mempool-size-bytes.md b/.changelog/v0.34.30/features/1512-metric-mempool-size-bytes.md new file mode 100644 index 00000000000..b935dc40842 --- /dev/null +++ b/.changelog/v0.34.30/features/1512-metric-mempool-size-bytes.md @@ -0,0 +1,2 @@ +- `[metrics]` Add metric for mempool size in bytes `SizeBytes`. + ([\#1512](https://github.com/cometbft/cometbft/pull/1512)) \ No newline at end of file diff --git a/.changelog/v0.34.30/improvements/1210-close-evidence-db.md b/.changelog/v0.34.30/improvements/1210-close-evidence-db.md new file mode 100644 index 00000000000..e32bc87dbe1 --- /dev/null +++ b/.changelog/v0.34.30/improvements/1210-close-evidence-db.md @@ -0,0 +1 @@ +- `[node]` Close evidence.db OnStop ([cometbft/cometbft\#1210](https://github.com/cometbft/cometbft/pull/1210): @chillyvee) diff --git a/.changelog/v0.34.30/improvements/1558-experimental-gossip-limiting.md b/.changelog/v0.34.30/improvements/1558-experimental-gossip-limiting.md new file mode 100644 index 00000000000..52e0d565785 --- /dev/null +++ b/.changelog/v0.34.30/improvements/1558-experimental-gossip-limiting.md @@ -0,0 +1,9 @@ +- `[mempool]` Add experimental feature to limit the number of persistent peers and non-persistent + peers to which the node gossip transactions (only for "v0" mempool). + ([\#1558](https://github.com/cometbft/cometbft/pull/1558), + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and + `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to + which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) diff --git a/.changelog/v0.34.30/improvements/857-make-handshake-cancelable.md b/.changelog/v0.34.30/improvements/857-make-handshake-cancelable.md new file mode 100644 index 00000000000..16b447f6d23 --- /dev/null +++ b/.changelog/v0.34.30/improvements/857-make-handshake-cancelable.md @@ -0,0 +1 @@ +- `[node]` Make handshake cancelable ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) diff --git a/.changelog/v0.34.30/summary.md b/.changelog/v0.34.30/summary.md new file mode 100644 index 00000000000..f1e5c7f755c --- /dev/null +++ b/.changelog/v0.34.30/summary.md @@ -0,0 +1,5 @@ +*November 17, 2023* + +This release contains, among other things, an opt-in, experimental feature to +help reduce the bandwidth consumption associated with the mempool's transaction +gossip. diff --git a/.changelog/v0.34.31/bug-fixes/1654-semaphore-wait.md b/.changelog/v0.34.31/bug-fixes/1654-semaphore-wait.md new file mode 100644 index 00000000000..9d0fb80adcc --- /dev/null +++ b/.changelog/v0.34.31/bug-fixes/1654-semaphore-wait.md @@ -0,0 +1,3 @@ +- `[mempool]` Avoid infinite wait in transaction sending routine when + using experimental parameters to limiting transaction gossiping to peers + ([\#1654](https://github.com/cometbft/cometbft/pull/1654)) \ No newline at end of file diff --git a/.changelog/v0.34.31/summary.md b/.changelog/v0.34.31/summary.md new file mode 100644 index 00000000000..dbf3680044d --- /dev/null +++ b/.changelog/v0.34.31/summary.md @@ -0,0 +1,3 @@ +*November 27, 2023* + +Fixes a small bug in the mempool for an experimental feature. diff --git a/.changelog/v0.37.1/breaking-changes/558-tm10011.md b/.changelog/v0.37.1/breaking-changes/558-tm10011.md new file mode 100644 index 00000000000..d1b9fca4aba --- /dev/null +++ b/.changelog/v0.37.1/breaking-changes/558-tm10011.md @@ -0,0 +1,2 @@ +- `[crypto/merkle]` Do not allow verification of Merkle Proofs against empty trees (`nil` root). `Proof.ComputeRootHash` now panics when it encounters an error, but `Proof.Verify` does not panic + ([\#558](https://github.com/cometbft/cometbft/issues/558)) diff --git a/.changelog/v0.37.1/bug-fixes/496-error-on-applyblock-should-panic.md b/.changelog/v0.37.1/bug-fixes/496-error-on-applyblock-should-panic.md new file mode 100644 index 00000000000..55e9c874f8c --- /dev/null +++ b/.changelog/v0.37.1/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/v0.37.1/bug-fixes/524-rename-peerstate-tojson.md b/.changelog/v0.37.1/bug-fixes/524-rename-peerstate-tojson.md new file mode 100644 index 00000000000..b9a43b3ce4e --- /dev/null +++ b/.changelog/v0.37.1/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/v0.37.1/bug-fixes/575-fix-light-client-panic.md b/.changelog/v0.37.1/bug-fixes/575-fix-light-client-panic.md new file mode 100644 index 00000000000..0ec55b923fb --- /dev/null +++ b/.changelog/v0.37.1/bug-fixes/575-fix-light-client-panic.md @@ -0,0 +1,6 @@ +- `[light]` Fixed an edge case where a light client would panic when attempting + to query a node that (1) has started from a non-zero height and (2) does + not yet have any data. The light client will now, correctly, not panic + _and_ keep the node in its list of providers in the same way it would if + it queried a node starting from height zero that does not yet have data + ([\#575](https://github.com/cometbft/cometbft/issues/575)) \ No newline at end of file diff --git a/.changelog/v0.37.1/improvements/638-json-rpc-error-message.md b/.changelog/v0.37.1/improvements/638-json-rpc-error-message.md new file mode 100644 index 00000000000..6922091fd25 --- /dev/null +++ b/.changelog/v0.37.1/improvements/638-json-rpc-error-message.md @@ -0,0 +1,3 @@ +- `[jsonrpc/client]` Improve the error message for client errors stemming from + bad HTTP responses. + ([cometbft/cometbft\#638](https://github.com/cometbft/cometbft/pull/638)) diff --git a/.changelog/v0.37.1/summary.md b/.changelog/v0.37.1/summary.md new file mode 100644 index 00000000000..ba3efa9d79e --- /dev/null +++ b/.changelog/v0.37.1/summary.md @@ -0,0 +1,6 @@ +*April 26, 2023* + +This release fixes several bugs, and has had to introduce one small Go +API-breaking change in the `crypto/merkle` package in order to address what +could be a security issue for some users who directly and explicitly make use of +that code. diff --git a/.changelog/v0.37.2/bug-fixes/771-kvindexer-parsing-big-ints.md b/.changelog/v0.37.2/bug-fixes/771-kvindexer-parsing-big-ints.md new file mode 100644 index 00000000000..ba19adbc8ba --- /dev/null +++ b/.changelog/v0.37.2/bug-fixes/771-kvindexer-parsing-big-ints.md @@ -0,0 +1,4 @@ +- `[state/kvindex]` Querying event attributes that are bigger than int64 is now + enabled. We are not supporting reading floats from the db into the indexer + nor parsing them into BigFloats to not introduce breaking changes in minor + releases. ([\#771](https://github.com/cometbft/cometbft/pull/771)) diff --git a/.changelog/v0.37.2/bug-fixes/771-pubsub-parsing-big-ints.md b/.changelog/v0.37.2/bug-fixes/771-pubsub-parsing-big-ints.md new file mode 100644 index 00000000000..fc5f25a90ff --- /dev/null +++ b/.changelog/v0.37.2/bug-fixes/771-pubsub-parsing-big-ints.md @@ -0,0 +1,4 @@ +- `[pubsub]` Pubsub queries are now able to parse big integers (larger than + int64). Very big floats are also properly parsed into very big integers + instead of being truncated to int64. + ([\#771](https://github.com/cometbft/cometbft/pull/771)) diff --git a/.changelog/v0.37.2/improvements/654-rpc-rm-response-data-logs.md b/.changelog/v0.37.2/improvements/654-rpc-rm-response-data-logs.md new file mode 100644 index 00000000000..3fddfee8e71 --- /dev/null +++ b/.changelog/v0.37.2/improvements/654-rpc-rm-response-data-logs.md @@ -0,0 +1,3 @@ +- `[rpc]` Remove response data from response failure logs in order + to prevent large quantities of log data from being produced + ([\#654](https://github.com/cometbft/cometbft/issues/654)) \ No newline at end of file diff --git a/.changelog/v0.37.2/security-fixes/787-rpc-client-pw.md b/.changelog/v0.37.2/security-fixes/787-rpc-client-pw.md new file mode 100644 index 00000000000..209b799d9ad --- /dev/null +++ b/.changelog/v0.37.2/security-fixes/787-rpc-client-pw.md @@ -0,0 +1,3 @@ +- `[rpc/jsonrpc/client]` **Low severity** - Prevent RPC + client credentials from being inadvertently dumped to logs + ([\#787](https://github.com/cometbft/cometbft/pull/787)) \ No newline at end of file diff --git a/.changelog/v0.37.2/security-fixes/793-cli-debug-kill-unsafe-cast.md b/.changelog/v0.37.2/security-fixes/793-cli-debug-kill-unsafe-cast.md new file mode 100644 index 00000000000..7482a5ae039 --- /dev/null +++ b/.changelog/v0.37.2/security-fixes/793-cli-debug-kill-unsafe-cast.md @@ -0,0 +1,2 @@ +- `[cmd/cometbft/commands/debug/kill]` **Low severity** - Fix unsafe int cast in + `debug kill` command ([\#793](https://github.com/cometbft/cometbft/pull/793)) \ No newline at end of file diff --git a/.changelog/v0.37.2/security-fixes/865-fix-peerstate-marshaljson.md b/.changelog/v0.37.2/security-fixes/865-fix-peerstate-marshaljson.md new file mode 100644 index 00000000000..fdd9172c209 --- /dev/null +++ b/.changelog/v0.37.2/security-fixes/865-fix-peerstate-marshaljson.md @@ -0,0 +1,3 @@ +- `[consensus]` **Low severity** - Avoid recursive call after rename to + `(*PeerState).MarshalJSON` + ([\#863](https://github.com/cometbft/cometbft/pull/863)) diff --git a/.changelog/v0.37.2/security-fixes/890-mempool-fix-cache.md b/.changelog/v0.37.2/security-fixes/890-mempool-fix-cache.md new file mode 100644 index 00000000000..bad30efc7ab --- /dev/null +++ b/.changelog/v0.37.2/security-fixes/890-mempool-fix-cache.md @@ -0,0 +1,3 @@ +- `[mempool/clist_mempool]` **Low severity** - Prevent a transaction from + appearing twice in the mempool + ([\#890](https://github.com/cometbft/cometbft/pull/890): @otrack) diff --git a/.changelog/v0.37.2/summary.md b/.changelog/v0.37.2/summary.md new file mode 100644 index 00000000000..7ecb2739409 --- /dev/null +++ b/.changelog/v0.37.2/summary.md @@ -0,0 +1,4 @@ +*June 14, 2023* + +Provides several minor bug fixes, as well as fixes for several low-severity +security issues. diff --git a/.changelog/v0.37.3/breaking-changes/1113-rm-upnp.md b/.changelog/v0.37.3/breaking-changes/1113-rm-upnp.md new file mode 100644 index 00000000000..5526319ae5b --- /dev/null +++ b/.changelog/v0.37.3/breaking-changes/1113-rm-upnp.md @@ -0,0 +1,2 @@ +- `[p2p]` Remove unused UPnP functionality + ([\#1113](https://github.com/cometbft/cometbft/issues/1113)) diff --git a/.changelog/v0.37.3/bug-fixes/1529-indexer-respect-height-params-on-query.md b/.changelog/v0.37.3/bug-fixes/1529-indexer-respect-height-params-on-query.md new file mode 100644 index 00000000000..d12f3eda536 --- /dev/null +++ b/.changelog/v0.37.3/bug-fixes/1529-indexer-respect-height-params-on-query.md @@ -0,0 +1,2 @@ +- `[state/indexer]` Respect both height params while querying for events + ([\#1529](https://github.com/cometbft/cometbft/pull/1529)) diff --git a/.changelog/v0.37.3/features/1057-bootstrap-state-api.md b/.changelog/v0.37.3/features/1057-bootstrap-state-api.md new file mode 100644 index 00000000000..ff3dcb6820a --- /dev/null +++ b/.changelog/v0.37.3/features/1057-bootstrap-state-api.md @@ -0,0 +1,2 @@ +- `[node/state]` Add Go API to bootstrap block store and state store to a height + ([\#1057](https://github.com/tendermint/tendermint/pull/#1057)) (@yihuang) \ No newline at end of file diff --git a/.changelog/v0.37.3/features/1512-metric-mempool-size-bytes.md b/.changelog/v0.37.3/features/1512-metric-mempool-size-bytes.md new file mode 100644 index 00000000000..b935dc40842 --- /dev/null +++ b/.changelog/v0.37.3/features/1512-metric-mempool-size-bytes.md @@ -0,0 +1,2 @@ +- `[metrics]` Add metric for mempool size in bytes `SizeBytes`. + ([\#1512](https://github.com/cometbft/cometbft/pull/1512)) \ No newline at end of file diff --git a/.changelog/v0.37.3/improvements/1210-close-evidence-db.md b/.changelog/v0.37.3/improvements/1210-close-evidence-db.md new file mode 100644 index 00000000000..e32bc87dbe1 --- /dev/null +++ b/.changelog/v0.37.3/improvements/1210-close-evidence-db.md @@ -0,0 +1 @@ +- `[node]` Close evidence.db OnStop ([cometbft/cometbft\#1210](https://github.com/cometbft/cometbft/pull/1210): @chillyvee) diff --git a/.changelog/v0.37.3/improvements/1558-experimental-gossip-limiting.md b/.changelog/v0.37.3/improvements/1558-experimental-gossip-limiting.md new file mode 100644 index 00000000000..c8918d0251e --- /dev/null +++ b/.changelog/v0.37.3/improvements/1558-experimental-gossip-limiting.md @@ -0,0 +1,9 @@ +- `[mempool]` Add experimental feature to limit the number of persistent peers and non-persistent + peers to which the node gossip transactions (only for "v0" mempool). + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and + `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to + which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) diff --git a/.changelog/v0.37.3/improvements/475-upgrade-go-schnorrkel.md b/.changelog/v0.37.3/improvements/475-upgrade-go-schnorrkel.md new file mode 100644 index 00000000000..bdaf96c14cf --- /dev/null +++ b/.changelog/v0.37.3/improvements/475-upgrade-go-schnorrkel.md @@ -0,0 +1 @@ +- `[crypto/sr25519]` Upgrade to go-schnorrkel@v1.0.0 ([\#475](https://github.com/cometbft/cometbft/issues/475)) diff --git a/.changelog/v0.37.3/improvements/857-make-handshake-cancelable.md b/.changelog/v0.37.3/improvements/857-make-handshake-cancelable.md new file mode 100644 index 00000000000..16b447f6d23 --- /dev/null +++ b/.changelog/v0.37.3/improvements/857-make-handshake-cancelable.md @@ -0,0 +1 @@ +- `[node]` Make handshake cancelable ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) diff --git a/.changelog/v0.37.3/summary.md b/.changelog/v0.37.3/summary.md new file mode 100644 index 00000000000..f1e5c7f755c --- /dev/null +++ b/.changelog/v0.37.3/summary.md @@ -0,0 +1,5 @@ +*November 17, 2023* + +This release contains, among other things, an opt-in, experimental feature to +help reduce the bandwidth consumption associated with the mempool's transaction +gossip. diff --git a/.changelog/v0.37.4/bug-fixes/1654-semaphore-wait.md b/.changelog/v0.37.4/bug-fixes/1654-semaphore-wait.md new file mode 100644 index 00000000000..9d0fb80adcc --- /dev/null +++ b/.changelog/v0.37.4/bug-fixes/1654-semaphore-wait.md @@ -0,0 +1,3 @@ +- `[mempool]` Avoid infinite wait in transaction sending routine when + using experimental parameters to limiting transaction gossiping to peers + ([\#1654](https://github.com/cometbft/cometbft/pull/1654)) \ No newline at end of file diff --git a/.changelog/v0.37.4/features/1643-nop-mempool.md b/.changelog/v0.37.4/features/1643-nop-mempool.md new file mode 100644 index 00000000000..e12ec43fc1a --- /dev/null +++ b/.changelog/v0.37.4/features/1643-nop-mempool.md @@ -0,0 +1,17 @@ +- `[mempool]` Add `nop` mempool ([\#1643](https://github.com/cometbft/cometbft/pull/1643)) + + If you want to use it, change mempool's `type` to `nop`: + + ```toml + [mempool] + + # The type of mempool for this node to use. + # + # Possible types: + # - "flood" : concurrent linked list mempool with flooding gossip protocol + # (default) + # - "nop" : nop-mempool (short for no operation; the ABCI app is responsible + # for storing, disseminating and proposing txs). "create_empty_blocks=false" + # is not supported. + type = "nop" + ``` \ No newline at end of file diff --git a/.changelog/v0.37.4/summary.md b/.changelog/v0.37.4/summary.md new file mode 100644 index 00000000000..a391feeea23 --- /dev/null +++ b/.changelog/v0.37.4/summary.md @@ -0,0 +1,9 @@ +*November 27, 2023* + +This release provides the **nop** mempool for applications that want to build +their own mempool. Using this mempool effectively disables all mempool +functionality in CometBFT, including transaction dissemination and the +`broadcast_tx_*` endpoints. + +Also fixes a small bug in the mempool for an experimental feature, and reverts +the change from v0.37.3 that bumped the minimum Go version to v1.21. diff --git a/.changelog/v0.38.0/breaking-changes/1057-bootstrap-state-api.md b/.changelog/v0.38.0/breaking-changes/1057-bootstrap-state-api.md new file mode 100644 index 00000000000..dec9de27bfa --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/1057-bootstrap-state-api.md @@ -0,0 +1,4 @@ +- `[node/state]` Add Go API to bootstrap block store and state store to a height. Make sure block sync starts syncing from bootstrapped height. + ([\#1057](https://github.com/tendermint/tendermint/pull/#1057)) (@yihuang) +- `[state/store]` Added Go functions to save height at which offline state sync is performed. + ([\#1057](https://github.com/tendermint/tendermint/pull/#1057)) (@jmalicevic) diff --git a/.changelog/v0.38.0/breaking-changes/1113-rm-upnp.md b/.changelog/v0.38.0/breaking-changes/1113-rm-upnp.md new file mode 100644 index 00000000000..bb95f20c082 --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/1113-rm-upnp.md @@ -0,0 +1,2 @@ +- `[p2p]` Remove UPnP functionality + ([\#1113](https://github.com/cometbft/cometbft/issues/1113)) \ No newline at end of file diff --git a/.changelog/v0.38.0/breaking-changes/1120-node-api-cleanup.md b/.changelog/v0.38.0/breaking-changes/1120-node-api-cleanup.md new file mode 100644 index 00000000000..8c049370997 --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/1120-node-api-cleanup.md @@ -0,0 +1,3 @@ +- `[node]` Removed `ConsensusState()` accessor from `Node` + struct - all access to consensus state should go via the reactor + ([\#1120](https://github.com/cometbft/cometbft/pull/1120)) diff --git a/.changelog/v0.38.0/breaking-changes/1270-executor_extend_vote.md b/.changelog/v0.38.0/breaking-changes/1270-executor_extend_vote.md new file mode 100644 index 00000000000..975c8f8232e --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/1270-executor_extend_vote.md @@ -0,0 +1,3 @@ +- `[state]` Signature of `ExtendVote` changed in `BlockExecutor`. + It now includes the block whose precommit will be extended, an the state object. + ([\#1270](https://github.com/cometbft/cometbft/pull/1270)) diff --git a/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool-config.md b/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool-config.md new file mode 100644 index 00000000000..c989879b9e4 --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool-config.md @@ -0,0 +1,2 @@ +- `[config]` Remove `Version` field from `MempoolConfig`. + ([\#260](https://github.com/cometbft/cometbft/issues/260)) diff --git a/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool-proto.md b/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool-proto.md new file mode 100644 index 00000000000..042001178b3 --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool-proto.md @@ -0,0 +1,2 @@ +- `[protobuf]` Remove fields `sender`, `priority`, and `mempool_error` from + `ResponseCheckTx`. ([\#260](https://github.com/cometbft/cometbft/issues/260)) diff --git a/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool.md b/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool.md new file mode 100644 index 00000000000..e76a567afeb --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/260-remove-priority-mempool.md @@ -0,0 +1,2 @@ +- `[mempool]` Remove priority mempool. + ([\#260](https://github.com/cometbft/cometbft/issues/260)) diff --git a/.changelog/v0.38.0/breaking-changes/558-tm10011.md b/.changelog/v0.38.0/breaking-changes/558-tm10011.md new file mode 100644 index 00000000000..d1b9fca4aba --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/558-tm10011.md @@ -0,0 +1,2 @@ +- `[crypto/merkle]` Do not allow verification of Merkle Proofs against empty trees (`nil` root). `Proof.ComputeRootHash` now panics when it encounters an error, but `Proof.Verify` does not panic + ([\#558](https://github.com/cometbft/cometbft/issues/558)) diff --git a/.changelog/unreleased/breaking-changes/6541-state-move-pruneblocks-execution.md b/.changelog/v0.38.0/breaking-changes/6541-state-move-pruneblocks-execution.md similarity index 100% rename from .changelog/unreleased/breaking-changes/6541-state-move-pruneblocks-execution.md rename to .changelog/v0.38.0/breaking-changes/6541-state-move-pruneblocks-execution.md diff --git a/.changelog/v0.38.0/breaking-changes/774-state-indexerevent-remove-function-type copy.md b/.changelog/v0.38.0/breaking-changes/774-state-indexerevent-remove-function-type copy.md new file mode 100644 index 00000000000..4e8fcb82295 --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/774-state-indexerevent-remove-function-type copy.md @@ -0,0 +1,3 @@ +- `[rpc]` Removed `begin_block_events` and `end_block_events` from `BlockResultsResponse`. + The events are merged into one field called `finalize_block_events`. + ([\#9427](https://github.com/tendermint/tendermint/issues/9427)) diff --git a/.changelog/v0.38.0/breaking-changes/774-state-indexerevent-remove-function-type.md b/.changelog/v0.38.0/breaking-changes/774-state-indexerevent-remove-function-type.md new file mode 100644 index 00000000000..22a3b9fc5a3 --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/774-state-indexerevent-remove-function-type.md @@ -0,0 +1,3 @@ +- `[state/kvindexer]` Remove the function type from the event key stored in the database. This should be breaking only +for people who forked CometBFT and interact directly with the indexers kvstore. + ([\#774](https://github.com/cometbft/cometbft/pull/774)) \ No newline at end of file diff --git a/.changelog/v0.38.0/breaking-changes/797-kvindexer-support-for-big-numbers.md b/.changelog/v0.38.0/breaking-changes/797-kvindexer-support-for-big-numbers.md new file mode 100644 index 00000000000..e64e2775d34 --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/797-kvindexer-support-for-big-numbers.md @@ -0,0 +1,3 @@ +- `[kvindexer]` Added support for big integers and big floats in the kvindexer. + Breaking changes: function `Number` in package `libs/pubsub/query/syntax` changed its return value. + ([\#797](https://github.com/cometbft/cometbft/pull/797)) diff --git a/.changelog/v0.38.0/breaking-changes/797-pubsub-support-for-big-numbers.md b/.changelog/v0.38.0/breaking-changes/797-pubsub-support-for-big-numbers.md new file mode 100644 index 00000000000..33778282eaf --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/797-pubsub-support-for-big-numbers.md @@ -0,0 +1,3 @@ +- `[pubsub]` Added support for big integers and big floats in the pubsub event query system. + Breaking changes: function `Number` in package `libs/pubsub/query/syntax` changed its return value. + ([\#797](https://github.com/cometbft/cometbft/pull/797)) diff --git a/.changelog/unreleased/breaking-changes/8664-move-app-hash-to-commit.md b/.changelog/v0.38.0/breaking-changes/8664-move-app-hash-to-commit.md similarity index 85% rename from .changelog/unreleased/breaking-changes/8664-move-app-hash-to-commit.md rename to .changelog/v0.38.0/breaking-changes/8664-move-app-hash-to-commit.md index cbc4ba25a18..a22b3926477 100644 --- a/.changelog/unreleased/breaking-changes/8664-move-app-hash-to-commit.md +++ b/.changelog/v0.38.0/breaking-changes/8664-move-app-hash-to-commit.md @@ -1,2 +1,2 @@ -- `[abci]` Move `app_hash` parameter from `Commit` to `FinalizeBlock` (@sergio-mena) - ([\#8664](https://github.com/tendermint/tendermint/pull/8664)) \ No newline at end of file +- `[abci]` Move `app_hash` parameter from `Commit` to `FinalizeBlock` + ([\#8664](https://github.com/tendermint/tendermint/pull/8664)) diff --git a/.changelog/unreleased/breaking-changes/9468-finalize-block.md b/.changelog/v0.38.0/breaking-changes/9468-finalize-block.md similarity index 65% rename from .changelog/unreleased/breaking-changes/9468-finalize-block.md rename to .changelog/v0.38.0/breaking-changes/9468-finalize-block.md index 7bf64790dc8..e27f65e55e5 100644 --- a/.changelog/unreleased/breaking-changes/9468-finalize-block.md +++ b/.changelog/v0.38.0/breaking-changes/9468-finalize-block.md @@ -1,2 +1,3 @@ -- `[abci]` Introduce `FinalizeBlock` which condenses `BeginBlock`, `DeliverTx` and `EndBlock` into a single method call (@cmwaters) - ([\#9468](https://github.com/tendermint/tendermint/pull/9468)) \ No newline at end of file +- `[abci]` Introduce `FinalizeBlock` which condenses `BeginBlock`, `DeliverTx` + and `EndBlock` into a single method call + ([\#9468](https://github.com/tendermint/tendermint/pull/9468)) diff --git a/.changelog/unreleased/breaking-changes/9625-p2p-remove-trust-package.md b/.changelog/v0.38.0/breaking-changes/9625-p2p-remove-trust-package.md similarity index 100% rename from .changelog/unreleased/breaking-changes/9625-p2p-remove-trust-package.md rename to .changelog/v0.38.0/breaking-changes/9625-p2p-remove-trust-package.md diff --git a/.changelog/unreleased/breaking-changes/9655-inspect-add-command.md b/.changelog/v0.38.0/breaking-changes/9655-inspect-add-command.md similarity index 100% rename from .changelog/unreleased/breaking-changes/9655-inspect-add-command.md rename to .changelog/v0.38.0/breaking-changes/9655-inspect-add-command.md diff --git a/.changelog/unreleased/breaking-changes/9655-node-move-DB-vars-config.md b/.changelog/v0.38.0/breaking-changes/9655-node-move-DB-vars-config.md similarity index 100% rename from .changelog/unreleased/breaking-changes/9655-node-move-DB-vars-config.md rename to .changelog/v0.38.0/breaking-changes/9655-node-move-DB-vars-config.md diff --git a/.changelog/unreleased/breaking-changes/9655-rpc-remove-environment-var.md b/.changelog/v0.38.0/breaking-changes/9655-rpc-remove-environment-var.md similarity index 100% rename from .changelog/unreleased/breaking-changes/9655-rpc-remove-environment-var.md rename to .changelog/v0.38.0/breaking-changes/9655-rpc-remove-environment-var.md diff --git a/.changelog/unreleased/breaking-changes/9682-metrics-refactor-state-block-synching.md b/.changelog/v0.38.0/breaking-changes/9682-metrics-refactor-state-block-synching.md similarity index 100% rename from .changelog/unreleased/breaking-changes/9682-metrics-refactor-state-block-synching.md rename to .changelog/v0.38.0/breaking-changes/9682-metrics-refactor-state-block-synching.md diff --git a/.changelog/v0.38.0/breaking-changes/980-max-size-more-control.md b/.changelog/v0.38.0/breaking-changes/980-max-size-more-control.md new file mode 100644 index 00000000000..e4354e3cb05 --- /dev/null +++ b/.changelog/v0.38.0/breaking-changes/980-max-size-more-control.md @@ -0,0 +1,9 @@ +- `[mempool]` Application can now set `ConsensusParams.Block.MaxBytes` to -1 + to have visibility on all transactions in the + mempool at `PrepareProposal` time. + This means that the total size of transactions sent via `RequestPrepareProposal` + might exceed `RequestPrepareProposal.max_tx_bytes`. + If that is the case, the application MUST make sure that the total size of transactions + returned in `ResponsePrepareProposal.txs` does not exceed `RequestPrepareProposal.max_tx_bytes`, + otherwise CometBFT will panic. + ([\#980](https://github.com/cometbft/cometbft/issues/980)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/423-forwardport-default-kvindexer-behaviour.md b/.changelog/v0.38.0/bug-fixes/423-forwardport-default-kvindexer-behaviour.md similarity index 100% rename from .changelog/unreleased/bug-fixes/423-forwardport-default-kvindexer-behaviour.md rename to .changelog/v0.38.0/bug-fixes/423-forwardport-default-kvindexer-behaviour.md diff --git a/.changelog/v0.38.0/bug-fixes/496-error-on-applyblock-should-panic.md b/.changelog/v0.38.0/bug-fixes/496-error-on-applyblock-should-panic.md new file mode 100644 index 00000000000..55e9c874f8c --- /dev/null +++ b/.changelog/v0.38.0/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/v0.38.0/bug-fixes/524-rename-peerstate-tojson.md b/.changelog/v0.38.0/bug-fixes/524-rename-peerstate-tojson.md new file mode 100644 index 00000000000..b9a43b3ce4e --- /dev/null +++ b/.changelog/v0.38.0/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/v0.38.0/bug-fixes/575-fix-light-client-panic.md b/.changelog/v0.38.0/bug-fixes/575-fix-light-client-panic.md new file mode 100644 index 00000000000..0ec55b923fb --- /dev/null +++ b/.changelog/v0.38.0/bug-fixes/575-fix-light-client-panic.md @@ -0,0 +1,6 @@ +- `[light]` Fixed an edge case where a light client would panic when attempting + to query a node that (1) has started from a non-zero height and (2) does + not yet have any data. The light client will now, correctly, not panic + _and_ keep the node in its list of providers in the same way it would if + it queried a node starting from height zero that does not yet have data + ([\#575](https://github.com/cometbft/cometbft/issues/575)) \ No newline at end of file diff --git a/.changelog/v0.38.0/bug-fixes/855-snake-case-json-for-exec-tx-result-fields.md b/.changelog/v0.38.0/bug-fixes/855-snake-case-json-for-exec-tx-result-fields.md new file mode 100644 index 00000000000..27f5fe53512 --- /dev/null +++ b/.changelog/v0.38.0/bug-fixes/855-snake-case-json-for-exec-tx-result-fields.md @@ -0,0 +1,2 @@ +- `[abci]` Restore the snake_case naming in JSON serialization of + `ExecTxResult` ([\#855](https://github.com/cometbft/cometbft/issues/855)). diff --git a/.changelog/v0.38.0/bug-fixes/865-fix-peerstate-marshaljson.md b/.changelog/v0.38.0/bug-fixes/865-fix-peerstate-marshaljson.md new file mode 100644 index 00000000000..318bda315c5 --- /dev/null +++ b/.changelog/v0.38.0/bug-fixes/865-fix-peerstate-marshaljson.md @@ -0,0 +1,2 @@ +- `[consensus]` Avoid recursive call after rename to (*PeerState).MarshalJSON + ([\#863](https://github.com/cometbft/cometbft/pull/863)) diff --git a/.changelog/v0.38.0/bug-fixes/890-mempool-fix-cache.md b/.changelog/v0.38.0/bug-fixes/890-mempool-fix-cache.md new file mode 100644 index 00000000000..78ade6f4c1c --- /dev/null +++ b/.changelog/v0.38.0/bug-fixes/890-mempool-fix-cache.md @@ -0,0 +1,2 @@ +- `[mempool/clist_mempool]` Prevent a transaction to appear twice in the mempool + ([\#890](https://github.com/cometbft/cometbft/pull/890): @otrack) diff --git a/.changelog/unreleased/bug-fixes/9462-docker-go-use-consistent-version.md b/.changelog/v0.38.0/bug-fixes/9462-docker-go-use-consistent-version.md similarity index 100% rename from .changelog/unreleased/bug-fixes/9462-docker-go-use-consistent-version.md rename to .changelog/v0.38.0/bug-fixes/9462-docker-go-use-consistent-version.md diff --git a/.changelog/unreleased/bug-fixes/9717-abci-cli-fix-help.md b/.changelog/v0.38.0/bug-fixes/9717-abci-cli-fix-help.md similarity index 100% rename from .changelog/unreleased/bug-fixes/9717-abci-cli-fix-help.md rename to .changelog/v0.38.0/bug-fixes/9717-abci-cli-fix-help.md diff --git a/.changelog/v0.38.0/deprecations/650-deprecate-grpc-broadcast-api.md b/.changelog/v0.38.0/deprecations/650-deprecate-grpc-broadcast-api.md new file mode 100644 index 00000000000..7ab623a6998 --- /dev/null +++ b/.changelog/v0.38.0/deprecations/650-deprecate-grpc-broadcast-api.md @@ -0,0 +1,4 @@ +- `[rpc/grpc]` Mark the gRPC broadcast API as deprecated. + It will be superseded by a broader API as part of + [\#81](https://github.com/cometbft/cometbft/issues/81) + ([\#650](https://github.com/cometbft/cometbft/issues/650)) \ No newline at end of file diff --git a/.changelog/v0.38.0/features/1057-bootstrap-state-api.md b/.changelog/v0.38.0/features/1057-bootstrap-state-api.md new file mode 100644 index 00000000000..ff3dcb6820a --- /dev/null +++ b/.changelog/v0.38.0/features/1057-bootstrap-state-api.md @@ -0,0 +1,2 @@ +- `[node/state]` Add Go API to bootstrap block store and state store to a height + ([\#1057](https://github.com/tendermint/tendermint/pull/#1057)) (@yihuang) \ No newline at end of file diff --git a/.changelog/v0.38.0/features/9830-proxy-introduce-newconnsynclocalclientcreator.md b/.changelog/v0.38.0/features/9830-proxy-introduce-newconnsynclocalclientcreator.md new file mode 100644 index 00000000000..a7c8a0f69fc --- /dev/null +++ b/.changelog/v0.38.0/features/9830-proxy-introduce-newconnsynclocalclientcreator.md @@ -0,0 +1,5 @@ +- `[proxy]` Introduce `NewConnSyncLocalClientCreator`, 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"). + ([tendermint/tendermint\#9830](https://github.com/tendermint/tendermint/pull/9830) + and [\#1145](https://github.com/cometbft/cometbft/pull/1145)) diff --git a/.changelog/unreleased/features/9830-proxy-introduce-newunsynclocalclientcreator.md b/.changelog/v0.38.0/features/9830-proxy-introduce-newunsynclocalclientcreator.md similarity index 100% rename from .changelog/unreleased/features/9830-proxy-introduce-newunsynclocalclientcreator.md rename to .changelog/v0.38.0/features/9830-proxy-introduce-newunsynclocalclientcreator.md diff --git a/.changelog/v0.38.0/features/9836-abci-add-vote-extension.md b/.changelog/v0.38.0/features/9836-abci-add-vote-extension.md new file mode 100644 index 00000000000..4d8df79c720 --- /dev/null +++ b/.changelog/v0.38.0/features/9836-abci-add-vote-extension.md @@ -0,0 +1 @@ +- `[abci]` New ABCI methods `VerifyVoteExtension` and `ExtendVote` allow validators to validate the vote extension data attached to a pre-commit message and allow applications to let their validators do more than just validate within consensus ([\#9836](https://github.com/tendermint/tendermint/pull/9836)) diff --git a/.changelog/v0.38.0/improvements/1210-close-evidence-db.md b/.changelog/v0.38.0/improvements/1210-close-evidence-db.md new file mode 100644 index 00000000000..e32bc87dbe1 --- /dev/null +++ b/.changelog/v0.38.0/improvements/1210-close-evidence-db.md @@ -0,0 +1 @@ +- `[node]` Close evidence.db OnStop ([cometbft/cometbft\#1210](https://github.com/cometbft/cometbft/pull/1210): @chillyvee) diff --git a/.changelog/v0.38.0/improvements/1264-log-app-hash-as-hex.md b/.changelog/v0.38.0/improvements/1264-log-app-hash-as-hex.md new file mode 100644 index 00000000000..2e530c73895 --- /dev/null +++ b/.changelog/v0.38.0/improvements/1264-log-app-hash-as-hex.md @@ -0,0 +1,2 @@ +- `[state]` Make logging `block_app_hash` and `app_hash` consistent by logging them both as hex. + ([\#1264](https://github.com/cometbft/cometbft/pull/1264)) diff --git a/.changelog/unreleased/improvements/543-metrics-for-blocksync.md b/.changelog/v0.38.0/improvements/543-metrics-for-blocksync.md similarity index 100% rename from .changelog/unreleased/improvements/543-metrics-for-blocksync.md rename to .changelog/v0.38.0/improvements/543-metrics-for-blocksync.md diff --git a/.changelog/v0.38.0/improvements/638-json-rpc-error-message.md b/.changelog/v0.38.0/improvements/638-json-rpc-error-message.md new file mode 100644 index 00000000000..6922091fd25 --- /dev/null +++ b/.changelog/v0.38.0/improvements/638-json-rpc-error-message.md @@ -0,0 +1,3 @@ +- `[jsonrpc/client]` Improve the error message for client errors stemming from + bad HTTP responses. + ([cometbft/cometbft\#638](https://github.com/cometbft/cometbft/pull/638)) diff --git a/.changelog/unreleased/improvements/6443-merkle-hashalternatives-perf-improv-a.md b/.changelog/v0.38.0/improvements/6443-merkle-hashalternatives-perf-improv-a.md similarity index 100% rename from .changelog/unreleased/improvements/6443-merkle-hashalternatives-perf-improv-a.md rename to .changelog/v0.38.0/improvements/6443-merkle-hashalternatives-perf-improv-a.md diff --git a/.changelog/unreleased/improvements/6509-pex-addrbook-perf-improv.md b/.changelog/v0.38.0/improvements/6509-pex-addrbook-perf-improv.md similarity index 100% rename from .changelog/unreleased/improvements/6509-pex-addrbook-perf-improv.md rename to .changelog/v0.38.0/improvements/6509-pex-addrbook-perf-improv.md diff --git a/.changelog/unreleased/improvements/6513-merkle-hashalternatives-perf-improv-b.md b/.changelog/v0.38.0/improvements/6513-merkle-hashalternatives-perf-improv-b.md similarity index 100% rename from .changelog/unreleased/improvements/6513-merkle-hashalternatives-perf-improv-b.md rename to .changelog/v0.38.0/improvements/6513-merkle-hashalternatives-perf-improv-b.md diff --git a/.changelog/v0.38.0/improvements/654-rpc-rm-response-data-logs.md b/.changelog/v0.38.0/improvements/654-rpc-rm-response-data-logs.md new file mode 100644 index 00000000000..3fddfee8e71 --- /dev/null +++ b/.changelog/v0.38.0/improvements/654-rpc-rm-response-data-logs.md @@ -0,0 +1,3 @@ +- `[rpc]` Remove response data from response failure logs in order + to prevent large quantities of log data from being produced + ([\#654](https://github.com/cometbft/cometbft/issues/654)) \ No newline at end of file diff --git a/.changelog/unreleased/improvements/7319-pubsub-query-perf-improv.md b/.changelog/v0.38.0/improvements/7319-pubsub-query-perf-improv.md similarity index 100% rename from .changelog/unreleased/improvements/7319-pubsub-query-perf-improv.md rename to .changelog/v0.38.0/improvements/7319-pubsub-query-perf-improv.md diff --git a/.changelog/v0.38.0/improvements/797-pubsub-float.md b/.changelog/v0.38.0/improvements/797-pubsub-float.md new file mode 100644 index 00000000000..c3d1a878554 --- /dev/null +++ b/.changelog/v0.38.0/improvements/797-pubsub-float.md @@ -0,0 +1,3 @@ +- `[pubsub/kvindexer]` Numeric query conditions and event values are represented as big floats with default precision of 125. + Integers are read as "big ints" and represented with as many bits as they need when converting to floats. + ([\#797](https://github.com/cometbft/cometbft/pull/797)) diff --git a/.changelog/v0.38.0/improvements/857-make-handshake-cancelable.md b/.changelog/v0.38.0/improvements/857-make-handshake-cancelable.md new file mode 100644 index 00000000000..16b447f6d23 --- /dev/null +++ b/.changelog/v0.38.0/improvements/857-make-handshake-cancelable.md @@ -0,0 +1 @@ +- `[node]` Make handshake cancelable ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) diff --git a/.changelog/v0.38.0/improvements/980-max-size-more-control.md b/.changelog/v0.38.0/improvements/980-max-size-more-control.md new file mode 100644 index 00000000000..e319779984c --- /dev/null +++ b/.changelog/v0.38.0/improvements/980-max-size-more-control.md @@ -0,0 +1,5 @@ +- `[mempool]` Application can now set `ConsensusParams.Block.MaxBytes` to -1 + to gain more control on the max size of transactions in a block. + It also allows the application to have visibility on all transactions in the + mempool at `PrepareProposal` time. + ([\#980](https://github.com/cometbft/cometbft/pull/980)) \ No newline at end of file diff --git a/.changelog/v0.38.0/summary.md b/.changelog/v0.38.0/summary.md new file mode 100644 index 00000000000..f34c7c5f82b --- /dev/null +++ b/.changelog/v0.38.0/summary.md @@ -0,0 +1,13 @@ +*September 12, 2023* + +This release includes the second part of ABCI++, called ABCI 2.0. +ABCI 2.0 introduces ABCI methods `ExtendVote` and `VerifyVoteExtension`. +These new methods allow the application to add data (opaque to CometBFT), +called _vote extensions_ to precommit votes sent by validators. +These vote extensions are made available to the proposer(s) of the next height. +Additionally, ABCI 2.0 coalesces `BeginBlock`, `DeliverTx`, and `EndBlock` +into one method, `FinalizeBlock`, whose `Request*` and `Response*` +data structures contain the sum of all data previously contained +in the respective `Request*` and `Response*` data structures in +`BeginBlock`, `DeliverTx`, and `EndBlock`. +See the [specification](./spec/abci/) for more details on ABCI 2.0. diff --git a/.changelog/v0.38.1/bug-fixes/1529-indexer-respect-height-params-on-query.md b/.changelog/v0.38.1/bug-fixes/1529-indexer-respect-height-params-on-query.md new file mode 100644 index 00000000000..d12f3eda536 --- /dev/null +++ b/.changelog/v0.38.1/bug-fixes/1529-indexer-respect-height-params-on-query.md @@ -0,0 +1,2 @@ +- `[state/indexer]` Respect both height params while querying for events + ([\#1529](https://github.com/cometbft/cometbft/pull/1529)) diff --git a/.changelog/v0.38.1/features/1512-metric-mempool-size-bytes.md b/.changelog/v0.38.1/features/1512-metric-mempool-size-bytes.md new file mode 100644 index 00000000000..b935dc40842 --- /dev/null +++ b/.changelog/v0.38.1/features/1512-metric-mempool-size-bytes.md @@ -0,0 +1,2 @@ +- `[metrics]` Add metric for mempool size in bytes `SizeBytes`. + ([\#1512](https://github.com/cometbft/cometbft/pull/1512)) \ No newline at end of file diff --git a/.changelog/v0.38.1/improvements/1558-experimental-gossip-limiting.md b/.changelog/v0.38.1/improvements/1558-experimental-gossip-limiting.md new file mode 100644 index 00000000000..58fc6c6f863 --- /dev/null +++ b/.changelog/v0.38.1/improvements/1558-experimental-gossip-limiting.md @@ -0,0 +1,9 @@ +- `[mempool]` Add experimental feature to limit the number of persistent peers and non-persistent + peers to which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and + `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to + which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) diff --git a/.changelog/v0.38.1/summary.md b/.changelog/v0.38.1/summary.md new file mode 100644 index 00000000000..f1e5c7f755c --- /dev/null +++ b/.changelog/v0.38.1/summary.md @@ -0,0 +1,5 @@ +*November 17, 2023* + +This release contains, among other things, an opt-in, experimental feature to +help reduce the bandwidth consumption associated with the mempool's transaction +gossip. diff --git a/.changelog/v0.38.2/bug-fixes/1654-semaphore-wait.md b/.changelog/v0.38.2/bug-fixes/1654-semaphore-wait.md new file mode 100644 index 00000000000..9d0fb80adcc --- /dev/null +++ b/.changelog/v0.38.2/bug-fixes/1654-semaphore-wait.md @@ -0,0 +1,3 @@ +- `[mempool]` Avoid infinite wait in transaction sending routine when + using experimental parameters to limiting transaction gossiping to peers + ([\#1654](https://github.com/cometbft/cometbft/pull/1654)) \ No newline at end of file diff --git a/.changelog/v0.38.2/features/1643-nop-mempool.md b/.changelog/v0.38.2/features/1643-nop-mempool.md new file mode 100644 index 00000000000..e12ec43fc1a --- /dev/null +++ b/.changelog/v0.38.2/features/1643-nop-mempool.md @@ -0,0 +1,17 @@ +- `[mempool]` Add `nop` mempool ([\#1643](https://github.com/cometbft/cometbft/pull/1643)) + + If you want to use it, change mempool's `type` to `nop`: + + ```toml + [mempool] + + # The type of mempool for this node to use. + # + # Possible types: + # - "flood" : concurrent linked list mempool with flooding gossip protocol + # (default) + # - "nop" : nop-mempool (short for no operation; the ABCI app is responsible + # for storing, disseminating and proposing txs). "create_empty_blocks=false" + # is not supported. + type = "nop" + ``` \ No newline at end of file diff --git a/.changelog/v0.38.2/summary.md b/.changelog/v0.38.2/summary.md new file mode 100644 index 00000000000..97d902edcc7 --- /dev/null +++ b/.changelog/v0.38.2/summary.md @@ -0,0 +1,6 @@ +*November 27, 2023* + +This release provides the **nop** mempool for applications that want to build their own mempool. +Using this mempool effectively disables all mempool functionality in CometBFT, including transaction dissemination and the `broadcast_tx_*` endpoints. + +Also fixes a small bug in the mempool for an experimental feature. diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 00000000000..64ea3325012 --- /dev/null +++ b/.codespellrc @@ -0,0 +1,4 @@ +[codespell] +skip = *.sum,go.mod,LOG,*/consensus-paper/*,*/grammar-auto/*,*.qnt,*.tla,.github/workflows/fuzz-nightly.yml +quiet-level = 2 +ignore-words = .github/workflows/ignore-words.txt diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 87f93c4cdc3..efe2d4ac7e6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,6 +7,6 @@ # global owners are only requested if there isn't a more specific # codeowner specified below. For this reason, the global codeowners # are often repeated in package-level definitions. -* @CometBFT/engineering +* @cometbft/engineering @cometbft/devrel -/spec @CometBFT/research @CometBFT/engineering +/spec @cometbft/research @cometbft/engineering diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 852aa44b461..e1f3e83598c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -28,4 +28,4 @@ https://github.com/orgs/cometbft/projects/1 - [ ] Tests written/updated - [ ] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [ ] Updated relevant documentation (`docs/` or `spec/`) and code comments - +- [ ] Title follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) spec diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 54e17557a09..0757966d064 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,6 +10,26 @@ updates: - dependencies - automerge + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + target-branch: "v1.x" + open-pull-requests-limit: 10 + labels: + - dependencies + - automerge + + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + target-branch: "v0.38.x" + open-pull-requests-limit: 10 + labels: + - dependencies + - automerge + - package-ecosystem: github-actions directory: "/" schedule: @@ -44,6 +64,28 @@ updates: - dependencies - automerge + - package-ecosystem: gomod + directory: "/" + schedule: + interval: weekly + target-branch: "v1.x" + open-pull-requests-limit: 10 + labels: + - dependencies + - automerge + + - package-ecosystem: gomod + directory: "/" + schedule: + interval: daily + target-branch: "v0.38.x" + # Only allow automated security-related dependency updates on release + # branches. + open-pull-requests-limit: 0 + labels: + - dependencies + - automerge + - package-ecosystem: gomod directory: "/" schedule: diff --git a/.github/mergify.yml b/.github/mergify.yml index 74f285949d7..3aed235dcef 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -1,22 +1,20 @@ -queue_rules: - - name: default +pull_request_rules: + - name: backport patches to v1.x branch conditions: - base=main - - label=automerge - -pull_request_rules: - - name: Automerge to main + - label=backport-to-v1.x + actions: + backport: + branches: + - v1.x + - name: backport patches to v0.38.x branch conditions: - base=main - - label=automerge + - label=backport-to-v0.38.x actions: - queue: - method: squash - name: default - commit_message_template: | - {{ title }} (#{{ number }}) - - {{ body }} + backport: + branches: + - v0.38.x - name: backport patches to v0.37.x branch conditions: - base=main diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 579466cdcb7..c246e42317c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,7 @@ name: Build # All jobs will pass without running if no *{.go, .mod, .sum} files have been modified on: pull_request: + merge_group: push: branches: - main @@ -20,10 +21,10 @@ jobs: goos: ["linux"] timeout-minutes: 5 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.20" - - uses: actions/checkout@v3 + go-version: "1.22" + - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6 with: PATTERNS: | @@ -42,10 +43,10 @@ jobs: needs: build timeout-minutes: 5 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.20" - - uses: actions/checkout@v3 + go-version: "1.22" + - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6 with: PATTERNS: | @@ -64,10 +65,10 @@ jobs: needs: build timeout-minutes: 5 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.20" - - uses: actions/checkout@v3 + go-version: "1.22" + - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6 with: PATTERNS: | diff --git a/.github/workflows/check-generated.yml b/.github/workflows/check-generated.yml index 45bec88585a..a470317633e 100644 --- a/.github/workflows/check-generated.yml +++ b/.github/workflows/check-generated.yml @@ -3,36 +3,37 @@ # Note that we run these checks regardless whether the input files have # changed, because generated code can change in response to toolchain updates # even if no files in the repository are modified. + name: Check generated code on: pull_request: - branches: - - main + merge_group: permissions: contents: read jobs: - check-mocks: + check-mocks-metrics: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.22" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - name: "Check generated mocks" + - name: "Check generated mocks and metrics" run: | set -euo pipefail - make mockery + make mockery metrics - if ! git diff --stat --exit-code ; then + git add . + if ! git diff HEAD --stat --exit-code ; then echo ">> ERROR:" echo ">>" - echo ">> Generated mocks require update (either Mockery or source files may have changed)." - echo ">> Ensure your tools are up-to-date, re-run 'make mockery' and update this PR." + echo ">> Generated mocks and/or metrics require update (either Mockery or source files may have changed)." + echo ">> Ensure your tools are up-to-date, re-run 'make mockery metrics' and update this PR." echo ">>" git diff exit 1 @@ -41,13 +42,13 @@ jobs: check-proto: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.22" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: - fetch-depth: 1 # we need a .git directory to run git diff + fetch-depth: 1 # we need a .git directory to run git diff - name: "Check protobuf generated code" run: | @@ -55,7 +56,8 @@ jobs: make proto-gen - if ! git diff --stat --exit-code ; then + git add . + if ! git diff HEAD --stat --exit-code ; then echo ">> ERROR:" echo ">>" echo ">> Protobuf generated code requires update (either tools or .proto files may have changed)." diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8319c6745b2..9d19f02fab7 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -40,11 +40,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -58,7 +58,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -71,6 +71,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/cometbft-docker.yml b/.github/workflows/cometbft-docker.yml index f55725d8b3d..2f4fffdee22 100644 --- a/.github/workflows/cometbft-docker.yml +++ b/.github/workflows/cometbft-docker.yml @@ -15,7 +15,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Prepare id: prep run: | @@ -41,17 +41,17 @@ jobs: platforms: all - name: Set up Docker Build - uses: docker/setup-buildx-action@v2.5.0 + uses: docker/setup-buildx-action@v3.3.0 - name: Login to DockerHub if: ${{ github.event_name != 'pull_request' }} - uses: docker/login-action@v2.1.0 + uses: docker/login-action@v3.1.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Publish to Docker Hub - uses: docker/build-push-action@v4.0.0 + uses: docker/build-push-action@v5.3.0 with: context: . file: ./DOCKER/Dockerfile diff --git a/.github/workflows/conventional-pr-title.yml b/.github/workflows/conventional-pr-title.yml new file mode 100644 index 00000000000..d58e82f2c1a --- /dev/null +++ b/.github/workflows/conventional-pr-title.yml @@ -0,0 +1,65 @@ +name: "Conventional PR Title" + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +permissions: + pull-requests: write + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + id: lint_pr_title + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + feat + fix + build + chore + ci + docs + refactor + perf + test + revert + spec + merge + + - uses: marocchino/sticky-pull-request-comment@v2 + # When the previous steps fails, the workflow would stop. By adding this + # condition you can continue the execution with the populated error message. + if: always() && (steps.lint_pr_title.outputs.error_message != null) + with: + header: pr-title-lint-error + message: | + Hey there and thank you for opening this pull request! 👋🏼 + + We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted. + + Details: + + ``` + ${{ steps.lint_pr_title.outputs.error_message }} + ``` + + General format: `type(scope): msg` + Breaking change: `type(scope)!: msg` + Multi-scope change: `type: msg` + Types: `feat`, `fix`, `build`, `chore`, `ci`, `docs`, `refactor`, `perf`, `test`, `revert`, `spec`, `merge`. + Example: `fix(cmd/cometbft/commands/debug): execute p.Signal only when p is not nil` + + # Delete a previous comment when the issue has been resolved + - if: ${{ steps.lint_pr_title.outputs.error_message == null }} + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: pr-title-lint-error + delete: true diff --git a/.github/workflows/docs-toc.yml b/.github/workflows/docs-toc.yml index 589be02c68a..f36b75d81eb 100644 --- a/.github/workflows/docs-toc.yml +++ b/.github/workflows/docs-toc.yml @@ -10,7 +10,7 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6 with: PATTERNS: | diff --git a/.github/workflows/e2e-long-main.yml b/.github/workflows/e2e-long-main.yml index 302e29d1ecb..e7fc3e2c611 100644 --- a/.github/workflows/e2e-long-main.yml +++ b/.github/workflows/e2e-long-main.yml @@ -7,19 +7,17 @@ name: e2e-long-main on: workflow_dispatch: - schedule: - - cron: '0 3 * * 4' jobs: e2e-long-test: runs-on: ubuntu-latest timeout-minutes: 120 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build working-directory: test/e2e @@ -36,7 +34,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify Slack on failure - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@v1.25.0 env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.github/workflows/e2e-manual-multiversion.yml b/.github/workflows/e2e-manual-multiversion.yml index 164ee3b9e21..f459298c4ce 100644 --- a/.github/workflows/e2e-manual-multiversion.yml +++ b/.github/workflows/e2e-manual-multiversion.yml @@ -15,11 +15,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build working-directory: test/e2e diff --git a/.github/workflows/e2e-manual.yml b/.github/workflows/e2e-manual.yml index d69cdf892c3..46ae2ec6720 100644 --- a/.github/workflows/e2e-manual.yml +++ b/.github/workflows/e2e-manual.yml @@ -15,11 +15,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build working-directory: test/e2e diff --git a/.github/workflows/e2e-nightly-1x.yml b/.github/workflows/e2e-nightly-1x.yml new file mode 100644 index 00000000000..b19c7065abd --- /dev/null +++ b/.github/workflows/e2e-nightly-1x.yml @@ -0,0 +1,77 @@ +# Runs randomly generated E2E testnets nightly on the v1.x branch. + +# !! This file should be kept in sync with the e2e-nightly-main.yml file, +# modulo changes to the version labels. + +name: e2e-nightly-1x +on: + schedule: + - cron: '0 2 * * *' + +jobs: + e2e-nightly-test: + # Run parallel jobs for the listed testnet groups (must match the + # ./build/generator -g flag) + strategy: + fail-fast: false + matrix: + group: ['00', '01', '02', '03', "04"] + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/setup-go@v5 + with: + go-version: "1.22" + + - uses: actions/checkout@v4 + with: + ref: 'v1.x' + + - name: Capture git repo info + id: git-info + run: | + echo "branch=`git branch --show-current`" >> $GITHUB_OUTPUT + + - name: Build + working-directory: test/e2e + # Run make jobs in parallel, since we can't run steps in parallel. + run: make -j2 docker generator runner tests + + - name: Generate testnets + working-directory: test/e2e + # When changing -g, also change the matrix groups above + run: ./build/generator -g 5 -d networks/nightly/ -p + + - name: Run ${{ matrix.p2p }} p2p testnets + working-directory: test/e2e + run: ./run-multiple.sh networks/nightly/*-group${{ matrix.group }}-*.toml + + outputs: + git-branch: ${{ steps.git-info.outputs.branch }} + + e2e-nightly-fail: + needs: e2e-nightly-test + if: ${{ failure() }} + runs-on: ubuntu-latest + steps: + - name: Notify Slack on failure + uses: slackapi/slack-github-action@v1.25.0 + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + BRANCH: ${{ needs.e2e-nightly-test.outputs.git-branch }} + RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + COMMITS_URL: "${{ github.server_url }}/${{ github.repository }}/commits/${{ needs.e2e-nightly-test.outputs.git-branch }}" + with: + payload: | + { + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ":skull: Nightly E2E tests for `${{ env.BRANCH }}` failed. See the <${{ env.RUN_URL }}|run details> and the <${{ env.COMMITS_URL }}|latest commits> possibly related to the failure." + } + } + ] + } diff --git a/.github/workflows/e2e-nightly-34x.yml b/.github/workflows/e2e-nightly-34x.yml index bffbf66676f..4f750e7dffb 100644 --- a/.github/workflows/e2e-nightly-34x.yml +++ b/.github/workflows/e2e-nightly-34x.yml @@ -19,11 +19,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.18' + go-version: '1.20' - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: 'v0.34.x' @@ -55,7 +55,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify Slack on failure - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@v1.25.0 env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.github/workflows/e2e-nightly-37x.yml b/.github/workflows/e2e-nightly-37x.yml index 26614fe4b42..44ee7fb277d 100644 --- a/.github/workflows/e2e-nightly-37x.yml +++ b/.github/workflows/e2e-nightly-37x.yml @@ -19,11 +19,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: 'v0.37.x' @@ -55,7 +55,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify Slack on failure - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@v1.25.0 env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.github/workflows/e2e-nightly-38x.yml b/.github/workflows/e2e-nightly-38x.yml new file mode 100644 index 00000000000..9ec59cce762 --- /dev/null +++ b/.github/workflows/e2e-nightly-38x.yml @@ -0,0 +1,77 @@ +# Runs randomly generated E2E testnets nightly on the v0.38.x branch. + +# !! This file should be kept in sync with the e2e-nightly-main.yml file, +# modulo changes to the version labels. + +name: e2e-nightly-38x +on: + schedule: + - cron: '0 2 * * *' + +jobs: + e2e-nightly-test: + # Run parallel jobs for the listed testnet groups (must match the + # ./build/generator -g flag) + strategy: + fail-fast: false + matrix: + group: ['00', '01', '02', '03', "04"] + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/setup-go@v5 + with: + go-version: "1.22" + + - uses: actions/checkout@v4 + with: + ref: 'v0.38.x' + + - name: Capture git repo info + id: git-info + run: | + echo "branch=`git branch --show-current`" >> $GITHUB_OUTPUT + + - name: Build + working-directory: test/e2e + # Run make jobs in parallel, since we can't run steps in parallel. + run: make -j2 docker generator runner tests + + - name: Generate testnets + working-directory: test/e2e + # When changing -g, also change the matrix groups above + run: ./build/generator -g 5 -d networks/nightly/ -p + + - name: Run ${{ matrix.p2p }} p2p testnets + working-directory: test/e2e + run: ./run-multiple.sh networks/nightly/*-group${{ matrix.group }}-*.toml + + outputs: + git-branch: ${{ steps.git-info.outputs.branch }} + + e2e-nightly-fail: + needs: e2e-nightly-test + if: ${{ failure() }} + runs-on: ubuntu-latest + steps: + - name: Notify Slack on failure + uses: slackapi/slack-github-action@v1.25.0 + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + BRANCH: ${{ needs.e2e-nightly-test.outputs.git-branch }} + RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + COMMITS_URL: "${{ github.server_url }}/${{ github.repository }}/commits/${{ needs.e2e-nightly-test.outputs.git-branch }}" + with: + payload: | + { + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ":skull: Nightly E2E tests for `${{ env.BRANCH }}` failed. See the <${{ env.RUN_URL }}|run details> and the <${{ env.COMMITS_URL }}|latest commits> possibly related to the failure." + } + } + ] + } diff --git a/.github/workflows/e2e-nightly-main.yml b/.github/workflows/e2e-nightly-main.yml index b031f78fd1d..f533fd9016a 100644 --- a/.github/workflows/e2e-nightly-main.yml +++ b/.github/workflows/e2e-nightly-main.yml @@ -20,11 +20,11 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build working-directory: test/e2e @@ -46,7 +46,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify Slack on failure - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@v1.25.0 env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index e6a4a7e730f..df9269db0b9 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -4,6 +4,7 @@ name: e2e on: workflow_dispatch: # allow running workflow manually pull_request: + merge_group: push: branches: - main @@ -14,10 +15,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' - - uses: actions/checkout@v3 + go-version: "1.22" + - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6 with: PATTERNS: | @@ -28,7 +29,7 @@ jobs: - name: Build working-directory: test/e2e # Run two make jobs in parallel, since we can't run steps in parallel. - run: make -j2 docker runner tests + run: make -j2 docker runner if: "env.GIT_DIFF != ''" - name: Run CI testnet diff --git a/.github/workflows/fuzz-nightly.yml b/.github/workflows/fuzz-nightly.yml index 15a20f06407..3f3b0eeab3d 100644 --- a/.github/workflows/fuzz-nightly.yml +++ b/.github/workflows/fuzz-nightly.yml @@ -13,11 +13,11 @@ jobs: fuzz-nightly-test: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install go-fuzz working-directory: test/fuzz @@ -49,14 +49,14 @@ jobs: continue-on-error: true - name: Archive crashers - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crashers path: test/fuzz/**/crashers retention-days: 3 - name: Archive suppressions - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: suppressions path: test/fuzz/**/suppressions @@ -76,7 +76,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify Slack on failure - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@v1.25.0 env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index f7e1e10818a..a9708c20d84 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -6,6 +6,7 @@ name: Check for Go vulnerabilities # Run `make vulncheck` from the root of the repo to run this workflow locally. on: pull_request: + merge_group: push: branches: - main @@ -15,10 +16,11 @@ jobs: govulncheck: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.20.2" - - uses: actions/checkout@v3 + go-version: "1.22" + check-latest: true + - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6 with: PATTERNS: | diff --git a/.github/workflows/ignore-words.txt b/.github/workflows/ignore-words.txt new file mode 100644 index 00000000000..1ce3d6eaeab --- /dev/null +++ b/.github/workflows/ignore-words.txt @@ -0,0 +1,5 @@ +caf +consequentially +fo +onlyonce +toi diff --git a/.github/workflows/janitor.yml b/.github/workflows/janitor.yml index 22cba4a93af..29ad2ceb54b 100644 --- a/.github/workflows/janitor.yml +++ b/.github/workflows/janitor.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 3 steps: - - uses: styfle/cancel-workflow-action@0.11.0 + - uses: styfle/cancel-workflow-action@0.12.1 with: workflow_id: 1041851,1401230,2837803 access_token: ${{ github.token }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b3271d53895..5ba76ace8e1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,37 +1,28 @@ -name: Golang Linter -# Lint runs golangci-lint over the entire CometBFT repository. +name: Lint, format and check the code for typos +# Lint runs `make lint` # # This workflow is run on every pull request and push to main. # -# The `golangci` job will pass without running if no *.{go, mod, sum} -# files have been modified. -# # To run this locally, simply run `make lint` from the root of the repo. on: pull_request: + merge_group: push: branches: - main + jobs: - golangci: - name: golangci-lint + lint: + name: lint runs-on: ubuntu-latest - timeout-minutes: 8 + timeout-minutes: 10 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v4 - with: - go-version: '1.20' - - uses: technote-space/get-diff-action@v6 + - uses: actions/setup-python@v5 with: - PATTERNS: | - **/**.go - go.mod - go.sum - - uses: golangci/golangci-lint-action@v3 + python-version: '3.x' + - uses: actions/setup-go@v5 with: - version: v1.51 - args: --timeout 10m - github-token: ${{ secrets.github_token }} - if: env.GIT_DIFF + go-version: "1.22" + - uses: actions/checkout@v4 + - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/markdown-linter.yml b/.github/workflows/markdown-linter.yml index 0caa6c679ac..b50f10dce7e 100644 --- a/.github/workflows/markdown-linter.yml +++ b/.github/workflows/markdown-linter.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Lint Code Base uses: docker://github/super-linter:v4 env: diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index bbd28cbd067..9d34053d091 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -12,13 +12,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" # Similar check to ./release-version.yml, but enforces this when pushing # tags. The ./release-version.yml check can be bypassed and is mainly @@ -44,7 +44,7 @@ jobs: echo "See the [CHANGELOG](${CHANGELOG_URL}) for changes available in this pre-release, but not yet officially released." > ../release_notes.md - name: Release - uses: goreleaser/goreleaser-action@v4 + uses: goreleaser/goreleaser-action@v5 with: version: latest args: release --clean --release-notes ../release_notes.md @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify Slack upon pre-release - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@v1.25.0 env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.github/workflows/proto-lint.yml b/.github/workflows/proto-lint.yml index 55f5feff79a..facaf4b62ed 100644 --- a/.github/workflows/proto-lint.yml +++ b/.github/workflows/proto-lint.yml @@ -3,6 +3,7 @@ on: pull_request: paths: - 'proto/**' + merge_group: push: branches: - main @@ -14,8 +15,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v3 - - uses: bufbuild/buf-setup-action@v1.15.1 + - uses: actions/checkout@v4 + - uses: bufbuild/buf-setup-action@v1.30.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 773e9339ab3..0cb32202380 100644 --- a/.github/workflows/release-version.yml +++ b/.github/workflows/release-version.yml @@ -11,11 +11,11 @@ jobs: check-version: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" - name: Check version run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e1c959c3f32..5388063d52f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,13 +10,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: "1.22" # Similar check to ./release-version.yml, but enforces this when pushing # tags. The ./release-version.yml check can be bypassed and is mainly @@ -43,7 +43,7 @@ jobs: echo "See the [CHANGELOG](${CHANGELOG_URL}) for this release." > ../release_notes.md - name: Release - uses: goreleaser/goreleaser-action@v4 + uses: goreleaser/goreleaser-action@v5 with: version: latest args: release --clean --release-notes ../release_notes.md @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Notify Slack upon release - uses: slackapi/slack-github-action@v1.23.0 + uses: slackapi/slack-github-action@v1.25.0 env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 396f41b1aba..35bfb53d77f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: "This pull request has been automatically marked as stale because it has not had diff --git a/.github/workflows/testapp-docker.yml b/.github/workflows/testapp-docker.yml index d503a9868f7..bbb3ef09250 100644 --- a/.github/workflows/testapp-docker.yml +++ b/.github/workflows/testapp-docker.yml @@ -15,7 +15,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Prepare id: prep run: | @@ -41,17 +41,17 @@ jobs: platforms: all - name: Set up Docker Build - uses: docker/setup-buildx-action@v2.5.0 + uses: docker/setup-buildx-action@v3.3.0 - name: Login to DockerHub if: ${{ github.event_name != 'pull_request' }} - uses: docker/login-action@v2.1.0 + uses: docker/login-action@v3.1.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Publish to Docker Hub - uses: docker/build-push-action@v4.0.0 + uses: docker/build-push-action@v5.3.0 with: context: . file: ./test/e2e/docker/Dockerfile diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 69801355d55..17aa02bf940 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,7 @@ name: Test on: pull_request: + merge_group: push: paths: - "**.go" @@ -14,12 +15,12 @@ jobs: strategy: fail-fast: false matrix: - part: ["00", "01", "02", "03", "04", "05"] + part: ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"] steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.20" - - uses: actions/checkout@v3 + go-version: "1.22" + - uses: actions/checkout@v4 - uses: technote-space/get-diff-action@v6 with: PATTERNS: | @@ -30,5 +31,5 @@ jobs: Makefile - name: Run Go Tests run: | - make test-group-${{ matrix.part }} NUM_SPLIT=6 + make test-group-${{ matrix.part }} NUM_SPLIT=20 if: env.GIT_DIFF diff --git a/.gitignore b/.gitignore index d9247f281a0..3b7ac8f6252 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,8 @@ remote_dump rpc/test/.cometbft scripts/cutWALUntil/cutWALUntil scripts/wal2json/wal2json +scripts/db_measurements/measurements.txt +scripts/db_measurements/process_measurements.py shunit2 terraform.tfstate terraform.tfstate.backup @@ -40,9 +42,12 @@ terraform.tfstate.d test/app/grpc_client test/loadtime/build test/e2e/build +test/e2e/data/ test/e2e/networks/*/ test/logs test/p2p/data/ +tools/goleveldb_perf/.ipynb_checkpoints +tools/goleveldb_perf/measurements vendor test/fuzz/**/corpus test/fuzz/**/crashers @@ -57,3 +62,4 @@ proto/spec/**/*.pb.go *.dvi # Python virtual environments .venv +go.work.sum diff --git a/.golangci.yml b/.golangci.yml index 80e7214b2c0..f92890b5dfe 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,44 +1,180 @@ +run: + tests: true + timeout: 10m + linters: - enable: - - asciicheck - - bodyclose - - depguard - - dogsled - - dupl - - errcheck - - exportloopref - - goconst - - gofmt - - goimports - - revive - - gosec - - gosimple - - govet - - ineffassign - - misspell - - nakedret - - nolintlint - - prealloc - - staticcheck - # - structcheck // to be fixed by golangci-lint - - stylecheck - - typecheck - - unconvert - - unused + enable-all: true + disable: + - containedctx + - contextcheck + - cyclop + - deadcode + - dupword + - errorlint + - errname + - exhaustive + - exhaustivestruct + - exhaustruct + - forbidigo + - forcetypeassert + - funlen + - gochecknoglobals + - gochecknoinits + - gocognit + - gocyclo + - godox + - goerr113 + - golint + - gomnd + - ifshort + - interfacebloat + - interfacer + - ireturn + - lll + - maintidx + - maligned + - nestif + - nilnil + - nlreturn + - nonamedreturns + - nosnakecase + - predeclared + - scopelint + - structcheck + - tagliatelle + - testifylint + - varcheck + - varnamelen + - wrapcheck + - wsl issues: exclude-rules: - path: _test\.go linters: + - gocritic + - gofmt + - goimport - gosec - max-same-issues: 50 - + - noctx + - paralleltest + - testpackage + - tparallel + - path: \.pb\.go + linters: + - gofmt + - goimports + - govet + - stylecheck + max-same-issues: 10000 + max-issues-per-linter: 10000 linters-settings: dogsled: max-blank-identifiers: 3 - golint: - min-confidence: 0 - maligned: - suggest-new: true + goconst: + ignore-tests: true misspell: locale: US + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - blank # blank imports + - dot # dot imports + - prefix(github.com/cometbft/cometbft, github.com/cometbft/cometbft-db, github.com/cometbft/cometbft-load-test) + custom-order: true + depguard: + rules: + main: + files: + - $all + - "!$test" + allow: + - $gostd + - github.com/cometbft + - github.com/cosmos + - github.com/btcsuite/btcd/btcec/v2 + - github.com/BurntSushi/toml + - github.com/go-git/go-git/v5 + - github.com/go-kit + - github.com/go-logfmt/logfmt + - github.com/gofrs/uuid + - github.com/google + - github.com/gorilla/websocket + - github.com/lib/pq + - github.com/libp2p/go-buffer-pool + - github.com/Masterminds/semver/v3 + - github.com/minio/highwayhash + - github.com/oasisprotocol/curve25519-voi + - github.com/pkg/errors + - github.com/prometheus + - github.com/rcrowley/go-metrics + - github.com/rs/cors + - github.com/snikch/goodman + - github.com/spf13 + - github.com/stretchr/testify/require + - github.com/syndtr/goleveldb + test: + files: + - "$test" + allow: + - $gostd + - github.com/cosmos + - github.com/cometbft + - github.com/adlio/schema + - github.com/btcsuite/btcd + - github.com/fortytw2/leaktest + - github.com/go-kit + - github.com/google/uuid + - github.com/gorilla/websocket + - github.com/lib/pq + - github.com/oasisprotocol/curve25519-voi/primitives/merlin + - github.com/ory/dockertest + - github.com/pkg/errors + - github.com/prometheus/client_golang/prometheus/promhttp + - github.com/spf13 + - github.com/stretchr/testify + + revive: + enable-all-rules: true + rules: + - name: max-public-structs + disabled: true + - name: cognitive-complexity + disabled: true + - name: argument-limit + disabled: true + - name: cyclomatic + disabled: true + - name: deep-exit + disabled: true + - name: file-header + disabled: true + - name: function-length + disabled: true + - name: function-result-limit + disabled: true + - name: line-length-limit + disabled: true + - name: flag-parameter + disabled: true + - name: add-constant + disabled: true + - name: empty-lines + disabled: true + - name: import-shadowing + disabled: true + - name: modifies-value-receiver + disabled: true + - name: confusing-naming + disabled: true + - name: defer + disabled: true + - name: unchecked-type-assertion + disabled: true + - name: unhandled-error + disabled: true + arguments: + - "fmt.Printf" + - "fmt.Print" + - "fmt.Println" diff --git a/.goreleaser.yml b/.goreleaser.yml index da0b5e23053..b9a76a3d4e5 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -8,7 +8,7 @@ builds: - id: "cometbft" main: ./cmd/cometbft/main.go ldflags: - - -s -w -X github.com/cometbft/cometbft/version.TMCoreSemVer={{ .Version }} + - -s -w -X github.com/cometbft/cometbft/version.CMTSemVer={{ .Version }} env: - CGO_ENABLED=0 goos: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000000..f5a4338c6a7 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +--- +# Details: https://pre-commit.com/#new-hooks + +repos: + # golangci-lint + - repo: https://github.com/golangci/golangci-lint + rev: v1.56.1 + hooks: + - id: golangci-lint-full + args: [--timeout, 10m] # for CI + + # gofumpt (does not have .pre-commmit-hooks.yaml) + - repo: local + hooks: + - id: gofumpt + name: "gofumpt" + additional_dependencies: + - mvdan.cc/gofumpt@v0.6.0 + entry: "gofumpt" + language: golang + args: [-w, .] + types: [go] + pass_filenames: false + + # codespell + - repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + args: [-w] diff --git a/CHANGELOG.md b/CHANGELOG.md index fd6c3aab928..1dc6e13b79a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,831 @@ # CHANGELOG +## Unreleased + +### BREAKING CHANGES + +- `[proto]` Renamed the packages from `tendermint.*` to `cometbft.*` + and introduced versioned packages to distinguish between proto definitions + released in 0.34.x, 0.37.x, 0.38.x, and 1.0.x versions. + Prior to the 1.0 release, the versioned packages are suffixed with + `.v1beta1`, `.v1beta2`, and so on; all definitions describing the protocols + as per the 1.0.0 release are in packages suffixed with `.v1`. + Relocated generated Go code into a new `api` folder and changed the import + paths accordingly. + ([\#495](https://github.com/cometbft/cometbft/pull/495) + [\#1504](https://github.com/cometbft/cometbft/issues/1504)) +- `[crypto/merkle]` The public `Proof.ComputeRootHash` function has been deleted. + ([\#558](https://github.com/cometbft/cometbft/issues/558)) +- `[rpc/grpc]` Remove the deprecated gRPC broadcast API + ([\#650](https://github.com/cometbft/cometbft/issues/650)) +- `[proto]` The names in the `cometbft.abci.v1` versioned proto package + are changed to satisfy the + [buf guidelines](https://buf.build/docs/best-practices/style-guide/) + ([#736](https://github.com/cometbft/cometbft/issues/736), + [#1504](https://github.com/cometbft/cometbft/issues/1504), + [#1530](https://github.com/cometbft/cometbft/issues/1530)): + * Names of request and response types used in gRPC changed by making + `Request`/`Response` the suffix instead of the prefix, e.g. + `RequestCheckTx` ⭢ `CheckTxRequest`. + * The `Request` and `Response` multiplex messages are redefined accordingly. + * `CheckTxType` values renamed with the `CHECK_TX_TYPE_` prefix. + * `MisbehaviorType` values renamed with the `MISBEHAVIOR_TYPE_` prefix. + * `Result` enum formerly nested in `ResponseOfferSnapshot` replaced with the package-level + `OfferSnapshotResult`, its values named with the + `OFFER_SNAPSHOT_RESULT_` prefix. + * `Result` enum formerly nested in `ResponseApplyShapshotChunk` replaced with the package-level + `ApplySnapshotChunkResult`, its values named with the + `APPLY_SNAPSHOT_CHUNK_RESULT_` prefix. + * `Status` enum formerly nested in `ResponseProcessProposal` replaced with the package-level + `ProcessProposalStatus`, its values named with the + `PROCESS_PROPOSAL_STATUS_` prefix. + * `Status` enum formerly nested in `ResponseVerifyVoteExtension` replaced with the package-level + `VerifyVoteExtensionStatus`, its values named with the + `VERIFY_VOTE_EXTENSION_STATUS_` prefix. + * New definition of `Misbehavior` using the changed `MisbehaviorType`. + * The gRPC service is renamed `ABCIService` and defined using the types listed above. +- `[proto]` In the `cometbft.state.v1` package, the definition for `ABCIResponsesInfo` + is changed, renaming `response_finalize_block` field to `finalize_block`. +- `[abci]` Changed the proto-derived enum type and constant aliases to the + buf-recommended naming conventions adopted in the `abci/v1` proto package. + For example, `ResponseProcessProposal_ACCEPT` is renamed to `PROCESS_PROPOSAL_STATUS_ACCEPT` + ([\#736](https://github.com/cometbft/cometbft/issues/736)). +- `[abci]` The `Type` enum field is now required to be set to a value other + than the default `CHECK_TX_TYPE_UNKNOWN` for a valid `CheckTxRequest` + ([\#736](https://github.com/cometbft/cometbft/issues/736)). +- `[rpc]` The endpoints `broadcast_tx_*` now return an error when the node is + performing block sync or state sync. + ([\#785](https://github.com/cometbft/cometbft/issues/785)) +- `[mempool]` When the node is performing block sync or state sync, the mempool + reactor now discards incoming transactions from peers, and does not propagate + transactions to peers. + ([\#785](https://github.com/cometbft/cometbft/issues/785)) +- `[consensus]` `Handshaker.Handshake` now requires `context.Context` ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) +- `[node]` `NewNode` now requires `context.Context` as the first parameter ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) +`[mempool]` Change the signature of `CheckTx` in the `Mempool` interface to +`CheckTx(tx types.Tx) (*abcicli.ReqRes, error)`. Also, add new method +`SetTxRemovedCallback`. +([\#1010](https://github.com/cometbft/cometbft/issues/1010)) +- `[state]` The `state.Store` interface has been expanded + to accommodate the data pull companion API of ADR 101 + ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) +- `[proxy]` Expand `ClientCreator` interface to allow + for per-"connection" control of client creation + ([\#1141](https://github.com/cometbft/cometbft/pull/1141)) +- `[mempool]` Remove `mempoolIDs` for internally storing peer ids as `p2p.ID` + instead of `uint16`. + ([\#1146](https://github.com/cometbft/cometbft/pull/1146)) +- `[cmd]` Remove `replay` and `replay-console` subcommands + and corresponding consensus file replay code, such as + `consensus.RunReplayFile`, and `consensus.State.ReplayFile` + ([\#1170](https://github.com/cometbft/cometbft/pull/1170)) +- `[state/indexer/block]` BlockIndexer now has additional method `Prune`, `GetRetainHeight`, `SetRetainHeight` ([\#1176](https://github.com/cometbft/cometbft/pull/1176)) +- `[state/txindex]` TxIndexer now has additional methods: `Prune`, `GetRetainHeight`, `SetRetainHeight` ([\#1176](https://github.com/cometbft/cometbft/pull/1176)) +- `[node]` Change the signature of `GenesisDocProvider` to + return the checksum of JSON content alongside the parsed genesis data + ([\#1287](https://github.com/cometbft/cometbft/issues/1287)). +- `[node]` Go-API breaking: Change the signature of `LoadStateFromDBOrGenesisDocProvider` + to accept an optional operator provided hash of the genesis file + ([\#1324](https://github.com/cometbft/cometbft/pull/1324)). +- `[version]` Bumped the P2P version from 8 to 9, as this release contains new P2P messages. + ([\#1411](https://github.com/cometbft/cometbft/pull/1411)) +- `[rpc/client]` Hard-code the `/websocket` endpoint path such that it is + no longer configurable, removing the related client constructor parameter + ([\#1412](https://github.com/cometbft/cometbft/pull/1412)) +- `[libs/os]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[store]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/autofile]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/tempfile]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/clist]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/net]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/strings]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[state]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/rand]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/flowrate]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/async]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/timer]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/sync]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[statesync]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/bits]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/progressbar]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[blocksync]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/protoio]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/events]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/cmap]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[inspect]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/service]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[evidence]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/pubsub]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[libs/fail]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[consensus]` Move to `internal` + ([\#1485](https://github.com/cometbft/cometbft/pull/1485)) +- `[abci]` Renamed the alias types for gRPC requests, responses, and service + instances to follow the naming changes in the proto-derived + `api/cometbft/abci/v1` package + ([\#1533](https://github.com/cometbft/cometbft/pull/1533)): + * The prefixed naming pattern `RequestFoo`, `ReponseFoo` changed to + suffixed `FooRequest`, `FooResponse`. + * Each method gets its own unique request and response type to allow for + independent evolution with backward compatibility. + * `ABCIClient` renamed to `ABCIServiceClient`. + * `ABCIServer` renamed to `ABCIServiceServer`. +- `[store]` Make the `LoadBlock` method also return block metadata + ([\#1556](https://github.com/cometbft/cometbft/issues/1556)) +- Made `/api` a standalone Go module with its own `go.mod` + ([\#1561](https://github.com/cometbft/cometbft/issues/1561)) +- `[comet]` Version variables, in `version/version.go`, have been renamed to reflect the CometBFT rebranding. + ([cometbft/cometbft\#1621](https://github.com/cometbft/cometbft/pull/1621)) +- `[state/store]` go-API breaking change in `PruneStates`: added parameter to pass the number of pruned states and return pruned entries in current pruning iteration. ([\#1972](https://github.com/cometbft/cometbft/pull/1972)) +- `[state/store]` go-API breaking change in `PruneABCIResponses`: added parameter to force compaction. ([\#1972](https://github.com/cometbft/cometbft/pull/1972)) +- `[proto]` Remove stateful block data retrieval methods from the + data companion gRPC API as per + [RFC 106](https://github.com/cometbft/cometbft/blob/main/docs/references/rfc/rfc-106-separate-stateful-methods.md) + ([\#2230](https://github.com/cometbft/cometbft/issues/2230)): + * `GetLatest` from `cometbft.services.block.v1.BlockService`; + * `GetLatestBlockResults` from `cometbft.services.block_results.v1.BlockResultsService`. +- `[rpc/grpc]` Remove support for stateful block data retrieval methods from the + data companion APIs as per [RFC 106](https://github.com/cometbft/cometbft/blob/main/docs/references/rfc/rfc-106-separate-stateful-methods.md) + * `GetLatestBlock` method removed from the `BlockServiceClient` interface. + * `GetLatestBlockResults` method removed from the `BlockResultServiceClient` interface. + * `GetLatest` endpoint is no longer served by `BlockServiceServer` instances. + * `GetLatestBlockResults` endpoint is no longer served by `BlockResultServiceServer` instances. +- `[p2p]` Rename `IPeerSet#List` to `Copy`, add `Random`, `ForEach` methods. + Rename `PeerSet#List` to `Copy`, add `Random`, `ForEach` methods. + ([\#2246](https://github.com/cometbft/cometbft/pull/2246)) +- `[abci]` Deprecates `ABCIParams` field of `ConsensusParam` and + introduces replacement in `FeatureParams` to enable Vote Extensions. + ([\#2322](https://github.com/cometbft/cometbft/pull/2322)) +- `[internal/state]` Moved function `MedianTime` to package `types`, + and made it a method of `Commit` so it can be used by external packages. + ([\#2397](https://github.com/cometbft/cometbft/pull/2397)) + +### BUG FIXES + +`[consensus]` Fix for "Validation of `VoteExtensionsEnableHeight` can cause chain halt" + ([ASA-2024-001](https://github.com/cometbft/cometbft/security/advisories/GHSA-qr8r-m495-7hc4)) +- `[mempool]` Fix data races in `CListMempool` by making atomic the types of `height`, `txsBytes`, and + `notifiedTxsAvailable`. ([\#642](https://github.com/cometbft/cometbft/pull/642)) +- `[consensus]` Consensus now prevotes `nil` when the proposed value does not + match the value the local validator has locked on + ([\#1203](https://github.com/cometbft/cometbft/pull/1203)) +- `[consensus]` Remove logic to unlock block on +2/3 prevote for nil + ([\#1175](https://github.com/cometbft/cometbft/pull/1175): @BrendanChou) +- `[state/indexer]` Respect both height params while querying for events + ([\#1529](https://github.com/cometbft/cometbft/pull/1529)) +- `[state/pruning]` When no blocks are pruned, do not attempt to prune statestore + ([\#1616](https://github.com/cometbft/cometbft/pull/1616)) +- `[mempool]` The calculation method of tx size returned by calling proxyapp should be consistent with that of mempool + ([\#1687](https://github.com/cometbft/cometbft/pull/1687)) +- `[evidence]` When `VerifyCommitLight` & `VerifyCommitLightTrusting` are called as part + of evidence verification, all signatures present in the evidence must be verified + ([\#1749](https://github.com/cometbft/cometbft/pull/1749)) +- `[crypto]` `SupportsBatchVerifier` returns false + if public key is nil instead of dereferencing nil. + ([\#1825](https://github.com/cometbft/cometbft/pull/1825)) +- `[blocksync]` wait for `poolRoutine` to stop in `(*Reactor).OnStop` + ([\#1879](https://github.com/cometbft/cometbft/pull/1879)) +- `[p2p/pex]` gracefully shutdown Reactor ([\#2010](https://github.com/cometbft/cometbft/pull/2010)) +- `[privval]` Retry accepting a connection ([\#2047](https://github.com/cometbft/cometbft/pull/2047)) +- `[state]` Fix rollback to a specific height + ([\#2136](https://github.com/cometbft/cometbft/pull/2136)) + +### DEPENDENCIES + +- Bump cometbft-db to v0.9.0, providing support for RocksDB v8 + ([\#1725](https://github.com/cometbft/cometbft/pull/1725)) + +### FEATURES + +- `[rpc/grpc]` Add gRPC server to the node, configurable + via a new `[grpc]` section in the configuration file + ([\#816](https://github.com/cometbft/cometbft/issues/816)) +- `[rpc/grpc]` Add gRPC version service to allow clients to + establish the software and protocol versions of the node + ([\#816](https://github.com/cometbft/cometbft/issues/816)) +- `[rpc/grpc]` Add gRPC client with support for version service + ([\#816](https://github.com/cometbft/cometbft/issues/816)) +- `[grpc]` Add `BlockService` with client to facilitate fetching of blocks and + streaming of the latest committed block height + ([\#1094](https://github.com/cometbft/cometbft/issues/1094)) +- `[config]` Add `[grpc.block_service]` section to configure gRPC `BlockService` + ([\#1094](https://github.com/cometbft/cometbft/issues/1094)) +- `[grpc]` Add `BlockResultsService` with client to fetch BlockResults + for a given height, or latest. + ([\#1095](https://github.com/cometbft/cometbft/issues/1095)) +- `[config]` Add `[grpc.block_results_service]` gRPC configuration `BlockResultsService` + ([\#1095](https://github.com/cometbft/cometbft/issues/1095)) +- `[proto]` Add definitions and generated code for + [ADR-101](./docs/architecture/adr-101-data-companion-pull-api.md) + `PruningService` in the `cometbft.services.pruning.v1` proto package + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[rpc/grpc]` Add privileged gRPC server and client facilities, in + `server/privileged` and `client/privileged` packages respectively, to + enable a separate API server within the node which serves trusted clients + without authentication and should never be exposed to public internet + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[rpc/grpc]` Add a pruning service adding on the privileged gRPC server API to + give an [ADR-101](./docs/architecture/adr-101-data-companion-pull-api.md) data + companion control over block data retained by the node. The + `WithPruningService` option method in `server/privileged` is provided to + configure the pruning service + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[rpc/grpc]` Add `PruningServiceClient` interface + for the gRPC client in `client/privileged` along with a configuration option + to enable it + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[config]` Add `[grpc.privileged]` section to configure the privileged + gRPC server for the node, and `[grpc.privileged.pruning_service]` section + to control the pruning service + ([\#1097](https://github.com/cometbft/cometbft/issues/1097)). +- `[metrics]` Add metrics to monitor pruning and current available data in stores: `PruningServiceBlockRetainHeight`, `PruningServiceBlockResultsRetainHeight`, `ApplicationBlockRetainHeight`, `BlockStoreBaseHeight`, `ABCIResultsBaseHeight`. + ([\#1234](https://github.com/cometbft/cometbft/pull/1234)) +`[rpc/grpc]` Add gRPC endpoint for pruning the block and transaction indexes +([\#1327](https://github.com/cometbft/cometbft/pull/1327)) +- `[state]` Add TxIndexer and BlockIndexer pruning metrics + ([\#1334](https://github.com/cometbft/cometbft/issues/1334)) +- `[metrics]` Add metric for mempool size in bytes `SizeBytes`. + ([\#1512](https://github.com/cometbft/cometbft/pull/1512)) +- `[mempool]` Add `nop` mempool ([\#1643](https://github.com/cometbft/cometbft/pull/1643)) + + If you want to use it, change mempool's `type` to `nop`: + + ```toml + [mempool] + + # The type of mempool for this node to use. + # + # Possible types: + # - "flood" : concurrent linked list mempool with flooding gossip protocol + # (default) + # - "nop" : nop-mempool (short for no operation; the ABCI app is responsible + # for storing, disseminating and proposing txs). "create_empty_blocks=false" + # is not supported. + type = "nop" + ``` +- `[config]` Add configuration parameters to tweak forced compaction. ([\#1972](https://github.com/cometbft/cometbft/pull/1972)) +- `[store]` When pruning force compaction of the database. ([\#1972](https://github.com/cometbft/cometbft/pull/1972)) +- `[metrics]` Added metrics to monitor state store access. ([\#1974](https://github.com/cometbft/cometbft/pull/1974)) +- `[metrics]` Added metrics to monitor block store access. ([\#1974](https://github.com/cometbft/cometbft/pull/1974)) +- `[test]` Added monitoring tools and dashboards for local testing with `localnet`. ([\#2107](https://github.com/cometbft/cometbft/issues/2107)) +- Add [`pebbledb`](https://github.com/cockroachdb/pebble). To use, build with + `pebbledb` tag (`go build -tags pebbledb`) ([\#2132](https://github.com/cometbft/cometbft/pull/2132/)) +- [light/store] Added support for a different DB key representation within the light block store ([\#2327](https://github.com/cometbft/cometbft/pull/2327/)) +- [store] Added support for a different DB key representation to state and block store ([\#2327](https://github.com/cometbft/cometbft/pull/2327/)) +- [evidence/store] Added support for a different DB key representation within the evidence store ([\#2327](https://github.com/cometbft/cometbft/pull/2327/)) +- `[e2e]` Add `block_max_bytes` option to the manifest file. + ([\#2362](https://github.com/cometbft/cometbft/pull/2362)) +- `[e2e]` Add new `--testnet-dir` parameter to set a custom directory for the generated testnet files. + ([\#2433](https://github.com/cometbft/cometbft/pull/2433)) +- `[docs]` Add report on storage improvements and findings. ([\#2569](https://github.com/cometbft/cometbft/pull/2569)) +- `[consensus]` add a new `synchrony` field to the `ConsensusParameter` struct + for controlling the parameters of the proposer-based timestamp algorithm. (@williambanfield) + ([tendermint/tendermint\#7354](https://github.com/tendermint/tendermint/pull/7354)) +- `[consensus]` Update the proposal logic per the Propose-based timestamps specification + so that the proposer will wait for the previous block time to occur + before proposing the next block. (@williambanfield) + ([tendermint/tendermint\#7376](https://github.com/tendermint/tendermint/pull/7376)) +- `[consensus]` Update block validation to no longer require the block timestamp + to be the median of the timestamps of the previous commit. (@anca) + ([tendermint/tendermint\#7382](https://github.com/tendermint/tendermint/pull/7382)) +- `[consensus]` Use the proposed block timestamp as the proposal timestamp. + Update the block validation logic to ensure that the proposed block's timestamp + matches the timestamp in the proposal message. (@williambanfield) + ([tendermint/tendermint\#7391](https://github.com/tendermint/tendermint/pull/7391)) +- `[consensus]` Update proposal validation logic to Prevote nil + if a proposal does not meet the conditions for Timeliness + per the proposer-based timestamp specification. (@anca) + ([tendermint/tendermint\#7415](https://github.com/tendermint/tendermint/pull/7415)) +- `[consensus]` Use the proposer timestamp for the first height instead of the genesis time. + Chains will still start consensus at the genesis time. (@anca) + ([tendermint/tendermint\#7711](https://github.com/tendermint/tendermint/pull/7711)) + +### IMPROVEMENTS + +- `[state/indexer]` Add transaction and block index pruning + ([\#1176](https://github.com/cometbft/cometbft/pull/1176)) +- `[mempool]` Add a metric (a counter) to measure whether a tx was received more than once. + ([\#634](https://github.com/cometbft/cometbft/pull/634)) +- `[docs/references]` Added ADR-102: RPC Companion. + ([\#658](https://github.com/cometbft/cometbft/pull/658)) +- `[consensus]` New metrics (counters) to track duplicate votes and block parts. + ([\#896](https://github.com/cometbft/cometbft/pull/896)) +- `[consensus]` Optimize vote and block part gossip with new message `HasProposalBlockPartMessage`, + which is similar to `HasVoteMessage`; and random sleep in the loop broadcasting those messages. + The sleep can be configured with new config `peer_gossip_intraloop_sleep_duration`, which is set to 0 + by default as this is experimental. + Our scale tests show substantial bandwidth improvement with a value of 50 ms. + ([\#904](https://github.com/cometbft/cometbft/pull/904)) +- Update Apalache type annotations in the light client spec ([#955](https://github.com/cometbft/cometbft/pull/955)) +- `[node]` Remove genesis persistence in state db, replaced by a hash + ([cometbft/cometbft\#1017](https://github.com/cometbft/cometbft/pull/1017), + [cometbft/cometbft\#1295](https://github.com/cometbft/cometbft/pull/1295)) +- `[consensus]` Log vote validation failures at info level + ([\#1022](https://github.com/cometbft/cometbft/pull/1022)) +- `[config]` Added `[storage.pruning]` and `[storage.pruning.data_companion]` + sections to facilitate background pruning and data companion (ADR 101) + operations ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) +- `[state]` ABCI response pruning has been added for use by the data companion + ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) +- `[state]` Block pruning has been moved from the block executor into a + background process ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) +- `[node]` The `node.Node` struct now manages a + `state.Pruner` service to facilitate background pruning + ([\#1096](https://github.com/cometbft/cometbft/issues/1096)) +- `[abci/client]` Add fully unsynchronized local client creator, which + imposes no mutexes on the application, leaving all handling of concurrency up + to the application ([\#1141](https://github.com/cometbft/cometbft/pull/1141)) +- `[abci/client]` Add consensus-synchronized local client creator, + which only imposes a mutex on the consensus "connection", leaving + the concurrency of all other "connections" up to the application + ([\#1141](https://github.com/cometbft/cometbft/pull/1141)) +- `[consensus]` When prevoting, avoid calling PropocessProposal when we know the + proposal was already validated by correct nodes. + ([\#1230](https://github.com/cometbft/cometbft/pull/1230)) +- `[node]` On upgrade, after [\#1296](https://github.com/cometbft/cometbft/pull/1296), delete the genesis file existing in the DB. + ([cometbft/cometbft\#1297](https://github.com/cometbft/cometbft/pull/1297) +- `[cli/node]` The genesis hash provided with the `--genesis-hash` is now + forwarded to the node, instead of reading the file. + ([\#1324](https://github.com/cometbft/cometbft/pull/1324)). +- `[rpc]` The RPC API is now versioned, with all existing endpoints accessible + via `/v1/*` as well as `/*` + ([\#1412](https://github.com/cometbft/cometbft/pull/1412)) +- `[consensus]` Reduce the default MaxBytes to 4MB and increase MaxGas to 10 million + ([\#1518](https://github.com/cometbft/cometbft/pull/1518)) +- `[mempool]` Add experimental feature to limit the number of persistent peers and non-persistent + peers to which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and + `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to + which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[e2e]` Allow latency emulation between nodes. + ([\#1559](https://github.com/cometbft/cometbft/pull/1559)) +- `[e2e]` Allow latency emulation between nodes. + ([\#1560](https://github.com/cometbft/cometbft/pull/1560)) +- `[e2e]` Allow disabling the PEX reactor on all nodes in the testnet + ([\#1579](https://github.com/cometbft/cometbft/pull/1579)) +- `[rpc]` Export `MakeHTTPDialer` to allow HTTP client constructors more flexibility. + ([\#1594](https://github.com/cometbft/cometbft/pull/1594)) +- `[types]` Validate `Validator#Address` in `ValidateBasic` ([\#1715](https://github.com/cometbft/cometbft/pull/1715)) +- `[abci]` Increase ABCI socket message size limit to 2GB ([\#1730](https://github.com/cometbft/cometbft/pull/1730): @troykessler) +- `[state]` Save the state using a single DB batch ([\#1735](https://github.com/cometbft/cometbft/pull/1735)) +- `[store]` Save block using a single DB batch if block is less than 640kB, otherwise each block part is saved individually + ([\#1755](https://github.com/cometbft/cometbft/pull/1755)) +- `[rpc]` Support setting proxy from env to `DefaultHttpClient`. + ([\#1900](https://github.com/cometbft/cometbft/pull/1900)) +- `[p2p]` Export p2p package errors ([\#1901](https://github.com/cometbft/cometbft/pull/1901)) (contributes to [\#1140](https://github.com/cometbft/cometbft/issues/1140)) +- `[rpc]` Use default port for HTTP(S) URLs when there is no explicit port ([\#1903](https://github.com/cometbft/cometbft/pull/1903)) +- `[light]` Export light package errors ([\#1904](https://github.com/cometbft/cometbft/pull/1904)) (contributes to [\#1140](https://github.com/cometbft/cometbft/issues/1140)) +- `[crypto/merkle]` faster calculation of hashes ([#1921](https://github.com/cometbft/cometbft/pull/1921)) +- Removed undesired linting from `Makefile` and added dependency check for `codespell`. +- `[blocksync]` Avoid double-calling `types.BlockFromProto` for performance + reasons ([\#2016](https://github.com/cometbft/cometbft/pull/2016)) +- `[state]` avoid double-saving `FinalizeBlockResponse` for performance reasons + ([\#2017](https://github.com/cometbft/cometbft/pull/2017)) +- `[e2e]` Add manifest option `VoteExtensionsUpdateHeight` to test + vote extension activation via `InitChain` and `FinalizeBlock`. + Also, extend the manifest generator to produce different values + of this new option + ([\#2065](https://github.com/cometbft/cometbft/pull/2065)) +- `[consensus]` Add `chain_size_bytes` metric for measuring the size of the blockchain in bytes + ([\#2093](https://github.com/cometbft/cometbft/pull/2093)) +- `[e2e]` Add manifest option `load_max_txs` to limit the number of transactions generated by the + `load` command. ([\#2094](https://github.com/cometbft/cometbft/pull/2094)) +- Optimized the PSQL indexer + ([\#2142](https://github.com/cometbft/cometbft/pull/2142)) thanks to external contributor @k0marov ! +- `[e2e]` Add new targets `fast` and `clean` to Makefile. + ([\#2192](https://github.com/cometbft/cometbft/pull/2192)) +- `[rpc]` Export RPC package errors ([\#2200](https://github.com/cometbft/cometbft/pull/2200)) (contributes to [\#1140](https://github.com/cometbft/cometbft/issues/1140)) +- `[p2p]` make `PeerSet.Remove` more efficient (Author: @odeke-em) [\#2246](https://github.com/cometbft/cometbft/pull/2246) +- `[jsonrpc]` enable HTTP basic auth in websocket client ([#2434](https://github.com/cometbft/cometbft/pull/2434)) +- `[e2e]` Introduce the possibility in the manifest for some nodes + to run in a preconfigured clock skew. + ([\#2453](https://github.com/cometbft/cometbft/pull/2453)) +- `[blocksync]` make the max number of downloaded blocks dynamic. + Previously it was a const 600. Now it's `peersCount * maxPendingRequestsPerPeer (20)` + [\#2467](https://github.com/cometbft/cometbft/pull/2467) +- `[blocksync]` Request a block from peer B if we are approaching pool's height + (less than 50 blocks) and the current peer A is slow in sending us the + block [\#2475](https://github.com/cometbft/cometbft/pull/2475) +- `[blocksync]` Request the block N from peer B immediately after getting + `NoBlockResponse` from peer A + [\#2475](https://github.com/cometbft/cometbft/pull/2475) +- `[blocksync]` Sort peers by download rate (the fastest peer is picked first) + [\#2475](https://github.com/cometbft/cometbft/pull/2475) +- `[privval]` DO NOT require extension signature from privval if vote + extensions are disabled. Remote signers can skip signing the extension if + `skip_extension_signing` flag in `SignVoteRequest` is true. + [\#2496](https://github.com/cometbft/cometbft/pull/2496) +- `[proto]` Add `skip_extension_signing` field to the `SignVoteRequest` message + in `cometbft.privval.v1` ([\#2522](https://github.com/cometbft/cometbft/pull/2522)). + The `cometbft.privval.v1beta2` package is added to capture the protocol as it was + released in CometBFT 0.38.x + ([\#2529](https://github.com/cometbft/cometbft/pull/2529)). + +### MINIMUM GO VERSION + +- Bump minimum Go version to v1.21 + ([\#1244](https://github.com/cometbft/cometbft/pull/1244)) + +## v0.38.2 + +*November 27, 2023* + +This release provides the **nop** mempool for applications that want to build their own mempool. +Using this mempool effectively disables all mempool functionality in CometBFT, including transaction dissemination and the `broadcast_tx_*` endpoints. + +Also fixes a small bug in the mempool for an experimental feature. + +### BUG FIXES + +- `[mempool]` Avoid infinite wait in transaction sending routine when + using experimental parameters to limiting transaction gossiping to peers + ([\#1654](https://github.com/cometbft/cometbft/pull/1654)) + +### FEATURES + +- `[mempool]` Add `nop` mempool ([\#1643](https://github.com/cometbft/cometbft/pull/1643)) + + If you want to use it, change mempool's `type` to `nop`: + + ```toml + [mempool] + + # The type of mempool for this node to use. + # + # Possible types: + # - "flood" : concurrent linked list mempool with flooding gossip protocol + # (default) + # - "nop" : nop-mempool (short for no operation; the ABCI app is responsible + # for storing, disseminating and proposing txs). "create_empty_blocks=false" + # is not supported. + type = "nop" + ``` + +## v0.38.1 + +*November 17, 2023* + +This release contains, among other things, an opt-in, experimental feature to +help reduce the bandwidth consumption associated with the mempool's transaction +gossip. + +### BUG FIXES + +- `[state/indexer]` Respect both height params while querying for events + ([\#1529](https://github.com/cometbft/cometbft/pull/1529)) + +### FEATURES + +- `[metrics]` Add metric for mempool size in bytes `SizeBytes`. + ([\#1512](https://github.com/cometbft/cometbft/pull/1512)) + +### IMPROVEMENTS + +- `[mempool]` Add experimental feature to limit the number of persistent peers and non-persistent + peers to which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and + `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to + which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) + +## v0.38.0 + +*September 12, 2023* + +This release includes the second part of ABCI++, called ABCI 2.0. +ABCI 2.0 introduces ABCI methods `ExtendVote` and `VerifyVoteExtension`. +These new methods allow the application to add data (opaque to CometBFT), +called _vote extensions_ to precommit votes sent by validators. +These vote extensions are made available to the proposer(s) of the next height. +Additionally, ABCI 2.0 coalesces `BeginBlock`, `DeliverTx`, and `EndBlock` +into one method, `FinalizeBlock`, whose `Request*` and `Response*` +data structures contain the sum of all data previously contained +in the respective `Request*` and `Response*` data structures in +`BeginBlock`, `DeliverTx`, and `EndBlock`. +See the [specification](./spec/abci/) for more details on ABCI 2.0. + +### BREAKING CHANGES + +- `[mempool]` Remove priority mempool. + ([\#260](https://github.com/cometbft/cometbft/issues/260)) +- `[config]` Remove `Version` field from `MempoolConfig`. + ([\#260](https://github.com/cometbft/cometbft/issues/260)) +- `[protobuf]` Remove fields `sender`, `priority`, and `mempool_error` from + `ResponseCheckTx`. ([\#260](https://github.com/cometbft/cometbft/issues/260)) +- `[crypto/merkle]` Do not allow verification of Merkle Proofs against empty trees (`nil` root). `Proof.ComputeRootHash` now panics when it encounters an error, but `Proof.Verify` does not panic + ([\#558](https://github.com/cometbft/cometbft/issues/558)) +- `[state/kvindexer]` Remove the function type from the event key stored in the database. This should be breaking only +for people who forked CometBFT and interact directly with the indexers kvstore. + ([\#774](https://github.com/cometbft/cometbft/pull/774)) +- `[rpc]` Removed `begin_block_events` and `end_block_events` from `BlockResultsResponse`. + The events are merged into one field called `finalize_block_events`. + ([\#9427](https://github.com/tendermint/tendermint/issues/9427)) +- `[pubsub]` Added support for big integers and big floats in the pubsub event query system. + Breaking changes: function `Number` in package `libs/pubsub/query/syntax` changed its return value. + ([\#797](https://github.com/cometbft/cometbft/pull/797)) +- `[kvindexer]` Added support for big integers and big floats in the kvindexer. + Breaking changes: function `Number` in package `libs/pubsub/query/syntax` changed its return value. + ([\#797](https://github.com/cometbft/cometbft/pull/797)) +- `[mempool]` Application can now set `ConsensusParams.Block.MaxBytes` to -1 + to have visibility on all transactions in the + mempool at `PrepareProposal` time. + This means that the total size of transactions sent via `RequestPrepareProposal` + might exceed `RequestPrepareProposal.max_tx_bytes`. + If that is the case, the application MUST make sure that the total size of transactions + returned in `ResponsePrepareProposal.txs` does not exceed `RequestPrepareProposal.max_tx_bytes`, + otherwise CometBFT will panic. + ([\#980](https://github.com/cometbft/cometbft/issues/980)) +- `[node/state]` Add Go API to bootstrap block store and state store to a height. Make sure block sync starts syncing from bootstrapped height. + ([\#1057](https://github.com/tendermint/tendermint/pull/#1057)) (@yihuang) +- `[state/store]` Added Go functions to save height at which offline state sync is performed. + ([\#1057](https://github.com/tendermint/tendermint/pull/#1057)) (@jmalicevic) +- `[p2p]` Remove UPnP functionality + ([\#1113](https://github.com/cometbft/cometbft/issues/1113)) +- `[node]` Removed `ConsensusState()` accessor from `Node` + struct - all access to consensus state should go via the reactor + ([\#1120](https://github.com/cometbft/cometbft/pull/1120)) +- `[state]` Signature of `ExtendVote` changed in `BlockExecutor`. + It now includes the block whose precommit will be extended, an the state object. + ([\#1270](https://github.com/cometbft/cometbft/pull/1270)) +- `[state]` Move pruneBlocks from node/state to state/execution. + ([\#6541](https://github.com/tendermint/tendermint/pull/6541)) +- `[abci]` Move `app_hash` parameter from `Commit` to `FinalizeBlock` + ([\#8664](https://github.com/tendermint/tendermint/pull/8664)) +- `[abci]` Introduce `FinalizeBlock` which condenses `BeginBlock`, `DeliverTx` + and `EndBlock` into a single method call + ([\#9468](https://github.com/tendermint/tendermint/pull/9468)) +- `[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)) + +### BUG FIXES + +- `[kvindexer]` Forward porting the fixes done to the kvindexer in 0.37 in PR \#77 + ([\#423](https://github.com/cometbft/cometbft/pull/423)) +- `[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)) +- `[consensus]` Rename `(*PeerState).ToJSON` to `MarshalJSON` to fix a logging data race + ([\#524](https://github.com/cometbft/cometbft/pull/524)) +- `[light]` Fixed an edge case where a light client would panic when attempting + to query a node that (1) has started from a non-zero height and (2) does + not yet have any data. The light client will now, correctly, not panic + _and_ keep the node in its list of providers in the same way it would if + it queried a node starting from height zero that does not yet have data + ([\#575](https://github.com/cometbft/cometbft/issues/575)) +- `[abci]` Restore the snake_case naming in JSON serialization of + `ExecTxResult` ([\#855](https://github.com/cometbft/cometbft/issues/855)). +- `[consensus]` Avoid recursive call after rename to (*PeerState).MarshalJSON + ([\#863](https://github.com/cometbft/cometbft/pull/863)) +- `[mempool/clist_mempool]` Prevent a transaction to appear twice in the mempool + ([\#890](https://github.com/cometbft/cometbft/pull/890): @otrack) +- `[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)) + +### DEPRECATIONS + +- `[rpc/grpc]` Mark the gRPC broadcast API as deprecated. + It will be superseded by a broader API as part of + [\#81](https://github.com/cometbft/cometbft/issues/81) + ([\#650](https://github.com/cometbft/cometbft/issues/650)) + +### FEATURES + +- `[node/state]` Add Go API to bootstrap block store and state store to a height + ([\#1057](https://github.com/tendermint/tendermint/pull/#1057)) (@yihuang) +- `[proxy]` Introduce `NewConnSyncLocalClientCreator`, 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"). + ([tendermint/tendermint\#9830](https://github.com/tendermint/tendermint/pull/9830) + and [\#1145](https://github.com/cometbft/cometbft/pull/1145)) +- `[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 `VerifyVoteExtension` and `ExtendVote` allow validators to validate the vote extension data attached to a pre-commit message and allow applications to let their validators do more than just validate within consensus ([\#9836](https://github.com/tendermint/tendermint/pull/9836)) + +### IMPROVEMENTS + +- `[blocksync]` Generate new metrics during BlockSync + ([\#543](https://github.com/cometbft/cometbft/pull/543)) +- `[jsonrpc/client]` Improve the error message for client errors stemming from + bad HTTP responses. + ([cometbft/cometbft\#638](https://github.com/cometbft/cometbft/pull/638)) +- `[rpc]` Remove response data from response failure logs in order + to prevent large quantities of log data from being produced + ([\#654](https://github.com/cometbft/cometbft/issues/654)) +- `[pubsub/kvindexer]` Numeric query conditions and event values are represented as big floats with default precision of 125. + Integers are read as "big ints" and represented with as many bits as they need when converting to floats. + ([\#797](https://github.com/cometbft/cometbft/pull/797)) +- `[node]` Make handshake cancelable ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) +- `[mempool]` Application can now set `ConsensusParams.Block.MaxBytes` to -1 + to gain more control on the max size of transactions in a block. + It also allows the application to have visibility on all transactions in the + mempool at `PrepareProposal` time. + ([\#980](https://github.com/cometbft/cometbft/pull/980)) +- `[node]` Close evidence.db OnStop ([cometbft/cometbft\#1210](https://github.com/cometbft/cometbft/pull/1210): @chillyvee) +- `[state]` Make logging `block_app_hash` and `app_hash` consistent by logging them both as hex. + ([\#1264](https://github.com/cometbft/cometbft/pull/1264)) +- `[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)) + +## v0.37.4 + +*November 27, 2023* + +This release provides the **nop** mempool for applications that want to build +their own mempool. Using this mempool effectively disables all mempool +functionality in CometBFT, including transaction dissemination and the +`broadcast_tx_*` endpoints. + +Also fixes a small bug in the mempool for an experimental feature, and reverts +the change from v0.37.3 that bumped the minimum Go version to v1.21. + +### BUG FIXES + +- `[mempool]` Avoid infinite wait in transaction sending routine when + using experimental parameters to limiting transaction gossiping to peers + ([\#1654](https://github.com/cometbft/cometbft/pull/1654)) + +### FEATURES + +- `[mempool]` Add `nop` mempool ([\#1643](https://github.com/cometbft/cometbft/pull/1643)) + + If you want to use it, change mempool's `type` to `nop`: + + ```toml + [mempool] + + # The type of mempool for this node to use. + # + # Possible types: + # - "flood" : concurrent linked list mempool with flooding gossip protocol + # (default) + # - "nop" : nop-mempool (short for no operation; the ABCI app is responsible + # for storing, disseminating and proposing txs). "create_empty_blocks=false" + # is not supported. + type = "nop" + ``` + +## v0.37.3 + +*November 17, 2023* + +This release contains, among other things, an opt-in, experimental feature to +help reduce the bandwidth consumption associated with the mempool's transaction +gossip. + +### BREAKING CHANGES + +- `[p2p]` Remove unused UPnP functionality + ([\#1113](https://github.com/cometbft/cometbft/issues/1113)) + +### BUG FIXES + +- `[state/indexer]` Respect both height params while querying for events + ([\#1529](https://github.com/cometbft/cometbft/pull/1529)) + +### FEATURES + +- `[node/state]` Add Go API to bootstrap block store and state store to a height + ([\#1057](https://github.com/tendermint/tendermint/pull/#1057)) (@yihuang) +- `[metrics]` Add metric for mempool size in bytes `SizeBytes`. + ([\#1512](https://github.com/cometbft/cometbft/pull/1512)) + +### IMPROVEMENTS + +- `[crypto/sr25519]` Upgrade to go-schnorrkel@v1.0.0 ([\#475](https://github.com/cometbft/cometbft/issues/475)) +- `[node]` Make handshake cancelable ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) +- `[node]` Close evidence.db OnStop ([cometbft/cometbft\#1210](https://github.com/cometbft/cometbft/pull/1210): @chillyvee) +- `[mempool]` Add experimental feature to limit the number of persistent peers and non-persistent + peers to which the node gossip transactions (only for "v0" mempool). + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and + `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to + which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) + +## v0.37.2 + +*June 14, 2023* + +Provides several minor bug fixes, as well as fixes for several low-severity +security issues. + +### BUG FIXES + +- `[state/kvindex]` Querying event attributes that are bigger than int64 is now + enabled. We are not supporting reading floats from the db into the indexer + nor parsing them into BigFloats to not introduce breaking changes in minor + releases. ([\#771](https://github.com/cometbft/cometbft/pull/771)) +- `[pubsub]` Pubsub queries are now able to parse big integers (larger than + int64). Very big floats are also properly parsed into very big integers + instead of being truncated to int64. + ([\#771](https://github.com/cometbft/cometbft/pull/771)) + +### IMPROVEMENTS + +- `[rpc]` Remove response data from response failure logs in order + to prevent large quantities of log data from being produced + ([\#654](https://github.com/cometbft/cometbft/issues/654)) + +### SECURITY FIXES + +- `[rpc/jsonrpc/client]` **Low severity** - Prevent RPC + client credentials from being inadvertently dumped to logs + ([\#787](https://github.com/cometbft/cometbft/pull/787)) +- `[cmd/cometbft/commands/debug/kill]` **Low severity** - Fix unsafe int cast in + `debug kill` command ([\#793](https://github.com/cometbft/cometbft/pull/793)) +- `[consensus]` **Low severity** - Avoid recursive call after rename to + `(*PeerState).MarshalJSON` + ([\#863](https://github.com/cometbft/cometbft/pull/863)) +- `[mempool/clist_mempool]` **Low severity** - Prevent a transaction from + appearing twice in the mempool + ([\#890](https://github.com/cometbft/cometbft/pull/890): @otrack) + +## v0.37.1 + +*April 26, 2023* + +This release fixes several bugs, and has had to introduce one small Go +API-breaking change in the `crypto/merkle` package in order to address what +could be a security issue for some users who directly and explicitly make use of +that code. + +### BREAKING CHANGES + +- `[crypto/merkle]` Do not allow verification of Merkle Proofs against empty trees (`nil` root). `Proof.ComputeRootHash` now panics when it encounters an error, but `Proof.Verify` does not panic + ([\#558](https://github.com/cometbft/cometbft/issues/558)) + +### BUG FIXES + +- `[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)) +- `[consensus]` Rename `(*PeerState).ToJSON` to `MarshalJSON` to fix a logging data race + ([\#524](https://github.com/cometbft/cometbft/pull/524)) +- `[light]` Fixed an edge case where a light client would panic when attempting + to query a node that (1) has started from a non-zero height and (2) does + not yet have any data. The light client will now, correctly, not panic + _and_ keep the node in its list of providers in the same way it would if + it queried a node starting from height zero that does not yet have data + ([\#575](https://github.com/cometbft/cometbft/issues/575)) + +### IMPROVEMENTS + +- `[jsonrpc/client]` Improve the error message for client errors stemming from + bad HTTP responses. + ([cometbft/cometbft\#638](https://github.com/cometbft/cometbft/pull/638)) + ## v0.37.0 *March 6, 2023* @@ -139,6 +965,120 @@ See below for more details. - `[consensus]` Save peer LastCommit correctly to achieve 50% reduction in gossiped precommits. ([\#9760](https://github.com/tendermint/tendermint/pull/9760)) +## v0.34.31 + +*November 27, 2023* + +Fixes a small bug in the mempool for an experimental feature. + +### BUG FIXES + +- `[mempool]` Avoid infinite wait in transaction sending routine when + using experimental parameters to limiting transaction gossiping to peers + ([\#1654](https://github.com/cometbft/cometbft/pull/1654)) + +## v0.34.30 + +*November 17, 2023* + +This release contains, among other things, an opt-in, experimental feature to +help reduce the bandwidth consumption associated with the mempool's transaction +gossip. + +### BUILD + +- Bump Go version used to v1.20 since v1.19 has reached EOL + ([\#1351](https://github.com/cometbft/cometbft/pull/1351)) + +### FEATURES + +- `[metrics]` Add metric for mempool size in bytes `SizeBytes`. + ([\#1512](https://github.com/cometbft/cometbft/pull/1512)) + +### IMPROVEMENTS + +- `[node]` Make handshake cancelable ([cometbft/cometbft\#857](https://github.com/cometbft/cometbft/pull/857)) +- `[node]` Close evidence.db OnStop ([cometbft/cometbft\#1210](https://github.com/cometbft/cometbft/pull/1210): @chillyvee) +- `[mempool]` Add experimental feature to limit the number of persistent peers and non-persistent + peers to which the node gossip transactions (only for "v0" mempool). + ([\#1558](https://github.com/cometbft/cometbft/pull/1558), + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) +- `[config]` Add mempool parameters `experimental_max_gossip_connections_to_persistent_peers` and + `experimental_max_gossip_connections_to_non_persistent_peers` for limiting the number of peers to + which the node gossip transactions. + ([\#1558](https://github.com/cometbft/cometbft/pull/1558)) + ([\#1584](https://github.com/cometbft/cometbft/pull/1584)) + +## v0.34.29 + +*June 14, 2023* + +Provides several minor bug fixes, as well as fixes for several low-severity +security issues. + +### BUG FIXES + +- `[state/kvindex]` Querying event attributes that are bigger than int64 is now + enabled. ([\#771](https://github.com/cometbft/cometbft/pull/771)) +- `[pubsub]` Pubsub queries are now able to parse big integers (larger than + int64). Very big floats are also properly parsed into very big integers + instead of being truncated to int64. + ([\#771](https://github.com/cometbft/cometbft/pull/771)) + +### IMPROVEMENTS + +- `[rpc]` Remove response data from response failure logs in order + to prevent large quantities of log data from being produced + ([\#654](https://github.com/cometbft/cometbft/issues/654)) + +### SECURITY FIXES + +- `[rpc/jsonrpc/client]` **Low severity** - Prevent RPC + client credentials from being inadvertently dumped to logs + ([\#788](https://github.com/cometbft/cometbft/pull/788)) +- `[cmd/cometbft/commands/debug/kill]` **Low severity** - Fix unsafe int cast in + `debug kill` command ([\#794](https://github.com/cometbft/cometbft/pull/794)) +- `[consensus]` **Low severity** - Avoid recursive call after rename to + `(*PeerState).MarshalJSON` + ([\#863](https://github.com/cometbft/cometbft/pull/863)) +- `[mempool/clist_mempool]` **Low severity** - Prevent a transaction from + appearing twice in the mempool + ([\#890](https://github.com/cometbft/cometbft/pull/890): @otrack) + +## v0.34.28 + +*April 26, 2023* + +This release fixes several bugs, and has had to introduce one small Go +API-breaking change in the `crypto/merkle` package in order to address what +could be a security issue for some users who directly and explicitly make use of +that code. + +### BREAKING CHANGES + +- `[crypto/merkle]` Do not allow verification of Merkle Proofs against empty trees (`nil` root). `Proof.ComputeRootHash` now panics when it encounters an error, but `Proof.Verify` does not panic + ([\#558](https://github.com/cometbft/cometbft/issues/558)) + +### BUG FIXES + +- `[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)) +- `[consensus]` Rename `(*PeerState).ToJSON` to `MarshalJSON` to fix a logging data race + ([\#524](https://github.com/cometbft/cometbft/pull/524)) +- `[light]` Fixed an edge case where a light client would panic when attempting + to query a node that (1) has started from a non-zero height and (2) does + not yet have any data. The light client will now, correctly, not panic + _and_ keep the node in its list of providers in the same way it would if + it queried a node starting from height zero that does not yet have data + ([\#575](https://github.com/cometbft/cometbft/issues/575)) + +### IMPROVEMENTS + +- `[crypto/sr25519]` Upgrade to go-schnorrkel@v1.0.0 ([\#475](https://github.com/cometbft/cometbft/issues/475)) +- `[jsonrpc/client]` Improve the error message for client errors stemming from + bad HTTP responses. + ([cometbft/cometbft\#638](https://github.com/cometbft/cometbft/pull/638)) + ## v0.34.27 *Feb 27, 2023* diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index c25964180e6..3f93f1e5e83 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,13 +1,13 @@ # The CometBFT Code of Conduct -This code of conduct applies to all projects run by the CometBFT/Cosmos team and +This code of conduct applies to all projects run by the CometBFT team and hence to CometBFT. ---- # Conduct -## Contact: conduct@interchain.io +## Contact: conduct@informal.systems * We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender, gender identity and @@ -35,7 +35,7 @@ hence to CometBFT. * Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community - member, please contact one of the channel admins or the person mentioned above + member, please get in touch with one of the channel admins or the contact address above immediately. Whether you’re a regular contributor or a newcomer, we care about making this community a safe place for you and we’ve got your back. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 812e329e679..8f53af5f174 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,76 +5,182 @@ may be helpful to understand the goal of the project. The goal of CometBFT is to develop a BFT consensus engine robust enough to support permissionless value-carrying networks. While all contributions are welcome, contributors should bear this goal in mind in deciding if they should target the main -CometBFT project or a potential fork. When targeting the main CometBFT project, -the following process leads to the best chance of landing changes in `main`. - -All work on the code base should be motivated by a [GitHub -Issue](https://github.com/cometbft/cometbft/issues). -[Search](https://github.com/cometbft/cometbft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) -is a good place to start when looking for places to contribute. If you would -like to work on an issue which already exists, please indicate so by leaving a -comment. - -All new contributions should start with a [GitHub -Issue](https://github.com/cometbft/cometbft/issues/new/choose). The issue helps -capture the problem you're trying to solve and allows for early feedback. Once -the issue is created the process can proceed in different directions depending -on how well defined the problem and potential solution are. If the change is -simple and well understood, maintainers will indicate their support with a -heartfelt emoji. +CometBFT project or a potential fork. + +## Overview + +When targeting the main CometBFT project, following the processes outlined in +this document will lead to the best chance of landing changes in a release. + +### Core team responsibility + +The CometBFT core team is responsible for stewarding this +project over time. This means that the core team needs to understand the nature +of, and agree to maintain, all of the changes that land on `main` or a backport +branch. It may cost a few days/weeks' worth of time to _submit_ a +particular change, but _maintaining_ that change over the years has a +much higher cost that the core team will bear. + +### Ease of reviewing + +The fact that the core team needs to be able to deeply understand the short-, +medium- and long-term consequences of incoming changes means that changes need +to be **easily reviewed**. + +What makes a change easy to review, and more likely to land in an upcoming +release? + +1. **Each pull request must do _one thing_**. It must be very clear what that + one thing is when looking at the pull request title, description, and linked + issues. It must also be very clear what value it ultimately aims to deliver, + and to which user(s). A single pull request that does multiple things, or + without a clear articulation of the problem it attempts to solve, may be + rejected immediately. + +2. **Each pull request must be at most 300 lines of code changes**. Larger + changes must be structured as a series of pull requests of at most 300 lines + of code changes each, each building upon the previous one, all ideally + tracked in a tracking issue. + + If a single PR absolutely has to be larger, it _must_ be structured such that + it can be reviewed commit by commit, with each commit doing _one logical + thing_ (with a good description of what it aims to achieve in the Git + commit), and each commit ideally being no larger than 300 lines of code + changes. Poorly structured pull requests may be rejected immediately with a + request to restructure them. + + This does not necessarily apply to documentation-related changes or + automatically generated code (e.g. generated from Protobuf definitions). But + automatically generated code changes should occur within separate commits, so + they are easily distinguishable from manual code changes. + +## Workflow + +The following diagram summarizes the general workflow used by the core team to +make changes, with a full description of the workflow below the diagram. +Exceptions to this process will naturally occur (e.g. in the case of urgent +security fixes), but this is rare. + +Each stage of the process is aimed at creating feedback cycles which align +contributors and maintainers to make sure: + +- Contributors don’t waste their time implementing/proposing features which + won't land in `main`. +- Maintainers have the necessary context in order to support and review + contributions. + +```mermaid +flowchart LR + complexity{Problem\ncomplexity} + issue("New issue\n(Problem articulation\nfor discussion)") + clarity{"Problem +\nsolution clarity"} + rfc("RFC pull request(s)") + rfc_merge("Merge RFC to main") + risk{"Solution\ncomplexity/risk"} + adr("ADR + PoC\npull request(s)") + adr_merge("Merge ADR to main\nand create tracking issue") + pr("Solution\npull request(s)") + merge("Merge to main/backport\nor feature branch") + + complexity --"Low/Moderate/High"--> issue + complexity --Trivial--> pr + issue --> clarity + clarity --High--> risk + clarity --Low--> rfc + rfc --Approved--> rfc_merge + risk --"Moderate/High"--> adr + adr --"ADR accepted by core team"--> adr_merge + adr_merge --> pr + risk --Low--> pr + pr --Approved--> merge +``` + +### GitHub issues + +All non-trivial work on the code base should be motivated by a [GitHub +Issue][gh-issues]. [Search][search-issues] is a good place to start when looking +for places to contribute. If you would like to work on an issue which already +exists, please indicate so by leaving a comment. If someone else is already +assigned to that issue and you would like to contribute to it or take it over, +please coordinate with the existing assignee(s) and only start work on it once +you have been assigned to it. Unsolicited pull requests relating to issues +assigned to other users may be rejected immediately. + +All new contributions should start with a [GitHub Issue][new-gh-issue]. The +issue helps capture the **problem** being solved and allows for early feedback. +Problems must be captured in terms of the **impact** that they have on specific +users. Once the issue is created the process can proceed in different directions +depending on how well defined the problem and potential solution are. If the +change is simple and well understood, maintainers will indicate their support +with a heartfelt emoji. + +### Request for comments (RFCs) If the issue would benefit from thorough discussion, maintainers may request -that you create a [Request For -Comment](https://github.com/cometbft/cometbft/tree/main/docs/rfc) in the -CometBFT repo. Discussion at the RFC stage will build collective -understanding of the dimensions of the problems and help structure conversations -around trade-offs. +that you create a [Request For Comment][rfcs] in the CometBFT repo. Discussion +at the RFC stage will build collective understanding of the dimensions of the +problems and help structure conversations around trade-offs. -When the problem is well understood but the solution leads to large structural -changes to the code base, these changes should be proposed in the form of an -[Architectural Decision Record (ADR)](./docs/architecture/). The ADR will help -build consensus on an overall strategy to ensure the code base maintains -coherence in the larger context. If you are not comfortable with writing an ADR, -you can open a less-formal issue and the maintainers will help you turn it into -an ADR. +### Architecture decision records (ADRs) -> How to pick a number for the ADR? +When the problem is well understood but the solution leads to +large/complex/risky structural changes to the code base, these changes should be +proposed in the form of an [Architectural Decision Record +(ADR)](docs/references/architecture/). The ADR will help build consensus on an overall +strategy to ensure the code base maintains coherence in the larger context. If +you are not comfortable with writing an ADR, you can open a less-formal issue +and the maintainers will help you turn it into an ADR. Sometimes the best way to +demonstrate the value of an ADR is to build a proof-of-concept (PoC) along with +the ADR - in this case, link to the PoC from the ADR PR. -Find the largest existing ADR number and bump it by 1. +**How does one pick a number for an new ADR?** -When the problem as well as proposed solution are well understood, -changes should start with a [draft -pull request](https://github.blog/2019-02-14-introducing-draft-pull-requests/) -against `main`. The draft signals that work is underway. When the work -is ready for feedback, hitting "Ready for Review" will signal to the -maintainers to take a look. +Find the largest existing ADR number (between those in `./docs/architecture/` +and those that may be open as issues or pull requests) and bump it by 1. -![Contributing flow](./docs/imgs/contributing.png) +### Pull requests -Each stage of the process is aimed at creating feedback cycles which align contributors and maintainers to make sure: +When the problem as well as proposed solution are well understood and low-risk, +changes should start with a **pull request**. -- Contributors don’t waste their time implementing/proposing features which won’t land in `main`. -- Maintainers have the necessary context in order to support and review contributions. +Please adhere to the guidelines in the [Ease of reviewing](#ease-of-reviewing) +section above when submitting pull requests. +### Draft pull requests + +One can optionally submit a [draft pull request][gh-draft-prs] against `main`, +in which case this signals that work is underway and is not ready for review. +Only users that are familiar with the issue, or those that the author explicitly +requested a review from are expected to write comments at this point. When the +work is ready for feedback, hitting "Ready for Review" will signal to the +maintainers to take a look, and to the rest of the community that feedback is +welcome. + +**The team may opt to ignore unsolicited comments/feedback on draft PRs**, as +having to respond to feedback on work that is not marked as "Ready for Review" +interferes with the process of getting the work to the point that it is ready to +review. ## Forking -Please note that Go requires code to live under absolute paths, which complicates forking. -While my fork lives at `https://github.com/ebuchman/cometbft`, -the code should never exist at `$GOPATH/src/github.com/ebuchman/cometbft`. -Instead, we use `git remote` to add the fork as a new remote for the original repo, +Please note that Go requires code to live under absolute paths, which +complicates forking. While my fork lives at +`https://github.com/ebuchman/cometbft`, the code should never exist at +`$GOPATH/src/github.com/ebuchman/cometbft`. Instead, we use `git remote` to add +the fork as a new remote for the original repo, `$GOPATH/src/github.com/cometbft/cometbft`, and do all the work there. For instance, to create a fork and work on a branch of it, I would: - Create the fork on GitHub, using the fork button. -- Go to the original repo checked out locally (i.e. `$GOPATH/src/github.com/cometbft/cometbft`) +- Go to the original repo checked out locally (i.e. + `$GOPATH/src/github.com/cometbft/cometbft`) - `git remote rename origin upstream` - `git remote add origin git@github.com:ebuchman/basecoin.git` -Now `origin` refers to my fork and `upstream` refers to the CometBFT version. -So I can `git push -u origin main` to update my fork, and make pull requests to CometBFT from there. -Of course, replace `ebuchman` with your git handle. +Now `origin` refers to my fork and `upstream` refers to the CometBFT version. So +I can `git push -u origin main` to update my fork, and make pull requests to +CometBFT from there. Of course, replace `ebuchman` with your git handle. To pull in updates from the origin repo, run @@ -83,34 +189,133 @@ To pull in updates from the origin repo, run ## Dependencies -We use [go modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. +We use [Go modules] to manage dependencies. -That said, the `main` branch of every CometBFT repository should just build -with `go get`, which means they should be kept up-to-date with their -dependencies so we can get away with telling people they can just `go get` our -software. +That said, the `main` branch of every CometBFT repository should just build with +`go get`, which means they should be kept up-to-date with their dependencies so +we can get away with telling people they can just `go get` our software. Since some dependencies are not under our control, a third party may break our -build, in which case we can fall back on `go mod tidy`. Even for dependencies under our control, go helps us to -keep multiple repos in sync as they evolve. Anything with an executable, such -as apps, tools, and the core, should use dep. +build, in which case we can fall back on `go mod tidy`. Even for dependencies +under our control, go helps us to keep multiple repos in sync as they evolve. +Anything with an executable, such as apps, tools, and the core, should use dep. Run `go list -u -m all` to get a list of dependencies that may not be up-to-date. When updating dependencies, please only update the particular dependencies you -need. Instead of running `go get -u=patch`, which will update anything, -specify exactly the dependency you want to update. +need. Instead of running `go get -u=patch`, which will update anything, specify +exactly the dependency you want to update. + +## Logging + +Operators, consensus engine and application developers all need information from +the system while it is running. One avenue through which they get that +information is via the logs. Whenever making contributions, please think +carefully about what each of those groups of users would want to know about the +operation of the system and try to adhere to the following guidelines as far as +reasonably possible. + +### To log, or not to log + +Whether or not to log something at all should take into consideration how +frequently the log message will appear. Users hate being spammed by large +quantities of useless log messages. If you anticipate that a particular log +message will occur frequently (e.g. a few times per minute), try to find ways to +either eliminate that message or reduce its frequency (e.g. only logging every +Nth message, or a summary message every minute or hour). + +### Log levels + +Different log levels should target different groups of users. At present, only +**Debug**, **Info** and **Error** levels are supported. + +- **Debug**: Should primarily target consensus engine developers (i.e. core team + members and developers working on CometBFT forks). +- **Info** and **Error**: Should primarily target operators and application + developers. + +### Sensitive information + +It should go without saying, but sensitive information (passwords/tokens, +private keys, etc.) should **never** be logged. If one needs to inspect such +information while debugging, rather use a [debugger][delve] or even a +_temporary_ `fmt.Printf` statement. + +The logging infrastructure in CometBFT does not automatically scrub such +sensitive information from the logs, so it is up to developers to ensure that +they do not log such information. + +### Log messages + +Log messages should always be tailored to the intended target audience. Unlike +Go errors, **log messages must have the first letter of the message +capitalized**. Only _errors_ in Go should start with a lowercase letter because +they may end up being chained/embedded, but log messages are not chained in this +same way. + +### Logging parameters + +In general, log messages should contain the **bare minimum** amount of +information for those messages to be actionable by the target audience. So +instead of dumping large quantities of raw data into the logs (e.g. RPC +responses, transactions, block data), include lightweight references to the data +that users can go look up via the RPC, CLI tools, etc. if they are genuinely +interested in the details. + +When outputting variables, also keep in mind **concurrency concerns** of doing +so. If outputting a pointer, understand that the value associated with that +pointer at the time of calling the log function may differ to its value at the +time it is finally serialized into the log message. Perhaps consider creating a +temporary copy of the specific value you want to output and logging that +temporary value. Also keep in mind potential data races when doing so. + +Finally, **use expensive operations like `fmt.Sprintf` sparingly**, as this can +have a meaningful performance impact on a running production system. Consider an +example where one may call `fmt.Sprintf` when logging something at **debug** +level: even though an operator has configured their system to only log at +**info** level and above, the expensive `fmt.Sprintf` calls will still take +place, potentially slowing the system down. In such instances, consider printing +values [lazily][log-lazy]. + +### Examples of good log messages + +```golang +// Operators generally wouldn't care whether an internal construct, like module +// construction, has executed successfully. +logger.Debug("Starting reactor", "module", "consensus") + +logger.Info("Committed block", "height", height, "appHash", appHash) + +// Include information about the error. +logger.Error("Failed to execute important operation", "err", err) +``` + +### Examples of bad log messages + +```golang +// Message starts with a lowercase letter, and will probably be called very +// frequently, effectively spamming operators. +logger.Info("connected to peer", "peerID", peerID) + +// Potentially prints huge quantities of data (unnecessary) in a single message, +// and at info level, spamming operators. +logger.Info("Committed block", "block", fmt.Sprintf("%v", block)) + +// Just as bad as the info-level message above because the (expensive) +// fmt.Sprintf is always called, regardless of the operator's configured log +// level, potentially creating a meaningful performance hit. +logger.Debug("Committed block", "block", fmt.Sprintf("%v", block)) +``` ## Protobuf -We use [Protocol Buffers](https://developers.google.com/protocol-buffers) along -with [`gogoproto`](https://github.com/cosmos/gogoproto) to generate code for use +We use [Protocol Buffers] along with [`gogoproto`] to generate code for use across CometBFT. To generate proto stubs, lint, and check protos for breaking changes, you will -need to install [buf](https://buf.build/) and `gogoproto`. Then, from the root -of the repository, run: +need to install [buf] and `gogoproto`. Then, from the root of the repository, +run: ```bash # Lint all of the .proto files @@ -124,9 +329,8 @@ make proto-check-breaking make proto-gen ``` -To automatically format `.proto` files, you will need -[`clang-format`](https://clang.llvm.org/docs/ClangFormat.html) installed. Once -installed, you can run: +To automatically format `.proto` files, you will need [`clang-format`] +installed. Once installed, you can run: ```bash make proto-format @@ -134,7 +338,8 @@ make proto-format ### Visual Studio Code -If you are a VS Code user, you may want to add the following to your `.vscode/settings.json`: +If you are a VS Code user, you may want to add the following to your +`.vscode/settings.json`: ```json { @@ -148,12 +353,13 @@ If you are a VS Code user, you may want to add the following to your `.vscode/se ## Changelog -To manage and generate our changelog, we currently use [unclog](https://github.com/informalsystems/unclog). +To manage and generate our changelog, we currently use [unclog]. Every fix, improvement, feature, or breaking change should be made in a pull-request that includes a file `.changelog/unreleased/${category}/${issue-or-pr-number}-${description}.md`, where: + - `category` is one of `improvements`, `breaking-changes`, `bug-fixes`, `features` and if multiple apply, create multiple files; - `description` is a short (4 to 6 word), hyphen separated description of the @@ -176,20 +382,23 @@ title of the PR _very_ clearly explains the benefit of a change to a user. Some good examples of changelog entry descriptions: ```md -- [consensus] \#1111 Small transaction throughput improvement (approximately - 3-5\% from preliminary tests) through refactoring the way we use channels -- [mempool] \#1112 Refactor Go API to be able to easily swap out the current - mempool implementation in CometBFT forks -- [p2p] \#1113 Automatically ban peers when their messages are unsolicited or - are received too frequently +- `[consensus]` Small transaction throughput improvement (approximately 3-5\% + from preliminary tests) through refactoring the way we use channels + ([\#1111](https://github.com/cometbft/cometbft/issues/1111)) +- `[mempool]` Refactor Go API to be able to easily swap out the current mempool + implementation in CometBFT forks + ([\#1112](https://github.com/cometbft/cometbft/issues/1112)) +- `[p2p]` Automatically ban peers when their messages are unsolicited or are + received too frequently + ([\#1113](https://github.com/cometbft/cometbft/issues/1113)) ``` Some bad examples of changelog entry descriptions: ```md -- [consensus] \#1111 Refactor channel usage -- [mempool] \#1112 Make API generic -- [p2p] \#1113 Ban for PEX message abuse +- `[consensus]` Refactor channel usage +- `[mempool]` Make API generic +- `[p2p]` Ban for PEX message abuse ``` For more on how to write good changelog entries, see: @@ -203,24 +412,24 @@ For more on how to write good changelog entries, see: Changelog entries should be formatted as follows: ```md -- [module] \#xxx Some description of the change (@contributor) +- `[module]` Some description of the change + ([\#1234](https://github.com/cometbft/cometbft/issues/1234): @contributor) ``` Here, `module` is the part of the code that changed (typically a top-level Go -package), `xxx` is the pull-request number, and `contributor` is the author/s of -the change. +package), `1234` is the pull-request number, and `contributor` is the author/s +of the change (only necessary if you are not a member of the CometBFT core +team). -It's also acceptable for `xxx` to refer to the relevant issue number, but +It's also acceptable for `1234` to refer to the relevant issue number, but pull-request numbers are preferred. Note this means pull-requests should be opened first so the changelog can then be updated with the pull-request's -number. There is no need to include the full link, as this will be added -automatically during release. But please include the backslash and pound, eg. -`\#2313`. +number. Changelog entries should be ordered alphabetically according to the `module`, and numerically according to the pull-request number. -Changes with multiple classifications should be doubly included (eg. a bug fix +Changes with multiple classifications should be doubly included (e.g. a bug fix that is also a breaking change should be recorded under both). Breaking changes are further subdivided according to the APIs/users they impact. @@ -233,7 +442,8 @@ removed from the header in RPC responses as well. The main development branch is `main`. -Every release is maintained in a release branch named `vX.Y.Z`. +Every release is maintained in a release branch named according to its major +release number (e.g. `v0.38.x` or `v1.x`). Pending minor releases have long-lived release candidate ("RC") branches. Minor release changes should be merged to these long-lived RC branches at the same @@ -248,8 +458,8 @@ the feature is complete, the feature branch is merged back (merge commit) into different features in different releases. Note, all pull requests should be squash merged except for merging to a release -branch (named `vX.Y`). This keeps the commit history clean and makes it easy to -reference the pull request where a change was introduced. +branch. This keeps the commit history clean and makes it easy to reference the +pull request where a change was introduced. ### Development Procedure @@ -275,6 +485,29 @@ means that you shouldn't update someone else's branch for them; even if it seems like you're doing them a favor, you may be interfering with their git flow in some way!) +### Formatting & Linting + +When submitting a change, please make sure to: + +1. Format the code using [gofumpt](https://github.com/mvdan/gofumpt) +2. Lint the code using [golangci-lint](https://golangci-lint.run/) +3. Check the code and docs for spelling errors using [codespell](https://github.com/codespell-project/codespell). + +It's recommended to install a Git pre-commit hook: `make pre-commit`. The hook will +automatically run the above steps for you every time you commit something. You +can also do this manually with `make lint`. + +The pre-commit hook uses [the pre-commit framework](https://pre-commit.com/). +If you have Python 3 installed, you don't need to do anything else. Otherwise, +please refer to [the installation guide](https://pre-commit.com/#install). + +In rare cases, you may want to skip the pre-commit hook. You can do so by adding +`-n` (or `--no-verify`) flag to `git commit`: + +```bash +git commit -n -m "add X" +``` + #### Merging Pull Requests It is also our convention that authors merge their own pull requests, when @@ -287,43 +520,28 @@ Before merging a pull request: - Ensure pull branch is up-to-date with a recent `main` (GitHub won't let you merge without this!) - Run `make test` to ensure that all tests pass -- [Squash](https://stackoverflow.com/questions/5189560/squash-my-last-x-commits-together-using-git) - merge pull request - -#### Pull Requests for Minor Releases +- [Squash][git-squash] merge pull request -If your change should be included in a minor release, please also open a PR -against the long-lived minor release candidate branch (e.g., `rc1/v0.33.5`) -_immediately after your change has been merged to main_. - -You can do this by cherry-picking your commit off `main`: - -```sh -$ git checkout rc1/v0.33.5 -$ git checkout -b {new branch name} -$ git cherry-pick {commit SHA from main} -# may need to fix conflicts, and then use git add and git cherry-pick --continue -$ git push origin {new branch name} -``` +### Git Commit Style -After this, you can open a PR. Please note in the PR body if there were merge -conflicts so that reviewers can be sure to take a thorough look. +We follow the [Conventional Commits][conventional-commits] spec. Write concise +commits that start with a type (`fix`, `feat`, `chore`, `ci`, `docs`, etc.) and +an optional scope - package name (e.g., `feat(internal/consensus)`), followed +by a description that finishes the sentence "This change modifies CometBFT +to...". -### Git Commit Style +If the commit introduces a breaking change, append the `!` after the scope +(e.g., `feat(internal/consensus)!`). -We follow the [Go style guide on commit -messages](https://tip.golang.org/doc/contribute.html#commit_messages). Write -concise commits that start with the package name and have a description that -finishes the sentence "This change modifies CometBFT to...". For example, +For example, ```sh -cmd/debug: execute p.Signal only when p is not nil +fix(cmd/cometbft/commands/debug): execute p.Signal only when p is not nil [potentially longer description in the body] Fixes #nnnn ``` - Each PR should have one commit once it lands on `main`; this can be accomplished by using the "squash and merge" button on GitHub. Be sure to edit your commit message, though! @@ -333,15 +551,15 @@ message, though! ### Unit tests Unit tests are located in `_test.go` files as directed by [the Go testing -package](https://golang.org/pkg/testing/). If you're adding or removing a -function, please check there's a `TestType_Method` test for it. +package][go-testing]. If you're adding or removing a function, please check +there's a `TestType_Method` test for it. Run: `make test` ### Integration tests -Integration tests are also located in `_test.go` files. What differentiates -them is a more complicated setup, which usually involves setting up two or more +Integration tests are also located in `_test.go` files. What differentiates them +is a more complicated setup, which usually involves setting up two or more components. Run: `make test_integrations` @@ -365,26 +583,30 @@ cd test/e2e && \ *NOTE: if you're just submitting your first PR, you won't need to touch these most probably (99.9%)*. -[Fuzz tests](https://en.wikipedia.org/wiki/Fuzzing) can be found inside the -`./test/fuzz` directory. See [README.md](./test/fuzz/README.md) for details. +[Fuzz tests] can be found inside the `./test/fuzz` directory. See +[README.md](./test/fuzz/README.md) for details. Run: `cd test/fuzz && make fuzz-{PACKAGE-COMPONENT}` ### RPC Testing -**If you contribute to the RPC endpoints it's important to document your -changes in the [Openapi file](./rpc/openapi/openapi.yaml)**. - -To test your changes you must install `nodejs` and run: - -```bash -npm i -g dredd -make build-linux build-contract-tests-hooks -make contract-tests -``` - -**WARNING: these are currently broken due to -not supporting complete OpenAPI 3**. - -This command will popup a network and check every endpoint against what has -been documented. +**If you contribute to the RPC endpoints it's important to document your changes +in the [OpenAPI file](./rpc/openapi/openapi.yaml)**. + +[gh-issues]: https://github.com/cometbft/cometbft/issues +[search-issues]: https://github.com/cometbft/cometbft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22 +[new-gh-issue]: https://github.com/cometbft/cometbft/issues/new/choose +[rfcs]: https://github.com/cometbft/cometbft/tree/main/docs/rfc +[gh-draft-prs]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ +[Go modules]: https://github.com/golang/go/wiki/Modules +[Protocol Buffers]: https://protobuf.dev/ +[`gogoproto`]: https://github.com/cosmos/gogoproto +[buf]: https://buf.build/ +[`clang-format`]: https://clang.llvm.org/docs/ClangFormat.html +[unclog]: https://github.com/informalsystems/unclog +[git-squash]: https://stackoverflow.com/questions/5189560/squash-my-last-x-commits-together-using-git +[go-testing]: https://golang.org/pkg/testing/ +[Fuzz tests]: https://en.wikipedia.org/wiki/Fuzzing +[delve]: https://github.com/go-delve/delve +[log-lazy]: https://github.com/cometbft/cometbft/blob/main/libs/log/lazy.go +[conventional-commits]: https://www.conventionalcommits.org/en/v1.0.0/ diff --git a/DOCKER/Dockerfile b/DOCKER/Dockerfile index cf997137572..55931c348d0 100644 --- a/DOCKER/Dockerfile +++ b/DOCKER/Dockerfile @@ -1,6 +1,6 @@ # Use a build arg to ensure that both stages use the same, # hopefully current, go version. -ARG GOLANG_BASE_IMAGE=golang:1.20-alpine +ARG GOLANG_BASE_IMAGE=golang:1.22-alpine # stage 1 Generate CometBFT Binary FROM --platform=$BUILDPLATFORM $GOLANG_BASE_IMAGE as builder diff --git a/DOCKER/Dockerfile.build_c-amazonlinux b/DOCKER/Dockerfile.build_c-amazonlinux deleted file mode 100644 index 633b2a99775..00000000000 --- a/DOCKER/Dockerfile.build_c-amazonlinux +++ /dev/null @@ -1,28 +0,0 @@ -FROM amazonlinux:2 - -RUN yum -y update && \ - yum -y install wget - -RUN wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && \ - rpm -ivh epel-release-latest-7.noarch.rpm - -RUN yum -y groupinstall "Development Tools" -RUN yum -y install leveldb-devel which - -ENV GOVERSION=1.12.9 - -RUN cd /tmp && \ - wget https://dl.google.com/go/go${GOVERSION}.linux-amd64.tar.gz && \ - tar -C /usr/local -xf go${GOVERSION}.linux-amd64.tar.gz && \ - mkdir -p /go/src && \ - mkdir -p /go/bin - -ENV PATH=$PATH:/usr/local/go/bin:/go/bin -ENV GOBIN=/go/bin -ENV GOPATH=/go/src - -RUN mkdir -p /cometbft -WORKDIR /cometbft - -CMD ["/usr/bin/make", "build", "COMETBFT_BUILD_OPTIONS=cleveldb"] - diff --git a/DOCKER/Makefile b/DOCKER/Makefile index 103d70c4d08..0bf457e7a4d 100644 --- a/DOCKER/Makefile +++ b/DOCKER/Makefile @@ -7,7 +7,4 @@ push: build_testing: docker build --tag cometbft/testing -f ./Dockerfile.testing . -build_amazonlinux_buildimage: - docker build -t "cometbft/cometbft:build_c-amazonlinux" -f Dockerfile.build_c-amazonlinux . - -.PHONY: build push build_testing build_amazonlinux_buildimage +.PHONY: build push build_testing diff --git a/DOCKER/README.md b/DOCKER/README.md index 21f3dd2000b..9d052842da2 100644 --- a/DOCKER/README.md +++ b/DOCKER/README.md @@ -22,7 +22,7 @@ CometBFT is Byzantine Fault Tolerant (BFT) middleware that takes a state transit For more background, see the [the docs](https://docs.cometbft.com/main/introduction/#quick-start). -To get started developing applications, see the [application developers guide](https://docs.cometbft.com/main/introduction/quick-start.html). +To get started developing applications, see the [application developers guide](https://docs.cometbft.com/main/guides/quick-start.html). ## How to use this image diff --git a/DOCKER/build.sh b/DOCKER/build.sh index 3d8a6a01b97..35eb27d7032 100755 --- a/DOCKER/build.sh +++ b/DOCKER/build.sh @@ -3,7 +3,7 @@ set -e # Get the tag from the version, or try to figure it out. if [ -z "$TAG" ]; then - TAG=$(awk -F\" '/TMCoreSemVer =/ { print $2; exit }' < ../version/version.go) + TAG=$(awk -F\" '/CMTSemVer =/ { print $2; exit }' < ../version/version.go) fi if [ -z "$TAG" ]; then echo "Please specify a tag." diff --git a/DOCKER/push.sh b/DOCKER/push.sh index 3ceeeeba958..6948c6761ef 100755 --- a/DOCKER/push.sh +++ b/DOCKER/push.sh @@ -3,7 +3,7 @@ set -e # Get the tag from the version, or try to figure it out. if [ -z "$TAG" ]; then - TAG=$(awk -F\" '/TMCoreSemVer =/ { print $2; exit }' < ../version/version.go) + TAG=$(awk -F\" '/CMTSemVer =/ { print $2; exit }' < ../version/version.go) fi if [ -z "$TAG" ]; then echo "Please specify a tag." diff --git a/Makefile b/Makefile index 0d63f4a8dc4..605c8ef5956 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ OUTPUT?=$(BUILDDIR)/cometbft HTTPS_GIT := https://github.com/cometbft/cometbft.git CGO_ENABLED ?= 0 -# Process Docker environment varible TARGETPLATFORM +# Process Docker environment variable TARGETPLATFORM # in order to build binary with correspondent ARCH # by default will always build for linux/amd64 TARGETPLATFORM ?= @@ -68,6 +68,7 @@ ifeq (linux/riscv64,$(findstring linux/riscv64,$(TARGETPLATFORM))) GOARCH=riscv64 endif +#? all: Run target check, build, test and install all: check build test install .PHONY: all @@ -77,18 +78,21 @@ include tests.mk ### Build CometBFT ### ############################################################################### +#? build: Build CometBFT build: CGO_ENABLED=$(CGO_ENABLED) go build $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o $(OUTPUT) ./cmd/cometbft/ .PHONY: build +#? install: Install CometBFT to GOBIN install: - CGO_ENABLED=$(CGO_ENABLED) go install $(BUILD_FLAGS) -tags $(BUILD_TAGS) ./cmd/cometbft + CGO_ENABLED=$(CGO_ENABLED) go install $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' ./cmd/cometbft .PHONY: install ############################################################################### ### Metrics ### ############################################################################### +#? metrics: Generate metrics metrics: testdata-metrics go generate -run="scripts/metricsgen" ./... .PHONY: metrics @@ -96,6 +100,7 @@ metrics: testdata-metrics # By convention, the go tool ignores subdirectories of directories named # 'testdata'. This command invokes the generate command on the folder directly # to avoid this. +#? testdata-metrics: Generate test data for metrics testdata-metrics: ls ./scripts/metricsgen/testdata | xargs -I{} go generate -v -run="scripts/metricsgen" ./scripts/metricsgen/testdata/{} .PHONY: testdata-metrics @@ -104,6 +109,7 @@ testdata-metrics: ### Mocks ### ############################################################################### +#? mockery: Generate test mocks mockery: go generate -run="./scripts/mockery_generate.sh" ./... .PHONY: mockery @@ -112,57 +118,64 @@ mockery: ### Protobuf ### ############################################################################### +#? check-proto-deps: Check protobuf deps check-proto-deps: -ifeq (,$(shell which protoc-gen-gogofaster)) - @go install github.com/cosmos/gogoproto/protoc-gen-gogofaster@latest +ifeq (,$(shell which protoc-gen-gocosmos)) + @go install github.com/cosmos/gogoproto/protoc-gen-gocosmos@latest endif .PHONY: check-proto-deps +#? check-proto-format-deps: Check protobuf format deps check-proto-format-deps: ifeq (,$(shell which clang-format)) $(error "clang-format is required for Protobuf formatting. See instructions for your platform on how to install it.") endif .PHONY: check-proto-format-deps +#? proto-gen: Generate protobuf files proto-gen: check-proto-deps @echo "Generating Protobuf files" - @go run github.com/bufbuild/buf/cmd/buf generate - @mv ./proto/tendermint/abci/types.pb.go ./abci/types/ - @cp ./proto/tendermint/rpc/grpc/types.pb.go ./rpc/grpc + @go run github.com/bufbuild/buf/cmd/buf@latest generate --path proto/cometbft .PHONY: proto-gen # These targets are provided for convenience and are intended for local # execution only. +#? proto-lint: Lint protobuf files proto-lint: check-proto-deps @echo "Linting Protobuf files" - @go run github.com/bufbuild/buf/cmd/buf lint + @go run github.com/bufbuild/buf/cmd/buf@latest lint .PHONY: proto-lint +#? proto-format: Format protobuf files proto-format: check-proto-format-deps @echo "Formatting Protobuf files" @find . -name '*.proto' -path "./proto/*" -exec clang-format -i {} \; .PHONY: proto-format +#? proto-check-breaking: Check for breaking changes in Protobuf files against local branch. This is only useful if your changes have not yet been committed proto-check-breaking: check-proto-deps @echo "Checking for breaking changes in Protobuf files against local branch" @echo "Note: This is only useful if your changes have not yet been committed." @echo " Otherwise read up on buf's \"breaking\" command usage:" @echo " https://docs.buf.build/breaking/usage" - @go run github.com/bufbuild/buf/cmd/buf breaking --against ".git" + @go run github.com/bufbuild/buf/cmd/buf@latest breaking --against ".git" .PHONY: proto-check-breaking +#? proto-check-breaking-ci: Check for breaking changes in Protobuf files against v0.34.x. This is only useful if your changes have not yet been committed proto-check-breaking-ci: - @go run github.com/bufbuild/buf/cmd/buf breaking --against $(HTTPS_GIT)#branch=v0.34.x + @go run github.com/bufbuild/buf/cmd/buf@latest breaking --against $(HTTPS_GIT)#branch=v0.34.x .PHONY: proto-check-breaking-ci ############################################################################### ### Build ABCI ### ############################################################################### +#? build_abci: Build abci build_abci: @go build -mod=readonly -i ./abci/cmd/... .PHONY: build_abci +#? install_abci: Install abci install_abci: @go install -mod=readonly ./abci/cmd/... .PHONY: install_abci @@ -173,20 +186,25 @@ install_abci: # dist builds binaries for all platforms and packages them for distribution # TODO add abci to these scripts +#? dist: Build binaries for all platforms and package them for distribution dist: @BUILD_TAGS=$(BUILD_TAGS) sh -c "'$(CURDIR)/scripts/dist.sh'" .PHONY: dist +#? go-mod-cache: Download go modules to local cache go-mod-cache: go.sum @echo "--> Download go modules to local cache" @go mod download .PHONY: go-mod-cache +#? go.sum: Ensure dependencies have not been modified go.sum: go.mod @echo "--> Ensure dependencies have not been modified" @go mod verify @go mod tidy +.PHONY: go.sum +#? draw_deps: Generate deps graph draw_deps: @# requires brew install graphviz or apt-get install graphviz go get github.com/RobotsAndPencils/goviz @@ -204,7 +222,7 @@ get_deps_bin_size: ### Libs ### ############################################################################### -# generates certificates for TLS testing in remotedb and RPC server +#? gen_certs: Generate certificates for TLS testing in remotedb and RPC server gen_certs: clean_certs certstrap init --common-name "cometbft.com" --passphrase "" certstrap request-cert --common-name "server" -ip "127.0.0.1" --passphrase "" @@ -214,7 +232,7 @@ gen_certs: clean_certs rm -rf out .PHONY: gen_certs -# deletes generated certificates +#? clean_certs: Delete generated certificates clean_certs: rm -f rpc/jsonrpc/server/test.crt rm -f rpc/jsonrpc/server/test.key @@ -224,20 +242,22 @@ clean_certs: ### Formatting, linting, and vetting ### ############################################################################### -format: - find . -name '*.go' -type f -not -path "*.git*" -not -name '*.pb.go' -not -name '*pb_test.go' | xargs gofmt -w -s - find . -name '*.go' -type f -not -path "*.git*" -not -name '*.pb.go' -not -name '*pb_test.go' | xargs goimports -w -local github.com/cometbft/cometbft -.PHONY: format - -lint: - @echo "--> Running linter" - @go run github.com/golangci/golangci-lint/cmd/golangci-lint run +#? lint: Lint, format and fix typos +lint: pre-commit + @pre-commit run .PHONY: lint +#? vulncheck: Run latest govulncheck vulncheck: @go run golang.org/x/vuln/cmd/govulncheck@latest ./... .PHONY: vulncheck +#? pre-commit: Create pre-commit hook using the pre-commit framework. +pre-commit: + @which pre-commit || pip3 install pre-commit + @pre-commit install +.PHONY: pre-commit + DESTINATION = ./index.html.md @@ -245,7 +265,7 @@ DESTINATION = ./index.html.md ### Documentation ### ############################################################################### -# Verify that important design docs have ToC entries. +#? check-docs-toc: Verify that important design docs have ToC entries. check-docs-toc: @./docs/presubmit.sh .PHONY: check-docs-toc @@ -256,6 +276,7 @@ check-docs-toc: # On Linux, you may need to run `DOCKER_BUILDKIT=1 make build-docker` for this # to work. +#? build-docker: Build docker image cometbft/cometbft build-docker: docker build \ --label=cometbft \ @@ -267,35 +288,37 @@ build-docker: ### Local testnet using docker ### ############################################################################### -# Build linux binary on other platforms +#? build-linux: Build linux binary on other platforms build-linux: GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) $(MAKE) build .PHONY: build-linux +#? build-docker-localnode: Build the "localnode" docker image build-docker-localnode: @cd networks/local && make .PHONY: build-docker-localnode -# Runs `make build COMETBFT_BUILD_OPTIONS=cleveldb` from within an Amazon -# Linux (v2)-based Docker build container in order to build an Amazon -# Linux-compatible binary. Produces a compatible binary at ./build/cometbft -build_c-amazonlinux: - $(MAKE) -C ./DOCKER build_amazonlinux_buildimage - docker run --rm -it -v `pwd`:/cometbft cometbft/cometbft:build_c-amazonlinux -.PHONY: build_c-amazonlinux -# Run a 4-node testnet locally +#? localnet-start: Run a 4-node testnet locally localnet-start: localnet-stop build-docker-localnode @if ! [ -f build/node0/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/cometbft:Z cometbft/localnode testnet --config /etc/cometbft/config-template.toml --o . --starting-ip-address 192.167.10.2; fi - docker-compose up + docker-compose up -d .PHONY: localnet-start -# Stop testnet +#? localnet-stop: Stop testnet localnet-stop: docker-compose down .PHONY: localnet-stop -# Build hooks for dredd, to skip or add information on some steps +#? monitoring-start: Start Prometheus and Grafana servers for localnet monitoring +monitoring-start: + cd test/monitoring && docker-compose up -d + +#? monitoring-stop: Stop the Prometheus and Grafana servers +monitoring-stop: + cd test/monitoring && docker-compose down + +#? build-contract-tests-hooks: Build hooks for dredd, to skip or add information on some steps build-contract-tests-hooks: ifeq ($(OS),Windows_NT) go build -mod=readonly $(BUILD_FLAGS) -o build/contract_tests.exe ./cmd/contract_tests @@ -304,9 +327,9 @@ else endif .PHONY: build-contract-tests-hooks -# Run a nodejs tool to test endpoints against a localnet +#? contract-tests: Run a nodejs tool to test endpoints against a localnet # The command takes care of starting and stopping the network -# prerequisits: build-contract-tests-hooks build-linux +# prerequisites: build-contract-tests-hooks build-linux # the two build commands were not added to let this command run from generic containers or machines. # The binaries should be built beforehand contract-tests: @@ -333,4 +356,10 @@ $(BUILDDIR)/packages.txt:$(GO_TEST_FILES) $(BUILDDIR) split-test-packages:$(BUILDDIR)/packages.txt split -d -n l/$(NUM_SPLIT) $< $<. test-group-%:split-test-packages - cat $(BUILDDIR)/packages.txt.$* | xargs go test -mod=readonly -timeout=15m -race -coverprofile=$(BUILDDIR)/$*.profile.out + cat $(BUILDDIR)/packages.txt.$* | xargs go test -mod=readonly -timeout=400s -race -coverprofile=$(BUILDDIR)/$*.profile.out + +#? help: Get more info on make commands. +help: Makefile + @echo " Choose a command run in comebft:" + @sed -n 's/^#?//p' $< | column -t -s ':' | sort | sed -e 's/^/ /' +.PHONY: help diff --git a/README.md b/README.md index 2d39be1faa3..97917afa341 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,13 @@ [![License][license-badge]][license-url] [![Sourcegraph][sg-badge]][sg-url] -| Branch | Tests | Linting | -|---------|------------------------------------------|---------------------------------------| -| main | [![Tests][tests-badge]][tests-url] | [![Lint][lint-badge]][lint-url] | -| v0.37.x | [![Tests][tests-badge-v037x]][tests-url] | [![Lint][lint-badge-v037x]][lint-url] | -| v0.34.x | [![Tests][tests-badge-v034x]][tests-url] | [![Lint][lint-badge-v034x]][lint-url] | +| Branch | Tests | Linting | +|---------|------------------------------------------------|---------------------------------------------| +| main | [![Tests][tests-badge]][tests-url] | [![Lint][lint-badge]][lint-url] | +| v1.x | [![Tests][tests-badge-v1x]][tests-url-v1x] | [![Lint][lint-badge-v1x]][lint-url-v1x] | +| v0.38.x | [![Tests][tests-badge-v038x]][tests-url-v038x] | [![Lint][lint-badge-v038x]][lint-url-v038x] | +| v0.37.x | [![Tests][tests-badge-v037x]][tests-url-v037x] | [![Lint][lint-badge-v037x]][lint-url-v037x] | +| v0.34.x | [![Tests][tests-badge-v034x]][tests-url-v034x] | [![Lint][lint-badge-v034x]][lint-url-v034x] | CometBFT is a Byzantine Fault Tolerant (BFT) middleware that takes a state transition machine - written in any programming language - and securely @@ -36,42 +38,44 @@ Complete documentation can be found on the ## Releases -Please do not depend on `main` as your production branch. Use +Please do not depend on `main` as your production branch, as it may receive +significant breaking changes at any time. Use [releases](https://github.com/cometbft/cometbft/releases) instead. -We haven't released v1.0 yet -since we are making breaking changes to the protocol and the APIs. See below for -more details about [versioning](#versioning). +If you intend to run CometBFT in production, we're happy to help. To contact us, +in order of preference: -In any case, if you intend to run CometBFT in production, we're happy to help. - -To contact us, you can also -[join the chat](https://discord.com/channels/669268347736686612/669283915743232011). +- [Create a new discussion on + GitHub](https://github.com/cometbft/cometbft/discussions) +- Reach out to us via [Telegram](https://t.me/CometBFT) +- [Join the Cosmos Network Discord](https://discord.gg/cosmosnetwork) and + discuss in + [`#cometbft`](https://discord.com/channels/669268347736686612/1069933855307472906) More on how releases are conducted can be found [here](./RELEASES.md). ## Security -To report a security vulnerability, see our [bug bounty -program](https://hackerone.com/cosmos). For examples of the kinds of bugs we're -looking for, see [our security policy](SECURITY.md). +Please see [SECURITY.md](./SECURITY.md). ## Minimum requirements -| CometBFT version | Requirement | Notes | -|------------------|-------------|-------------------| -| 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 | +| CometBFT version | Requirement | Version | Tested with | +|------------------|-------------|----------------|-------------| +| main | Go version | 1.22 or higher | 1.22 | +| v1.x | Go version | 1.22 or higher | 1.22 | +| v0.38.x | Go version | 1.21 or higher | 1.22 | +| v0.37.x | Go version | 1.20 or higher | 1.22 | +| v0.34.x | Go version | 1.20 or higher | 1.20 | ### Install -See the [install guide](./docs/guides/install.md). +See the [install guide](docs/tutorials/install.md). ### Quick Start -- [Single node](./docs/guides/quick-start.md) -- [Local cluster using docker-compose](./docs/networks/docker-compose.md) +- [Single node](docs/tutorials/quick-start.md) +- [Local cluster using docker-compose](./docs/guides/networks/docker-compose.md) ## Contributing @@ -81,35 +85,35 @@ Before contributing to the project, please take a look at the [contributing guidelines](CONTRIBUTING.md) and the [style guide](STYLE_GUIDE.md). You may also find it helpful to read the [specifications](./spec/README.md), and familiarize yourself with our [Architectural Decision Records -(ADRs)](./docs/architecture/README.md) and [Request For Comments -(RFCs)](./docs/rfc/README.md). +(ADRs)](docs/references/architecture/README.md) and [Request For Comments +(RFCs)](docs/references/rfc/README.md). ## Versioning -### Semantic Versioning - -CometBFT uses [Semantic Versioning](http://semver.org/) to determine when and -how the version changes. According to SemVer, anything in the public API can -change at any time before version 1.0.0 +As of v1, CometBFT uses the following approach to versioning: -To provide some stability to users of 0.X.X versions of CometBFT, the MINOR -version is used to signal breaking changes across CometBFT's API. This API -includes all publicly exposed types, functions, and methods in non-internal Go -packages as well as the types and methods accessible via the CometBFT RPC -interface. - -Breaking changes to these public APIs will be documented in the CHANGELOG. +- **Major version** bumps, such as v1.0.0 to v2.0.0, would generally involve + changes that _force_ users to perform a coordinated upgrade in order to use + the new version, such as protocol-breaking changes (e.g. changes to how block + hashes are computed and thus what the network considers to be "valid blocks", + or how the consensus protocol works, or changes that affect network-level + compatibility between nodes, etc.). +- **Minor version** bumps, such as v1.1.0 to v1.2.0, are reserved for rolling + out new features or substantial changes that do not force a coordinated + upgrade (i.e. not protocol-breaking), but could potentially break Go APIs. +- **Patch version** bumps, such as v1.0.0 to v1.0.1, are reserved for + bug/security fixes that are not protocol- or Go API-breaking. ### Upgrades -In an effort to avoid accumulating technical debt prior to 1.0.0, we do not -guarantee that breaking changes (i.e. bumps in the MINOR version) will work with -existing CometBFT blockchains. In these cases you will have to start a new -blockchain, or write something custom to get the old data into the new chain. -However, any bump in the PATCH version should be compatible with existing -blockchain histories. +We do not guarantee compatibility between major releases of CometBFT. Minor +releases of the same major release series (v1.1, v1.2, etc.) should, unless +otherwise specified, be compatible with each other. Patch releases of the same +minor release series (v1.0.1, v1.0.2, etc.) are guaranteed to be compatible with +each other. -For more information on upgrading, see [UPGRADING.md](./UPGRADING.md). +For more detailed information on upgrading from one version to another, see +[UPGRADING.md](./UPGRADING.md). ### Supported Versions @@ -120,6 +124,12 @@ CometBFT up-to-date. Upgrading instructions can be found in Currently supported versions include: +- v1.x: Currently in pre-release with no guarantees as to API stability until a + release candidate is cut. See [RELEASES.md](./RELEASES.md) for details on our + process as to API stability guarantees that can be expected of CometBFT + pre-releases. +- v0.38.x: CometBFT v0.38 introduces ABCI 2.0, which implements the entirety of + ABCI++ - 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 @@ -129,23 +139,22 @@ Currently supported versions include: ### Libraries -- [Cosmos SDK](http://github.com/cosmos/cosmos-sdk); A framework for building - applications in Golang +- [Cosmos SDK](http://github.com/cosmos/cosmos-sdk): A framework for building + high-value public blockchain applications in Go - [Tendermint in Rust](https://github.com/informalsystems/tendermint-rs) - [ABCI Tower](https://github.com/penumbra-zone/tower-abci) ### Applications - [Cosmos Hub](https://hub.cosmos.network/) -- [Terra](https://www.terra.money/) - [Celestia](https://celestia.org/) - [Anoma](https://anoma.network/) -- [Vocdoni](https://docs.vocdoni.io/) +- [Vocdoni](https://developer.vocdoni.io/) ### Research Below are links to the original Tendermint consensus algorithm and relevant -whitepapers which CosmosBFT will continue to build on. +whitepapers, which CometBFT will continue to build on. - [The latest gossip on BFT consensus](https://arxiv.org/abs/1807.04938) - [Master's Thesis on Tendermint](https://atrium.lib.uoguelph.ca/xmlui/handle/10214/9769) @@ -168,7 +177,7 @@ maintains [cometbft.com](https://cometbft.com). [version-url]: https://github.com/cometbft/cometbft/releases/latest [api-badge]: https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667 [api-url]: https://pkg.go.dev/github.com/cometbft/cometbft -[go-badge]: https://img.shields.io/badge/go-1.20-blue.svg +[go-badge]: https://img.shields.io/badge/go-1.21-blue.svg [go-url]: https://github.com/moovweb/gvm [discord-badge]: https://img.shields.io/discord/669268347736686612.svg [discord-url]: https://discord.gg/cosmosnetwork @@ -177,11 +186,23 @@ maintains [cometbft.com](https://cometbft.com). [sg-badge]: https://sourcegraph.com/github.com/cometbft/cometbft/-/badge.svg [sg-url]: https://sourcegraph.com/github.com/cometbft/cometbft?badge [tests-url]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml +[tests-url-v1x]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml?query=branch%3Av1.x +[tests-url-v038x]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml?query=branch%3Av0.38.x +[tests-url-v037x]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml?query=branch%3Av0.37.x +[tests-url-v034x]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml?query=branch%3Av0.34.x [tests-badge]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml/badge.svg?branch=main +[tests-badge-v1x]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml/badge.svg?branch=v1.x +[tests-badge-v038x]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml/badge.svg?branch=v0.38.x [tests-badge-v037x]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml/badge.svg?branch=v0.37.x [tests-badge-v034x]: https://github.com/cometbft/cometbft/actions/workflows/tests.yml/badge.svg?branch=v0.34.x [lint-badge]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml/badge.svg?branch=main [lint-badge-v034x]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml/badge.svg?branch=v0.34.x [lint-badge-v037x]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml/badge.svg?branch=v0.37.x +[lint-badge-v038x]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml/badge.svg?branch=v0.38.x +[lint-badge-v1x]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml/badge.svg?branch=v1.x [lint-url]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml +[lint-url-v034x]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml?query=branch%3Av0.34.x +[lint-url-v037x]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml?query=branch%3Av0.37.x +[lint-url-v038x]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml?query=branch%3Av0.38.x +[lint-url-v1x]: https://github.com/cometbft/cometbft/actions/workflows/lint.yml?query=branch%3Av1.x [tm-core]: https://github.com/tendermint/tendermint diff --git a/RELEASES.md b/RELEASES.md index 0122b113fe6..2298208759c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,17 +1,17 @@ # Releases CometBFT uses modified [semantic versioning](https://semver.org/) with each -release following a `vX.Y.Z` format. CometBFT is currently on major version 0 -and uses the minor version to signal breaking changes. The `main` branch is -used for active development and thus it is not advisable to build against it. +release following a `vX.Y.Z` format. The versioning approach used by CometBFT +v1.x onwards differs from that of the v0.x series, and is documented in +[README.md](./README.md#versioning). The `main` branch is used for active +development and thus it is not advisable to build against it. The latest changes are always initially merged into `main`. Releases are specified using tags and are built from long-lived "backport" branches that are -cut from `main` when the release process begins. Each release "line" (e.g. -0.34 or 0.33) has its own long-lived backport branch, and the backport branches -have names like `v0.34.x` or `v0.33.x` (literally, `x`; it is not a placeholder -in this case). CometBFT only maintains the last two releases at a time (the -oldest release is predominantly just security patches). +cut from `main` when the release process begins. Each release "line" (e.g. 1.0 +or 0.38) has its own long-lived backport branch, and the backport branches have +names like `v1.x` or `v0.38.x` (literally, `x`; it is not a placeholder in this +case). ## Backporting @@ -22,44 +22,41 @@ We use Mergify's [backport feature](https://mergify.io/features/backports) to automatically backport to the needed branch. There should be a label for any backport branch that you'll be targeting. To notify the bot to backport a pull request, mark the pull request with the label corresponding to the correct -backport branch. For example, to backport to v0.38.x, add the label -`S:backport-to-v0.38.x`. Once the original pull request is merged, the bot will +backport branch. For example, to backport to v1.x, add the label +`S:backport-to-v1.x`. Once the original pull request is merged, the bot will try to cherry-pick the pull request to the backport branch. If the bot fails to backport, it will open a pull request. The author of the original pull request is responsible for solving the conflicts and merging the pull request. ### Creating a backport branch -If this is the first release candidate for a minor version release, e.g. -v0.25.0, you get to have the honor of creating the backport branch! +If this is the first release candidate for a major version release, e.g. v2.0.0, +you get to have the honor of creating the backport branch! Note that, after creating the backport branch, you'll also need to update the -tags on `main` so that `go mod` is able to order the branches correctly. You -should tag `main` with a "dev" tag that is "greater than" the backport -branches tags. Otherwise, `go mod` does not 'know' whether commits on `main` -come before or after the release. +tags on `main` so that `go mod` is able to order the branches correctly. In the following example, we'll assume that we're making a backport branch for -the 0.38.x line. +the 2.x line. 1. Start on `main` 2. Ensure that there is a [branch protection - rule](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule) for the - branch you are about to create (you will need admin access to the repository - in order to do this). + rule](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule) + for the branch you are about to create (you will need admin access to the + repository in order to do this). 3. Create and push the backport branch: ```sh - git checkout -b v0.38.x - git push origin v0.38.x + git checkout -b v2.x + git push origin v2.x ``` 4. Create a PR to update the documentation directory for the backport branch. - We rewrite any URLs pointing to `main` to point to the backport branch, - so that generated documentation will link to the correct versions of files + We rewrite any URLs pointing to `main` to point to the backport branch, so + that generated documentation will link to the correct versions of files elsewhere in the repository. The following files are to be excluded from this search: @@ -73,65 +70,77 @@ the 0.38.x line. * `https://github.com/cometbft/cometbft/blob/main/LICENSE` Be sure to search for all of the following links and replace `main` with your - corresponding branch label or version (e.g. `v0.38.x` or `v0.38`): + corresponding branch label or version (e.g. `v2.x` or `v2.0`): * `github.com/cometbft/cometbft/blob/main` -> - `github.com/cometbft/cometbft/blob/v0.38.x` + `github.com/cometbft/cometbft/blob/v2.x` * `github.com/cometbft/cometbft/tree/main` -> - `github.com/cometbft/cometbft/tree/v0.38.x` - * `docs.cometbft.com/main` -> `docs.cometbft.com/v0.38` + `github.com/cometbft/cometbft/tree/v2.x` + * `docs.cometbft.com/main` -> `docs.cometbft.com/v2` Once you have updated all of the relevant documentation: ```sh # Create and push the PR. - git checkout -b update-docs-v038x - git commit -m "Update docs for v0.38.x backport branch." - git push -u origin update-docs-v038x + git checkout -b update-docs-v2.x + git commit -m "Update docs for v2.x backport branch." + git push -u origin update-docs-v2.x ``` Be sure to merge this PR before making other changes on the newly-created backport branch. +5. Ensure that the RPC docs' `version` field in `rpc/openapi/openapi.yaml` has + been updated from `main` to the backport branch version. + +6. Prepare the [CometBFT documentation + repository](https://github.com/cometbft/cometbft-docs) to build the release + branch's version by updating the + [VERSIONS](https://github.com/cometbft/cometbft-docs/blob/main/VERSIONS) + file. + After doing these steps, go back to `main` and do the following: -1. Create a new workflow to run e2e nightlies for the new backport branch. (See +1. Create a new workflow to run E2E nightlies for the new backport branch. (See [e2e-nightly-main.yml][e2e] for an example.) 2. Add a new section to the Mergify config (`.github/mergify.yml`) to enable the - backport bot to work on this branch, and add a corresponding `backport-to-v0.38.x` + backport bot to work on this branch, and add a corresponding `backport-to-v2.x` [label](https://github.com/cometbft/cometbft/labels) so the bot can be triggered. 3. Add a new section to the Dependabot config (`.github/dependabot.yml`) to enable automatic update of Go dependencies on this branch. Copy and edit one of the existing branch configurations to set the correct `target-branch`. +4. Remove all changelog entries from `.changelog/unreleased` that are destined + for release from the backport branch. + [e2e]: https://github.com/cometbft/cometbft/blob/main/.github/workflows/e2e-nightly-main.yml ## Pre-releases -Before creating an official release, especially a minor release, we may want to +Before creating an official release, especially a major release, we may want to create an alpha or beta version, or release candidate (RC) for our friends and partners to test out. We use git tags to create pre-releases, and we build them off of backport branches, for example: -* `v0.38.0-alpha.1` - The first alpha release of `v0.38.0`. Subsequent alpha - releases will be numbered `v0.38.0-alpha.2`, `v0.38.0-alpha.3`, etc. +* `v2.0.0-alpha.1` - The first alpha release of `v2.0.0`. Subsequent alpha + releases will be numbered `v2.0.0-alpha.2`, `v2.0.0-alpha.3`, etc. Alpha releases are to be considered the _most_ unstable of pre-releases, and are most likely not yet properly QA'd. These are made available to allow early adopters to start integrating and testing new functionality before we're done with QA. -* `v0.38.0-beta.1` - The first beta release of `v0.38.0`. Subsequent beta - releases will be numbered `v0.38.0-beta.2`, `v0.38.0-beta.3`, etc. +* `v2.0.0-beta.1` - The first beta release of `v2.0.0`. Subsequent beta + releases will be numbered `v2.0.0-beta.2`, `v2.0.0-beta.3`, etc. Beta releases can be considered more stable than alpha releases in that we will have QA'd them better than alpha releases, but there still may be minor breaking API changes if users have strong demands for such changes. -* `v0.38.0-rc1` - The first release candidate (RC) of `v0.38.0`. Subsequent RCs - will be numbered `v0.38.0-rc2`, `v0.38.0-rc3`, etc. +* `v2.0.0-rc1` - The first release candidate (RC) of `v2.0.0`. Subsequent RCs + will be numbered `v2.0.0-rc2`, `v2.0.0-rc3`, etc. RCs are considered more stable than beta releases in that we will have completed our QA on them. APIs will most likely be stable at this point. The @@ -142,97 +151,130 @@ off of backport branches, for example: (Note that branches and tags _cannot_ have the same names, so it's important that these branches have distinct names from the tags/release names.) -If this is the first pre-release for a minor release, you'll have to make a new +If this is the first pre-release for a major release, you'll have to make a new backport branch (see above). Otherwise: -1. Start from the backport branch (e.g. `v0.38.x`). -2. Run the integration tests and the E2E nightlies - (which can be triggered from the GitHub UI; - e.g., ). +1. Start from the backport branch (e.g. `v2.x`). +2. Run the E2E nightlies (which can be triggered from the GitHub UI; e.g., + ). 3. Prepare the pre-release documentation: - * Build the changelog with [unclog] _without_ doing an unclog release, and + * Build the changelog with [unclog] _without_ doing an unclog release (`unclog build -a > CHANGELOG.md`), and commit the built changelog. This ensures that all changelog entries appear under an "Unreleased" heading in the pre-release's changelog. The changes are only considered officially "released" once we cut a regular (final) release. * Ensure that `UPGRADING.md` is up-to-date and includes notes on any breaking changes or other upgrading flows. -4. Prepare the versioning: - * Bump TMVersionDefault version in `version.go` +4. Check the dependency to `github.com/cometbft/cometbft/api` in the `go.mod` + file. If it does not point to an official api version, run `go get` + so that it points to one. You may need to tag a new version of the api + if the last version is too old (i.e., it does not contain the latest + changes to the protos). If that is the case: + * `git tag -a api/v2.0.0-rc1 -s -m "Release api module v2.0.0-rc1" origin/v2.x` + * `git push origin api/v2.0.0-rc1` + * Notice the prefix `api/`, which denotes that the version refers to the `api` module. +5. Prepare the versioning: + * Bump CometBFT version in `version.go` * Bump P2P and block protocol versions in `version.go`, if necessary. Check the changelog for breaking changes in these components. * Bump ABCI protocol version in `version.go`, if necessary -5. Open a PR with these changes against the backport branch. -6. Once these changes have landed on the backport branch, be sure to pull them back down locally. -7. Once you have the changes locally, create the new tag, specifying a name and a tag "message": - `git tag -a v0.38.0-rc1 -m "Release Candidate v0.38.0-rc1` -8. Push the tag back up to origin: - `git push origin v0.38.0-rc1` +6. Open a PR with these changes against the backport branch. +7. Once these changes have landed on the backport branch, be sure to pull them + back down locally. +8. Once you have the changes locally, create the new tag, specifying a name and + a tag "message": + `git tag -a v2.0.0-rc1 -s -m "Release Candidate v2.0.0-rc1` +9. Push the tag back up to origin: + `git push origin v2.0.0-rc1` Now the tag should be available on the repo's releases page. -9. Future pre-releases will continue to be built off of this branch. +10. Future pre-releases will continue to be built off of this branch. -## Minor release +## Major release -This minor release process assumes that this release was preceded by release +This major release process assumes that this release was preceded by release candidates. If there were no release candidates, begin by creating a backport branch, as described above. Before performing these steps, be sure the -[Minor Release Checklist](#minor-release-checklist) has been completed. +[Major Release Checklist](#major-release-checklist) has been completed. -1. Start on the backport branch (e.g. `v0.38.x`) -2. Run integration tests (`make test_integrations`) and the e2e nightlies. +1. Start on the backport branch (e.g. `v2.x`) +2. Run the E2E nightlies (which can be triggered from the GitHub UI; e.g., + ). 3. Prepare the release: + * Check the dependency to `github.com/cometbft/cometbft/api` in the `go.mod` + file. If it does not point to an official api version, run `go get` + so that it points to one. You may need to tag a new version of the api + if the last released version is too old (i.e., it does not contain the latest + changes to the protos). If that is the case: + * `git tag -a api/v2.0.0 -s -m "Release api module v2.0.0" origin/v2.x` + * `git push origin api/v2.0.0` + * Notice the prefix `api/`, which denotes that the version refers to the `api` module. * Do a [release][unclog-release] with [unclog] for the desired version, ensuring that you write up a good summary of the major highlights of the release that users would be interested in. * Build the changelog using unclog, and commit the built changelog. * Ensure that `UPGRADING.md` is up-to-date and includes notes on any breaking changes or other upgrading flows. - * Bump TMVersionDefault version in `version.go` + * Bump CometBFT version in `version.go` * Bump P2P and block protocol versions in `version.go`, if necessary * Bump ABCI protocol version in `version.go`, if necessary 4. Open a PR with these changes against the backport branch. -5. Once these changes are on the backport branch, push a tag with prepared release details. - This will trigger the actual release `v0.38.0`. - * `git tag -a v0.38.0 -m 'Release v0.38.0'` - * `git push origin v0.38.0` -6. Make sure that `main` is updated with the latest `CHANGELOG.md`, `CHANGELOG_PENDING.md`, and `UPGRADING.md`. +5. Once these changes are on the backport branch, push a tag with prepared + release details. This will trigger the actual release `v2.0.0`. + * `git tag -a v2.0.0 -s -m 'Release v2.0.0'` + * `git push origin v2.0.0` +6. Make sure that `main` is updated with the latest `CHANGELOG.md`, + `CHANGELOG_PENDING.md`, and `UPGRADING.md`. -## Patch release +## Minor and patch releases -Patch releases are done differently from minor releases: They are built off of -long-lived backport branches, rather than from main. As non-breaking changes -land on `main`, they should also be backported into these backport branches. +Minor and patch releases are done differently from major releases: they are +built off of long-lived backport branches, rather than from `main`. As +non-breaking changes land on `main`, they should also be backported into these +backport branches. Patch releases don't have release candidates by default, although any tricky changes may merit a release candidate. To create a patch release: -1. Checkout the long-lived backport branch: `git checkout v0.38.x` -2. Run integration tests (`make test_integrations`) and the nightlies. +1. Checkout the long-lived backport branch: `git checkout v2.x` +2. Run the E2E nightlies (which can be triggered from the GitHub UI; e.g., + ). 3. Check out a new branch and prepare the release: + * Check the dependency to `github.com/cometbft/cometbft/api` in the `go.mod` + file. If it does not point to an official api version, run `go get` + so that it points to one. You may need to tag a new version of the api + if the last released version is too old (i.e., it does not contain the latest + changes to the protos). If that is the case: + * `git tag -a api/v2.0.1 -s -m "Release api module v2.0.1" origin/v2.x` + * `git push origin api/v2.0.1` + * Notice the prefix `api/`, which denotes that the version refers to the `api` module. * Do a [release][unclog-release] with [unclog] for the desired version, ensuring that you write up a good summary of the major highlights of the release that users would be interested in. * Build the changelog using unclog, and commit the built changelog. - * Bump the TMDefaultVersion in `version.go` + * Bump the CometBFT in `version.go` * Bump the ABCI version number, if necessary. (Note that ABCI follows semver, and that ABCI versions are the only versions which can change during patch releases, and only field additions are valid patch changes.) -4. Open a PR with these changes that will land them back on `v0.38.x` +4. Open a PR with these changes that will land them back on `v2.x` 5. Once this change has landed on the backport branch, make sure to pull it locally, then push a tag. - * `git tag -a v0.38.1 -m 'Release v0.38.1'` - * `git push origin v0.38.1` -6. Create a pull request back to main with the CHANGELOG & version changes from the latest release. - * Remove all `R:patch` labels from the pull requests that were included in the release. + * `git tag -a v2.0.1 -s -m 'Release v2.0.1'` + * `git push origin v2.0.1` + + The process for minor releases is similar to patch releases: + * `git tag -a v2.1.0 -s -m 'Release v2.1.0` + * `git push origin v2.1.0` +6. Create a pull request back to main with the CHANGELOG and version changes + from the latest release. * Do not merge the backport branch into main. -## Minor Release Checklist +## Major Release Checklist The following set of steps are performed on all releases that increment the -_minor_ version, e.g. v0.25 to v0.26. These steps ensure that CometBFT is well +_major_ version, e.g. v1.0 to v2.0. These steps ensure that CometBFT is well tested, stable, and suitable for adoption by the various diverse projects that rely on CometBFT. @@ -316,22 +358,44 @@ and limitation that real-world deployments of CometBFT experience in production #### 200 Node Testnet To test the stability and performance of CometBFT in a real world scenario, -a 200 node test network is run. The network comprises 5 seed nodes, 100 -validators and 95 non-validating full nodes. All nodes begin by dialing +a 200 node test network is run. The network comprises 5 seed nodes, 175 +validators and 20 non-validating full nodes. All nodes begin by dialing a subset of the seed nodes to discover peers. The network is run for several days, with metrics being collected continuously. In cases of changes to performance critical systems, testnets of larger sizes should be considered. #### Rotating Node Testnet -Real-world deployments of CometBFT frequently see new nodes arrive and old -nodes exit the network. The rotating node testnet ensures that CometBFT is -able to handle this reliably. In this test, a network with 10 validators and -3 seed nodes is started. A rolling set of 25 full nodes are started and each -connects to the network by dialing one of the seed nodes. Once the node is able -to blocksync to the head of the chain and begins producing blocks using -consensus it is stopped. Once stopped, a new node is started and -takes its place. This network is run for several days. +Real-world deployments of CometBFT frequently see new nodes arrive and old nodes +exit the network. The rotating node testnet ensures that CometBFT is able to +handle this reliably. In this test, a network with 10 validators and 3 seed +nodes is started. A rolling set of 25 full nodes are started and each connects +to the network by dialing one of the seed nodes. Once the node is able to +blocksync to the head of the chain and begins producing blocks using consensus +it is stopped. Once stopped, a new node is started and takes its place. This +network is run for several days. + +#### Vote-extension Testnet + +CometBFT v0.38.0 introduced **vote-extensions**, which are added as the name +suggests, to precommit votes sent by validators. The Vote-extension Testnet is +used to determine how vote-extensions affect the performance of CometBFT, under +various settings. The application used in the experiment is the same used on the +(#200-node-testnet), but is configured differently to gauge de effects of +varying vote extension sizes. In the (#200-node-testnet) the application extends +pre-commit votes with a 64 bit number encoded with variable compression. In the +Vote-extension Testnet, pre-commit votes are extended with a non-compressed +extension of configurable size. Experiments are run with multiple sizes to +determine their impact and, for comparison sake, we include a run with the same +settings as in the (#200-node-testnet). + +The testnet consists of 175 validators, 20 non-validator full-nodes, and 5 seed +nodes. All 195 full-nodes begin by dialing a subset of the seed nodes to +discover peers. Once all full-nodes are started, a 5 minute period is waited +before starting an experiment. For each experiment, the load generators issue +requests at a constant rate during 150 seconds, then wait for 5 minutes to allow +the system to quiesce, then repeat the load generation; the load generation step +is repeated 5 times for each experiment. #### Network Partition Testnet @@ -339,24 +403,23 @@ CometBFT is expected to recover from network partitions. A partition where no subset of the nodes is left with the super-majority of the stake is expected to stop making blocks. Upon alleviation of the partition, the network is expected to once again become fully connected and capable of producing blocks. The -network partition testnet ensures that CometBFT is able to handle this -reliably at scale. In this test, a network with 100 validators and 95 full -nodes is started. All validators have equal stake. Once the network is -producing blocks, a set of firewall rules is deployed to create a partitioned -network with 50% of the stake on one side and 50% on the other. Once the -network stops producing blocks, the firewall rules are removed and the nodes -are monitored to ensure they reconnect and that the network again begins -producing blocks. +network partition testnet ensures that CometBFT is able to handle this reliably +at scale. In this test, a network with 100 validators and 95 full nodes is +started. All validators have equal stake. Once the network is producing blocks, +a set of firewall rules is deployed to create a partitioned network with 50% of +the stake on one side and 50% on the other. Once the network stops producing +blocks, the firewall rules are removed and the nodes are monitored to ensure +they reconnect and that the network again begins producing blocks. #### Absent Stake Testnet -CometBFT networks often run with _some_ portion of the voting power offline. -The absent stake testnet ensures that large networks are able to handle this +CometBFT networks often run with _some_ portion of the voting power offline. The +absent stake testnet ensures that large networks are able to handle this reliably. A set of 150 validator nodes and three seed nodes is started. The set -of 150 validators is configured to only possess a cumulative stake of 67% of -the total stake. The remaining 33% of the stake is configured to belong to -a validator that is never actually run in the test network. The network is run -for multiple days, ensuring that it is able to produce blocks without issue. +of 150 validators is configured to only possess a cumulative stake of 67% of the +total stake. The remaining 33% of the stake is configured to belong to a +validator that is never actually run in the test network. The network is run for +multiple days, ensuring that it is able to produce blocks without issue. [unclog]: https://github.com/informalsystems/unclog [unclog-release]: https://github.com/informalsystems/unclog#releasing-a-new-versions-change-set diff --git a/SECURITY.md b/SECURITY.md index 01b989c6b1f..2a5c5666415 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,208 +1,33 @@ -# Security +# How to Report a Security Bug -## Reporting a Bug +If you believe you have found a security vulnerability in the Interchain Stack, +you can report it to our primary vulnerability disclosure channel, the [Cosmos +HackerOne Bug Bounty program][h1]. -As part of our Coordinated Vulnerability Disclosure Policy (link will be added -once this policy is finalized for CometBFT), we operate a [bug -bounty][hackerone]. See the policy for more details on submissions and rewards, -and see "Example Vulnerabilities" (below) for examples of the kinds of bugs -we're most interested in. +If you prefer to report an issue via email, you may send a bug report to + with the issue details, reproduction, impact, and other +information. Please submit only one unique email thread per vulnerability. Any +issues reported via email are ineligible for bounty rewards. -### Guidelines +Artifacts from an email report are saved at the time the email is triaged. +Please note: our team is not able to monitor dynamic content (e.g. a Google Docs +link that is edited after receipt) throughout the lifecycle of a report. If you +would like to share additional information or modify previous information, +please include it in an additional reply as an additional attachment. -We require that all researchers: +Please **DO NOT** file a public issue in this repository to report a security +vulnerability. -* Use the bug bounty to disclose all vulnerabilities, and avoid posting - vulnerability information in public places, including GitHub Issues, Discord - channels, and Telegram groups -* Make every effort to avoid privacy violations, degradation of user experience, - disruption to production systems (including but not limited to the Cosmos - Hub), and destruction of data -* Keep any information about vulnerabilities that you’ve discovered confidential - between yourself and the CometBFT engineering team until the issue has been - resolved and disclosed -* Avoid posting personally identifiable information, privately or publicly +## Coordinated Vulnerability Disclosure Policy and Safe Harbor -If you follow these guidelines when reporting an issue to us, we commit to: +For the most up-to-date version of the policies that govern vulnerability +disclosure, please consult the [HackerOne program page][h1-policy]. -* Not pursue or support any legal action related to your research on this - vulnerability -* Work with you to understand, resolve and ultimately disclose the issue in a - timely fashion +The policy hosted on HackerOne is the official Coordinated Vulnerability +Disclosure policy and Safe Harbor for the Interchain Stack, and the teams and +infrastructure it supports, and it supersedes previous security policies that +have been used in the past by individual teams and projects with targets in +scope of the program. -## Disclosure Process - -CometBFT uses the following disclosure process: - -1. Once a security report is received, the CometBFT team works to verify the - issue and confirm its severity level using CVSS. -2. The CometBFT team collaborates with the Gaia team to determine the - vulnerability’s potential impact on the Cosmos Hub. -3. Patches are prepared for eligible releases of CometBFT in private - repositories. See “Supported Releases” below for more information on which - releases are considered eligible. -4. If it is determined that a CVE-ID is required, we request a CVE through a CVE - Numbering Authority. -5. We notify the community that a security release is coming, to give users time - to prepare their systems for the update. Notifications can include forum - posts, tweets, and emails to partners and validators. -6. 24 hours following this notification, the fixes are applied publicly and new - releases are issued. -7. Cosmos SDK and Gaia update their CometBFT dependencies to use these releases, - and then themselves issue new releases. -8. Once releases are available for CometBFT, Cosmos SDK and Gaia, we notify the - community, again, through the same channels as above. We also publish a - Security Advisory on GitHub and publish the CVE, as long as neither the - Security Advisory nor the CVE include any information on how to exploit these - vulnerabilities beyond what information is already available in the patch - itself. -9. Once the community is notified, we will pay out any relevant bug bounties to - submitters. -10. One week after the releases go out, we will publish a post with further - details on the vulnerability as well as our response to it. - -This process can take some time. Every effort will be made to handle the bug in -as timely a manner as possible, however it's important that we follow the -process described above to ensure that disclosures are handled consistently and -to keep CometBFT and its downstream dependent projects--including but not -limited to Gaia and the Cosmos Hub--as secure as possible. - -### Example Timeline - -The following is an example timeline for the triage and response. The required -roles and team members are described in parentheses after each task; however, -multiple people can play each role and each person may play multiple roles. - -#### 24+ Hours Before Release Time - -1. Request CVE number (ADMIN) -2. Gather emails and other contact info for validators (COMMS LEAD) -3. Create patches in a private security repo, and ensure that PRs are open - targeting all relevant release branches (CometBFT ENG, CometBFT LEAD) -4. Test fixes on a testnet (CometBFT ENG, COSMOS SDK ENG) -5. Write “Security Advisory” for forum (CometBFT LEAD) - -#### 24 Hours Before Release Time - -1. Post “Security Advisory” pre-notification on forum (CometBFT LEAD) -2. Post Tweet linking to forum post (COMMS LEAD) -3. Announce security advisory/link to post in various other social channels - (Telegram, Discord) (COMMS LEAD) -4. Send emails to validators or other users (PARTNERSHIPS LEAD) - -#### Release Time - -1. Cut CometBFT releases for eligible versions (CometBFT ENG, CometBFT - LEAD) -2. Cut Cosmos SDK release for eligible versions (COSMOS ENG) -3. Cut Gaia release for eligible versions (GAIA ENG) -4. Post “Security releases” on forum (CometBFT LEAD) -5. Post new Tweet linking to forum post (COMMS LEAD) -6. Remind everyone via social channels (Telegram, Discord) that the release is - out (COMMS LEAD) -7. Send emails to validators or other users (COMMS LEAD) -8. Publish Security Advisory and CVE, if CVE has no sensitive information - (ADMIN) - -#### After Release Time - -1. Write forum post with exploit details (CometBFT LEAD) -2. Approve pay-out on HackerOne for submitter (ADMIN) - -#### 7 Days After Release Time - -1. Publish CVE if it has not yet been published (ADMIN) -2. Publish forum post with exploit details (CometBFT ENG, CometBFT LEAD) - -## Supported Releases - -The CometBFT team commits to releasing security patch releases for both -the latest minor release as well for the major/minor release that the Cosmos Hub -is running. - -If you are running older versions of CometBFT, we encourage you to -upgrade at your earliest opportunity so that you can receive security patches -directly from the CometBFT repo. While you are welcome to backport security -patches to older versions for your own use, we will not publish or promote these -backports. - -## Scope - -The full scope of our bug bounty program is outlined on our -[Hacker One program page][hackerone]. Please also note that, in the interest of -the safety of our users and staff, a few things are explicitly excluded from -scope: - -* Any third-party services -* Findings from physical testing, such as office access -* Findings derived from social engineering (e.g., phishing) - -## Example Vulnerabilities - -The following is a list of examples of the kinds of vulnerabilities that we’re -most interested in. It is not exhaustive: there are other kinds of issues we may -also be interested in! - -### Specification - -* Conceptual flaws -* Ambiguities, inconsistencies, or incorrect statements -* Mis-match between specification and implementation of any component - -### Consensus - -Assuming less than 1/3 of the voting power is Byzantine (malicious): - -* Validation of blockchain data structures, including blocks, block parts, - votes, and so on -* Execution of blocks -* Validator set changes -* Proposer round robin -* Two nodes committing conflicting blocks for the same height (safety failure) -* A correct node signing conflicting votes -* A node halting (liveness failure) -* Syncing new and old nodes - -Assuming more than 1/3 the voting power is Byzantine: - -* Attacks that go unpunished (unhandled evidence) - -### Networking - -* Authenticated encryption (MITM, information leakage) -* Eclipse attacks -* Sybil attacks -* Long-range attacks -* Denial-of-Service - -### RPC - -* Write-access to anything besides sending transactions -* Denial-of-Service -* Leakage of secrets - -### Denial-of-Service - -Attacks may come through the P2P network or the RPC layer: - -* Amplification attacks -* Resource abuse -* Deadlocks and race conditions - -### Libraries - -* Serialization -* Reading/Writing files and databases - -### Cryptography - -* Elliptic curves for validator signatures -* Hash algorithms and Merkle trees for block validation -* Authenticated encryption for P2P connections - -### Light Client - -* Core verification -* Bisection/sequential algorithms - -[hackerone]: https://hackerone.com/cosmos +[h1]: https://hackerone.com/cosmos?type=team +[h1-policy]: https://hackerone.com/cosmos?type=team&view_policy=true diff --git a/UPGRADING.md b/UPGRADING.md index cec35029b87..84c0e8fd38f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -4,28 +4,293 @@ This guide provides instructions for upgrading to specific versions of CometBFT. ## Unreleased +CometBFT `v1.0` includes some substantial breaking API changes that will hopefully +allow future changes to be rolled out quicker. + +### Versioning + +As of v1.0, the CometBFT team provides the following guarantees relating to +versioning: + +- **Major version** bumps, such as v1.0.0 to v2.0.0, would generally involve + changes that _force_ users to perform a coordinated upgrade in order to use + the new version, such as protocol-breaking changes (e.g. changes to how block + hashes are computed and thus what the network considers to be "valid blocks", + or how the consensus protocol works, or changes that affect network-level + compatibility between nodes, etc.). +- **Minor version** bumps, such as v1.1.0 to v1.2.0, are reserved for rolling + out new features or substantial changes that do not force a coordinated + upgrade (i.e. not protocol-breaking), but could potentially break Go APIs. +- **Patch version** bumps, such as v1.0.0 to v1.0.1, are reserved for + bug/security fixes that are not protocol- or Go API-breaking. + +### Building CometBFT + +The minimum Go version has been bumped to [v1.21][go121]. + +### Proposer-Based Timestamps + +CometBFT `v1.0` contains a new algorithm for generating and verifying block timestamps +called Proposer-Based Timestamps (PBTS). +The existing algorithm, called BFT-Time is kept for backwards compatibility. +Upgrading to `v1.0` does not automatically switch the chain from BFT-Time +to PBTS; rather a ConsensusParam called `PbtsEnableHeight` can be set to a future +height to transition from BFT-Time to PBTS. +This flexible mechanism allows chains disentagle the upgrade to `v1.0` from the transition +in the algorithm used for block times. +For further information, please check the [PBTS specification][pbts-spec]. + +### ABCI Mutex + +CometBFT's existing ABCI local client is prevented from making +concurrent calls to ABCI implementations by virtue of a mutex taken +by the client's implementation. +In this release, two additional local ABCI clients have been added. +The first, supports one different mutex per ABCI connection +(consensus connection, mempool connection, etc.), allowing concurrency +in the application in different ABCI connections, but still serializing +ABCI calls within the same connection. +The second, totally removes mutexes from the ABCI client. +When using either of the new ABCI clients, the application is now +responsible to coordinate concurrent ABCI calls in order to prevent +race conditions or the possibility of non determinism. +If you are not sure how to ensure those guarantees in your application, +you are strongly advised to keep on using the existing ABCI client +containing one global mutex. + +### Consensus + +Removed the `consensus.State.ReplayFile` and `consensus.RunReplayFile` methods, +as these were exclusively used by the `replay` and `replay-console` subcommands, +which were also removed. (See +[\#1170](https://github.com/cometbft/cometbft/pull/1170)) + +### CLI Subcommands + +- The `replay` and `replay-console` subcommands were removed + ([\#1170](https://github.com/cometbft/cometbft/pull/1170)). + +### Go API + +As per [ADR 109](docs/references/architecture/adr-109-reduce-go-api-surface.md), the +following packages that were publicly accessible in CometBFT v0.38 were moved +into the `internal` directory: + +- `blocksync` +- `consensus` +- `evidence` +- `inspect` +- `libs/async` +- `libs/autofile` +- `libs/bits` +- `libs/clist` +- `libs/cmap` +- `libs/events` +- `libs/fail` +- `libs/flowrate` +- `libs/net` +- `libs/os` +- `libs/progressbar` +- `libs/protoio` +- `libs/pubsub` +- `libs/rand` +- `libs/service` +- `libs/strings` +- `libs/sync` +- `libs/tempfile` +- `libs/timer` +- `state` +- `statesync` +- `store` + +If you rely on any of these packages and would like us to make them public +again, please [log an issue on +GitHub](https://github.com/cometbft/cometbft/issues/new/choose) describing your +use case and we will evaluate the best approach to helping you address it. + +### Mempool + +#### `nop` mempool + +CometBFT v1.0.0 provides users with the option of a `nop` (no-op) mempool which, +if selected via configuration, turns off all mempool-related functionality in +Comet (e.g. ability to receive transactions, transaction gossip). Comet then +expects applications to provide their transactions when it calls +`PrepareProposal`, and that application developers will use some external means +of disseminating their transactions. + +If you want to use it, change mempool's `type` to `nop` in your `config.toml` +file: + +```toml +[mempool] + +# The type of mempool for this node to use. +# +# Possible types: +# - "flood" : concurrent linked list mempool with flooding gossip protocol +# (default) +# - "nop" : nop-mempool (short for no operation; the ABCI app is responsible +# for storing, disseminating and proposing txs). "create_empty_blocks=false" +# is not supported. +type = "nop" +``` + +#### Internal `CheckTx` Go API changes + +The `Mempool` interface was modified on `CheckTx`. Note that this interface is +meant for internal use only, so you should be aware of these changes only if you +happen to call these methods directly. + +`CheckTx`'s signature changed from `CheckTx(tx types.Tx, cb +func(*abci.ResponseCheckTx), txInfo TxInfo) error` to `CheckTx(tx types.Tx) +(abcicli.ReqRes, error)`. +- The method used to take a callback function `cb` to be applied to the + ABCI `CheckTx` response. Now `CheckTx` returns the ABCI response of + type `abcicli.ReqRes`, on which the callback must be applied manually. + For example: + + ```golang + reqRes, err := CheckTx(tx) + cb(reqRes.Response.GetCheckTx()) + ``` + +- The second parameter was `txInfo`, which essentially contained + information about the sender of the transaction. Now that information + is stored in the mempool reactor instead of the data structure, so it + is no longer needed in this method. + +### Protobufs and Generated Go Code + +Several major changes have been implemented relating to the Protobuf +definitions: + +1. CometBFT now makes use of the `cometbft.*` Protobuf definitions in + [`proto/cometbft`](./proto/cometbft/). This is a breaking change for all + users who rely on serialization of the Protobuf type paths, such as + integrators who serialize CometBFT's Protobuf data types into `Any`-typed + fields. For example, the `tendermint.types.Block` type in CometBFT v0.38.x is + now accessible as `cometbft.types.v1.Block` (see the next point in the list + for details on versioning). + + See the CometBFT Protobufs [README](/proto/README.md) file for more details. + +2. All CometBFT Protobuf packages include a version whose number will be + independent of the CometBFT version. As mentioned in (1), the + `tendermint.types.Block` type is now available under + `cometbft.types.v1.Block` - the `v1` in the type path indicates the version + of the `types` package used by this version of CometBFT. + + The Protobuf definitions that are wire-level compatible (but not type + path-compatible) with CometBFT v0.34, v0.37 and v0.38, where breaking changes + were introduced, are available under `v1beta*`-versioned types. For example: + + - The `tendermint.abci.Request` type from CometBFT v0.34 is now available as + `cometbft.abci.v1beta1.Request`. + - The `tendermint.abci.Request` type from CometBFT v0.37 is now available as + `cometbft.abci.v1beta2.Request`. + - The `tendermint.abci.Request` type from CometBFT v0.38 is now available as + `cometbft.abci.v1beta3.Request`. + + See the CometBFT Protobufs [README](/proto/README.md) file for more details. + +3. All Go code generated from the `cometbft.*` types is now available under the + [`api`](./api/) directory. This directory is also an independently versioned + Go module. This code is still generated using the Cosmos SDK's [gogoproto + fork](https://github.com/cosmos/gogoproto) at present. + +4. Several ABCI-related types were renamed in order to align with [Buf + guidelines](https://buf.build/docs/best-practices/style-guide/). `Request*` + and `Response*` were renamed to `*Request` and `*Response` (e.g. + `RequestQuery` was renamed to `QueryRequest`). See the changelog for more + details. + +### RPC + +- The RPC API is now versioned, with the existing RPC being available under both + the `/` path (as in CometBFT v0.38) and a `/v1` path. + + Although invoking methods without specifying the version is still supported + for now, support will be dropped in future releases and users are encouraged + to use the versioned approach. For example, instead of + `curl localhost:26657/block?height=5`, use `curl localhost:26657/v1/block?height=5`. + +- The `/websocket` endpoint path is no longer configurable in the client or + server. Creating an RPC client now takes the form: + + ```golang + // The WebSocket endpoint in the following example is assumed to be available + // at http://localhost:26657/v1/websocket + rpcClient, err := client.New("http://localhost:26657/v1") + ``` + +## v0.38.0 + +This release introduces state machine-breaking changes, as well as substantial changes +on the ABCI interface and indexing. It therefore requires a +coordinated upgrade. + ### Config Changes -* A new config field, `BootstrapPeers` has been introduced as a means of - adding a list of addresses to the addressbook upon initializing a node. This is an - alternative to `PersistentPeers`. `PersistentPeers` shold be only used for - nodes that you want to keep a constant connection with i.e. sentry nodes -* The field `Version` in the mempool section has been removed. The priority +- The field `Version` in the mempool section has been removed. The priority mempool (what was called version `v1`) has been removed (see below), thus there is only one implementation of the mempool available (what was called `v0`). -* Config fields `TTLDuration` and `TTLNumBlocks`, which were only used by the priority - mempool, have been removed. +- 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 +- 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 + 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". +### 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%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`. +- The Application's hash (or any data representing the Application's current state) + is known by the time `FinalizeBlock` finishes its execution. + Accordingly, the `app_hash` parameter has been moved from `ResponseCommit` + to `ResponseFinalizeBlock`. +- Field `signed_last_block` in structure `VoteInfo` has been replaced by the + more expressive `block_id_flag`. Applications willing to keep the semantics + of `signed_last_block` can now use the following predicate + - `voteInfo.block_id_flag != BlockIDFlagAbsent` +- For further details, please see the updated [specification](spec/abci/README.md) + +### `block_results` RPC endpoint - query result display change (breaking) + +- When returning a block, all block events are displayed within the `finalize_block_events` field. + For blocks generated with older versions of CometBFT, that means that block results that appeared + as `begin_block_events` and `end_block_events` are merged into `finalize_block_events`. + For users who rely on the events to be grouped by the function they were generated by, this change + is breaking. + +### kvindexer changes to indexing block events + +The changes described here are internal to the implementation of the kvindexer, and they are transparent to the +user. However, if you own a fork with a modified version of the indexer, you should be aware of these changes. + +- Indexer key for block events will not contain information about the function that returned the event. +The events were indexed by their attributes, event type, the function that returned them, the height and +event sequence. The functions returning events in old (pre `v0.38.0`) versions of CometBFT were `BeginBlock` or `EndBlock`. +As events are returned now only via `FinalizeBlock`, the value of this field has no use, and has been removed. +The main motivation is the reduction of the storage footprint. + +Events indexed with previous CometBFT or Tendermint Core versions, will still be transparently processed. +There is no need to re-index the events. This function field is not exposed to queries, and was not +visible to users. However, if you forked CometBFT and changed the indexer code directly to accommodate for this, +this will impact your code. + ## v0.37.0 This release introduces state machine-breaking changes, and therefore requires a @@ -38,19 +303,29 @@ 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%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`. -* The Application's hash (or any data representing the Application's current state) - is known by the time `FinalizeBlock` finishes its execution. - Accordingly, the `app_hash` parameter has been moved from `ResponseCommit` - to `ResponseFinalizeBlock`. -* For details, please see the updated [specification](spec/abci/README.md) - +- The `ABCIVersion` is now `1.0.0`. +- Added new ABCI methods `PrepareProposal` and `ProcessProposal`. For details, + please see the [spec](spec/abci/README.md). Applications upgrading to + v0.37.0 must implement these methods, at the very minimum, as described + [here](./spec/abci/abci++_app_requirements.md) +- Deduplicated `ConsensusParams` and `BlockParams`. + In the v0.34 branch they are defined both in `abci/types.proto` and `types/params.proto`. + The definitions in `abci/types.proto` have been removed. + In-process applications should make sure they are not using the deleted + version of those structures. +- In v0.34, messages on the wire used to be length-delimited with `int64` varint + values, which was inconsistent with the `uint64` varint length delimiters used + in the P2P layer. Both now consistently use `uint64` varint length delimiters. +- Added `AbciVersion` to `RequestInfo`. + Applications should check that CometBFT's ABCI version matches the one they expect + in order to ensure compatibility. +- The `SetOption` method has been removed from the ABCI `Client` interface. + The corresponding Protobuf types have been deprecated. +- The `key` and `value` fields in the `EventAttribute` type have been changed + from type `bytes` to `string`. As per the [Protocol Buffers updating + guidelines](https://developers.google.com/protocol-buffers/docs/proto3#updating), + this should have no effect on the wire-level encoding for UTF8-encoded + strings. ### RPC @@ -93,7 +368,7 @@ 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`. +example, `TMHOME` becomes `CMTHOME`. 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 @@ -120,3 +395,5 @@ please see the [Tendermint Core upgrading instructions][tmupgrade]. [discussions]: https://github.com/cometbft/cometbft/discussions [tmupgrade]: https://github.com/tendermint/tendermint/blob/35581cf54ec436b8c37fabb43fdaa3f48339a170/UPGRADING.md [go120]: https://go.dev/blog/go1.20 +[go121]: https://go.dev/blog/go1.21 +[pbts-spec]: ./spec/consensus/proposer-based-timestamp/README.md diff --git a/abci/README.md b/abci/README.md index e83e61d42a8..fdbe05ac579 100644 --- a/abci/README.md +++ b/abci/README.md @@ -12,14 +12,14 @@ Previously, the ABCI was referred to as TMSP. ## Installation & Usage -To get up and running quickly, see the [getting started guide](../docs/app-dev/getting-started.md) along with the [abci-cli documentation](../docs/app-dev/abci-cli.md) which will go through the examples found in the [examples](./example/) directory. +To get up and running quickly, see the [getting started guide](../docs/guides/app-dev/getting-started.md) along with the [abci-cli documentation](../docs/guides/app-dev/abci-cli.md) which will go through the examples found in the [examples](./example/) directory. ## Specification A detailed description of the ABCI methods and message types is contained in: - [The main spec](https://github.com/cometbft/cometbft/blob/main/spec/abci/README.md) -- [A protobuf file](../proto/tendermint/types/types.proto) +- [A protobuf file](../proto/cometbft/types/v1/types.proto) - [A Go interface](./types/application.go) ## Protocol Buffers diff --git a/abci/client/client.go b/abci/client/client.go index 2802ab7d510..891066d6278 100644 --- a/abci/client/client.go +++ b/abci/client/client.go @@ -2,12 +2,11 @@ package abcicli import ( "context" - "fmt" "sync" "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) const ( @@ -29,22 +28,22 @@ type Client interface { // TODO: remove as each method now returns an error Error() error // TODO: remove as this is not implemented - Flush(context.Context) error - Echo(context.Context, string) (*types.ResponseEcho, error) + Flush(ctx context.Context) error + Echo(ctx context.Context, echo string) (*types.EchoResponse, error) // FIXME: All other operations are run synchronously and rely // on the caller to dictate concurrency (i.e. run a go routine), // with the exception of `CheckTxAsync` which we maintain // for the v0 mempool. We should explore refactoring the // mempool to remove this vestige behavior. - SetResponseCallback(Callback) - CheckTxAsync(context.Context, *types.RequestCheckTx) (*ReqRes, error) + SetResponseCallback(cb Callback) + CheckTxAsync(ctx context.Context, req *types.CheckTxRequest) (*ReqRes, error) } -//---------------------------------------- +// ---------------------------------------- // NewClient returns a new ABCI client of the specified transport type. -// It returns an error if the transport is not "socket" or "grpc" +// It returns an error if the transport is not "socket" or "grpc". func NewClient(addr, transport string, mustConnect bool) (client Client, err error) { switch transport { case "socket": @@ -52,9 +51,9 @@ func NewClient(addr, transport string, mustConnect bool) (client Client, err err case "grpc": client = NewGRPCClient(addr, mustConnect) default: - err = fmt.Errorf("unknown abci transport %s", transport) + err = ErrUnknownAbciTransport{Transport: transport} } - return + return client, err } type Callback func(*types.Request, *types.Response) @@ -129,5 +128,5 @@ func (r *ReqRes) GetCallback() func(*types.Response) { func waitGroup1() (wg *sync.WaitGroup) { wg = &sync.WaitGroup{} wg.Add(1) - return + return wg } diff --git a/abci/client/errors.go b/abci/client/errors.go new file mode 100644 index 00000000000..a7f3edc4d61 --- /dev/null +++ b/abci/client/errors.go @@ -0,0 +1,25 @@ +package abcicli + +import ( + "fmt" + + "github.com/cometbft/cometbft/abci/types" +) + +// ErrUnknownAbciTransport is returned when trying to create a client with an invalid transport option. +type ErrUnknownAbciTransport struct { + Transport string +} + +func (e ErrUnknownAbciTransport) Error() string { + return "unknown abci transport: " + e.Transport +} + +type ErrUnexpectedResponse struct { + Response types.Response + Reason string +} + +func (e ErrUnexpectedResponse) Error() string { + return fmt.Sprintf("unexpected response %T: %s", e.Response.Value, e.Reason) +} diff --git a/abci/client/grpc_client.go b/abci/client/grpc_client.go index cd8f61d3f95..cf11f237ddc 100644 --- a/abci/client/grpc_client.go +++ b/abci/client/grpc_client.go @@ -11,19 +11,19 @@ import ( "google.golang.org/grpc/credentials/insecure" "github.com/cometbft/cometbft/abci/types" - cmtnet "github.com/cometbft/cometbft/libs/net" - "github.com/cometbft/cometbft/libs/service" + cmtnet "github.com/cometbft/cometbft/internal/net" + "github.com/cometbft/cometbft/internal/service" ) var _ Client = (*grpcClient)(nil) // A stripped copy of the remoteClient that makes -// synchronous calls using grpc +// synchronous calls using grpc. type grpcClient struct { service.BaseService mustConnect bool - client types.ABCIClient + client types.ABCIServiceClient conn *grpc.ClientConn chReqRes chan *ReqRes // dispatches "async" responses to callbacks *in order*, needed by mempool @@ -49,7 +49,7 @@ func NewGRPCClient(addr string, mustConnect bool) Client { return cli } -func dialerFunc(ctx context.Context, addr string) (net.Conn, error) { +func dialerFunc(_ context.Context, addr string) (net.Conn, error) { return cmtnet.Connect(addr) } @@ -106,7 +106,7 @@ RETRY_LOOP: ENSURE_CONNECTED: for { - _, err := client.Echo(context.Background(), &types.RequestEcho{Message: "hello"}, grpc.WaitForReady(true)) + _, err := client.Echo(context.Background(), &types.EchoRequest{Message: "hello"}, grpc.WaitForReady(true)) if err == nil { break ENSURE_CONNECTED } @@ -159,15 +159,15 @@ func (cli *grpcClient) SetResponseCallback(resCb Callback) { cli.mtx.Unlock() } -//---------------------------------------- +// ---------------------------------------- -func (cli *grpcClient) CheckTxAsync(ctx context.Context, req *types.RequestCheckTx) (*ReqRes, error) { +func (cli *grpcClient) CheckTxAsync(ctx context.Context, req *types.CheckTxRequest) (*ReqRes, error) { res, err := cli.client.CheckTx(ctx, req, grpc.WaitForReady(true)) if err != nil { cli.StopForError(err) return nil, err } - return cli.finishAsyncCall(types.ToRequestCheckTx(req), &types.Response{Value: &types.Response_CheckTx{CheckTx: res}}), nil + return cli.finishAsyncCall(types.ToCheckTxRequest(req), &types.Response{Value: &types.Response_CheckTx{CheckTx: res}}), nil } // finishAsyncCall creates a ReqRes for an async call, and immediately populates it @@ -179,69 +179,69 @@ func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) return reqres } -//---------------------------------------- +// ---------------------------------------- func (cli *grpcClient) Flush(ctx context.Context) error { - _, err := cli.client.Flush(ctx, types.ToRequestFlush().GetFlush(), grpc.WaitForReady(true)) + _, err := cli.client.Flush(ctx, types.ToFlushRequest().GetFlush(), grpc.WaitForReady(true)) return err } -func (cli *grpcClient) Echo(ctx context.Context, msg string) (*types.ResponseEcho, error) { - return cli.client.Echo(ctx, types.ToRequestEcho(msg).GetEcho(), grpc.WaitForReady(true)) +func (cli *grpcClient) Echo(ctx context.Context, msg string) (*types.EchoResponse, error) { + return cli.client.Echo(ctx, types.ToEchoRequest(msg).GetEcho(), grpc.WaitForReady(true)) } -func (cli *grpcClient) Info(ctx context.Context, req *types.RequestInfo) (*types.ResponseInfo, error) { +func (cli *grpcClient) Info(ctx context.Context, req *types.InfoRequest) (*types.InfoResponse, error) { return cli.client.Info(ctx, req, grpc.WaitForReady(true)) } -func (cli *grpcClient) CheckTx(ctx context.Context, req *types.RequestCheckTx) (*types.ResponseCheckTx, error) { +func (cli *grpcClient) CheckTx(ctx context.Context, req *types.CheckTxRequest) (*types.CheckTxResponse, error) { return cli.client.CheckTx(ctx, req, grpc.WaitForReady(true)) } -func (cli *grpcClient) Query(ctx context.Context, req *types.RequestQuery) (*types.ResponseQuery, error) { - return cli.client.Query(ctx, types.ToRequestQuery(req).GetQuery(), grpc.WaitForReady(true)) +func (cli *grpcClient) Query(ctx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) { + return cli.client.Query(ctx, types.ToQueryRequest(req).GetQuery(), grpc.WaitForReady(true)) } -func (cli *grpcClient) Commit(ctx context.Context, req *types.RequestCommit) (*types.ResponseCommit, error) { - return cli.client.Commit(ctx, types.ToRequestCommit().GetCommit(), grpc.WaitForReady(true)) +func (cli *grpcClient) Commit(ctx context.Context, _ *types.CommitRequest) (*types.CommitResponse, error) { + return cli.client.Commit(ctx, types.ToCommitRequest().GetCommit(), grpc.WaitForReady(true)) } -func (cli *grpcClient) InitChain(ctx context.Context, req *types.RequestInitChain) (*types.ResponseInitChain, error) { - return cli.client.InitChain(ctx, types.ToRequestInitChain(req).GetInitChain(), grpc.WaitForReady(true)) +func (cli *grpcClient) InitChain(ctx context.Context, req *types.InitChainRequest) (*types.InitChainResponse, error) { + return cli.client.InitChain(ctx, types.ToInitChainRequest(req).GetInitChain(), grpc.WaitForReady(true)) } -func (cli *grpcClient) ListSnapshots(ctx context.Context, req *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) { - return cli.client.ListSnapshots(ctx, types.ToRequestListSnapshots(req).GetListSnapshots(), grpc.WaitForReady(true)) +func (cli *grpcClient) ListSnapshots(ctx context.Context, req *types.ListSnapshotsRequest) (*types.ListSnapshotsResponse, error) { + return cli.client.ListSnapshots(ctx, types.ToListSnapshotsRequest(req).GetListSnapshots(), grpc.WaitForReady(true)) } -func (cli *grpcClient) OfferSnapshot(ctx context.Context, req *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) { - return cli.client.OfferSnapshot(ctx, types.ToRequestOfferSnapshot(req).GetOfferSnapshot(), grpc.WaitForReady(true)) +func (cli *grpcClient) OfferSnapshot(ctx context.Context, req *types.OfferSnapshotRequest) (*types.OfferSnapshotResponse, error) { + return cli.client.OfferSnapshot(ctx, types.ToOfferSnapshotRequest(req).GetOfferSnapshot(), grpc.WaitForReady(true)) } -func (cli *grpcClient) LoadSnapshotChunk(ctx context.Context, req *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { - return cli.client.LoadSnapshotChunk(ctx, types.ToRequestLoadSnapshotChunk(req).GetLoadSnapshotChunk(), grpc.WaitForReady(true)) +func (cli *grpcClient) LoadSnapshotChunk(ctx context.Context, req *types.LoadSnapshotChunkRequest) (*types.LoadSnapshotChunkResponse, error) { + return cli.client.LoadSnapshotChunk(ctx, types.ToLoadSnapshotChunkRequest(req).GetLoadSnapshotChunk(), grpc.WaitForReady(true)) } -func (cli *grpcClient) ApplySnapshotChunk(ctx context.Context, req *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) { - return cli.client.ApplySnapshotChunk(ctx, types.ToRequestApplySnapshotChunk(req).GetApplySnapshotChunk(), grpc.WaitForReady(true)) +func (cli *grpcClient) ApplySnapshotChunk(ctx context.Context, req *types.ApplySnapshotChunkRequest) (*types.ApplySnapshotChunkResponse, error) { + return cli.client.ApplySnapshotChunk(ctx, types.ToApplySnapshotChunkRequest(req).GetApplySnapshotChunk(), grpc.WaitForReady(true)) } -func (cli *grpcClient) PrepareProposal(ctx context.Context, req *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { - return cli.client.PrepareProposal(ctx, types.ToRequestPrepareProposal(req).GetPrepareProposal(), grpc.WaitForReady(true)) +func (cli *grpcClient) PrepareProposal(ctx context.Context, req *types.PrepareProposalRequest) (*types.PrepareProposalResponse, error) { + return cli.client.PrepareProposal(ctx, types.ToPrepareProposalRequest(req).GetPrepareProposal(), grpc.WaitForReady(true)) } -func (cli *grpcClient) ProcessProposal(ctx context.Context, req *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { - return cli.client.ProcessProposal(ctx, types.ToRequestProcessProposal(req).GetProcessProposal(), grpc.WaitForReady(true)) +func (cli *grpcClient) ProcessProposal(ctx context.Context, req *types.ProcessProposalRequest) (*types.ProcessProposalResponse, error) { + return cli.client.ProcessProposal(ctx, types.ToProcessProposalRequest(req).GetProcessProposal(), grpc.WaitForReady(true)) } -func (cli *grpcClient) ExtendVote(ctx context.Context, req *types.RequestExtendVote) (*types.ResponseExtendVote, error) { - return cli.client.ExtendVote(ctx, types.ToRequestExtendVote(req).GetExtendVote(), grpc.WaitForReady(true)) +func (cli *grpcClient) ExtendVote(ctx context.Context, req *types.ExtendVoteRequest) (*types.ExtendVoteResponse, error) { + return cli.client.ExtendVote(ctx, types.ToExtendVoteRequest(req).GetExtendVote(), grpc.WaitForReady(true)) } -func (cli *grpcClient) VerifyVoteExtension(ctx context.Context, req *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) { - return cli.client.VerifyVoteExtension(ctx, types.ToRequestVerifyVoteExtension(req).GetVerifyVoteExtension(), grpc.WaitForReady(true)) +func (cli *grpcClient) VerifyVoteExtension(ctx context.Context, req *types.VerifyVoteExtensionRequest) (*types.VerifyVoteExtensionResponse, error) { + return cli.client.VerifyVoteExtension(ctx, types.ToVerifyVoteExtensionRequest(req).GetVerifyVoteExtension(), grpc.WaitForReady(true)) } -func (cli *grpcClient) FinalizeBlock(ctx context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { - return cli.client.FinalizeBlock(ctx, types.ToRequestFinalizeBlock(req).GetFinalizeBlock(), grpc.WaitForReady(true)) +func (cli *grpcClient) FinalizeBlock(ctx context.Context, req *types.FinalizeBlockRequest) (*types.FinalizeBlockResponse, error) { + return cli.client.FinalizeBlock(ctx, types.ToFinalizeBlockRequest(req).GetFinalizeBlock(), grpc.WaitForReady(true)) } diff --git a/abci/client/grpc_client_test.go b/abci/client/grpc_client_test.go index ac866d39b64..85b410cd06d 100644 --- a/abci/client/grpc_client_test.go +++ b/abci/client/grpc_client_test.go @@ -9,16 +9,14 @@ import ( "time" "github.com/stretchr/testify/require" - - "google.golang.org/grpc" - "golang.org/x/net/context" - - "github.com/cometbft/cometbft/libs/log" - cmtnet "github.com/cometbft/cometbft/libs/net" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" abciserver "github.com/cometbft/cometbft/abci/server" "github.com/cometbft/cometbft/abci/types" + cmtnet "github.com/cometbft/cometbft/internal/net" + "github.com/cometbft/cometbft/libs/log" ) func TestGRPC(t *testing.T) { @@ -41,8 +39,7 @@ func TestGRPC(t *testing.T) { }) // Connect to the socket - //nolint:staticcheck // SA1019 Existing use of deprecated but supported dial option. - conn, err := grpc.Dial(socket, grpc.WithInsecure(), grpc.WithContextDialer(dialerFunc)) + conn, err := grpc.Dial(socket, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(dialerFunc)) require.NoError(t, err) t.Cleanup(func() { @@ -56,7 +53,12 @@ func TestGRPC(t *testing.T) { // Write requests for counter := 0; counter < numCheckTxs; counter++ { // Send request - response, err := client.CheckTx(context.Background(), &types.RequestCheckTx{Tx: []byte("test")}) + response, err := client.CheckTx( + context.Background(), + &types.CheckTxRequest{ + Tx: []byte("test"), + Type: types.CHECK_TX_TYPE_CHECK, + }) require.NoError(t, err) counter++ if response.Code != 0 { @@ -71,10 +73,9 @@ func TestGRPC(t *testing.T) { time.Sleep(time.Second * 1) // Wait for a bit to allow counter overflow }() } - } } -func dialerFunc(ctx context.Context, addr string) (net.Conn, error) { +func dialerFunc(_ context.Context, addr string) (net.Conn, error) { return cmtnet.Connect(addr) } diff --git a/abci/client/local_client.go b/abci/client/local_client.go index 63345a56265..ce55c1dc58b 100644 --- a/abci/client/local_client.go +++ b/abci/client/local_client.go @@ -3,9 +3,9 @@ package abcicli import ( "context" - types "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" + "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) // NOTE: use defer to unlock mutex because Application might panic (e.g., in @@ -22,10 +22,12 @@ type localClient struct { var _ Client = (*localClient)(nil) -// NewLocalClient creates a local client, which wraps the application interface that -// Tendermint as the client will call to the application as the server. The only -// difference, is that the local client has a global mutex which enforces serialization -// of all the ABCI calls from Tendermint to the Application. +// NewLocalClient creates a local client, which wraps the application interface +// that Comet as the client will call to the application as the server. +// +// Concurrency control in each client instance is enforced by way of a single +// mutex. If a mutex is not supplied (i.e. if mtx is nil), then one will be +// created. func NewLocalClient(mtx *cmtsync.Mutex, app types.Application) Client { if mtx == nil { mtx = new(cmtsync.Mutex) @@ -44,7 +46,7 @@ func (app *localClient) SetResponseCallback(cb Callback) { app.mtx.Unlock() } -func (app *localClient) CheckTxAsync(ctx context.Context, req *types.RequestCheckTx) (*ReqRes, error) { +func (app *localClient) CheckTxAsync(ctx context.Context, req *types.CheckTxRequest) (*ReqRes, error) { app.mtx.Lock() defer app.mtx.Unlock() @@ -53,8 +55,8 @@ func (app *localClient) CheckTxAsync(ctx context.Context, req *types.RequestChec return nil, err } return app.callback( - types.ToRequestCheckTx(req), - types.ToResponseCheckTx(res), + types.ToCheckTxRequest(req), + types.ToCheckTxResponse(res), ), nil } @@ -71,63 +73,63 @@ func newLocalReqRes(req *types.Request, res *types.Response) *ReqRes { return reqRes } -//------------------------------------------------------- +// ------------------------------------------------------- -func (app *localClient) Error() error { +func (*localClient) Error() error { return nil } -func (app *localClient) Flush(context.Context) error { +func (*localClient) Flush(context.Context) error { return nil } -func (app *localClient) Echo(_ context.Context, msg string) (*types.ResponseEcho, error) { - return &types.ResponseEcho{Message: msg}, nil +func (*localClient) Echo(_ context.Context, msg string) (*types.EchoResponse, error) { + return &types.EchoResponse{Message: msg}, nil } -func (app *localClient) Info(ctx context.Context, req *types.RequestInfo) (*types.ResponseInfo, error) { +func (app *localClient) Info(ctx context.Context, req *types.InfoRequest) (*types.InfoResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.Info(ctx, req) } -func (app *localClient) CheckTx(ctx context.Context, req *types.RequestCheckTx) (*types.ResponseCheckTx, error) { +func (app *localClient) CheckTx(ctx context.Context, req *types.CheckTxRequest) (*types.CheckTxResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.CheckTx(ctx, req) } -func (app *localClient) Query(ctx context.Context, req *types.RequestQuery) (*types.ResponseQuery, error) { +func (app *localClient) Query(ctx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.Query(ctx, req) } -func (app *localClient) Commit(ctx context.Context, req *types.RequestCommit) (*types.ResponseCommit, error) { +func (app *localClient) Commit(ctx context.Context, req *types.CommitRequest) (*types.CommitResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.Commit(ctx, req) } -func (app *localClient) InitChain(ctx context.Context, req *types.RequestInitChain) (*types.ResponseInitChain, error) { +func (app *localClient) InitChain(ctx context.Context, req *types.InitChainRequest) (*types.InitChainResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.InitChain(ctx, req) } -func (app *localClient) ListSnapshots(ctx context.Context, req *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) { +func (app *localClient) ListSnapshots(ctx context.Context, req *types.ListSnapshotsRequest) (*types.ListSnapshotsResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.ListSnapshots(ctx, req) } -func (app *localClient) OfferSnapshot(ctx context.Context, req *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) { +func (app *localClient) OfferSnapshot(ctx context.Context, req *types.OfferSnapshotRequest) (*types.OfferSnapshotResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() @@ -135,7 +137,8 @@ func (app *localClient) OfferSnapshot(ctx context.Context, req *types.RequestOff } func (app *localClient) LoadSnapshotChunk(ctx context.Context, - req *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { + req *types.LoadSnapshotChunkRequest, +) (*types.LoadSnapshotChunkResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() @@ -143,42 +146,43 @@ func (app *localClient) LoadSnapshotChunk(ctx context.Context, } func (app *localClient) ApplySnapshotChunk(ctx context.Context, - req *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) { + req *types.ApplySnapshotChunkRequest, +) (*types.ApplySnapshotChunkResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.ApplySnapshotChunk(ctx, req) } -func (app *localClient) PrepareProposal(ctx context.Context, req *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { +func (app *localClient) PrepareProposal(ctx context.Context, req *types.PrepareProposalRequest) (*types.PrepareProposalResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.PrepareProposal(ctx, req) } -func (app *localClient) ProcessProposal(ctx context.Context, req *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { +func (app *localClient) ProcessProposal(ctx context.Context, req *types.ProcessProposalRequest) (*types.ProcessProposalResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.ProcessProposal(ctx, req) } -func (app *localClient) ExtendVote(ctx context.Context, req *types.RequestExtendVote) (*types.ResponseExtendVote, error) { +func (app *localClient) ExtendVote(ctx context.Context, req *types.ExtendVoteRequest) (*types.ExtendVoteResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.ExtendVote(ctx, req) } -func (app *localClient) VerifyVoteExtension(ctx context.Context, req *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) { +func (app *localClient) VerifyVoteExtension(ctx context.Context, req *types.VerifyVoteExtensionRequest) (*types.VerifyVoteExtensionResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() return app.Application.VerifyVoteExtension(ctx, req) } -func (app *localClient) FinalizeBlock(ctx context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { +func (app *localClient) FinalizeBlock(ctx context.Context, req *types.FinalizeBlockRequest) (*types.FinalizeBlockResponse, error) { app.mtx.Lock() defer app.mtx.Unlock() diff --git a/abci/client/mocks/client.go b/abci/client/mocks/client.go index 6494bdb5db7..e18372bde4e 100644 --- a/abci/client/mocks/client.go +++ b/abci/client/mocks/client.go @@ -11,7 +11,7 @@ import ( mock "github.com/stretchr/testify/mock" - types "github.com/cometbft/cometbft/abci/types" + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" ) // Client is an autogenerated mock type for the Client type @@ -19,25 +19,29 @@ type Client struct { mock.Mock } -// ApplySnapshotChunk provides a mock function with given fields: _a0, _a1 -func (_m *Client) ApplySnapshotChunk(_a0 context.Context, _a1 *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) { - ret := _m.Called(_a0, _a1) +// ApplySnapshotChunk provides a mock function with given fields: ctx, req +func (_m *Client) ApplySnapshotChunk(ctx context.Context, req *v1.ApplySnapshotChunkRequest) (*v1.ApplySnapshotChunkResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseApplySnapshotChunk + if len(ret) == 0 { + panic("no return value specified for ApplySnapshotChunk") + } + + var r0 *v1.ApplySnapshotChunkResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ApplySnapshotChunkRequest) (*v1.ApplySnapshotChunkResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestApplySnapshotChunk) *types.ResponseApplySnapshotChunk); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ApplySnapshotChunkRequest) *v1.ApplySnapshotChunkResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseApplySnapshotChunk) + r0 = ret.Get(0).(*v1.ApplySnapshotChunkResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestApplySnapshotChunk) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ApplySnapshotChunkRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -45,25 +49,29 @@ func (_m *Client) ApplySnapshotChunk(_a0 context.Context, _a1 *types.RequestAppl return r0, r1 } -// CheckTx provides a mock function with given fields: _a0, _a1 -func (_m *Client) CheckTx(_a0 context.Context, _a1 *types.RequestCheckTx) (*types.ResponseCheckTx, error) { - ret := _m.Called(_a0, _a1) +// CheckTx provides a mock function with given fields: ctx, req +func (_m *Client) CheckTx(ctx context.Context, req *v1.CheckTxRequest) (*v1.CheckTxResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for CheckTx") + } - var r0 *types.ResponseCheckTx + var r0 *v1.CheckTxResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) (*types.ResponseCheckTx, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) (*v1.CheckTxResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) *types.ResponseCheckTx); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) *v1.CheckTxResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseCheckTx) + r0 = ret.Get(0).(*v1.CheckTxResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestCheckTx) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.CheckTxRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -71,25 +79,29 @@ func (_m *Client) CheckTx(_a0 context.Context, _a1 *types.RequestCheckTx) (*type return r0, r1 } -// CheckTxAsync provides a mock function with given fields: _a0, _a1 -func (_m *Client) CheckTxAsync(_a0 context.Context, _a1 *types.RequestCheckTx) (*abcicli.ReqRes, error) { - ret := _m.Called(_a0, _a1) +// CheckTxAsync provides a mock function with given fields: ctx, req +func (_m *Client) CheckTxAsync(ctx context.Context, req *v1.CheckTxRequest) (*abcicli.ReqRes, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for CheckTxAsync") + } var r0 *abcicli.ReqRes var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) (*abcicli.ReqRes, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) (*abcicli.ReqRes, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) *abcicli.ReqRes); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) *abcicli.ReqRes); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*abcicli.ReqRes) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestCheckTx) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.CheckTxRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -97,25 +109,29 @@ func (_m *Client) CheckTxAsync(_a0 context.Context, _a1 *types.RequestCheckTx) ( return r0, r1 } -// Commit provides a mock function with given fields: _a0, _a1 -func (_m *Client) Commit(_a0 context.Context, _a1 *types.RequestCommit) (*types.ResponseCommit, error) { - ret := _m.Called(_a0, _a1) +// Commit provides a mock function with given fields: ctx, req +func (_m *Client) Commit(ctx context.Context, req *v1.CommitRequest) (*v1.CommitResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for Commit") + } - var r0 *types.ResponseCommit + var r0 *v1.CommitResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCommit) (*types.ResponseCommit, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CommitRequest) (*v1.CommitResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCommit) *types.ResponseCommit); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CommitRequest) *v1.CommitResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseCommit) + r0 = ret.Get(0).(*v1.CommitResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestCommit) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.CommitRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -123,25 +139,29 @@ func (_m *Client) Commit(_a0 context.Context, _a1 *types.RequestCommit) (*types. return r0, r1 } -// Echo provides a mock function with given fields: _a0, _a1 -func (_m *Client) Echo(_a0 context.Context, _a1 string) (*types.ResponseEcho, error) { - ret := _m.Called(_a0, _a1) +// Echo provides a mock function with given fields: ctx, echo +func (_m *Client) Echo(ctx context.Context, echo string) (*v1.EchoResponse, error) { + ret := _m.Called(ctx, echo) + + if len(ret) == 0 { + panic("no return value specified for Echo") + } - var r0 *types.ResponseEcho + var r0 *v1.EchoResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (*types.ResponseEcho, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, string) (*v1.EchoResponse, error)); ok { + return rf(ctx, echo) } - if rf, ok := ret.Get(0).(func(context.Context, string) *types.ResponseEcho); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, string) *v1.EchoResponse); ok { + r0 = rf(ctx, echo) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseEcho) + r0 = ret.Get(0).(*v1.EchoResponse) } } if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(_a0, _a1) + r1 = rf(ctx, echo) } else { r1 = ret.Error(1) } @@ -153,6 +173,10 @@ func (_m *Client) Echo(_a0 context.Context, _a1 string) (*types.ResponseEcho, er func (_m *Client) Error() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Error") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -163,25 +187,29 @@ func (_m *Client) Error() error { return r0 } -// ExtendVote provides a mock function with given fields: _a0, _a1 -func (_m *Client) ExtendVote(_a0 context.Context, _a1 *types.RequestExtendVote) (*types.ResponseExtendVote, error) { - ret := _m.Called(_a0, _a1) +// ExtendVote provides a mock function with given fields: ctx, req +func (_m *Client) ExtendVote(ctx context.Context, req *v1.ExtendVoteRequest) (*v1.ExtendVoteResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for ExtendVote") + } - var r0 *types.ResponseExtendVote + var r0 *v1.ExtendVoteResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestExtendVote) (*types.ResponseExtendVote, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExtendVoteRequest) (*v1.ExtendVoteResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestExtendVote) *types.ResponseExtendVote); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExtendVoteRequest) *v1.ExtendVoteResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseExtendVote) + r0 = ret.Get(0).(*v1.ExtendVoteResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestExtendVote) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ExtendVoteRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -189,25 +217,29 @@ func (_m *Client) ExtendVote(_a0 context.Context, _a1 *types.RequestExtendVote) return r0, r1 } -// FinalizeBlock provides a mock function with given fields: _a0, _a1 -func (_m *Client) FinalizeBlock(_a0 context.Context, _a1 *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { - ret := _m.Called(_a0, _a1) +// FinalizeBlock provides a mock function with given fields: ctx, req +func (_m *Client) FinalizeBlock(ctx context.Context, req *v1.FinalizeBlockRequest) (*v1.FinalizeBlockResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseFinalizeBlock + if len(ret) == 0 { + panic("no return value specified for FinalizeBlock") + } + + var r0 *v1.FinalizeBlockResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.FinalizeBlockRequest) (*v1.FinalizeBlockResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestFinalizeBlock) *types.ResponseFinalizeBlock); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.FinalizeBlockRequest) *v1.FinalizeBlockResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseFinalizeBlock) + r0 = ret.Get(0).(*v1.FinalizeBlockResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestFinalizeBlock) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.FinalizeBlockRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -215,13 +247,17 @@ func (_m *Client) FinalizeBlock(_a0 context.Context, _a1 *types.RequestFinalizeB return r0, r1 } -// Flush provides a mock function with given fields: _a0 -func (_m *Client) Flush(_a0 context.Context) error { - ret := _m.Called(_a0) +// Flush provides a mock function with given fields: ctx +func (_m *Client) Flush(ctx context.Context) error { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for Flush") + } var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -229,25 +265,29 @@ func (_m *Client) Flush(_a0 context.Context) error { return r0 } -// Info provides a mock function with given fields: _a0, _a1 -func (_m *Client) Info(_a0 context.Context, _a1 *types.RequestInfo) (*types.ResponseInfo, error) { - ret := _m.Called(_a0, _a1) +// Info provides a mock function with given fields: ctx, req +func (_m *Client) Info(ctx context.Context, req *v1.InfoRequest) (*v1.InfoResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseInfo + if len(ret) == 0 { + panic("no return value specified for Info") + } + + var r0 *v1.InfoResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInfo) (*types.ResponseInfo, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InfoRequest) (*v1.InfoResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInfo) *types.ResponseInfo); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InfoRequest) *v1.InfoResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseInfo) + r0 = ret.Get(0).(*v1.InfoResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestInfo) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.InfoRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -255,25 +295,29 @@ func (_m *Client) Info(_a0 context.Context, _a1 *types.RequestInfo) (*types.Resp return r0, r1 } -// InitChain provides a mock function with given fields: _a0, _a1 -func (_m *Client) InitChain(_a0 context.Context, _a1 *types.RequestInitChain) (*types.ResponseInitChain, error) { - ret := _m.Called(_a0, _a1) +// InitChain provides a mock function with given fields: ctx, req +func (_m *Client) InitChain(ctx context.Context, req *v1.InitChainRequest) (*v1.InitChainResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for InitChain") + } - var r0 *types.ResponseInitChain + var r0 *v1.InitChainResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInitChain) (*types.ResponseInitChain, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InitChainRequest) (*v1.InitChainResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInitChain) *types.ResponseInitChain); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InitChainRequest) *v1.InitChainResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseInitChain) + r0 = ret.Get(0).(*v1.InitChainResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestInitChain) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.InitChainRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -285,6 +329,10 @@ func (_m *Client) InitChain(_a0 context.Context, _a1 *types.RequestInitChain) (* func (_m *Client) IsRunning() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsRunning") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -295,25 +343,29 @@ func (_m *Client) IsRunning() bool { return r0 } -// ListSnapshots provides a mock function with given fields: _a0, _a1 -func (_m *Client) ListSnapshots(_a0 context.Context, _a1 *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) { - ret := _m.Called(_a0, _a1) +// ListSnapshots provides a mock function with given fields: ctx, req +func (_m *Client) ListSnapshots(ctx context.Context, req *v1.ListSnapshotsRequest) (*v1.ListSnapshotsResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseListSnapshots + if len(ret) == 0 { + panic("no return value specified for ListSnapshots") + } + + var r0 *v1.ListSnapshotsResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestListSnapshots) (*types.ResponseListSnapshots, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ListSnapshotsRequest) (*v1.ListSnapshotsResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestListSnapshots) *types.ResponseListSnapshots); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ListSnapshotsRequest) *v1.ListSnapshotsResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseListSnapshots) + r0 = ret.Get(0).(*v1.ListSnapshotsResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestListSnapshots) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ListSnapshotsRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -321,25 +373,29 @@ func (_m *Client) ListSnapshots(_a0 context.Context, _a1 *types.RequestListSnaps return r0, r1 } -// LoadSnapshotChunk provides a mock function with given fields: _a0, _a1 -func (_m *Client) LoadSnapshotChunk(_a0 context.Context, _a1 *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { - ret := _m.Called(_a0, _a1) +// LoadSnapshotChunk provides a mock function with given fields: ctx, req +func (_m *Client) LoadSnapshotChunk(ctx context.Context, req *v1.LoadSnapshotChunkRequest) (*v1.LoadSnapshotChunkResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for LoadSnapshotChunk") + } - var r0 *types.ResponseLoadSnapshotChunk + var r0 *v1.LoadSnapshotChunkResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.LoadSnapshotChunkRequest) (*v1.LoadSnapshotChunkResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestLoadSnapshotChunk) *types.ResponseLoadSnapshotChunk); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.LoadSnapshotChunkRequest) *v1.LoadSnapshotChunkResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseLoadSnapshotChunk) + r0 = ret.Get(0).(*v1.LoadSnapshotChunkResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestLoadSnapshotChunk) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.LoadSnapshotChunkRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -347,25 +403,29 @@ func (_m *Client) LoadSnapshotChunk(_a0 context.Context, _a1 *types.RequestLoadS return r0, r1 } -// OfferSnapshot provides a mock function with given fields: _a0, _a1 -func (_m *Client) OfferSnapshot(_a0 context.Context, _a1 *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) { - ret := _m.Called(_a0, _a1) +// OfferSnapshot provides a mock function with given fields: ctx, req +func (_m *Client) OfferSnapshot(ctx context.Context, req *v1.OfferSnapshotRequest) (*v1.OfferSnapshotResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseOfferSnapshot + if len(ret) == 0 { + panic("no return value specified for OfferSnapshot") + } + + var r0 *v1.OfferSnapshotResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.OfferSnapshotRequest) (*v1.OfferSnapshotResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestOfferSnapshot) *types.ResponseOfferSnapshot); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.OfferSnapshotRequest) *v1.OfferSnapshotResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseOfferSnapshot) + r0 = ret.Get(0).(*v1.OfferSnapshotResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestOfferSnapshot) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.OfferSnapshotRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -377,6 +437,10 @@ func (_m *Client) OfferSnapshot(_a0 context.Context, _a1 *types.RequestOfferSnap func (_m *Client) OnReset() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for OnReset") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -391,6 +455,10 @@ func (_m *Client) OnReset() error { func (_m *Client) OnStart() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for OnStart") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -406,25 +474,29 @@ func (_m *Client) OnStop() { _m.Called() } -// PrepareProposal provides a mock function with given fields: _a0, _a1 -func (_m *Client) PrepareProposal(_a0 context.Context, _a1 *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { - ret := _m.Called(_a0, _a1) +// PrepareProposal provides a mock function with given fields: ctx, req +func (_m *Client) PrepareProposal(ctx context.Context, req *v1.PrepareProposalRequest) (*v1.PrepareProposalResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for PrepareProposal") + } - var r0 *types.ResponsePrepareProposal + var r0 *v1.PrepareProposalResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.PrepareProposalRequest) (*v1.PrepareProposalResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestPrepareProposal) *types.ResponsePrepareProposal); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.PrepareProposalRequest) *v1.PrepareProposalResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponsePrepareProposal) + r0 = ret.Get(0).(*v1.PrepareProposalResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestPrepareProposal) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.PrepareProposalRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -432,25 +504,29 @@ func (_m *Client) PrepareProposal(_a0 context.Context, _a1 *types.RequestPrepare return r0, r1 } -// ProcessProposal provides a mock function with given fields: _a0, _a1 -func (_m *Client) ProcessProposal(_a0 context.Context, _a1 *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { - ret := _m.Called(_a0, _a1) +// ProcessProposal provides a mock function with given fields: ctx, req +func (_m *Client) ProcessProposal(ctx context.Context, req *v1.ProcessProposalRequest) (*v1.ProcessProposalResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for ProcessProposal") + } - var r0 *types.ResponseProcessProposal + var r0 *v1.ProcessProposalResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestProcessProposal) (*types.ResponseProcessProposal, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ProcessProposalRequest) (*v1.ProcessProposalResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestProcessProposal) *types.ResponseProcessProposal); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ProcessProposalRequest) *v1.ProcessProposalResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseProcessProposal) + r0 = ret.Get(0).(*v1.ProcessProposalResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestProcessProposal) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ProcessProposalRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -458,25 +534,29 @@ func (_m *Client) ProcessProposal(_a0 context.Context, _a1 *types.RequestProcess return r0, r1 } -// Query provides a mock function with given fields: _a0, _a1 -func (_m *Client) Query(_a0 context.Context, _a1 *types.RequestQuery) (*types.ResponseQuery, error) { - ret := _m.Called(_a0, _a1) +// Query provides a mock function with given fields: ctx, req +func (_m *Client) Query(ctx context.Context, req *v1.QueryRequest) (*v1.QueryResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseQuery + if len(ret) == 0 { + panic("no return value specified for Query") + } + + var r0 *v1.QueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestQuery) (*types.ResponseQuery, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.QueryRequest) (*v1.QueryResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestQuery) *types.ResponseQuery); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.QueryRequest) *v1.QueryResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseQuery) + r0 = ret.Get(0).(*v1.QueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestQuery) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.QueryRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -488,6 +568,10 @@ func (_m *Client) Query(_a0 context.Context, _a1 *types.RequestQuery) (*types.Re func (_m *Client) Quit() <-chan struct{} { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Quit") + } + var r0 <-chan struct{} if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { r0 = rf() @@ -504,6 +588,10 @@ func (_m *Client) Quit() <-chan struct{} { func (_m *Client) Reset() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Reset") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -514,20 +602,24 @@ func (_m *Client) Reset() error { return r0 } -// SetLogger provides a mock function with given fields: _a0 -func (_m *Client) SetLogger(_a0 log.Logger) { - _m.Called(_a0) +// SetLogger provides a mock function with given fields: l +func (_m *Client) SetLogger(l log.Logger) { + _m.Called(l) } -// SetResponseCallback provides a mock function with given fields: _a0 -func (_m *Client) SetResponseCallback(_a0 abcicli.Callback) { - _m.Called(_a0) +// SetResponseCallback provides a mock function with given fields: cb +func (_m *Client) SetResponseCallback(cb abcicli.Callback) { + _m.Called(cb) } // Start provides a mock function with given fields: func (_m *Client) Start() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Start") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -542,6 +634,10 @@ func (_m *Client) Start() error { func (_m *Client) Stop() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Stop") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -556,6 +652,10 @@ func (_m *Client) Stop() error { func (_m *Client) String() string { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for String") + } + var r0 string if rf, ok := ret.Get(0).(func() string); ok { r0 = rf() @@ -566,25 +666,29 @@ func (_m *Client) String() string { return r0 } -// VerifyVoteExtension provides a mock function with given fields: _a0, _a1 -func (_m *Client) VerifyVoteExtension(_a0 context.Context, _a1 *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) { - ret := _m.Called(_a0, _a1) +// VerifyVoteExtension provides a mock function with given fields: ctx, req +func (_m *Client) VerifyVoteExtension(ctx context.Context, req *v1.VerifyVoteExtensionRequest) (*v1.VerifyVoteExtensionResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for VerifyVoteExtension") + } - var r0 *types.ResponseVerifyVoteExtension + var r0 *v1.VerifyVoteExtensionResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.VerifyVoteExtensionRequest) (*v1.VerifyVoteExtensionResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestVerifyVoteExtension) *types.ResponseVerifyVoteExtension); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.VerifyVoteExtensionRequest) *v1.VerifyVoteExtensionResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseVerifyVoteExtension) + r0 = ret.Get(0).(*v1.VerifyVoteExtensionResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestVerifyVoteExtension) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.VerifyVoteExtensionRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -592,13 +696,12 @@ func (_m *Client) VerifyVoteExtension(_a0 context.Context, _a1 *types.RequestVer return r0, r1 } -type mockConstructorTestingTNewClient interface { +// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClient(t mockConstructorTestingTNewClient) *Client { +}) *Client { mock := &Client{} mock.Mock.Test(t) diff --git a/abci/client/socket_client.go b/abci/client/socket_client.go index ccac4bbab19..7d573636d79 100644 --- a/abci/client/socket_client.go +++ b/abci/client/socket_client.go @@ -12,9 +12,9 @@ import ( "time" "github.com/cometbft/cometbft/abci/types" - cmtnet "github.com/cometbft/cometbft/libs/net" - "github.com/cometbft/cometbft/libs/service" - "github.com/cometbft/cometbft/libs/timer" + cmtnet "github.com/cometbft/cometbft/internal/net" + "github.com/cometbft/cometbft/internal/service" + "github.com/cometbft/cometbft/internal/timer" ) const ( @@ -108,7 +108,7 @@ func (cli *socketClient) Error() error { return cli.err } -//---------------------------------------- +// ---------------------------------------- // SetResponseCallback sets a callback, which will be executed for each // non-error & non-empty response from the server. @@ -120,11 +120,11 @@ func (cli *socketClient) SetResponseCallback(resCb Callback) { cli.mtx.Unlock() } -func (cli *socketClient) CheckTxAsync(ctx context.Context, req *types.RequestCheckTx) (*ReqRes, error) { - return cli.queueRequest(ctx, types.ToRequestCheckTx(req)) +func (cli *socketClient) CheckTxAsync(ctx context.Context, req *types.CheckTxRequest) (*ReqRes, error) { + return cli.queueRequest(ctx, types.ToCheckTxRequest(req)) } -//---------------------------------------- +// ---------------------------------------- func (cli *socketClient) sendRequestsRoutine(conn io.Writer) { w := bufio.NewWriter(conn) @@ -152,7 +152,7 @@ func (cli *socketClient) sendRequestsRoutine(conn io.Writer) { } case <-cli.flushTimer.Ch: // flush queue select { - case cli.reqQueue <- NewReqRes(types.ToRequestFlush()): + case cli.reqQueue <- NewReqRes(types.ToFlushRequest()): default: // Probably will fill the buffer, or retry later. } @@ -169,7 +169,7 @@ func (cli *socketClient) recvResponseRoutine(conn io.Reader) { return } - var res = &types.Response{} + res := &types.Response{} err := types.ReadMessage(r, res) if err != nil { cli.stopForError(fmt.Errorf("read message: %w", err)) @@ -210,12 +210,12 @@ func (cli *socketClient) didRecvResponse(res *types.Response) error { // Get the first ReqRes. next := cli.reqSent.Front() if next == nil { - return fmt.Errorf("unexpected response %T when no call was made", res.Value) + return ErrUnexpectedResponse{Response: *res, Reason: "no call was made"} } reqres := next.Value.(*ReqRes) if !resMatchesReq(reqres.Request, res) { - return fmt.Errorf("unexpected response %T to the request %T", res.Value, reqres.Request.Value) + return ErrUnexpectedResponse{Response: *res, Reason: fmt.Sprintf("unexpected response to the request %T", reqres.Request.Value)} } reqres.Response = res @@ -236,10 +236,10 @@ func (cli *socketClient) didRecvResponse(res *types.Response) error { return nil } -//---------------------------------------- +// ---------------------------------------- func (cli *socketClient) Flush(ctx context.Context) error { - reqRes, err := cli.queueRequest(ctx, types.ToRequestFlush()) + reqRes, err := cli.queueRequest(ctx, types.ToFlushRequest()) if err != nil { return err } @@ -247,8 +247,8 @@ func (cli *socketClient) Flush(ctx context.Context) error { return nil } -func (cli *socketClient) Echo(ctx context.Context, msg string) (*types.ResponseEcho, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestEcho(msg)) +func (cli *socketClient) Echo(ctx context.Context, msg string) (*types.EchoResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToEchoRequest(msg)) if err != nil { return nil, err } @@ -258,8 +258,8 @@ func (cli *socketClient) Echo(ctx context.Context, msg string) (*types.ResponseE return reqRes.Response.GetEcho(), cli.Error() } -func (cli *socketClient) Info(ctx context.Context, req *types.RequestInfo) (*types.ResponseInfo, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestInfo(req)) +func (cli *socketClient) Info(ctx context.Context, req *types.InfoRequest) (*types.InfoResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToInfoRequest(req)) if err != nil { return nil, err } @@ -269,8 +269,8 @@ func (cli *socketClient) Info(ctx context.Context, req *types.RequestInfo) (*typ return reqRes.Response.GetInfo(), cli.Error() } -func (cli *socketClient) CheckTx(ctx context.Context, req *types.RequestCheckTx) (*types.ResponseCheckTx, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestCheckTx(req)) +func (cli *socketClient) CheckTx(ctx context.Context, req *types.CheckTxRequest) (*types.CheckTxResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToCheckTxRequest(req)) if err != nil { return nil, err } @@ -280,8 +280,8 @@ func (cli *socketClient) CheckTx(ctx context.Context, req *types.RequestCheckTx) return reqRes.Response.GetCheckTx(), cli.Error() } -func (cli *socketClient) Query(ctx context.Context, req *types.RequestQuery) (*types.ResponseQuery, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestQuery(req)) +func (cli *socketClient) Query(ctx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToQueryRequest(req)) if err != nil { return nil, err } @@ -291,8 +291,8 @@ func (cli *socketClient) Query(ctx context.Context, req *types.RequestQuery) (*t return reqRes.Response.GetQuery(), cli.Error() } -func (cli *socketClient) Commit(ctx context.Context, req *types.RequestCommit) (*types.ResponseCommit, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestCommit()) +func (cli *socketClient) Commit(ctx context.Context, _ *types.CommitRequest) (*types.CommitResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToCommitRequest()) if err != nil { return nil, err } @@ -302,8 +302,8 @@ func (cli *socketClient) Commit(ctx context.Context, req *types.RequestCommit) ( return reqRes.Response.GetCommit(), cli.Error() } -func (cli *socketClient) InitChain(ctx context.Context, req *types.RequestInitChain) (*types.ResponseInitChain, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestInitChain(req)) +func (cli *socketClient) InitChain(ctx context.Context, req *types.InitChainRequest) (*types.InitChainResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToInitChainRequest(req)) if err != nil { return nil, err } @@ -313,8 +313,8 @@ func (cli *socketClient) InitChain(ctx context.Context, req *types.RequestInitCh return reqRes.Response.GetInitChain(), cli.Error() } -func (cli *socketClient) ListSnapshots(ctx context.Context, req *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestListSnapshots(req)) +func (cli *socketClient) ListSnapshots(ctx context.Context, req *types.ListSnapshotsRequest) (*types.ListSnapshotsResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToListSnapshotsRequest(req)) if err != nil { return nil, err } @@ -324,8 +324,8 @@ func (cli *socketClient) ListSnapshots(ctx context.Context, req *types.RequestLi return reqRes.Response.GetListSnapshots(), cli.Error() } -func (cli *socketClient) OfferSnapshot(ctx context.Context, req *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestOfferSnapshot(req)) +func (cli *socketClient) OfferSnapshot(ctx context.Context, req *types.OfferSnapshotRequest) (*types.OfferSnapshotResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToOfferSnapshotRequest(req)) if err != nil { return nil, err } @@ -335,8 +335,8 @@ func (cli *socketClient) OfferSnapshot(ctx context.Context, req *types.RequestOf return reqRes.Response.GetOfferSnapshot(), cli.Error() } -func (cli *socketClient) LoadSnapshotChunk(ctx context.Context, req *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestLoadSnapshotChunk(req)) +func (cli *socketClient) LoadSnapshotChunk(ctx context.Context, req *types.LoadSnapshotChunkRequest) (*types.LoadSnapshotChunkResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToLoadSnapshotChunkRequest(req)) if err != nil { return nil, err } @@ -346,8 +346,8 @@ func (cli *socketClient) LoadSnapshotChunk(ctx context.Context, req *types.Reque return reqRes.Response.GetLoadSnapshotChunk(), cli.Error() } -func (cli *socketClient) ApplySnapshotChunk(ctx context.Context, req *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestApplySnapshotChunk(req)) +func (cli *socketClient) ApplySnapshotChunk(ctx context.Context, req *types.ApplySnapshotChunkRequest) (*types.ApplySnapshotChunkResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToApplySnapshotChunkRequest(req)) if err != nil { return nil, err } @@ -357,8 +357,8 @@ func (cli *socketClient) ApplySnapshotChunk(ctx context.Context, req *types.Requ return reqRes.Response.GetApplySnapshotChunk(), cli.Error() } -func (cli *socketClient) PrepareProposal(ctx context.Context, req *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestPrepareProposal(req)) +func (cli *socketClient) PrepareProposal(ctx context.Context, req *types.PrepareProposalRequest) (*types.PrepareProposalResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToPrepareProposalRequest(req)) if err != nil { return nil, err } @@ -368,8 +368,8 @@ func (cli *socketClient) PrepareProposal(ctx context.Context, req *types.Request return reqRes.Response.GetPrepareProposal(), cli.Error() } -func (cli *socketClient) ProcessProposal(ctx context.Context, req *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestProcessProposal(req)) +func (cli *socketClient) ProcessProposal(ctx context.Context, req *types.ProcessProposalRequest) (*types.ProcessProposalResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToProcessProposalRequest(req)) if err != nil { return nil, err } @@ -379,8 +379,8 @@ func (cli *socketClient) ProcessProposal(ctx context.Context, req *types.Request return reqRes.Response.GetProcessProposal(), cli.Error() } -func (cli *socketClient) ExtendVote(ctx context.Context, req *types.RequestExtendVote) (*types.ResponseExtendVote, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestExtendVote(req)) +func (cli *socketClient) ExtendVote(ctx context.Context, req *types.ExtendVoteRequest) (*types.ExtendVoteResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToExtendVoteRequest(req)) if err != nil { return nil, err } @@ -390,8 +390,8 @@ func (cli *socketClient) ExtendVote(ctx context.Context, req *types.RequestExten return reqRes.Response.GetExtendVote(), cli.Error() } -func (cli *socketClient) VerifyVoteExtension(ctx context.Context, req *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestVerifyVoteExtension(req)) +func (cli *socketClient) VerifyVoteExtension(ctx context.Context, req *types.VerifyVoteExtensionRequest) (*types.VerifyVoteExtensionResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToVerifyVoteExtensionRequest(req)) if err != nil { return nil, err } @@ -401,8 +401,8 @@ func (cli *socketClient) VerifyVoteExtension(ctx context.Context, req *types.Req return reqRes.Response.GetVerifyVoteExtension(), cli.Error() } -func (cli *socketClient) FinalizeBlock(ctx context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { - reqRes, err := cli.queueRequest(ctx, types.ToRequestFinalizeBlock(req)) +func (cli *socketClient) FinalizeBlock(ctx context.Context, req *types.FinalizeBlockRequest) (*types.FinalizeBlockResponse, error) { + reqRes, err := cli.queueRequest(ctx, types.ToFinalizeBlockRequest(req)) if err != nil { return nil, err } @@ -457,7 +457,7 @@ LOOP: } } -//---------------------------------------- +// ---------------------------------------- func resMatchesReq(req *types.Request, res *types.Response) (ok bool) { switch req.Value.(type) { diff --git a/abci/client/socket_client_test.go b/abci/client/socket_client_test.go index ab37588e0df..57658995ad6 100644 --- a/abci/client/socket_client_test.go +++ b/abci/client/socket_client_test.go @@ -9,14 +9,13 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abcicli "github.com/cometbft/cometbft/abci/client" "github.com/cometbft/cometbft/abci/server" "github.com/cometbft/cometbft/abci/types" - cmtrand "github.com/cometbft/cometbft/libs/rand" - "github.com/cometbft/cometbft/libs/service" + cmtrand "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/internal/service" ) func TestCalls(t *testing.T) { @@ -39,7 +38,7 @@ func TestCalls(t *testing.T) { require.Fail(t, "No response arrived") case err, ok := <-resp: require.True(t, ok, "Must not close channel") - assert.NoError(t, err, "This should return success") + require.NoError(t, err) } } @@ -51,7 +50,9 @@ func TestHangingAsyncCalls(t *testing.T) { resp := make(chan error, 1) go func() { // Call CheckTx - reqres, err := c.CheckTxAsync(context.Background(), &types.RequestCheckTx{}) + reqres, err := c.CheckTxAsync(context.Background(), &types.CheckTxRequest{ + Type: types.CHECK_TX_TYPE_CHECK, + }) require.NoError(t, err) // wait 50 ms for all events to travel socket, but // no response yet from server @@ -70,7 +71,7 @@ func TestHangingAsyncCalls(t *testing.T) { require.Fail(t, "No response arrived") case err, ok := <-resp: require.True(t, ok, "Must not close channel") - assert.Error(t, err, "We should get EOF error") + require.Error(t, err, "We should get EOF error") } } @@ -104,14 +105,14 @@ func TestBulk(t *testing.T) { require.NoError(t, err) // Construct request - rfb := &types.RequestFinalizeBlock{Txs: make([][]byte, numTxs)} + rfb := &types.FinalizeBlockRequest{Txs: make([][]byte, numTxs)} for counter := 0; counter < numTxs; counter++ { rfb.Txs[counter] = []byte("test") } // Send bulk request res, err := client.FinalizeBlock(context.Background(), rfb) require.NoError(t, err) - require.Equal(t, numTxs, len(res.TxResults), "Number of txs doesn't match") + require.Len(t, res.TxResults, numTxs, "Number of txs doesn't match") for _, tx := range res.TxResults { require.Equal(t, uint32(0), tx.Code, "Tx failed") } @@ -122,7 +123,8 @@ func TestBulk(t *testing.T) { } func setupClientServer(t *testing.T, app types.Application) ( - service.Service, abcicli.Client) { + service.Service, abcicli.Client, +) { t.Helper() // some port between 20k and 30k @@ -156,9 +158,9 @@ type slowApp struct { types.BaseApplication } -func (slowApp) CheckTx(_ context.Context, req *types.RequestCheckTx) (*types.ResponseCheckTx, error) { +func (slowApp) CheckTx(context.Context, *types.CheckTxRequest) (*types.CheckTxResponse, error) { time.Sleep(time.Second) - return &types.ResponseCheckTx{}, nil + return &types.CheckTxResponse{}, nil } // TestCallbackInvokedWhenSetLaet ensures that the callback is invoked when @@ -175,7 +177,9 @@ func TestCallbackInvokedWhenSetLate(t *testing.T) { wg: wg, } _, c := setupClientServer(t, app) - reqRes, err := c.CheckTxAsync(ctx, &types.RequestCheckTx{}) + reqRes, err := c.CheckTxAsync(ctx, &types.CheckTxRequest{ + Type: types.CHECK_TX_TYPE_CHECK, + }) require.NoError(t, err) done := make(chan struct{}) @@ -199,7 +203,7 @@ type blockedABCIApplication struct { types.BaseApplication } -func (b blockedABCIApplication) CheckTxAsync(ctx context.Context, r *types.RequestCheckTx) (*types.ResponseCheckTx, error) { +func (b blockedABCIApplication) CheckTxAsync(ctx context.Context, r *types.CheckTxRequest) (*types.CheckTxResponse, error) { b.wg.Wait() return b.BaseApplication.CheckTx(ctx, r) } @@ -216,7 +220,9 @@ func TestCallbackInvokedWhenSetEarly(t *testing.T) { wg: wg, } _, c := setupClientServer(t, app) - reqRes, err := c.CheckTxAsync(ctx, &types.RequestCheckTx{}) + reqRes, err := c.CheckTxAsync(ctx, &types.CheckTxRequest{ + Type: types.CHECK_TX_TYPE_CHECK, + }) require.NoError(t, err) done := make(chan struct{}) diff --git a/abci/client/unsync_local_client.go b/abci/client/unsync_local_client.go new file mode 100644 index 00000000000..1f1487e80d4 --- /dev/null +++ b/abci/client/unsync_local_client.go @@ -0,0 +1,136 @@ +package abcicli + +import ( + "context" + "sync" + + "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/service" +) + +type unsyncLocalClient struct { + service.BaseService + + types.Application + + mtx sync.Mutex + Callback +} + +var _ Client = (*unsyncLocalClient)(nil) + +// NewUnsyncLocalClient creates a local client, which wraps the application +// interface that Comet as the client will call to the application as the +// server. +// +// This differs from [NewLocalClient] in that it returns a client that only +// maintains a mutex over the callback used by CheckTxAsync and not over the +// application, leaving it up to the proxy to handle all concurrency. If the +// proxy does not impose any concurrency restrictions, it is then left up to +// the application to implement its own concurrency for the relevant group of +// calls. +func NewUnsyncLocalClient(app types.Application) Client { + cli := &unsyncLocalClient{ + Application: app, + } + cli.BaseService = *service.NewBaseService(nil, "unsyncLocalClient", cli) + return cli +} + +func (app *unsyncLocalClient) SetResponseCallback(cb Callback) { + app.mtx.Lock() + app.Callback = cb + app.mtx.Unlock() +} + +func (app *unsyncLocalClient) CheckTxAsync(ctx context.Context, req *types.CheckTxRequest) (*ReqRes, error) { + res, err := app.Application.CheckTx(ctx, req) + if err != nil { + return nil, err + } + return app.callback( + types.ToCheckTxRequest(req), + types.ToCheckTxResponse(res), + ), nil +} + +func (app *unsyncLocalClient) callback(req *types.Request, res *types.Response) *ReqRes { + app.Callback(req, res) + rr := newLocalReqRes(req, res) + rr.callbackInvoked = true + return rr +} + +// ------------------------------------------------------- + +func (*unsyncLocalClient) Error() error { + return nil +} + +func (*unsyncLocalClient) Flush(context.Context) error { + return nil +} + +func (*unsyncLocalClient) Echo(_ context.Context, msg string) (*types.EchoResponse, error) { + return &types.EchoResponse{Message: msg}, nil +} + +func (app *unsyncLocalClient) Info(ctx context.Context, req *types.InfoRequest) (*types.InfoResponse, error) { + return app.Application.Info(ctx, req) +} + +func (app *unsyncLocalClient) CheckTx(ctx context.Context, req *types.CheckTxRequest) (*types.CheckTxResponse, error) { + return app.Application.CheckTx(ctx, req) +} + +func (app *unsyncLocalClient) Query(ctx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) { + return app.Application.Query(ctx, req) +} + +func (app *unsyncLocalClient) Commit(ctx context.Context, req *types.CommitRequest) (*types.CommitResponse, error) { + return app.Application.Commit(ctx, req) +} + +func (app *unsyncLocalClient) InitChain(ctx context.Context, req *types.InitChainRequest) (*types.InitChainResponse, error) { + return app.Application.InitChain(ctx, req) +} + +func (app *unsyncLocalClient) ListSnapshots(ctx context.Context, req *types.ListSnapshotsRequest) (*types.ListSnapshotsResponse, error) { + return app.Application.ListSnapshots(ctx, req) +} + +func (app *unsyncLocalClient) OfferSnapshot(ctx context.Context, req *types.OfferSnapshotRequest) (*types.OfferSnapshotResponse, error) { + return app.Application.OfferSnapshot(ctx, req) +} + +func (app *unsyncLocalClient) LoadSnapshotChunk(ctx context.Context, + req *types.LoadSnapshotChunkRequest, +) (*types.LoadSnapshotChunkResponse, error) { + return app.Application.LoadSnapshotChunk(ctx, req) +} + +func (app *unsyncLocalClient) ApplySnapshotChunk(ctx context.Context, + req *types.ApplySnapshotChunkRequest, +) (*types.ApplySnapshotChunkResponse, error) { + return app.Application.ApplySnapshotChunk(ctx, req) +} + +func (app *unsyncLocalClient) PrepareProposal(ctx context.Context, req *types.PrepareProposalRequest) (*types.PrepareProposalResponse, error) { + return app.Application.PrepareProposal(ctx, req) +} + +func (app *unsyncLocalClient) ProcessProposal(ctx context.Context, req *types.ProcessProposalRequest) (*types.ProcessProposalResponse, error) { + return app.Application.ProcessProposal(ctx, req) +} + +func (app *unsyncLocalClient) ExtendVote(ctx context.Context, req *types.ExtendVoteRequest) (*types.ExtendVoteResponse, error) { + return app.Application.ExtendVote(ctx, req) +} + +func (app *unsyncLocalClient) VerifyVoteExtension(ctx context.Context, req *types.VerifyVoteExtensionRequest) (*types.VerifyVoteExtensionResponse, error) { + return app.Application.VerifyVoteExtension(ctx, req) +} + +func (app *unsyncLocalClient) FinalizeBlock(ctx context.Context, req *types.FinalizeBlockRequest) (*types.FinalizeBlockResponse, error) { + return app.Application.FinalizeBlock(ctx, req) +} diff --git a/abci/cmd/abci-cli/abci-cli.go b/abci/cmd/abci-cli/abci-cli.go index 290474993e6..d12d1be6dba 100644 --- a/abci/cmd/abci-cli/abci-cli.go +++ b/abci/cmd/abci-cli/abci-cli.go @@ -11,38 +11,37 @@ import ( "github.com/spf13/cobra" - "github.com/cometbft/cometbft/libs/log" - cmtos "github.com/cometbft/cometbft/libs/os" - abcicli "github.com/cometbft/cometbft/abci/client" "github.com/cometbft/cometbft/abci/example/kvstore" "github.com/cometbft/cometbft/abci/server" servertest "github.com/cometbft/cometbft/abci/tests/server" "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/abci/version" - "github.com/cometbft/cometbft/proto/tendermint/crypto" + crypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + cmtos "github.com/cometbft/cometbft/internal/os" + "github.com/cometbft/cometbft/libs/log" ) -// client is a global variable so it can be reused by the console +// client is a global variable so it can be reused by the console. var ( client abcicli.Client logger log.Logger ) -// flags +// flags. var ( - // global + // global. flagAddress string flagAbci string flagVerbose bool // for the println output flagLogLevel string // for the logger - // query + // query. flagPath string flagHeight int flagProve bool - // kvstore + // kvstore. flagPersist string ) @@ -50,8 +49,7 @@ var RootCmd = &cobra.Command{ Use: "abci-cli", Short: "the ABCI CLI tool wraps an ABCI client", Long: "the ABCI CLI tool wraps an ABCI client and is used for testing ABCI servers", - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { switch cmd.Use { case "kvstore", "version", "help [command]": return nil @@ -196,6 +194,7 @@ var echoCmd = &cobra.Command{ Args: cobra.ExactArgs(1), RunE: cmdEcho, } + var infoCmd = &cobra.Command{ Use: "info", Short: "get some info about the application", @@ -233,7 +232,7 @@ var versionCmd = &cobra.Command{ Short: "print ABCI console version", Long: "print ABCI console version", Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { fmt.Println(version.Version) return nil }, @@ -279,9 +278,8 @@ var testCmd = &cobra.Command{ RunE: cmdTest, } -// Generates new Args array based off of previous call args to maintain flag persistence +// Generates new Args array based off of previous call args to maintain flag persistence. func persistentArgs(line []byte) []string { - // generate the arguments to run from original os.Args // to maintain flag arguments args := os.Args @@ -293,7 +291,7 @@ func persistentArgs(line []byte) []string { return args } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- func compose(fs []func() error) error { if len(fs) == 0 { @@ -308,7 +306,7 @@ func compose(fs []func() error) error { return err } -func cmdTest(cmd *cobra.Command, args []string) error { +func cmdTest(cmd *cobra.Command, _ []string) error { ctx := cmd.Context() return compose( []func() error{ @@ -356,16 +354,15 @@ func cmdTest(cmd *cobra.Command, args []string) error { func() error { return servertest.ProcessProposal(ctx, client, [][]byte{ {0x01}, - }, types.ResponseProcessProposal_ACCEPT) + }, types.PROCESS_PROPOSAL_STATUS_ACCEPT) }, }) } -func cmdBatch(cmd *cobra.Command, args []string) error { +func cmdBatch(cmd *cobra.Command, _ []string) error { bufReader := bufio.NewReader(os.Stdin) LOOP: for { - line, more, err := bufReader.ReadLine() switch { case more: @@ -387,7 +384,7 @@ LOOP: return nil } -func cmdConsole(cmd *cobra.Command, args []string) error { +func cmdConsole(cmd *cobra.Command, _ []string) error { for { fmt.Printf("> ") bufReader := bufio.NewReader(os.Stdin) @@ -493,7 +490,7 @@ func cmdUnimplemented(cmd *cobra.Command, args []string) error { return nil } -// Have the application echo a message +// Have the application echo a message. func cmdEcho(cmd *cobra.Command, args []string) error { msg := "" if len(args) > 0 { @@ -511,13 +508,13 @@ func cmdEcho(cmd *cobra.Command, args []string) error { return nil } -// Get some info from the application +// Get some info from the application. func cmdInfo(cmd *cobra.Command, args []string) error { var version string if len(args) == 1 { version = args[0] } - res, err := client.Info(cmd.Context(), &types.RequestInfo{Version: version}) + res, err := client.Info(cmd.Context(), &types.InfoRequest{Version: version}) if err != nil { return err } @@ -529,7 +526,7 @@ func cmdInfo(cmd *cobra.Command, args []string) error { const codeBad uint32 = 10 -// Append new txs to application +// Append new txs to application. func cmdFinalizeBlock(cmd *cobra.Command, args []string) error { if len(args) == 0 { printResponse(cmd, args, response{ @@ -546,7 +543,7 @@ func cmdFinalizeBlock(cmd *cobra.Command, args []string) error { } txs[i] = txBytes } - res, err := client.FinalizeBlock(cmd.Context(), &types.RequestFinalizeBlock{Txs: txs}) + res, err := client.FinalizeBlock(cmd.Context(), &types.FinalizeBlockRequest{Txs: txs}) if err != nil { return err } @@ -566,7 +563,7 @@ func cmdFinalizeBlock(cmd *cobra.Command, args []string) error { return nil } -// Validate a tx +// Validate a tx. func cmdCheckTx(cmd *cobra.Command, args []string) error { if len(args) == 0 { printResponse(cmd, args, response{ @@ -579,7 +576,10 @@ func cmdCheckTx(cmd *cobra.Command, args []string) error { if err != nil { return err } - res, err := client.CheckTx(cmd.Context(), &types.RequestCheckTx{Tx: txBytes}) + res, err := client.CheckTx(cmd.Context(), &types.CheckTxRequest{ + Tx: txBytes, + Type: types.CHECK_TX_TYPE_CHECK, + }) if err != nil { return err } @@ -592,9 +592,9 @@ func cmdCheckTx(cmd *cobra.Command, args []string) error { return nil } -// Get application Merkle root hash +// Get application Merkle root hash. func cmdCommit(cmd *cobra.Command, args []string) error { - _, err := client.Commit(cmd.Context(), &types.RequestCommit{}) + _, err := client.Commit(cmd.Context(), &types.CommitRequest{}) if err != nil { return err } @@ -602,7 +602,7 @@ func cmdCommit(cmd *cobra.Command, args []string) error { return nil } -// Query application state +// Query application state. func cmdQuery(cmd *cobra.Command, args []string) error { if len(args) == 0 { printResponse(cmd, args, response{ @@ -617,7 +617,7 @@ func cmdQuery(cmd *cobra.Command, args []string) error { return err } - resQuery, err := client.Query(cmd.Context(), &types.RequestQuery{ + resQuery, err := client.Query(cmd.Context(), &types.QueryRequest{ Data: queryBytes, Path: flagPath, Height: int64(flagHeight), @@ -651,7 +651,7 @@ func cmdPrepareProposal(cmd *cobra.Command, args []string) error { txsBytesArray[i] = txBytes } - res, err := client.PrepareProposal(cmd.Context(), &types.RequestPrepareProposal{ + res, err := client.PrepareProposal(cmd.Context(), &types.PrepareProposalRequest{ Txs: txsBytesArray, // kvstore has to have this parameter in order not to reject a tx as the default value is 0 MaxTxBytes: 65536, @@ -682,7 +682,7 @@ func cmdProcessProposal(cmd *cobra.Command, args []string) error { txsBytesArray[i] = txBytes } - res, err := client.ProcessProposal(cmd.Context(), &types.RequestProcessProposal{ + res, err := client.ProcessProposal(cmd.Context(), &types.ProcessProposalRequest{ Txs: txsBytesArray, }) if err != nil { @@ -695,7 +695,7 @@ func cmdProcessProposal(cmd *cobra.Command, args []string) error { return nil } -func cmdKVStore(cmd *cobra.Command, args []string) error { +func cmdKVStore(*cobra.Command, []string) error { logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Create the application - in memory or persisted to disk @@ -731,10 +731,9 @@ func cmdKVStore(cmd *cobra.Command, args []string) error { select {} } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- func printResponse(cmd *cobra.Command, args []string, rsps ...response) { - if flagVerbose { fmt.Println(">", cmd.Use, strings.Join(args, " ")) } @@ -745,7 +744,6 @@ func printResponse(cmd *cobra.Command, args []string, rsps ...response) { fmt.Printf("-> code: OK\n") } else { fmt.Printf("-> code: %d\n", rsp.Code) - } if len(rsp.Data) != 0 { @@ -760,7 +758,7 @@ func printResponse(cmd *cobra.Command, args []string, rsps ...response) { fmt.Printf("-> log: %s\n", rsp.Log) } if cmd.Use == "process_proposal" { - fmt.Printf("-> status: %s\n", types.ResponseProcessProposal_ProposalStatus_name[rsp.Status]) + fmt.Printf("-> status: %s\n", types.ProcessProposalStatus(rsp.Status).String()) } if rsp.Query != nil { @@ -780,7 +778,7 @@ func printResponse(cmd *cobra.Command, args []string, rsps ...response) { } } -// NOTE: s is interpreted as a string unless prefixed with 0x +// NOTE: s is interpreted as a string unless prefixed with 0x. func stringOrHexToBytes(s string) ([]byte, error) { if len(s) > 2 && strings.ToLower(s[:2]) == "0x" { b, err := hex.DecodeString(s[2:]) diff --git a/abci/example/kvstore/README.md b/abci/example/kvstore/README.md index e9e38b53c1e..55c13572366 100644 --- a/abci/example/kvstore/README.md +++ b/abci/example/kvstore/README.md @@ -8,9 +8,10 @@ The app has no replay protection (other than what the mempool provides). Validator set changes are effected using the following transaction format: ```md -"val:pubkey1!power1,pubkey2!power2,pubkey3!power3" +"val:pubkeytype1!pubkey1!power1,pubkeytype2!pubkey2!power2,pubkeytype3!pubkey3!power3" ``` -where `pubkeyN` is a base64-encoded 32-byte ed25519 key and `powerN` is a new voting power for the validator with `pubkeyN` (possibly a new one). +where `pubkeyN` is a base64-encoded 32-byte key, `pubkeytypeN` is a string representing the key type, +and `powerN` is a new voting power for the validator with `pubkeyN` (possibly a new one). To remove a validator from the validator set, set power to `0`. There is no sybil protection against new validators joining. diff --git a/abci/example/kvstore/code.go b/abci/example/kvstore/code.go index f58cfb83c77..06944f750fd 100644 --- a/abci/example/kvstore/code.go +++ b/abci/example/kvstore/code.go @@ -1,6 +1,6 @@ package kvstore -// Return codes for the examples +// Return codes for the examples. const ( CodeTypeOK uint32 = 0 CodeTypeEncodingError uint32 = 1 diff --git a/abci/example/kvstore/helpers.go b/abci/example/kvstore/helpers.go index 094f3ae1908..e252afa5e0b 100644 --- a/abci/example/kvstore/helpers.go +++ b/abci/example/kvstore/helpers.go @@ -7,14 +7,14 @@ import ( "strings" "github.com/cometbft/cometbft/abci/types" + pbcrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" cryptoencoding "github.com/cometbft/cometbft/crypto/encoding" - cmtrand "github.com/cometbft/cometbft/libs/rand" - "github.com/cometbft/cometbft/proto/tendermint/crypto" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) // RandVal creates one random validator, with a key derived -// from the input value -func RandVal(i int) types.ValidatorUpdate { +// from the input value. +func RandVal() types.ValidatorUpdate { pubkey := cmtrand.Bytes(32) power := cmtrand.Uint16() + 1 v := types.UpdateValidator(pubkey, int64(power), "") @@ -24,26 +24,26 @@ func RandVal(i int) types.ValidatorUpdate { // RandVals returns a list of cnt validators for initializing // the application. Note that the keys are deterministically // derived from the index in the array, while the power is -// random (Change this if not desired) +// random (Change this if not desired). func RandVals(cnt int) []types.ValidatorUpdate { res := make([]types.ValidatorUpdate, cnt) for i := 0; i < cnt; i++ { - res[i] = RandVal(i) + res[i] = RandVal() } return res } // InitKVStore initializes the kvstore app with some data, // which allows tests to pass and is fine as long as you -// don't make any tx that modify the validator state +// don't make any tx that modify the validator state. func InitKVStore(ctx context.Context, app *Application) error { - _, err := app.InitChain(ctx, &types.RequestInitChain{ + _, err := app.InitChain(ctx, &types.InitChainRequest{ Validators: RandVals(1), }) return err } -// Create a new transaction +// Create a new transaction. func NewTx(key, value string) []byte { return []byte(strings.Join([]string{key, value}, "=")) } @@ -69,11 +69,12 @@ func NewTxFromID(i int) []byte { // Create a transaction to add/remove/update a validator // To remove, set power to 0. -func MakeValSetChangeTx(pubkey crypto.PublicKey, power int64) []byte { +func MakeValSetChangeTx(pubkey pbcrypto.PublicKey, power int64) []byte { pk, err := cryptoencoding.PubKeyFromProto(pubkey) if err != nil { panic(err) } pubStr := base64.StdEncoding.EncodeToString(pk.Bytes()) - return []byte(fmt.Sprintf("%s%s!%d", ValidatorPrefix, pubStr, power)) + pubTypeStr := pk.Type() + return []byte(fmt.Sprintf("%s%s!%s!%d", ValidatorPrefix, pubTypeStr, pubStr, power)) } diff --git a/abci/example/kvstore/kvstore.go b/abci/example/kvstore/kvstore.go index 0f8794893b3..cfd6ed4feb1 100644 --- a/abci/example/kvstore/kvstore.go +++ b/abci/example/kvstore/kvstore.go @@ -11,11 +11,10 @@ import ( "strings" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/abci/types" + cryptoproto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" cryptoencoding "github.com/cometbft/cometbft/crypto/encoding" "github.com/cometbft/cometbft/libs/log" - cryptoproto "github.com/cometbft/cometbft/proto/tendermint/crypto" "github.com/cometbft/cometbft/version" ) @@ -33,12 +32,12 @@ var _ types.Application = (*Application)(nil) // Application is the kvstore state machine. It complies with the abci.Application interface. // It takes transactions in the form of key=value and saves them in a database. This is -// a somewhat trivial example as there is no real state execution +// a somewhat trivial example as there is no real state execution. type Application struct { types.BaseApplication state State - RetainBlocks int64 // blocks to retain after commit (via ResponseCommit.RetainHeight) + RetainBlocks int64 // blocks to retain after commit (via CommitResponse.RetainHeight) stagedTxs [][]byte logger log.Logger @@ -51,7 +50,7 @@ type Application struct { genBlockEvents bool } -// NewApplication creates an instance of the kvstore from the provided database +// NewApplication creates an instance of the kvstore from the provided database. func NewApplication(db dbm.DB) *Application { return &Application{ logger: log.NewNopLogger(), @@ -60,7 +59,7 @@ func NewApplication(db dbm.DB) *Application { } } -// NewPersistentApplication creates a new application using the goleveldb database engine +// NewPersistentApplication creates a new application using the goleveldb database engine. func NewPersistentApplication(dbDir string) *Application { name := "kvstore" db, err := dbm.NewGoLevelDB(name, dbDir) @@ -80,11 +79,11 @@ func (app *Application) SetGenBlockEvents() { app.genBlockEvents = true } -// Info returns information about the state of the application. This is generally used everytime a Tendermint instance +// Info returns information about the state of the application. This is generally used every time 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 -// Application returns a 0 appBlockHeight, Tendermint will call InitChain to initialize the application with consensus related data -func (app *Application) Info(_ context.Context, req *types.RequestInfo) (*types.ResponseInfo, error) { +// Application returns a 0 appBlockHeight, Tendermint will call InitChain to initialize the application with consensus related data. +func (app *Application) Info(context.Context, *types.InfoRequest) (*types.InfoResponse, error) { // Tendermint expects the application to persist validators, on start-up we need to reload them to memory if they exist if len(app.valAddrToPubKeyMap) == 0 && app.state.Height > 0 { validators := app.getValidators() @@ -97,7 +96,7 @@ func (app *Application) Info(_ context.Context, req *types.RequestInfo) (*types. } } - return &types.ResponseInfo{ + return &types.InfoResponse{ Data: fmt.Sprintf("{\"size\":%v}", app.state.Size), Version: version.ABCIVersion, AppVersion: AppVersion, @@ -109,13 +108,13 @@ func (app *Application) Info(_ context.Context, req *types.RequestInfo) (*types. // InitChain takes the genesis validators and stores them in the kvstore. It returns the application hash in the // case that the application starts prepopulated with values. This method is called whenever a new instance of the application // starts (i.e. app height = 0). -func (app *Application) InitChain(_ context.Context, req *types.RequestInitChain) (*types.ResponseInitChain, error) { +func (app *Application) InitChain(_ context.Context, req *types.InitChainRequest) (*types.InitChainResponse, error) { for _, v := range req.Validators { app.updateValidator(v) } appHash := make([]byte, 8) binary.PutVarint(appHash, app.state.Size) - return &types.ResponseInitChain{ + return &types.InitChainResponse{ AppHash: appHash, }, nil } @@ -126,23 +125,24 @@ func (app *Application) InitChain(_ context.Context, req *types.RequestInitChain // For the KVStore we check that each transaction has the valid tx format: // - Contains one and only one `=` // - `=` is not the first or last byte. -// - if key is `val` that the validator update transaction is also valid -func (app *Application) CheckTx(_ context.Context, req *types.RequestCheckTx) (*types.ResponseCheckTx, error) { +// - if key is `val` that the validator update transaction is also valid. +func (*Application) CheckTx(_ context.Context, req *types.CheckTxRequest) (*types.CheckTxResponse, error) { // If it is a validator update transaction, check that it is correctly formatted if isValidatorTx(req.Tx) { - if _, _, err := parseValidatorTx(req.Tx); err != nil { - return &types.ResponseCheckTx{Code: CodeTypeInvalidTxFormat}, nil + if _, _, _, err := parseValidatorTx(req.Tx); err != nil { + //nolint:nilerr + return &types.CheckTxResponse{Code: CodeTypeInvalidTxFormat}, nil } } else if !isValidTx(req.Tx) { - return &types.ResponseCheckTx{Code: CodeTypeInvalidTxFormat}, nil + return &types.CheckTxResponse{Code: CodeTypeInvalidTxFormat}, nil } - return &types.ResponseCheckTx{Code: CodeTypeOK, GasWanted: 1}, nil + return &types.CheckTxResponse{Code: CodeTypeOK, GasWanted: 1}, nil } // Tx must have a format like key:value or key=value. That is: // - it must have one and only one ":" or "=" -// - It must not begin or end with these special characters +// - It must not begin or end with these special characters. func isValidTx(tx []byte) bool { if bytes.Count(tx, []byte(":")) == 1 && bytes.Count(tx, []byte("=")) == 0 { if !bytes.HasPrefix(tx, []byte(":")) && !bytes.HasSuffix(tx, []byte(":")) { @@ -156,20 +156,20 @@ func isValidTx(tx []byte) bool { return false } -// PrepareProposal is called when the node is a proposer. Tendermint stages a set of transactions to the application. As the +// PrepareProposal is called when the node is a proposer. CometBFT stages a set of transactions to the application. As the // KVStore has two accepted formats, `:` and `=`, we modify all instances of `:` with `=` to make it consistent. Note: this is // quite a trivial example of transaction modification. -// NOTE: we assume that Tendermint will never provide more transactions than can fit in a block. -func (app *Application) PrepareProposal(ctx context.Context, req *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { - return &types.ResponsePrepareProposal{Txs: app.formatTxs(ctx, req.Txs)}, nil +// NOTE: we assume that CometBFT will never provide more transactions than can fit in a block. +func (app *Application) PrepareProposal(ctx context.Context, req *types.PrepareProposalRequest) (*types.PrepareProposalResponse, error) { + return &types.PrepareProposalResponse{Txs: app.formatTxs(ctx, req.Txs)}, nil } // formatTxs validates and excludes invalid transactions -// also substitutes all the transactions with x:y to x=y +// also substitutes all the transactions with x:y to x=y. func (app *Application) formatTxs(ctx context.Context, blockData [][]byte) [][]byte { txs := make([][]byte, 0, len(blockData)) for _, tx := range blockData { - if resp, err := app.CheckTx(ctx, &types.RequestCheckTx{Tx: tx}); err == nil && resp.Code == CodeTypeOK { + if resp, err := app.CheckTx(ctx, &types.CheckTxRequest{Tx: tx, Type: types.CHECK_TX_TYPE_CHECK}); err == nil && resp.Code == CodeTypeOK { txs = append(txs, bytes.Replace(tx, []byte(":"), []byte("="), 1)) } } @@ -178,29 +178,31 @@ func (app *Application) formatTxs(ctx context.Context, blockData [][]byte) [][]b // ProcessProposal is called whenever a node receives a complete proposal. It allows the application to validate the proposal. // Only validators who can vote will have this method called. For the KVstore we reuse CheckTx. -func (app *Application) ProcessProposal(ctx context.Context, req *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { +func (app *Application) ProcessProposal(ctx context.Context, req *types.ProcessProposalRequest) (*types.ProcessProposalResponse, error) { for _, tx := range req.Txs { // As CheckTx is a full validity check we can simply reuse this - if resp, err := app.CheckTx(ctx, &types.RequestCheckTx{Tx: tx}); err != nil || resp.Code != CodeTypeOK { - return &types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT}, nil + if resp, err := app.CheckTx(ctx, &types.CheckTxRequest{Tx: tx, Type: types.CHECK_TX_TYPE_CHECK}); err != nil || resp.Code != CodeTypeOK { + //nolint:nilerr + return &types.ProcessProposalResponse{Status: types.PROCESS_PROPOSAL_STATUS_REJECT}, nil } } - return &types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT}, nil + return &types.ProcessProposalResponse{Status: types.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil } // FinalizeBlock executes the block against the application state. It punishes validators who equivocated and // updates validators according to transactions in a block. The rest of the transactions are regular key value // updates and are cached in memory and will be persisted once Commit is called. // ConsensusParams are never changed. -func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { +func (app *Application) FinalizeBlock(_ context.Context, req *types.FinalizeBlockRequest) (*types.FinalizeBlockResponse, error) { // reset valset changes app.valUpdates = make([]types.ValidatorUpdate, 0) app.stagedTxs = make([][]byte, 0) // Punish validators who committed equivocation. for _, ev := range req.Misbehavior { - if ev.Type == types.MisbehaviorType_DUPLICATE_VOTE { + if ev.Type == types.MISBEHAVIOR_TYPE_DUPLICATE_VOTE { addr := string(ev.Validator.Address) + //nolint:revive // this is a false positive from early-return if pubKey, ok := app.valAddrToPubKeyMap[addr]; ok { app.valUpdates = append(app.valUpdates, types.ValidatorUpdate{ PubKey: pubKey, @@ -217,11 +219,11 @@ func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinal respTxs := make([]*types.ExecTxResult, len(req.Txs)) for i, tx := range req.Txs { if isValidatorTx(tx) { - pubKey, power, err := parseValidatorTx(tx) + keyType, pubKey, power, err := parseValidatorTx(tx) if err != nil { panic(err) } - app.valUpdates = append(app.valUpdates, types.UpdateValidator(pubKey, power, "")) + app.valUpdates = append(app.valUpdates, types.UpdateValidator(pubKey, power, keyType)) } else { app.stagedTxs = append(app.stagedTxs, tx) } @@ -262,7 +264,7 @@ func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinal app.state.Height = req.Height - response := &types.ResponseFinalizeBlock{TxResults: respTxs, ValidatorUpdates: app.valUpdates, AppHash: app.state.Hash()} + response := &types.FinalizeBlockResponse{TxResults: respTxs, ValidatorUpdates: app.valUpdates, AppHash: app.state.Hash()} if !app.genBlockEvents { return response, nil } @@ -323,9 +325,8 @@ func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinal // Commit is called after FinalizeBlock and after Tendermint state which includes the updates to // AppHash, ConsensusParams and ValidatorSet has occurred. -// The KVStore persists the validator updates and the new key values -func (app *Application) Commit(_ context.Context, _ *types.RequestCommit) (*types.ResponseCommit, error) { - +// The KVStore persists the validator updates and the new key values. +func (app *Application) Commit(context.Context, *types.CommitRequest) (*types.CommitResponse, error) { // apply the validator updates to state (note this is really the validator set at h + 2) for _, valUpdate := range app.valUpdates { app.updateValidator(valUpdate) @@ -347,7 +348,7 @@ func (app *Application) Commit(_ context.Context, _ *types.RequestCommit) (*type // persist the state (i.e. size and height) saveState(app.state) - resp := &types.ResponseCommit{} + resp := &types.CommitResponse{} if app.RetainBlocks > 0 && app.state.Height >= app.RetainBlocks { resp.RetainHeight = app.state.Height - app.RetainBlocks + 1 } @@ -355,8 +356,8 @@ func (app *Application) Commit(_ context.Context, _ *types.RequestCommit) (*type } // Returns an associated value or nil if missing. -func (app *Application) Query(_ context.Context, reqQuery *types.RequestQuery) (*types.ResponseQuery, error) { - resQuery := &types.ResponseQuery{} +func (app *Application) Query(_ context.Context, reqQuery *types.QueryRequest) (*types.QueryResponse, error) { + resQuery := &types.QueryResponse{} if reqQuery.Path == "/val" { key := []byte(ValidatorPrefix + string(reqQuery.Data)) @@ -365,7 +366,7 @@ func (app *Application) Query(_ context.Context, reqQuery *types.RequestQuery) ( panic(err) } - return &types.ResponseQuery{ + return &types.QueryResponse{ Key: reqQuery.Data, Value: value, }, nil @@ -414,36 +415,36 @@ func isValidatorTx(tx []byte) bool { return strings.HasPrefix(string(tx), ValidatorPrefix) } -func parseValidatorTx(tx []byte) ([]byte, int64, error) { +func parseValidatorTx(tx []byte) (string, []byte, int64, error) { tx = tx[len(ValidatorPrefix):] // get the pubkey and power - pubKeyAndPower := strings.Split(string(tx), "!") - if len(pubKeyAndPower) != 2 { - return nil, 0, fmt.Errorf("expected 'pubkey!power'. Got %v", pubKeyAndPower) + typePubKeyAndPower := strings.Split(string(tx), "!") + if len(typePubKeyAndPower) != 3 { + return "", nil, 0, fmt.Errorf("expected 'pubkeytype!pubkey!power'. Got %v", typePubKeyAndPower) } - pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1] + keyType, pubkeyS, powerS := typePubKeyAndPower[0], typePubKeyAndPower[1], typePubKeyAndPower[2] // decode the pubkey pubkey, err := base64.StdEncoding.DecodeString(pubkeyS) if err != nil { - return nil, 0, fmt.Errorf("pubkey (%s) is invalid base64", pubkeyS) + return "", nil, 0, fmt.Errorf("pubkey (%s) is invalid base64", pubkeyS) } // decode the power power, err := strconv.ParseInt(powerS, 10, 64) if err != nil { - return nil, 0, fmt.Errorf("power (%s) is not an int", powerS) + return "", nil, 0, fmt.Errorf("power (%s) is not an int", powerS) } if power < 0 { - return nil, 0, fmt.Errorf("power can not be less than 0, got %d", power) + return "", nil, 0, fmt.Errorf("power can not be less than 0, got %d", power) } - return pubkey, power, nil + return keyType, pubkey, power, nil } -// add, update, or remove a validator +// add, update, or remove a validator. func (app *Application) updateValidator(v types.ValidatorUpdate) { pubkey, err := cryptoencoding.PubKeyFromProto(v.PubKey) if err != nil { @@ -496,7 +497,7 @@ func (app *Application) getValidators() (validators []types.ValidatorUpdate) { if err = itr.Error(); err != nil { panic(err) } - return + return validators } // ----------------------------- @@ -541,7 +542,7 @@ func saveState(state State) { // as the size or number of transactions processed within the state. Note that this isn't // a strong guarantee of state machine replication because states could // have different kv values but still have the same size. -// This function is used as the "AppHash" +// This function is used as the "AppHash". func (s State) Hash() []byte { appHash := make([]byte, 8) binary.PutVarint(appHash, s.Size) diff --git a/abci/example/kvstore/kvstore_test.go b/abci/example/kvstore/kvstore_test.go index 9aa4e6f2d3b..6df7aaeebbd 100644 --- a/abci/example/kvstore/kvstore_test.go +++ b/abci/example/kvstore/kvstore_test.go @@ -8,12 +8,10 @@ import ( "github.com/stretchr/testify/require" - "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" - abcicli "github.com/cometbft/cometbft/abci/client" abciserver "github.com/cometbft/cometbft/abci/server" "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/libs/log" ) const ( @@ -27,34 +25,38 @@ func TestKVStoreKV(t *testing.T) { kvstore := NewInMemoryApplication() tx := []byte(testKey + ":" + testValue) - testKVStore(ctx, t, kvstore, tx, testKey, testValue) + testKVStore(ctx, t, kvstore, tx) tx = []byte(testKey + "=" + testValue) - testKVStore(ctx, t, kvstore, tx, testKey, testValue) + testKVStore(ctx, t, kvstore, tx) } -func testKVStore(ctx context.Context, t *testing.T, app types.Application, tx []byte, key, value string) { - checkTxResp, err := app.CheckTx(ctx, &types.RequestCheckTx{Tx: tx}) +func testKVStore(ctx context.Context, t *testing.T, app types.Application, tx []byte) { + t.Helper() + + value := "def" + key := "abc" + checkTxResp, err := app.CheckTx(ctx, &types.CheckTxRequest{Tx: tx, Type: types.CHECK_TX_TYPE_CHECK}) require.NoError(t, err) require.Equal(t, uint32(0), checkTxResp.Code) - ppResp, err := app.PrepareProposal(ctx, &types.RequestPrepareProposal{Txs: [][]byte{tx}}) + ppResp, err := app.PrepareProposal(ctx, &types.PrepareProposalRequest{Txs: [][]byte{tx}}) require.NoError(t, err) require.Len(t, ppResp.Txs, 1) - req := &types.RequestFinalizeBlock{Height: 1, Txs: ppResp.Txs} + req := &types.FinalizeBlockRequest{Height: 1, Txs: ppResp.Txs} ar, err := app.FinalizeBlock(ctx, req) require.NoError(t, err) - require.Equal(t, 1, len(ar.TxResults)) + require.Len(t, ar.TxResults, 1) require.False(t, ar.TxResults[0].IsErr()) // commit - _, err = app.Commit(ctx, &types.RequestCommit{}) + _, err = app.Commit(ctx, &types.CommitRequest{}) require.NoError(t, err) - info, err := app.Info(ctx, &types.RequestInfo{}) + info, err := app.Info(ctx, &types.InfoRequest{}) require.NoError(t, err) require.NotZero(t, info.LastBlockHeight) // make sure query is fine - resQuery, err := app.Query(ctx, &types.RequestQuery{ + resQuery, err := app.Query(ctx, &types.QueryRequest{ Path: "/store", Data: []byte(key), }) @@ -65,7 +67,7 @@ func testKVStore(ctx context.Context, t *testing.T, app types.Application, tx [] require.EqualValues(t, info.LastBlockHeight, resQuery.Height) // make sure proof is fine - resQuery, err = app.Query(ctx, &types.RequestQuery{ + resQuery, err = app.Query(ctx, &types.QueryRequest{ Path: "/store", Data: []byte(key), Prove: true, @@ -83,17 +85,17 @@ func TestPersistentKVStoreEmptyTX(t *testing.T) { kvstore := NewPersistentApplication(t.TempDir()) tx := []byte("") - reqCheck := types.RequestCheckTx{Tx: tx} + reqCheck := types.CheckTxRequest{Tx: tx, Type: types.CHECK_TX_TYPE_CHECK} resCheck, err := kvstore.CheckTx(ctx, &reqCheck) require.NoError(t, err) - require.Equal(t, resCheck.Code, CodeTypeInvalidTxFormat) + require.Equal(t, CodeTypeInvalidTxFormat, resCheck.Code) txs := make([][]byte, 0, 4) txs = append(txs, []byte("key=value"), []byte("key:val"), []byte(""), []byte("kee=value")) - reqPrepare := types.RequestPrepareProposal{Txs: txs, MaxTxBytes: 10 * 1024} + reqPrepare := types.PrepareProposalRequest{Txs: txs, MaxTxBytes: 10 * 1024} resPrepare, err := kvstore.PrepareProposal(ctx, &reqPrepare) require.NoError(t, err) - require.Equal(t, len(reqPrepare.Txs)-1, len(resPrepare.Txs), "Empty transaction not properly removed") + require.Len(t, resPrepare.Txs, len(reqPrepare.Txs)-1, "Empty transaction not properly removed") } func TestPersistentKVStoreKV(t *testing.T) { @@ -103,7 +105,7 @@ func TestPersistentKVStoreKV(t *testing.T) { kvstore := NewPersistentApplication(t.TempDir()) key := testKey value := testValue - testKVStore(ctx, t, kvstore, NewTx(key, value), key, value) + testKVStore(ctx, t, kvstore, NewTx(key, value)) } func TestPersistentKVStoreInfo(t *testing.T) { @@ -114,7 +116,7 @@ func TestPersistentKVStoreInfo(t *testing.T) { require.NoError(t, InitKVStore(ctx, kvstore)) height := int64(0) - resInfo, err := kvstore.Info(ctx, &types.RequestInfo{}) + resInfo, err := kvstore.Info(ctx, &types.InfoRequest{}) require.NoError(t, err) if resInfo.LastBlockHeight != height { t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) @@ -123,20 +125,19 @@ func TestPersistentKVStoreInfo(t *testing.T) { // make and apply block height = int64(1) hash := []byte("foo") - if _, err := kvstore.FinalizeBlock(ctx, &types.RequestFinalizeBlock{Hash: hash, Height: height}); err != nil { + if _, err := kvstore.FinalizeBlock(ctx, &types.FinalizeBlockRequest{Hash: hash, Height: height}); err != nil { t.Fatal(err) } - _, err = kvstore.Commit(ctx, &types.RequestCommit{}) + _, err = kvstore.Commit(ctx, &types.CommitRequest{}) require.NoError(t, err) - resInfo, err = kvstore.Info(ctx, &types.RequestInfo{}) + resInfo, err = kvstore.Info(ctx, &types.InfoRequest{}) require.NoError(t, err) require.Equal(t, height, resInfo.LastBlockHeight) - } -// add a validator, remove a validator, update a validator +// add a validator, remove a validator, update a validator. func TestValUpdates(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -148,7 +149,7 @@ func TestValUpdates(t *testing.T) { nInit := 5 vals := RandVals(total) // initialize with the first nInit - _, err := kvstore.InitChain(ctx, &types.RequestInitChain{ + _, err := kvstore.InitChain(ctx, &types.InitChainRequest{ Validators: vals[:nInit], }) require.NoError(t, err) @@ -181,7 +182,7 @@ func TestValUpdates(t *testing.T) { makeApplyBlock(ctx, t, kvstore, 2, diff, tx1, tx2, tx3) - vals1 = append(vals[:nInit-2], vals[nInit+1]) //nolint: gocritic + vals1 = append(vals[:nInit-2], vals[nInit+1]) vals2 = kvstore.getValidators() valsEqual(t, vals1, vals2) @@ -200,7 +201,6 @@ func TestValUpdates(t *testing.T) { vals1 = append([]types.ValidatorUpdate{v1}, vals1[1:]...) vals2 = kvstore.getValidators() valsEqual(t, vals1, vals2) - } func TestCheckTx(t *testing.T) { @@ -208,7 +208,7 @@ func TestCheckTx(t *testing.T) { defer cancel() kvstore := NewInMemoryApplication() - val := RandVal(1) + val := RandVal() testCases := []struct { expCode uint32 @@ -226,7 +226,10 @@ func TestCheckTx(t *testing.T) { } for idx, tc := range testCases { - resp, err := kvstore.CheckTx(ctx, &types.RequestCheckTx{Tx: tc.tx}) + resp, err := kvstore.CheckTx(ctx, &types.CheckTxRequest{ + Tx: tc.tx, + Type: types.CHECK_TX_TYPE_CHECK, + }) require.NoError(t, err, idx) fmt.Println(string(tc.tx)) require.Equal(t, tc.expCode, resp.Code, idx) @@ -238,13 +241,13 @@ func TestClientServer(t *testing.T) { defer cancel() // set up socket app kvstore := NewInMemoryApplication() - client, _, err := makeClientServer(t, kvstore, "kvstore-socket", "socket") + client, err := makeClientServer(t, kvstore, "kvstore-socket", "socket") require.NoError(t, err) runClientTests(ctx, t, client) // set up grpc app kvstore = NewInMemoryApplication() - gclient, _, err := makeClientServer(t, kvstore, t.TempDir(), "grpc") + gclient, err := makeClientServer(t, kvstore, t.TempDir(), "grpc") require.NoError(t, err) runClientTests(ctx, t, gclient) } @@ -255,25 +258,26 @@ func makeApplyBlock( kvstore types.Application, heightInt int, diff []types.ValidatorUpdate, - txs ...[]byte) { + txs ...[]byte, +) { + t.Helper() // make and apply block height := int64(heightInt) hash := []byte("foo") - resFinalizeBlock, err := kvstore.FinalizeBlock(ctx, &types.RequestFinalizeBlock{ + resFinalizeBlock, err := kvstore.FinalizeBlock(ctx, &types.FinalizeBlockRequest{ Hash: hash, Height: height, Txs: txs, }) require.NoError(t, err) - _, err = kvstore.Commit(ctx, &types.RequestCommit{}) + _, err = kvstore.Commit(ctx, &types.CommitRequest{}) require.NoError(t, err) valsEqual(t, diff, resFinalizeBlock.ValidatorUpdates) - } -// order doesn't matter +// order doesn't matter. func valsEqual(t *testing.T, vals1, vals2 []types.ValidatorUpdate) { t.Helper() if len(vals1) != len(vals2) { @@ -290,7 +294,8 @@ func valsEqual(t *testing.T, vals1, vals2 []types.ValidatorUpdate) { } } -func makeClientServer(t *testing.T, app types.Application, name, transport string) (abcicli.Client, service.Service, error) { +func makeClientServer(t *testing.T, app types.Application, name, transport string) (abcicli.Client, error) { + t.Helper() // Start the listener addr := fmt.Sprintf("unix://%s.sock", name) logger := log.TestingLogger() @@ -299,7 +304,7 @@ func makeClientServer(t *testing.T, app types.Application, name, transport strin require.NoError(t, err) server.SetLogger(logger.With("module", "abci-server")) if err := server.Start(); err != nil { - return nil, nil, err + return nil, err } t.Cleanup(func() { @@ -313,7 +318,7 @@ func makeClientServer(t *testing.T, app types.Application, name, transport strin require.NoError(t, err) client.SetLogger(logger.With("module", "abci-client")) if err := client.Start(); err != nil { - return nil, nil, err + return nil, err } t.Cleanup(func() { @@ -322,15 +327,16 @@ func makeClientServer(t *testing.T, app types.Application, name, transport strin } }) - return client, server, nil + return client, nil } func runClientTests(ctx context.Context, t *testing.T, client abcicli.Client) { + t.Helper() // run some tests.... tx := []byte(testKey + ":" + testValue) - testKVStore(ctx, t, client, tx, testKey, testValue) + testKVStore(ctx, t, client, tx) tx = []byte(testKey + "=" + testValue) - testKVStore(ctx, t, client, tx, testKey, testValue) + testKVStore(ctx, t, client, tx) } func TestTxGeneration(t *testing.T) { diff --git a/abci/server/errors.go b/abci/server/errors.go new file mode 100644 index 00000000000..0681c185891 --- /dev/null +++ b/abci/server/errors.go @@ -0,0 +1,33 @@ +package server + +import ( + "fmt" + + "github.com/cometbft/cometbft/abci/types" +) + +// ErrUnknownServerType is returned when trying to create a server with invalid transport option. +type ErrUnknownServerType struct { + ServerType string +} + +func (e ErrUnknownServerType) Error() string { + return "unknown server type " + e.ServerType +} + +// ErrConnectionDoesNotExist is returned when trying to access non-existent network connection. +type ErrConnectionDoesNotExist struct { + ConnID int +} + +func (e ErrConnectionDoesNotExist) Error() string { + return fmt.Sprintf("connection %d does not exist", e.ConnID) +} + +type ErrUnknownRequest struct { + Request types.Request +} + +func (e ErrUnknownRequest) Error() string { + return fmt.Sprintf("unknown request from client: %T", e.Request) +} diff --git a/abci/server/grpc_server.go b/abci/server/grpc_server.go index 6c0344cf0bb..2196f9bf046 100644 --- a/abci/server/grpc_server.go +++ b/abci/server/grpc_server.go @@ -7,8 +7,8 @@ import ( "google.golang.org/grpc" "github.com/cometbft/cometbft/abci/types" - cmtnet "github.com/cometbft/cometbft/libs/net" - "github.com/cometbft/cometbft/libs/service" + cmtnet "github.com/cometbft/cometbft/internal/net" + "github.com/cometbft/cometbft/internal/service" ) type GRPCServer struct { @@ -22,7 +22,7 @@ type GRPCServer struct { app types.Application } -// NewGRPCServer returns a new gRPC ABCI server +// NewGRPCServer returns a new gRPC ABCI server. func NewGRPCServer(protoAddr string, app types.Application) service.Service { proto, addr := cmtnet.ProtocolAndAddress(protoAddr) s := &GRPCServer{ @@ -37,7 +37,6 @@ func NewGRPCServer(protoAddr string, app types.Application) service.Service { // OnStart starts the gRPC service. func (s *GRPCServer) OnStart() error { - ln, err := net.Listen(s.proto, s.addr) if err != nil { return err @@ -61,17 +60,17 @@ func (s *GRPCServer) OnStop() { s.server.Stop() } -//------------------------------------------------------- +// ------------------------------------------------------- -// gRPCApplication is a gRPC shim for Application +// gRPCApplication is a gRPC shim for Application. type gRPCApplication struct { types.Application } -func (app *gRPCApplication) Echo(_ context.Context, req *types.RequestEcho) (*types.ResponseEcho, error) { - return &types.ResponseEcho{Message: req.Message}, nil +func (*gRPCApplication) Echo(_ context.Context, req *types.EchoRequest) (*types.EchoResponse, error) { + return &types.EchoResponse{Message: req.Message}, nil } -func (app *gRPCApplication) Flush(_ context.Context, req *types.RequestFlush) (*types.ResponseFlush, error) { - return &types.ResponseFlush{}, nil +func (*gRPCApplication) Flush(context.Context, *types.FlushRequest) (*types.FlushResponse, error) { + return &types.FlushResponse{}, nil } diff --git a/abci/server/server.go b/abci/server/server.go index 0577b504558..4ed2e695296 100644 --- a/abci/server/server.go +++ b/abci/server/server.go @@ -8,14 +8,12 @@ It contains two server implementation: package server import ( - "fmt" - "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/service" + "github.com/cometbft/cometbft/internal/service" ) // NewServer is a utility function for out of process applications to set up either a socket or -// grpc server that can listen to requests from the equivalent Tendermint client +// grpc server that can listen to requests from the equivalent Tendermint client. func NewServer(protoAddr, transport string, app types.Application) (service.Service, error) { var s service.Service var err error @@ -25,7 +23,7 @@ func NewServer(protoAddr, transport string, app types.Application) (service.Serv case "grpc": s = NewGRPCServer(protoAddr, app) default: - err = fmt.Errorf("unknown server type %s", transport) + err = ErrUnknownServerType{ServerType: transport} } return s, err } diff --git a/abci/server/socket_server.go b/abci/server/socket_server.go index d0b919200c7..e8437775697 100644 --- a/abci/server/socket_server.go +++ b/abci/server/socket_server.go @@ -11,17 +11,17 @@ import ( "runtime" "github.com/cometbft/cometbft/abci/types" + cmtnet "github.com/cometbft/cometbft/internal/net" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" cmtlog "github.com/cometbft/cometbft/libs/log" - cmtnet "github.com/cometbft/cometbft/libs/net" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" ) // SocketServer is the server-side implementation of the TSP (Tendermint Socket Protocol) // for out-of-process go applications. Note, in the case of an application written in golang, // the developer may also run both Tendermint and the application within the same process. // -// The socket server deliver +// The socket server deliver. type SocketServer struct { service.BaseService isLoggerSet bool @@ -97,14 +97,14 @@ func (s *SocketServer) addConn(conn net.Conn) int { return connID } -// deletes conn even if close errs +// deletes conn even if close errs. func (s *SocketServer) rmConn(connID int) error { s.connsMtx.Lock() defer s.connsMtx.Unlock() conn, ok := s.conns[connID] if !ok { - return fmt.Errorf("connection %d does not exist", connID) + return ErrConnectionDoesNotExist{ConnID: connID} } delete(s.conns, connID) @@ -159,15 +159,15 @@ func (s *SocketServer) waitForClose(closeConn chan error, connID int) { } } -// Read requests from conn and deal with them +// Read requests from conn and deal with them. func (s *SocketServer) handleRequests(closeConn chan error, conn io.Reader, responses chan<- *types.Response) { var count int - var bufReader = bufio.NewReader(conn) + bufReader := bufio.NewReader(conn) defer func() { // make sure to recover from any app-related panics to allow proper socket cleanup. // In the case of a panic, we do not notify the client by passing an exception so - // presume that the client is still running and retying to connect + // presume that the client is still running and retrying to connect r := recover() if r != nil { const size = 64 << 10 @@ -183,8 +183,7 @@ func (s *SocketServer) handleRequests(closeConn chan error, conn io.Reader, resp }() for { - - var req = &types.Request{} + req := &types.Request{} err := types.ReadMessage(bufReader, req) if err != nil { if err == io.EOF { @@ -201,7 +200,7 @@ func (s *SocketServer) handleRequests(closeConn chan error, conn io.Reader, resp // any error either from the application or because of an unknown request // throws an exception back to the client. This will stop the server and // should also halt the client. - responses <- types.ToResponseException(err.Error()) + responses <- types.ToExceptionResponse(err.Error()) } else { responses <- resp } @@ -209,108 +208,108 @@ func (s *SocketServer) handleRequests(closeConn chan error, conn io.Reader, resp } } -// handleRequests takes a request and calls the application passing the returned +// handleRequests takes a request and calls the application passing the returned. func (s *SocketServer) handleRequest(ctx context.Context, req *types.Request) (*types.Response, error) { switch r := req.Value.(type) { case *types.Request_Echo: - return types.ToResponseEcho(r.Echo.Message), nil + return types.ToEchoResponse(r.Echo.Message), nil case *types.Request_Flush: - return types.ToResponseFlush(), nil + return types.ToFlushResponse(), nil case *types.Request_Info: res, err := s.app.Info(ctx, r.Info) if err != nil { return nil, err } - return types.ToResponseInfo(res), nil + return types.ToInfoResponse(res), nil case *types.Request_CheckTx: res, err := s.app.CheckTx(ctx, r.CheckTx) if err != nil { return nil, err } - return types.ToResponseCheckTx(res), nil + return types.ToCheckTxResponse(res), nil case *types.Request_Commit: res, err := s.app.Commit(ctx, r.Commit) if err != nil { return nil, err } - return types.ToResponseCommit(res), nil + return types.ToCommitResponse(res), nil case *types.Request_Query: res, err := s.app.Query(ctx, r.Query) if err != nil { return nil, err } - return types.ToResponseQuery(res), nil + return types.ToQueryResponse(res), nil case *types.Request_InitChain: res, err := s.app.InitChain(ctx, r.InitChain) if err != nil { return nil, err } - return types.ToResponseInitChain(res), nil + return types.ToInitChainResponse(res), nil case *types.Request_FinalizeBlock: res, err := s.app.FinalizeBlock(ctx, r.FinalizeBlock) if err != nil { return nil, err } - return types.ToResponseFinalizeBlock(res), nil + return types.ToFinalizeBlockResponse(res), nil case *types.Request_ListSnapshots: res, err := s.app.ListSnapshots(ctx, r.ListSnapshots) if err != nil { return nil, err } - return types.ToResponseListSnapshots(res), nil + return types.ToListSnapshotsResponse(res), nil case *types.Request_OfferSnapshot: res, err := s.app.OfferSnapshot(ctx, r.OfferSnapshot) if err != nil { return nil, err } - return types.ToResponseOfferSnapshot(res), nil + return types.ToOfferSnapshotResponse(res), nil case *types.Request_PrepareProposal: res, err := s.app.PrepareProposal(ctx, r.PrepareProposal) if err != nil { return nil, err } - return types.ToResponsePrepareProposal(res), nil + return types.ToPrepareProposalResponse(res), nil case *types.Request_ProcessProposal: res, err := s.app.ProcessProposal(ctx, r.ProcessProposal) if err != nil { return nil, err } - return types.ToResponseProcessProposal(res), nil + return types.ToProcessProposalResponse(res), nil case *types.Request_LoadSnapshotChunk: res, err := s.app.LoadSnapshotChunk(ctx, r.LoadSnapshotChunk) if err != nil { return nil, err } - return types.ToResponseLoadSnapshotChunk(res), nil + return types.ToLoadSnapshotChunkResponse(res), nil case *types.Request_ApplySnapshotChunk: res, err := s.app.ApplySnapshotChunk(ctx, r.ApplySnapshotChunk) if err != nil { return nil, err } - return types.ToResponseApplySnapshotChunk(res), nil + return types.ToApplySnapshotChunkResponse(res), nil case *types.Request_ExtendVote: res, err := s.app.ExtendVote(ctx, r.ExtendVote) if err != nil { return nil, err } - return types.ToResponseExtendVote(res), nil + return types.ToExtendVoteResponse(res), nil case *types.Request_VerifyVoteExtension: res, err := s.app.VerifyVoteExtension(ctx, r.VerifyVoteExtension) if err != nil { return nil, err } - return types.ToResponseVerifyVoteExtension(res), nil + return types.ToVerifyVoteExtensionResponse(res), nil default: - return nil, fmt.Errorf("unknown request from client: %T", req) + return nil, ErrUnknownRequest{Request: *req} } } // Pull responses from 'responses' and write them to conn. -func (s *SocketServer) handleResponses(closeConn chan error, conn io.Writer, responses <-chan *types.Response) { +func (*SocketServer) handleResponses(closeConn chan error, conn io.Writer, responses <-chan *types.Response) { var count int - var bufWriter = bufio.NewWriter(conn) + bufWriter := bufio.NewWriter(conn) for { - var res = <-responses + res := <-responses err := types.WriteMessage(res, bufWriter) if err != nil { closeConn <- fmt.Errorf("error writing message: %w", err) diff --git a/abci/tests/benchmarks/parallel/parallel.go b/abci/tests/benchmarks/parallel/parallel.go index 974ba381538..cb2f2ca055c 100644 --- a/abci/tests/benchmarks/parallel/parallel.go +++ b/abci/tests/benchmarks/parallel/parallel.go @@ -6,11 +6,10 @@ import ( "log" "github.com/cometbft/cometbft/abci/types" - cmtnet "github.com/cometbft/cometbft/libs/net" + cmtnet "github.com/cometbft/cometbft/internal/net" ) func main() { - conn, err := cmtnet.Connect("unix://test.sock") if err != nil { log.Fatal(err.Error()) @@ -20,7 +19,7 @@ func main() { go func() { counter := 0 for { - var res = &types.Response{} + res := &types.Response{} err := types.ReadMessage(conn, res) if err != nil { log.Fatal(err.Error()) @@ -35,8 +34,8 @@ func main() { // Write a bunch of requests counter := 0 for i := 0; ; i++ { - var bufWriter = bufio.NewWriter(conn) - var req = types.ToRequestEcho("foobar") + bufWriter := bufio.NewWriter(conn) + req := types.ToEchoRequest("foobar") err := types.WriteMessage(req, bufWriter) if err != nil { diff --git a/abci/tests/benchmarks/simple/simple.go b/abci/tests/benchmarks/simple/simple.go index 2aaa056d068..79ecd391090 100644 --- a/abci/tests/benchmarks/simple/simple.go +++ b/abci/tests/benchmarks/simple/simple.go @@ -8,11 +8,10 @@ import ( "reflect" "github.com/cometbft/cometbft/abci/types" - cmtnet "github.com/cometbft/cometbft/libs/net" + cmtnet "github.com/cometbft/cometbft/internal/net" ) func main() { - conn, err := cmtnet.Connect("unix://test.sock") if err != nil { log.Fatal(err.Error()) @@ -21,7 +20,7 @@ func main() { // Make a bunch of requests counter := 0 for i := 0; ; i++ { - req := types.ToRequestEcho("foobar") + req := types.ToEchoRequest("foobar") _, err := makeRequest(conn, req) if err != nil { log.Fatal(err.Error()) @@ -34,14 +33,14 @@ func main() { } func makeRequest(conn io.ReadWriter, req *types.Request) (*types.Response, error) { - var bufWriter = bufio.NewWriter(conn) + bufWriter := bufio.NewWriter(conn) // Write desired request err := types.WriteMessage(req, bufWriter) if err != nil { return nil, err } - err = types.WriteMessage(types.ToRequestFlush(), bufWriter) + err = types.WriteMessage(types.ToFlushRequest(), bufWriter) if err != nil { return nil, err } @@ -51,12 +50,12 @@ func makeRequest(conn io.ReadWriter, req *types.Request) (*types.Response, error } // Read desired response - var res = &types.Response{} + res := &types.Response{} err = types.ReadMessage(conn, res) if err != nil { return nil, err } - var resFlush = &types.Response{} + resFlush := &types.Response{} err = types.ReadMessage(conn, resFlush) if err != nil { return nil, err diff --git a/abci/tests/client_server_test.go b/abci/tests/client_server_test.go index 79737a203c0..b1af64dec48 100644 --- a/abci/tests/client_server_test.go +++ b/abci/tests/client_server_test.go @@ -3,7 +3,7 @@ package tests import ( "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" abciclient "github.com/cometbft/cometbft/abci/client" "github.com/cometbft/cometbft/abci/example/kvstore" @@ -18,9 +18,9 @@ func TestClientServerNoAddrPrefix(t *testing.T) { app := kvstore.NewInMemoryApplication() server, err := abciserver.NewServer(addr, transport, app) - assert.NoError(t, err, "expected no error on NewServer") + require.NoError(t, err) err = server.Start() - assert.NoError(t, err, "expected no error on server.Start") + require.NoError(t, err) t.Cleanup(func() { if err := server.Stop(); err != nil { t.Error(err) @@ -28,9 +28,9 @@ func TestClientServerNoAddrPrefix(t *testing.T) { }) client, err := abciclient.NewClient(addr, transport, true) - assert.NoError(t, err, "expected no error on NewClient") + require.NoError(t, err) err = client.Start() - assert.NoError(t, err, "expected no error on client.Start") + require.NoError(t, err) t.Cleanup(func() { if err := client.Stop(); err != nil { t.Error(err) diff --git a/abci/tests/server/client.go b/abci/tests/server/client.go index fc745211d4d..685ec6a1bb8 100644 --- a/abci/tests/server/client.go +++ b/abci/tests/server/client.go @@ -8,7 +8,7 @@ import ( abcicli "github.com/cometbft/cometbft/abci/client" "github.com/cometbft/cometbft/abci/types" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) func InitChain(ctx context.Context, client abcicli.Client) error { @@ -19,7 +19,7 @@ func InitChain(ctx context.Context, client abcicli.Client) error { power := cmtrand.Int() vals[i] = types.UpdateValidator(pubkey, int64(power), "") } - _, err := client.InitChain(ctx, &types.RequestInitChain{ + _, err := client.InitChain(ctx, &types.InitChainRequest{ Validators: vals, }) if err != nil { @@ -31,7 +31,7 @@ func InitChain(ctx context.Context, client abcicli.Client) error { } func Commit(ctx context.Context, client abcicli.Client) error { - _, err := client.Commit(ctx, &types.RequestCommit{}) + _, err := client.Commit(ctx, &types.CommitRequest{}) if err != nil { fmt.Println("Failed test: Commit") fmt.Printf("error while committing: %v\n", err) @@ -42,7 +42,7 @@ func Commit(ctx context.Context, client abcicli.Client) error { } func FinalizeBlock(ctx context.Context, client abcicli.Client, txBytes [][]byte, codeExp []uint32, dataExp []byte, hashExp []byte) error { - res, _ := client.FinalizeBlock(ctx, &types.RequestFinalizeBlock{Txs: txBytes}) + res, _ := client.FinalizeBlock(ctx, &types.FinalizeBlockRequest{Txs: txBytes}) appHash := res.AppHash for i, tx := range res.TxResults { code, data, log := tx.Code, tx.Data, tx.Log @@ -68,8 +68,8 @@ func FinalizeBlock(ctx context.Context, client abcicli.Client, txBytes [][]byte, return nil } -func PrepareProposal(ctx context.Context, client abcicli.Client, txBytes [][]byte, txExpected [][]byte, dataExp []byte) error { - res, _ := client.PrepareProposal(ctx, &types.RequestPrepareProposal{Txs: txBytes}) +func PrepareProposal(ctx context.Context, client abcicli.Client, txBytes [][]byte, txExpected [][]byte, _ []byte) error { + res, _ := client.PrepareProposal(ctx, &types.PrepareProposalRequest{Txs: txBytes}) for i, tx := range res.Txs { if !bytes.Equal(tx, txExpected[i]) { fmt.Println("Failed test: PrepareProposal") @@ -82,8 +82,8 @@ func PrepareProposal(ctx context.Context, client abcicli.Client, txBytes [][]byt return nil } -func ProcessProposal(ctx context.Context, client abcicli.Client, txBytes [][]byte, statusExp types.ResponseProcessProposal_ProposalStatus) error { - res, _ := client.ProcessProposal(ctx, &types.RequestProcessProposal{Txs: txBytes}) +func ProcessProposal(ctx context.Context, client abcicli.Client, txBytes [][]byte, statusExp types.ProcessProposalStatus) error { + res, _ := client.ProcessProposal(ctx, &types.ProcessProposalRequest{Txs: txBytes}) if res.Status != statusExp { fmt.Println("Failed test: ProcessProposal") fmt.Printf("ProcessProposal response status was unexpected. Got %v expected %v.", @@ -95,7 +95,7 @@ func ProcessProposal(ctx context.Context, client abcicli.Client, txBytes [][]byt } func CheckTx(ctx context.Context, client abcicli.Client, txBytes []byte, codeExp uint32, dataExp []byte) error { - res, _ := client.CheckTx(ctx, &types.RequestCheckTx{Tx: txBytes}) + res, _ := client.CheckTx(ctx, &types.CheckTxRequest{Tx: txBytes, Type: types.CHECK_TX_TYPE_CHECK}) code, data, log := res.Code, res.Data, res.Log if code != codeExp { fmt.Println("Failed test: CheckTx") diff --git a/abci/tests/test_cli/ex1.abci.out b/abci/tests/test_cli/ex1.abci.out index 39b7f874bef..8b5d53badad 100644 --- a/abci/tests/test_cli/ex1.abci.out +++ b/abci/tests/test_cli/ex1.abci.out @@ -14,11 +14,11 @@ > process_proposal "abc==456" -> code: OK --> status: REJECT +-> status: PROCESS_PROPOSAL_STATUS_REJECT > process_proposal "abc=123" -> code: OK --> status: ACCEPT +-> status: PROCESS_PROPOSAL_STATUS_ACCEPT > finalize_block "abc=123" -> code: OK diff --git a/abci/types/application.go b/abci/types/application.go index 3d3a75b55a6..dd766f524ba 100644 --- a/abci/types/application.go +++ b/abci/types/application.go @@ -8,33 +8,33 @@ import "context" // to be driven by a blockchain-based replication engine via the ABCI. type Application interface { // Info/Query Connection - Info(context.Context, *RequestInfo) (*ResponseInfo, error) // Return application info - Query(context.Context, *RequestQuery) (*ResponseQuery, error) // Query for state + Info(ctx context.Context, req *InfoRequest) (*InfoResponse, error) // Return application info + Query(ctx context.Context, req *QueryRequest) (*QueryResponse, error) // Query for state // Mempool Connection - CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) // Validate a tx for the mempool + CheckTx(ctx context.Context, req *CheckTxRequest) (*CheckTxResponse, error) // Validate a tx for the mempool // Consensus Connection - InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) // Initialize blockchain w validators/other info from CometBFT - PrepareProposal(context.Context, *RequestPrepareProposal) (*ResponsePrepareProposal, error) - ProcessProposal(context.Context, *RequestProcessProposal) (*ResponseProcessProposal, error) + InitChain(ctx context.Context, req *InitChainRequest) (*InitChainResponse, error) // Initialize blockchain w validators/other info from CometBFT + PrepareProposal(ctx context.Context, req *PrepareProposalRequest) (*PrepareProposalResponse, error) + ProcessProposal(ctx context.Context, req *ProcessProposalRequest) (*ProcessProposalResponse, error) // Deliver the decided block with its txs to the Application - FinalizeBlock(context.Context, *RequestFinalizeBlock) (*ResponseFinalizeBlock, error) + FinalizeBlock(ctx context.Context, req *FinalizeBlockRequest) (*FinalizeBlockResponse, error) // Create application specific vote extension - ExtendVote(context.Context, *RequestExtendVote) (*ResponseExtendVote, error) + ExtendVote(ctx context.Context, req *ExtendVoteRequest) (*ExtendVoteResponse, error) // Verify application's vote extension data - VerifyVoteExtension(context.Context, *RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error) + VerifyVoteExtension(ctx context.Context, req *VerifyVoteExtensionRequest) (*VerifyVoteExtensionResponse, error) // Commit the state and return the application Merkle root hash - Commit(context.Context, *RequestCommit) (*ResponseCommit, error) + Commit(ctx context.Context, req *CommitRequest) (*CommitResponse, error) // State Sync Connection - ListSnapshots(context.Context, *RequestListSnapshots) (*ResponseListSnapshots, error) // List available snapshots - OfferSnapshot(context.Context, *RequestOfferSnapshot) (*ResponseOfferSnapshot, error) // Offer a snapshot to the application - LoadSnapshotChunk(context.Context, *RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) // Load a snapshot chunk - ApplySnapshotChunk(context.Context, *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) // Apply a shapshot chunk + ListSnapshots(ctx context.Context, req *ListSnapshotsRequest) (*ListSnapshotsResponse, error) // List available snapshots + OfferSnapshot(ctx context.Context, req *OfferSnapshotRequest) (*OfferSnapshotResponse, error) // Offer a snapshot to the application + LoadSnapshotChunk(ctx context.Context, req *LoadSnapshotChunkRequest) (*LoadSnapshotChunkResponse, error) // Load a snapshot chunk + ApplySnapshotChunk(ctx context.Context, req *ApplySnapshotChunkRequest) (*ApplySnapshotChunkResponse, error) // Apply a snapshot chunk } -//------------------------------------------------------- +// ------------------------------------------------------- // BaseApplication is a base form of Application var _ Application = (*BaseApplication)(nil) @@ -45,43 +45,43 @@ func NewBaseApplication() *BaseApplication { return &BaseApplication{} } -func (BaseApplication) Info(_ context.Context, req *RequestInfo) (*ResponseInfo, error) { - return &ResponseInfo{}, nil +func (BaseApplication) Info(context.Context, *InfoRequest) (*InfoResponse, error) { + return &InfoResponse{}, nil } -func (BaseApplication) CheckTx(_ context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { - return &ResponseCheckTx{Code: CodeTypeOK}, nil +func (BaseApplication) CheckTx(context.Context, *CheckTxRequest) (*CheckTxResponse, error) { + return &CheckTxResponse{Code: CodeTypeOK}, nil } -func (BaseApplication) Commit(_ context.Context, req *RequestCommit) (*ResponseCommit, error) { - return &ResponseCommit{}, nil +func (BaseApplication) Commit(context.Context, *CommitRequest) (*CommitResponse, error) { + return &CommitResponse{}, nil } -func (BaseApplication) Query(_ context.Context, req *RequestQuery) (*ResponseQuery, error) { - return &ResponseQuery{Code: CodeTypeOK}, nil +func (BaseApplication) Query(context.Context, *QueryRequest) (*QueryResponse, error) { + return &QueryResponse{Code: CodeTypeOK}, nil } -func (BaseApplication) InitChain(_ context.Context, req *RequestInitChain) (*ResponseInitChain, error) { - return &ResponseInitChain{}, nil +func (BaseApplication) InitChain(context.Context, *InitChainRequest) (*InitChainResponse, error) { + return &InitChainResponse{}, nil } -func (BaseApplication) ListSnapshots(_ context.Context, req *RequestListSnapshots) (*ResponseListSnapshots, error) { - return &ResponseListSnapshots{}, nil +func (BaseApplication) ListSnapshots(context.Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error) { + return &ListSnapshotsResponse{}, nil } -func (BaseApplication) OfferSnapshot(_ context.Context, req *RequestOfferSnapshot) (*ResponseOfferSnapshot, error) { - return &ResponseOfferSnapshot{}, nil +func (BaseApplication) OfferSnapshot(context.Context, *OfferSnapshotRequest) (*OfferSnapshotResponse, error) { + return &OfferSnapshotResponse{}, nil } -func (BaseApplication) LoadSnapshotChunk(_ context.Context, _ *RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) { - return &ResponseLoadSnapshotChunk{}, nil +func (BaseApplication) LoadSnapshotChunk(context.Context, *LoadSnapshotChunkRequest) (*LoadSnapshotChunkResponse, error) { + return &LoadSnapshotChunkResponse{}, nil } -func (BaseApplication) ApplySnapshotChunk(_ context.Context, req *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) { - return &ResponseApplySnapshotChunk{}, nil +func (BaseApplication) ApplySnapshotChunk(context.Context, *ApplySnapshotChunkRequest) (*ApplySnapshotChunkResponse, error) { + return &ApplySnapshotChunkResponse{}, nil } -func (BaseApplication) PrepareProposal(_ context.Context, req *RequestPrepareProposal) (*ResponsePrepareProposal, error) { +func (BaseApplication) PrepareProposal(_ context.Context, req *PrepareProposalRequest) (*PrepareProposalResponse, error) { txs := make([][]byte, 0, len(req.Txs)) var totalBytes int64 for _, tx := range req.Txs { @@ -91,29 +91,29 @@ func (BaseApplication) PrepareProposal(_ context.Context, req *RequestPreparePro } txs = append(txs, tx) } - return &ResponsePrepareProposal{Txs: txs}, nil + return &PrepareProposalResponse{Txs: txs}, nil } -func (BaseApplication) ProcessProposal(_ context.Context, req *RequestProcessProposal) (*ResponseProcessProposal, error) { - return &ResponseProcessProposal{Status: ResponseProcessProposal_ACCEPT}, nil +func (BaseApplication) ProcessProposal(context.Context, *ProcessProposalRequest) (*ProcessProposalResponse, error) { + return &ProcessProposalResponse{Status: PROCESS_PROPOSAL_STATUS_ACCEPT}, nil } -func (BaseApplication) ExtendVote(_ context.Context, req *RequestExtendVote) (*ResponseExtendVote, error) { - return &ResponseExtendVote{}, nil +func (BaseApplication) ExtendVote(context.Context, *ExtendVoteRequest) (*ExtendVoteResponse, error) { + return &ExtendVoteResponse{}, nil } -func (BaseApplication) VerifyVoteExtension(_ context.Context, req *RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error) { - return &ResponseVerifyVoteExtension{ - Status: ResponseVerifyVoteExtension_ACCEPT, +func (BaseApplication) VerifyVoteExtension(context.Context, *VerifyVoteExtensionRequest) (*VerifyVoteExtensionResponse, error) { + return &VerifyVoteExtensionResponse{ + Status: VERIFY_VOTE_EXTENSION_STATUS_ACCEPT, }, nil } -func (BaseApplication) FinalizeBlock(_ context.Context, req *RequestFinalizeBlock) (*ResponseFinalizeBlock, error) { +func (BaseApplication) FinalizeBlock(_ context.Context, req *FinalizeBlockRequest) (*FinalizeBlockResponse, error) { txs := make([]*ExecTxResult, len(req.Txs)) for i := range req.Txs { txs[i] = &ExecTxResult{Code: CodeTypeOK} } - return &ResponseFinalizeBlock{ + return &FinalizeBlockResponse{ TxResults: txs, }, nil } diff --git a/abci/types/messages.go b/abci/types/messages.go index b081098d0bd..4e9ddbab771 100644 --- a/abci/types/messages.go +++ b/abci/types/messages.go @@ -2,14 +2,16 @@ package types import ( "io" + "math" "github.com/cosmos/gogoproto/proto" - "github.com/cometbft/cometbft/libs/protoio" + pb "github.com/cometbft/cometbft/api/cometbft/abci/v1" + "github.com/cometbft/cometbft/internal/protoio" ) const ( - maxMsgSize = 104857600 // 100MB + maxMsgSize = math.MaxInt32 // 2GB ) // WriteMessage writes a varint length-delimited protobuf message. @@ -25,204 +27,204 @@ func ReadMessage(r io.Reader, msg proto.Message) error { return err } -//---------------------------------------- +// ---------------------------------------- -func ToRequestEcho(message string) *Request { +func ToEchoRequest(message string) *Request { return &Request{ - Value: &Request_Echo{&RequestEcho{Message: message}}, + Value: &pb.Request_Echo{Echo: &EchoRequest{Message: message}}, } } -func ToRequestFlush() *Request { +func ToFlushRequest() *Request { return &Request{ - Value: &Request_Flush{&RequestFlush{}}, + Value: &pb.Request_Flush{Flush: &FlushRequest{}}, } } -func ToRequestInfo(req *RequestInfo) *Request { +func ToInfoRequest(req *InfoRequest) *Request { return &Request{ - Value: &Request_Info{req}, + Value: &pb.Request_Info{Info: req}, } } -func ToRequestCheckTx(req *RequestCheckTx) *Request { +func ToCheckTxRequest(req *CheckTxRequest) *Request { return &Request{ - Value: &Request_CheckTx{req}, + Value: &pb.Request_CheckTx{CheckTx: req}, } } -func ToRequestCommit() *Request { +func ToCommitRequest() *Request { return &Request{ - Value: &Request_Commit{&RequestCommit{}}, + Value: &pb.Request_Commit{Commit: &CommitRequest{}}, } } -func ToRequestQuery(req *RequestQuery) *Request { +func ToQueryRequest(req *QueryRequest) *Request { return &Request{ - Value: &Request_Query{req}, + Value: &pb.Request_Query{Query: req}, } } -func ToRequestInitChain(req *RequestInitChain) *Request { +func ToInitChainRequest(req *InitChainRequest) *Request { return &Request{ - Value: &Request_InitChain{req}, + Value: &pb.Request_InitChain{InitChain: req}, } } -func ToRequestListSnapshots(req *RequestListSnapshots) *Request { +func ToListSnapshotsRequest(req *ListSnapshotsRequest) *Request { return &Request{ - Value: &Request_ListSnapshots{req}, + Value: &pb.Request_ListSnapshots{ListSnapshots: req}, } } -func ToRequestOfferSnapshot(req *RequestOfferSnapshot) *Request { +func ToOfferSnapshotRequest(req *OfferSnapshotRequest) *Request { return &Request{ - Value: &Request_OfferSnapshot{req}, + Value: &pb.Request_OfferSnapshot{OfferSnapshot: req}, } } -func ToRequestLoadSnapshotChunk(req *RequestLoadSnapshotChunk) *Request { +func ToLoadSnapshotChunkRequest(req *LoadSnapshotChunkRequest) *Request { return &Request{ - Value: &Request_LoadSnapshotChunk{req}, + Value: &pb.Request_LoadSnapshotChunk{LoadSnapshotChunk: req}, } } -func ToRequestApplySnapshotChunk(req *RequestApplySnapshotChunk) *Request { +func ToApplySnapshotChunkRequest(req *ApplySnapshotChunkRequest) *Request { return &Request{ - Value: &Request_ApplySnapshotChunk{req}, + Value: &pb.Request_ApplySnapshotChunk{ApplySnapshotChunk: req}, } } -func ToRequestPrepareProposal(req *RequestPrepareProposal) *Request { +func ToPrepareProposalRequest(req *PrepareProposalRequest) *Request { return &Request{ - Value: &Request_PrepareProposal{req}, + Value: &pb.Request_PrepareProposal{PrepareProposal: req}, } } -func ToRequestProcessProposal(req *RequestProcessProposal) *Request { +func ToProcessProposalRequest(req *ProcessProposalRequest) *Request { return &Request{ - Value: &Request_ProcessProposal{req}, + Value: &pb.Request_ProcessProposal{ProcessProposal: req}, } } -func ToRequestExtendVote(req *RequestExtendVote) *Request { +func ToExtendVoteRequest(req *ExtendVoteRequest) *Request { return &Request{ - Value: &Request_ExtendVote{req}, + Value: &pb.Request_ExtendVote{ExtendVote: req}, } } -func ToRequestVerifyVoteExtension(req *RequestVerifyVoteExtension) *Request { +func ToVerifyVoteExtensionRequest(req *VerifyVoteExtensionRequest) *Request { return &Request{ - Value: &Request_VerifyVoteExtension{req}, + Value: &pb.Request_VerifyVoteExtension{VerifyVoteExtension: req}, } } -func ToRequestFinalizeBlock(req *RequestFinalizeBlock) *Request { +func ToFinalizeBlockRequest(req *FinalizeBlockRequest) *Request { return &Request{ - Value: &Request_FinalizeBlock{req}, + Value: &pb.Request_FinalizeBlock{FinalizeBlock: req}, } } -//---------------------------------------- +// ---------------------------------------- -func ToResponseException(errStr string) *Response { +func ToExceptionResponse(errStr string) *Response { return &Response{ - Value: &Response_Exception{&ResponseException{Error: errStr}}, + Value: &pb.Response_Exception{Exception: &ExceptionResponse{Error: errStr}}, } } -func ToResponseEcho(message string) *Response { +func ToEchoResponse(message string) *Response { return &Response{ - Value: &Response_Echo{&ResponseEcho{Message: message}}, + Value: &pb.Response_Echo{Echo: &EchoResponse{Message: message}}, } } -func ToResponseFlush() *Response { +func ToFlushResponse() *Response { return &Response{ - Value: &Response_Flush{&ResponseFlush{}}, + Value: &pb.Response_Flush{Flush: &FlushResponse{}}, } } -func ToResponseInfo(res *ResponseInfo) *Response { +func ToInfoResponse(res *InfoResponse) *Response { return &Response{ - Value: &Response_Info{res}, + Value: &pb.Response_Info{Info: res}, } } -func ToResponseCheckTx(res *ResponseCheckTx) *Response { +func ToCheckTxResponse(res *CheckTxResponse) *Response { return &Response{ - Value: &Response_CheckTx{res}, + Value: &pb.Response_CheckTx{CheckTx: res}, } } -func ToResponseCommit(res *ResponseCommit) *Response { +func ToCommitResponse(res *CommitResponse) *Response { return &Response{ - Value: &Response_Commit{res}, + Value: &pb.Response_Commit{Commit: res}, } } -func ToResponseQuery(res *ResponseQuery) *Response { +func ToQueryResponse(res *QueryResponse) *Response { return &Response{ - Value: &Response_Query{res}, + Value: &pb.Response_Query{Query: res}, } } -func ToResponseInitChain(res *ResponseInitChain) *Response { +func ToInitChainResponse(res *InitChainResponse) *Response { return &Response{ - Value: &Response_InitChain{res}, + Value: &pb.Response_InitChain{InitChain: res}, } } -func ToResponseListSnapshots(res *ResponseListSnapshots) *Response { +func ToListSnapshotsResponse(res *ListSnapshotsResponse) *Response { return &Response{ - Value: &Response_ListSnapshots{res}, + Value: &pb.Response_ListSnapshots{ListSnapshots: res}, } } -func ToResponseOfferSnapshot(res *ResponseOfferSnapshot) *Response { +func ToOfferSnapshotResponse(res *OfferSnapshotResponse) *Response { return &Response{ - Value: &Response_OfferSnapshot{res}, + Value: &pb.Response_OfferSnapshot{OfferSnapshot: res}, } } -func ToResponseLoadSnapshotChunk(res *ResponseLoadSnapshotChunk) *Response { +func ToLoadSnapshotChunkResponse(res *LoadSnapshotChunkResponse) *Response { return &Response{ - Value: &Response_LoadSnapshotChunk{res}, + Value: &pb.Response_LoadSnapshotChunk{LoadSnapshotChunk: res}, } } -func ToResponseApplySnapshotChunk(res *ResponseApplySnapshotChunk) *Response { +func ToApplySnapshotChunkResponse(res *ApplySnapshotChunkResponse) *Response { return &Response{ - Value: &Response_ApplySnapshotChunk{res}, + Value: &pb.Response_ApplySnapshotChunk{ApplySnapshotChunk: res}, } } -func ToResponsePrepareProposal(res *ResponsePrepareProposal) *Response { +func ToPrepareProposalResponse(res *PrepareProposalResponse) *Response { return &Response{ - Value: &Response_PrepareProposal{res}, + Value: &pb.Response_PrepareProposal{PrepareProposal: res}, } } -func ToResponseProcessProposal(res *ResponseProcessProposal) *Response { +func ToProcessProposalResponse(res *ProcessProposalResponse) *Response { return &Response{ - Value: &Response_ProcessProposal{res}, + Value: &pb.Response_ProcessProposal{ProcessProposal: res}, } } -func ToResponseExtendVote(res *ResponseExtendVote) *Response { +func ToExtendVoteResponse(res *ExtendVoteResponse) *Response { return &Response{ - Value: &Response_ExtendVote{res}, + Value: &pb.Response_ExtendVote{ExtendVote: res}, } } -func ToResponseVerifyVoteExtension(res *ResponseVerifyVoteExtension) *Response { +func ToVerifyVoteExtensionResponse(res *VerifyVoteExtensionResponse) *Response { return &Response{ - Value: &Response_VerifyVoteExtension{res}, + Value: &pb.Response_VerifyVoteExtension{VerifyVoteExtension: res}, } } -func ToResponseFinalizeBlock(res *ResponseFinalizeBlock) *Response { +func ToFinalizeBlockResponse(res *FinalizeBlockResponse) *Response { return &Response{ - Value: &Response_FinalizeBlock{res}, + Value: &pb.Response_FinalizeBlock{FinalizeBlock: res}, } } diff --git a/abci/types/messages_test.go b/abci/types/messages_test.go index 624096cbec8..e70ebc7c8cc 100644 --- a/abci/types/messages_test.go +++ b/abci/types/messages_test.go @@ -8,16 +8,17 @@ import ( "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" ) func TestMarshalJSON(t *testing.T) { b, err := json.Marshal(&ExecTxResult{Code: 1}) - assert.NoError(t, err) + require.NoError(t, err) // include empty fields. assert.True(t, strings.Contains(string(b), "code")) - r1 := ResponseCheckTx{ + r1 := CheckTxResponse{ Code: 1, Data: []byte("hello"), GasWanted: 43, @@ -31,17 +32,17 @@ func TestMarshalJSON(t *testing.T) { }, } b, err = json.Marshal(&r1) - assert.Nil(t, err) + require.NoError(t, err) - var r2 ResponseCheckTx + var r2 CheckTxResponse err = json.Unmarshal(b, &r2) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, r1, r2) } func TestWriteReadMessageSimple(t *testing.T) { cases := []proto.Message{ - &RequestEcho{ + &EchoRequest{ Message: "Hello", }, } @@ -49,11 +50,11 @@ func TestWriteReadMessageSimple(t *testing.T) { for _, c := range cases { buf := new(bytes.Buffer) err := WriteMessage(c, buf) - assert.Nil(t, err) + require.NoError(t, err) - msg := new(RequestEcho) + msg := new(EchoRequest) err = ReadMessage(buf, msg) - assert.Nil(t, err) + require.NoError(t, err) assert.True(t, proto.Equal(c, msg)) } @@ -71,11 +72,11 @@ func TestWriteReadMessage(t *testing.T) { for _, c := range cases { buf := new(bytes.Buffer) err := WriteMessage(c, buf) - assert.Nil(t, err) + require.NoError(t, err) msg := new(cmtproto.Header) err = ReadMessage(buf, msg) - assert.Nil(t, err) + require.NoError(t, err) assert.True(t, proto.Equal(c, msg)) } @@ -84,7 +85,7 @@ func TestWriteReadMessage(t *testing.T) { func TestWriteReadMessage2(t *testing.T) { phrase := "hello-world" cases := []proto.Message{ - &ResponseCheckTx{ + &CheckTxResponse{ Data: []byte(phrase), Log: phrase, GasWanted: 10, @@ -103,11 +104,11 @@ func TestWriteReadMessage2(t *testing.T) { for _, c := range cases { buf := new(bytes.Buffer) err := WriteMessage(c, buf) - assert.Nil(t, err) + require.NoError(t, err) - msg := new(ResponseCheckTx) + msg := new(CheckTxResponse) err = ReadMessage(buf, msg) - assert.Nil(t, err) + require.NoError(t, err) assert.True(t, proto.Equal(c, msg)) } diff --git a/abci/types/mocks/application.go b/abci/types/mocks/application.go index b7f0b51ded0..e055d367803 100644 --- a/abci/types/mocks/application.go +++ b/abci/types/mocks/application.go @@ -5,8 +5,9 @@ package mocks import ( context "context" - types "github.com/cometbft/cometbft/abci/types" mock "github.com/stretchr/testify/mock" + + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" ) // Application is an autogenerated mock type for the Application type @@ -14,25 +15,29 @@ type Application struct { mock.Mock } -// ApplySnapshotChunk provides a mock function with given fields: _a0, _a1 -func (_m *Application) ApplySnapshotChunk(_a0 context.Context, _a1 *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) { - ret := _m.Called(_a0, _a1) +// ApplySnapshotChunk provides a mock function with given fields: ctx, req +func (_m *Application) ApplySnapshotChunk(ctx context.Context, req *v1.ApplySnapshotChunkRequest) (*v1.ApplySnapshotChunkResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for ApplySnapshotChunk") + } - var r0 *types.ResponseApplySnapshotChunk + var r0 *v1.ApplySnapshotChunkResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ApplySnapshotChunkRequest) (*v1.ApplySnapshotChunkResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestApplySnapshotChunk) *types.ResponseApplySnapshotChunk); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ApplySnapshotChunkRequest) *v1.ApplySnapshotChunkResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseApplySnapshotChunk) + r0 = ret.Get(0).(*v1.ApplySnapshotChunkResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestApplySnapshotChunk) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ApplySnapshotChunkRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -40,25 +45,29 @@ func (_m *Application) ApplySnapshotChunk(_a0 context.Context, _a1 *types.Reques return r0, r1 } -// CheckTx provides a mock function with given fields: _a0, _a1 -func (_m *Application) CheckTx(_a0 context.Context, _a1 *types.RequestCheckTx) (*types.ResponseCheckTx, error) { - ret := _m.Called(_a0, _a1) +// CheckTx provides a mock function with given fields: ctx, req +func (_m *Application) CheckTx(ctx context.Context, req *v1.CheckTxRequest) (*v1.CheckTxResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for CheckTx") + } - var r0 *types.ResponseCheckTx + var r0 *v1.CheckTxResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) (*types.ResponseCheckTx, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) (*v1.CheckTxResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) *types.ResponseCheckTx); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) *v1.CheckTxResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseCheckTx) + r0 = ret.Get(0).(*v1.CheckTxResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestCheckTx) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.CheckTxRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -66,25 +75,29 @@ func (_m *Application) CheckTx(_a0 context.Context, _a1 *types.RequestCheckTx) ( return r0, r1 } -// Commit provides a mock function with given fields: _a0, _a1 -func (_m *Application) Commit(_a0 context.Context, _a1 *types.RequestCommit) (*types.ResponseCommit, error) { - ret := _m.Called(_a0, _a1) +// Commit provides a mock function with given fields: ctx, req +func (_m *Application) Commit(ctx context.Context, req *v1.CommitRequest) (*v1.CommitResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseCommit + if len(ret) == 0 { + panic("no return value specified for Commit") + } + + var r0 *v1.CommitResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCommit) (*types.ResponseCommit, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CommitRequest) (*v1.CommitResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCommit) *types.ResponseCommit); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CommitRequest) *v1.CommitResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseCommit) + r0 = ret.Get(0).(*v1.CommitResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestCommit) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.CommitRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -92,25 +105,29 @@ func (_m *Application) Commit(_a0 context.Context, _a1 *types.RequestCommit) (*t return r0, r1 } -// ExtendVote provides a mock function with given fields: _a0, _a1 -func (_m *Application) ExtendVote(_a0 context.Context, _a1 *types.RequestExtendVote) (*types.ResponseExtendVote, error) { - ret := _m.Called(_a0, _a1) +// ExtendVote provides a mock function with given fields: ctx, req +func (_m *Application) ExtendVote(ctx context.Context, req *v1.ExtendVoteRequest) (*v1.ExtendVoteResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for ExtendVote") + } - var r0 *types.ResponseExtendVote + var r0 *v1.ExtendVoteResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestExtendVote) (*types.ResponseExtendVote, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExtendVoteRequest) (*v1.ExtendVoteResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestExtendVote) *types.ResponseExtendVote); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExtendVoteRequest) *v1.ExtendVoteResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseExtendVote) + r0 = ret.Get(0).(*v1.ExtendVoteResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestExtendVote) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ExtendVoteRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -118,25 +135,29 @@ func (_m *Application) ExtendVote(_a0 context.Context, _a1 *types.RequestExtendV return r0, r1 } -// FinalizeBlock provides a mock function with given fields: _a0, _a1 -func (_m *Application) FinalizeBlock(_a0 context.Context, _a1 *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { - ret := _m.Called(_a0, _a1) +// FinalizeBlock provides a mock function with given fields: ctx, req +func (_m *Application) FinalizeBlock(ctx context.Context, req *v1.FinalizeBlockRequest) (*v1.FinalizeBlockResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseFinalizeBlock + if len(ret) == 0 { + panic("no return value specified for FinalizeBlock") + } + + var r0 *v1.FinalizeBlockResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.FinalizeBlockRequest) (*v1.FinalizeBlockResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestFinalizeBlock) *types.ResponseFinalizeBlock); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.FinalizeBlockRequest) *v1.FinalizeBlockResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseFinalizeBlock) + r0 = ret.Get(0).(*v1.FinalizeBlockResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestFinalizeBlock) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.FinalizeBlockRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -144,25 +165,29 @@ func (_m *Application) FinalizeBlock(_a0 context.Context, _a1 *types.RequestFina return r0, r1 } -// Info provides a mock function with given fields: _a0, _a1 -func (_m *Application) Info(_a0 context.Context, _a1 *types.RequestInfo) (*types.ResponseInfo, error) { - ret := _m.Called(_a0, _a1) +// Info provides a mock function with given fields: ctx, req +func (_m *Application) Info(ctx context.Context, req *v1.InfoRequest) (*v1.InfoResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for Info") + } - var r0 *types.ResponseInfo + var r0 *v1.InfoResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInfo) (*types.ResponseInfo, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InfoRequest) (*v1.InfoResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInfo) *types.ResponseInfo); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InfoRequest) *v1.InfoResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseInfo) + r0 = ret.Get(0).(*v1.InfoResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestInfo) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.InfoRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -170,25 +195,29 @@ func (_m *Application) Info(_a0 context.Context, _a1 *types.RequestInfo) (*types return r0, r1 } -// InitChain provides a mock function with given fields: _a0, _a1 -func (_m *Application) InitChain(_a0 context.Context, _a1 *types.RequestInitChain) (*types.ResponseInitChain, error) { - ret := _m.Called(_a0, _a1) +// InitChain provides a mock function with given fields: ctx, req +func (_m *Application) InitChain(ctx context.Context, req *v1.InitChainRequest) (*v1.InitChainResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseInitChain + if len(ret) == 0 { + panic("no return value specified for InitChain") + } + + var r0 *v1.InitChainResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInitChain) (*types.ResponseInitChain, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InitChainRequest) (*v1.InitChainResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInitChain) *types.ResponseInitChain); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InitChainRequest) *v1.InitChainResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseInitChain) + r0 = ret.Get(0).(*v1.InitChainResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestInitChain) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.InitChainRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -196,25 +225,29 @@ func (_m *Application) InitChain(_a0 context.Context, _a1 *types.RequestInitChai return r0, r1 } -// ListSnapshots provides a mock function with given fields: _a0, _a1 -func (_m *Application) ListSnapshots(_a0 context.Context, _a1 *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) { - ret := _m.Called(_a0, _a1) +// ListSnapshots provides a mock function with given fields: ctx, req +func (_m *Application) ListSnapshots(ctx context.Context, req *v1.ListSnapshotsRequest) (*v1.ListSnapshotsResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for ListSnapshots") + } - var r0 *types.ResponseListSnapshots + var r0 *v1.ListSnapshotsResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestListSnapshots) (*types.ResponseListSnapshots, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ListSnapshotsRequest) (*v1.ListSnapshotsResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestListSnapshots) *types.ResponseListSnapshots); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ListSnapshotsRequest) *v1.ListSnapshotsResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseListSnapshots) + r0 = ret.Get(0).(*v1.ListSnapshotsResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestListSnapshots) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ListSnapshotsRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -222,25 +255,29 @@ func (_m *Application) ListSnapshots(_a0 context.Context, _a1 *types.RequestList return r0, r1 } -// LoadSnapshotChunk provides a mock function with given fields: _a0, _a1 -func (_m *Application) LoadSnapshotChunk(_a0 context.Context, _a1 *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { - ret := _m.Called(_a0, _a1) +// LoadSnapshotChunk provides a mock function with given fields: ctx, req +func (_m *Application) LoadSnapshotChunk(ctx context.Context, req *v1.LoadSnapshotChunkRequest) (*v1.LoadSnapshotChunkResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseLoadSnapshotChunk + if len(ret) == 0 { + panic("no return value specified for LoadSnapshotChunk") + } + + var r0 *v1.LoadSnapshotChunkResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.LoadSnapshotChunkRequest) (*v1.LoadSnapshotChunkResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestLoadSnapshotChunk) *types.ResponseLoadSnapshotChunk); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.LoadSnapshotChunkRequest) *v1.LoadSnapshotChunkResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseLoadSnapshotChunk) + r0 = ret.Get(0).(*v1.LoadSnapshotChunkResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestLoadSnapshotChunk) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.LoadSnapshotChunkRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -248,25 +285,29 @@ func (_m *Application) LoadSnapshotChunk(_a0 context.Context, _a1 *types.Request return r0, r1 } -// OfferSnapshot provides a mock function with given fields: _a0, _a1 -func (_m *Application) OfferSnapshot(_a0 context.Context, _a1 *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) { - ret := _m.Called(_a0, _a1) +// OfferSnapshot provides a mock function with given fields: ctx, req +func (_m *Application) OfferSnapshot(ctx context.Context, req *v1.OfferSnapshotRequest) (*v1.OfferSnapshotResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for OfferSnapshot") + } - var r0 *types.ResponseOfferSnapshot + var r0 *v1.OfferSnapshotResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.OfferSnapshotRequest) (*v1.OfferSnapshotResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestOfferSnapshot) *types.ResponseOfferSnapshot); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.OfferSnapshotRequest) *v1.OfferSnapshotResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseOfferSnapshot) + r0 = ret.Get(0).(*v1.OfferSnapshotResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestOfferSnapshot) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.OfferSnapshotRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -274,25 +315,29 @@ func (_m *Application) OfferSnapshot(_a0 context.Context, _a1 *types.RequestOffe return r0, r1 } -// PrepareProposal provides a mock function with given fields: _a0, _a1 -func (_m *Application) PrepareProposal(_a0 context.Context, _a1 *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { - ret := _m.Called(_a0, _a1) +// PrepareProposal provides a mock function with given fields: ctx, req +func (_m *Application) PrepareProposal(ctx context.Context, req *v1.PrepareProposalRequest) (*v1.PrepareProposalResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponsePrepareProposal + if len(ret) == 0 { + panic("no return value specified for PrepareProposal") + } + + var r0 *v1.PrepareProposalResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.PrepareProposalRequest) (*v1.PrepareProposalResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestPrepareProposal) *types.ResponsePrepareProposal); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.PrepareProposalRequest) *v1.PrepareProposalResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponsePrepareProposal) + r0 = ret.Get(0).(*v1.PrepareProposalResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestPrepareProposal) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.PrepareProposalRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -300,25 +345,29 @@ func (_m *Application) PrepareProposal(_a0 context.Context, _a1 *types.RequestPr return r0, r1 } -// ProcessProposal provides a mock function with given fields: _a0, _a1 -func (_m *Application) ProcessProposal(_a0 context.Context, _a1 *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { - ret := _m.Called(_a0, _a1) +// ProcessProposal provides a mock function with given fields: ctx, req +func (_m *Application) ProcessProposal(ctx context.Context, req *v1.ProcessProposalRequest) (*v1.ProcessProposalResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for ProcessProposal") + } - var r0 *types.ResponseProcessProposal + var r0 *v1.ProcessProposalResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestProcessProposal) (*types.ResponseProcessProposal, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ProcessProposalRequest) (*v1.ProcessProposalResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestProcessProposal) *types.ResponseProcessProposal); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ProcessProposalRequest) *v1.ProcessProposalResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseProcessProposal) + r0 = ret.Get(0).(*v1.ProcessProposalResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestProcessProposal) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ProcessProposalRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -326,25 +375,29 @@ func (_m *Application) ProcessProposal(_a0 context.Context, _a1 *types.RequestPr return r0, r1 } -// Query provides a mock function with given fields: _a0, _a1 -func (_m *Application) Query(_a0 context.Context, _a1 *types.RequestQuery) (*types.ResponseQuery, error) { - ret := _m.Called(_a0, _a1) +// Query provides a mock function with given fields: ctx, req +func (_m *Application) Query(ctx context.Context, req *v1.QueryRequest) (*v1.QueryResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseQuery + if len(ret) == 0 { + panic("no return value specified for Query") + } + + var r0 *v1.QueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestQuery) (*types.ResponseQuery, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.QueryRequest) (*v1.QueryResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestQuery) *types.ResponseQuery); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.QueryRequest) *v1.QueryResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseQuery) + r0 = ret.Get(0).(*v1.QueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestQuery) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.QueryRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -352,25 +405,29 @@ func (_m *Application) Query(_a0 context.Context, _a1 *types.RequestQuery) (*typ return r0, r1 } -// VerifyVoteExtension provides a mock function with given fields: _a0, _a1 -func (_m *Application) VerifyVoteExtension(_a0 context.Context, _a1 *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) { - ret := _m.Called(_a0, _a1) +// VerifyVoteExtension provides a mock function with given fields: ctx, req +func (_m *Application) VerifyVoteExtension(ctx context.Context, req *v1.VerifyVoteExtensionRequest) (*v1.VerifyVoteExtensionResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for VerifyVoteExtension") + } - var r0 *types.ResponseVerifyVoteExtension + var r0 *v1.VerifyVoteExtensionResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.VerifyVoteExtensionRequest) (*v1.VerifyVoteExtensionResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestVerifyVoteExtension) *types.ResponseVerifyVoteExtension); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.VerifyVoteExtensionRequest) *v1.VerifyVoteExtensionResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseVerifyVoteExtension) + r0 = ret.Get(0).(*v1.VerifyVoteExtensionResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestVerifyVoteExtension) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.VerifyVoteExtensionRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -378,13 +435,12 @@ func (_m *Application) VerifyVoteExtension(_a0 context.Context, _a1 *types.Reque return r0, r1 } -type mockConstructorTestingTNewApplication interface { +// NewApplication creates a new instance of Application. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewApplication(t interface { mock.TestingT Cleanup(func()) -} - -// NewApplication creates a new instance of Application. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewApplication(t mockConstructorTestingTNewApplication) *Application { +}) *Application { mock := &Application{} mock.Mock.Test(t) diff --git a/abci/types/pubkey.go b/abci/types/pubkey.go index 8341c0898d3..7c155589375 100644 --- a/abci/types/pubkey.go +++ b/abci/types/pubkey.go @@ -1,7 +1,7 @@ package types import ( - fmt "fmt" + "fmt" "github.com/cometbft/cometbft/crypto/ed25519" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" diff --git a/abci/types/types.go b/abci/types/types.go index cd9d0fcfad3..533e2fa5401 100644 --- a/abci/types/types.go +++ b/abci/types/types.go @@ -1,146 +1,204 @@ +//nolint:stylecheck,revive package types import ( - "bytes" "encoding/json" - "github.com/cosmos/gogoproto/jsonpb" -) + "github.com/cosmos/gogoproto/grpc" -const ( - CodeTypeOK uint32 = 0 + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" ) -// IsOK returns true if Code is OK. -func (r ResponseCheckTx) IsOK() bool { - return r.Code == CodeTypeOK -} +type ( + Request = v1.Request + EchoRequest = v1.EchoRequest + FlushRequest = v1.FlushRequest + InfoRequest = v1.InfoRequest + InitChainRequest = v1.InitChainRequest + QueryRequest = v1.QueryRequest + CheckTxRequest = v1.CheckTxRequest + CommitRequest = v1.CommitRequest + ListSnapshotsRequest = v1.ListSnapshotsRequest + OfferSnapshotRequest = v1.OfferSnapshotRequest + LoadSnapshotChunkRequest = v1.LoadSnapshotChunkRequest + ApplySnapshotChunkRequest = v1.ApplySnapshotChunkRequest + PrepareProposalRequest = v1.PrepareProposalRequest + ProcessProposalRequest = v1.ProcessProposalRequest + ExtendVoteRequest = v1.ExtendVoteRequest + VerifyVoteExtensionRequest = v1.VerifyVoteExtensionRequest + FinalizeBlockRequest = v1.FinalizeBlockRequest +) -// IsErr returns true if Code is something other than OK. -func (r ResponseCheckTx) IsErr() bool { - return r.Code != CodeTypeOK -} +// Discriminated Request variants are defined in the latest proto package. +type ( + Request_Echo = v1.Request_Echo + Request_Flush = v1.Request_Flush + Request_Info = v1.Request_Info + Request_InitChain = v1.Request_InitChain + Request_Query = v1.Request_Query + Request_CheckTx = v1.Request_CheckTx + Request_Commit = v1.Request_Commit + Request_ListSnapshots = v1.Request_ListSnapshots + Request_OfferSnapshot = v1.Request_OfferSnapshot + Request_LoadSnapshotChunk = v1.Request_LoadSnapshotChunk + Request_ApplySnapshotChunk = v1.Request_ApplySnapshotChunk + Request_PrepareProposal = v1.Request_PrepareProposal + Request_ProcessProposal = v1.Request_ProcessProposal + Request_ExtendVote = v1.Request_ExtendVote + Request_VerifyVoteExtension = v1.Request_VerifyVoteExtension + Request_FinalizeBlock = v1.Request_FinalizeBlock +) -// IsOK returns true if Code is OK. -func (r ExecTxResult) IsOK() bool { - return r.Code == CodeTypeOK -} +type ( + Response = v1.Response + ExceptionResponse = v1.ExceptionResponse + EchoResponse = v1.EchoResponse + FlushResponse = v1.FlushResponse + InfoResponse = v1.InfoResponse + InitChainResponse = v1.InitChainResponse + QueryResponse = v1.QueryResponse + CheckTxResponse = v1.CheckTxResponse + CommitResponse = v1.CommitResponse + ListSnapshotsResponse = v1.ListSnapshotsResponse + OfferSnapshotResponse = v1.OfferSnapshotResponse + LoadSnapshotChunkResponse = v1.LoadSnapshotChunkResponse + ApplySnapshotChunkResponse = v1.ApplySnapshotChunkResponse + PrepareProposalResponse = v1.PrepareProposalResponse + ProcessProposalResponse = v1.ProcessProposalResponse + ExtendVoteResponse = v1.ExtendVoteResponse + VerifyVoteExtensionResponse = v1.VerifyVoteExtensionResponse + FinalizeBlockResponse = v1.FinalizeBlockResponse +) -// IsErr returns true if Code is something other than OK. -func (r ExecTxResult) IsErr() bool { - return r.Code != CodeTypeOK -} +// Discriminated Response variants are defined in the latest proto package. +type ( + Response_Exception = v1.Response_Exception + Response_Echo = v1.Response_Echo + Response_Flush = v1.Response_Flush + Response_Info = v1.Response_Info + Response_InitChain = v1.Response_InitChain + Response_Query = v1.Response_Query + Response_CheckTx = v1.Response_CheckTx + Response_Commit = v1.Response_Commit + Response_ListSnapshots = v1.Response_ListSnapshots + Response_OfferSnapshot = v1.Response_OfferSnapshot + Response_LoadSnapshotChunk = v1.Response_LoadSnapshotChunk + Response_ApplySnapshotChunk = v1.Response_ApplySnapshotChunk + Response_PrepareProposal = v1.Response_PrepareProposal + Response_ProcessProposal = v1.Response_ProcessProposal + Response_ExtendVote = v1.Response_ExtendVote + Response_VerifyVoteExtension = v1.Response_VerifyVoteExtension + Response_FinalizeBlock = v1.Response_FinalizeBlock +) -// IsOK returns true if Code is OK. -func (r ResponseQuery) IsOK() bool { - return r.Code == CodeTypeOK -} +type ( + CommitInfo = v1.CommitInfo + ExecTxResult = v1.ExecTxResult + ExtendedCommitInfo = v1.ExtendedCommitInfo + ExtendedVoteInfo = v1.ExtendedVoteInfo + Event = v1.Event + EventAttribute = v1.EventAttribute + Misbehavior = v1.Misbehavior + Snapshot = v1.Snapshot + TxResult = v1.TxResult + Validator = v1.Validator + ValidatorUpdate = v1.ValidatorUpdate + VoteInfo = v1.VoteInfo +) -// IsErr returns true if Code is something other than OK. -func (r ResponseQuery) IsErr() bool { - return r.Code != CodeTypeOK -} +type ( + ABCIServiceClient = v1.ABCIServiceClient + ABCIServiceServer = v1.ABCIServiceServer +) -// IsAccepted returns true if Code is ACCEPT -func (r ResponseProcessProposal) IsAccepted() bool { - return r.Status == ResponseProcessProposal_ACCEPT +func NewABCIClient(cc grpc.ClientConn) ABCIServiceClient { + return v1.NewABCIServiceClient(cc) } -// IsStatusUnknown returns true if Code is UNKNOWN -func (r ResponseProcessProposal) IsStatusUnknown() bool { - return r.Status == ResponseProcessProposal_UNKNOWN +func RegisterABCIServer(s grpc.Server, srv ABCIServiceServer) { + v1.RegisterABCIServiceServer(s, srv) } -func (r ResponseVerifyVoteExtension) IsAccepted() bool { - return r.Status == ResponseVerifyVoteExtension_ACCEPT -} +type CheckTxType = v1.CheckTxType -// IsStatusUnknown returns true if Code is Unknown -func (r ResponseVerifyVoteExtension) IsStatusUnknown() bool { - return r.Status == ResponseVerifyVoteExtension_UNKNOWN -} +const ( + CHECK_TX_TYPE_UNKNOWN CheckTxType = v1.CHECK_TX_TYPE_UNKNOWN + CHECK_TX_TYPE_CHECK CheckTxType = v1.CHECK_TX_TYPE_CHECK + CHECK_TX_TYPE_RECHECK CheckTxType = v1.CHECK_TX_TYPE_RECHECK +) -//--------------------------------------------------------------------------- -// override JSON marshaling so we emit defaults (ie. disable omitempty) +type MisbehaviorType = v1.MisbehaviorType -var ( - jsonpbMarshaller = jsonpb.Marshaler{ - EnumsAsInts: true, - EmitDefaults: true, - } - jsonpbUnmarshaller = jsonpb.Unmarshaler{} +const ( + MISBEHAVIOR_TYPE_UNKNOWN MisbehaviorType = v1.MISBEHAVIOR_TYPE_UNKNOWN + MISBEHAVIOR_TYPE_DUPLICATE_VOTE MisbehaviorType = v1.MISBEHAVIOR_TYPE_DUPLICATE_VOTE + MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK MisbehaviorType = v1.MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK ) -func (r *ResponseCheckTx) MarshalJSON() ([]byte, error) { - s, err := jsonpbMarshaller.MarshalToString(r) - return []byte(s), err -} - -func (r *ResponseCheckTx) UnmarshalJSON(b []byte) error { - reader := bytes.NewBuffer(b) - return jsonpbUnmarshaller.Unmarshal(reader, r) -} +type ApplySnapshotChunkResult = v1.ApplySnapshotChunkResult -func (r *ExecTxResult) MarshalJSON() ([]byte, error) { - s, err := jsonpbMarshaller.MarshalToString(r) - return []byte(s), err -} +const ( + APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN ApplySnapshotChunkResult = v1.APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN + APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT ApplySnapshotChunkResult = v1.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT + APPLY_SNAPSHOT_CHUNK_RESULT_ABORT ApplySnapshotChunkResult = v1.APPLY_SNAPSHOT_CHUNK_RESULT_ABORT + APPLY_SNAPSHOT_CHUNK_RESULT_RETRY ApplySnapshotChunkResult = v1.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY + APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT ApplySnapshotChunkResult = v1.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT + APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT ApplySnapshotChunkResult = v1.APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT +) -func (r *ExecTxResult) UnmarshalJSON(b []byte) error { - reader := bytes.NewBuffer(b) - return jsonpbUnmarshaller.Unmarshal(reader, r) -} +type OfferSnapshotResult = v1.OfferSnapshotResult -func (r *ResponseQuery) MarshalJSON() ([]byte, error) { - s, err := jsonpbMarshaller.MarshalToString(r) - return []byte(s), err -} +const ( + OFFER_SNAPSHOT_RESULT_UNKNOWN OfferSnapshotResult = v1.OFFER_SNAPSHOT_RESULT_UNKNOWN + OFFER_SNAPSHOT_RESULT_ACCEPT OfferSnapshotResult = v1.OFFER_SNAPSHOT_RESULT_ACCEPT + OFFER_SNAPSHOT_RESULT_ABORT OfferSnapshotResult = v1.OFFER_SNAPSHOT_RESULT_ABORT + OFFER_SNAPSHOT_RESULT_REJECT OfferSnapshotResult = v1.OFFER_SNAPSHOT_RESULT_REJECT + OFFER_SNAPSHOT_RESULT_REJECT_FORMAT OfferSnapshotResult = v1.OFFER_SNAPSHOT_RESULT_REJECT_FORMAT + OFFER_SNAPSHOT_RESULT_REJECT_SENDER OfferSnapshotResult = v1.OFFER_SNAPSHOT_RESULT_REJECT_SENDER +) -func (r *ResponseQuery) UnmarshalJSON(b []byte) error { - reader := bytes.NewBuffer(b) - return jsonpbUnmarshaller.Unmarshal(reader, r) -} +type ProcessProposalStatus = v1.ProcessProposalStatus -func (r *ResponseCommit) MarshalJSON() ([]byte, error) { - s, err := jsonpbMarshaller.MarshalToString(r) - return []byte(s), err -} +const ( + PROCESS_PROPOSAL_STATUS_UNKNOWN ProcessProposalStatus = v1.PROCESS_PROPOSAL_STATUS_UNKNOWN + PROCESS_PROPOSAL_STATUS_ACCEPT ProcessProposalStatus = v1.PROCESS_PROPOSAL_STATUS_ACCEPT + PROCESS_PROPOSAL_STATUS_REJECT ProcessProposalStatus = v1.PROCESS_PROPOSAL_STATUS_REJECT +) -func (r *ResponseCommit) UnmarshalJSON(b []byte) error { - reader := bytes.NewBuffer(b) - return jsonpbUnmarshaller.Unmarshal(reader, r) -} +type VerifyVoteExtensionStatus = v1.VerifyVoteExtensionStatus -func (r *EventAttribute) MarshalJSON() ([]byte, error) { - s, err := jsonpbMarshaller.MarshalToString(r) - return []byte(s), err -} +const ( + VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN VerifyVoteExtensionStatus = v1.VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN + VERIFY_VOTE_EXTENSION_STATUS_ACCEPT VerifyVoteExtensionStatus = v1.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT + VERIFY_VOTE_EXTENSION_STATUS_REJECT VerifyVoteExtensionStatus = v1.VERIFY_VOTE_EXTENSION_STATUS_REJECT +) -func (r *EventAttribute) UnmarshalJSON(b []byte) error { - reader := bytes.NewBuffer(b) - return jsonpbUnmarshaller.Unmarshal(reader, r) -} +const ( + CodeTypeOK uint32 = 0 +) // Some compile time assertions to ensure we don't // have accidental runtime surprises later on. // jsonEncodingRoundTripper ensures that asserted -// interfaces implement both MarshalJSON and UnmarshalJSON +// interfaces implement both MarshalJSON and UnmarshalJSON. type jsonRoundTripper interface { json.Marshaler json.Unmarshaler } -var _ jsonRoundTripper = (*ResponseCommit)(nil) -var _ jsonRoundTripper = (*ResponseQuery)(nil) -var _ jsonRoundTripper = (*ExecTxResult)(nil) -var _ jsonRoundTripper = (*ResponseCheckTx)(nil) +var ( + _ jsonRoundTripper = (*CommitResponse)(nil) + _ jsonRoundTripper = (*QueryResponse)(nil) + _ jsonRoundTripper = (*ExecTxResult)(nil) + _ jsonRoundTripper = (*CheckTxResponse)(nil) +) var _ jsonRoundTripper = (*EventAttribute)(nil) -// deterministicExecTxResult constructs a copy of response that omits +// constructs a copy of response that omits // non-deterministic fields. The input response is not modified. -func deterministicExecTxResult(response *ExecTxResult) *ExecTxResult { +func DeterministicExecTxResult(response *ExecTxResult) *ExecTxResult { return &ExecTxResult{ Code: response.Code, Data: response.Data, @@ -149,14 +207,14 @@ func deterministicExecTxResult(response *ExecTxResult) *ExecTxResult { } } -// MarshalTxResults encodes the the TxResults as a list of byte +// MarshalTxResults encodes the TxResults as a list of byte // slices. It strips off the non-deterministic pieces of the TxResults // so that the resulting data can be used for hash comparisons and used // in Merkle proofs. func MarshalTxResults(r []*ExecTxResult) ([][]byte, error) { s := make([][]byte, len(r)) for i, e := range r { - d := deterministicExecTxResult(e) + d := DeterministicExecTxResult(e) b, err := d.Marshal() if err != nil { return nil, err diff --git a/abci/types/types_test.go b/abci/types/types_test.go index 9c4e62d4c2a..f11af133e27 100644 --- a/abci/types/types_test.go +++ b/abci/types/types_test.go @@ -41,7 +41,7 @@ func TestHashAndProveResults(t *testing.T) { require.NoError(t, err) valid := proofs[i].Verify(root, bz) - assert.NoError(t, valid, "%d", i) + require.NoError(t, valid, "%d", i) } } diff --git a/abci/types/util.go b/abci/types/util.go index 8205fef7e9d..946a95e92ce 100644 --- a/abci/types/util.go +++ b/abci/types/util.go @@ -4,9 +4,9 @@ import ( "sort" ) -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ -// ValidatorUpdates is a list of validators that implements the Sort interface +// ValidatorUpdates is a list of validators that implements the Sort interface. type ValidatorUpdates []ValidatorUpdate var _ sort.Interface = (ValidatorUpdates)(nil) @@ -21,7 +21,7 @@ func (v ValidatorUpdates) Len() int { return len(v) } -// XXX: doesn't distinguish same validator with different power +// XXX: doesn't distinguish same validator with different power. func (v ValidatorUpdates) Less(i, j int) bool { return v[i].PubKey.Compare(v[j].PubKey) <= 0 } diff --git a/api/cometbft/abci/v1/service.pb.go b/api/cometbft/abci/v1/service.pb.go new file mode 100644 index 00000000000..218bb7c1ca8 --- /dev/null +++ b/api/cometbft/abci/v1/service.pb.go @@ -0,0 +1,716 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/abci/v1/service.proto + +package v1 + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +func init() { proto.RegisterFile("cometbft/abci/v1/service.proto", fileDescriptor_728160d6a27c523b) } + +var fileDescriptor_728160d6a27c523b = []byte{ + // 497 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x95, 0xdd, 0x6e, 0xd3, 0x30, + 0x18, 0x86, 0x5b, 0x69, 0x0c, 0xe1, 0x09, 0x01, 0xe6, 0x6c, 0x82, 0x30, 0x7e, 0xc4, 0x3f, 0x89, + 0x0a, 0x57, 0xb0, 0x46, 0x9d, 0xa8, 0x36, 0xc1, 0x60, 0xd3, 0x90, 0x38, 0x22, 0xcd, 0xbe, 0x10, + 0xab, 0xa9, 0x6d, 0x6c, 0xa7, 0x5a, 0xb9, 0x0a, 0x2e, 0x8a, 0x03, 0x0e, 0x7b, 0xc8, 0x21, 0x6a, + 0x6f, 0x04, 0xa5, 0xb1, 0x09, 0x49, 0x5c, 0xaf, 0xa7, 0x7e, 0x9f, 0x3c, 0xaf, 0x1d, 0x7d, 0xd2, + 0x87, 0xbc, 0x98, 0x4d, 0x40, 0x8d, 0x12, 0x15, 0x44, 0xa3, 0x98, 0x04, 0xd3, 0x5e, 0x20, 0x41, + 0x4c, 0x49, 0x0c, 0x3e, 0x17, 0x4c, 0x31, 0x7c, 0xd3, 0xe4, 0x7e, 0x91, 0xfb, 0xd3, 0xde, 0xee, + 0x9d, 0xd6, 0x17, 0x6a, 0xc6, 0x41, 0x96, 0xfc, 0xeb, 0x9f, 0x3b, 0x68, 0x67, 0xbf, 0x1f, 0x0e, + 0x4f, 0x4a, 0x0b, 0x1e, 0xa0, 0xad, 0x41, 0x9c, 0x32, 0x7c, 0xd7, 0x6f, 0x8a, 0xfc, 0xe2, 0xfc, + 0x23, 0x7c, 0xcb, 0x41, 0xaa, 0x5d, 0x6f, 0x5d, 0x2c, 0x39, 0xa3, 0x12, 0xf0, 0x5b, 0x74, 0xe5, + 0x20, 0xcb, 0x65, 0x8a, 0x2d, 0xe0, 0x2a, 0x30, 0xa2, 0x7b, 0x6b, 0x73, 0x6d, 0x1a, 0xa0, 0xad, + 0x21, 0x4d, 0xac, 0x17, 0x2a, 0xce, 0x1d, 0x17, 0x2a, 0x63, 0xad, 0x79, 0x87, 0xae, 0x86, 0x29, + 0xc4, 0xe3, 0xd3, 0x0b, 0xbc, 0xd7, 0x46, 0x75, 0x64, 0x64, 0xf7, 0x1d, 0x44, 0xf5, 0xc0, 0x0f, + 0x39, 0x88, 0x99, 0xed, 0x81, 0xab, 0xc0, 0xf1, 0x40, 0x9d, 0x6b, 0xd3, 0x21, 0xda, 0x0e, 0xd9, + 0x64, 0x42, 0x14, 0xb6, 0xa0, 0x65, 0x62, 0x5c, 0x7b, 0xeb, 0x01, 0x2d, 0x3b, 0x45, 0xd7, 0x86, + 0x94, 0xa8, 0x30, 0x8d, 0x08, 0xc5, 0x0f, 0x6c, 0xff, 0x44, 0x87, 0x46, 0xf9, 0xd0, 0xc9, 0x68, + 0xeb, 0x17, 0x74, 0xfd, 0x88, 0x48, 0x75, 0x42, 0x23, 0x2e, 0x53, 0xa6, 0x24, 0x7e, 0xdc, 0xfe, + 0xaa, 0x06, 0x18, 0xfb, 0x93, 0x4b, 0xb9, 0xaa, 0xe1, 0x7d, 0x92, 0x80, 0x30, 0x89, 0xad, 0xa1, + 0x06, 0x38, 0x1a, 0x1a, 0x9c, 0x6e, 0xc8, 0xd0, 0xad, 0x23, 0x16, 0x9d, 0x9b, 0xf3, 0x30, 0xcd, + 0xe9, 0x18, 0x3f, 0xb7, 0xdc, 0xaf, 0x09, 0x99, 0xa6, 0x17, 0x1b, 0xb1, 0xba, 0x8d, 0x21, 0xbc, + 0xcf, 0x79, 0x36, 0xab, 0xd7, 0x59, 0x14, 0x6d, 0xca, 0xf4, 0xbd, 0xdc, 0x0c, 0xd6, 0x85, 0x09, + 0xba, 0x71, 0x2c, 0x80, 0x47, 0x02, 0x8e, 0x05, 0xe3, 0x4c, 0x46, 0x19, 0x7e, 0xda, 0x16, 0x34, + 0x10, 0x53, 0xf5, 0x6c, 0x03, 0xf2, 0xff, 0x1e, 0x16, 0x83, 0x94, 0xee, 0x9e, 0x1a, 0xe2, 0xec, + 0x69, 0x90, 0xba, 0xe7, 0x13, 0x42, 0x83, 0x0b, 0x05, 0xf4, 0xfc, 0x8c, 0x29, 0xc0, 0x96, 0x29, + 0xad, 0x52, 0x63, 0x7f, 0xe4, 0x86, 0xb4, 0x58, 0xa0, 0xdb, 0x67, 0x20, 0x48, 0x32, 0x2b, 0x4e, + 0x57, 0xb9, 0x24, 0x8c, 0x62, 0xcb, 0xdf, 0xb6, 0x60, 0xa6, 0xea, 0xd5, 0x86, 0x74, 0x35, 0xdd, + 0x07, 0x84, 0x46, 0x19, 0xf9, 0x0e, 0xfd, 0x8c, 0xc5, 0x63, 0xdb, 0x74, 0xd7, 0x00, 0xc7, 0x74, + 0x37, 0xb8, 0xb2, 0xa1, 0x7f, 0xf8, 0x6b, 0xe1, 0x75, 0xe7, 0x0b, 0xaf, 0xfb, 0x67, 0xe1, 0x75, + 0x7f, 0x2c, 0xbd, 0xce, 0x7c, 0xe9, 0x75, 0x7e, 0x2f, 0xbd, 0xce, 0xe7, 0xde, 0x57, 0xa2, 0xd2, + 0x7c, 0x54, 0x88, 0x82, 0x7f, 0x9b, 0xa0, 0x5a, 0x09, 0x9c, 0x04, 0xcd, 0xfd, 0x30, 0xda, 0x5e, + 0xad, 0x86, 0x37, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x53, 0x44, 0xb0, 0xec, 0x6c, 0x06, 0x00, + 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// ABCIServiceClient is the client API for ABCIService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type ABCIServiceClient interface { + // Echo returns back the same message it is sent. + Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) + // Flush flushes the write buffer. + Flush(ctx context.Context, in *FlushRequest, opts ...grpc.CallOption) (*FlushResponse, error) + // Info returns information about the application state. + Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error) + // CheckTx validates a transaction. + CheckTx(ctx context.Context, in *CheckTxRequest, opts ...grpc.CallOption) (*CheckTxResponse, error) + // Query queries the application state. + Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) + // Commit commits a block of transactions. + Commit(ctx context.Context, in *CommitRequest, opts ...grpc.CallOption) (*CommitResponse, error) + // InitChain initializes the blockchain. + InitChain(ctx context.Context, in *InitChainRequest, opts ...grpc.CallOption) (*InitChainResponse, error) + // ListSnapshots lists all the available snapshots. + ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) + // OfferSnapshot sends a snapshot offer. + OfferSnapshot(ctx context.Context, in *OfferSnapshotRequest, opts ...grpc.CallOption) (*OfferSnapshotResponse, error) + // LoadSnapshotChunk returns a chunk of snapshot. + LoadSnapshotChunk(ctx context.Context, in *LoadSnapshotChunkRequest, opts ...grpc.CallOption) (*LoadSnapshotChunkResponse, error) + // ApplySnapshotChunk applies a chunk of snapshot. + ApplySnapshotChunk(ctx context.Context, in *ApplySnapshotChunkRequest, opts ...grpc.CallOption) (*ApplySnapshotChunkResponse, error) + // PrepareProposal returns a proposal for the next block. + PrepareProposal(ctx context.Context, in *PrepareProposalRequest, opts ...grpc.CallOption) (*PrepareProposalResponse, error) + // ProcessProposal validates a proposal. + ProcessProposal(ctx context.Context, in *ProcessProposalRequest, opts ...grpc.CallOption) (*ProcessProposalResponse, error) + // ExtendVote extends a vote with application-injected data (vote extensions). + ExtendVote(ctx context.Context, in *ExtendVoteRequest, opts ...grpc.CallOption) (*ExtendVoteResponse, error) + // VerifyVoteExtension verifies a vote extension. + VerifyVoteExtension(ctx context.Context, in *VerifyVoteExtensionRequest, opts ...grpc.CallOption) (*VerifyVoteExtensionResponse, error) + // FinalizeBlock finalizes a block. + FinalizeBlock(ctx context.Context, in *FinalizeBlockRequest, opts ...grpc.CallOption) (*FinalizeBlockResponse, error) +} + +type aBCIServiceClient struct { + cc grpc1.ClientConn +} + +func NewABCIServiceClient(cc grpc1.ClientConn) ABCIServiceClient { + return &aBCIServiceClient{cc} +} + +func (c *aBCIServiceClient) Echo(ctx context.Context, in *EchoRequest, opts ...grpc.CallOption) (*EchoResponse, error) { + out := new(EchoResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/Echo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) Flush(ctx context.Context, in *FlushRequest, opts ...grpc.CallOption) (*FlushResponse, error) { + out := new(FlushResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/Flush", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error) { + out := new(InfoResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/Info", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) CheckTx(ctx context.Context, in *CheckTxRequest, opts ...grpc.CallOption) (*CheckTxResponse, error) { + out := new(CheckTxResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/CheckTx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) Query(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) { + out := new(QueryResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/Query", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) Commit(ctx context.Context, in *CommitRequest, opts ...grpc.CallOption) (*CommitResponse, error) { + out := new(CommitResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/Commit", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) InitChain(ctx context.Context, in *InitChainRequest, opts ...grpc.CallOption) (*InitChainResponse, error) { + out := new(InitChainResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/InitChain", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) ListSnapshots(ctx context.Context, in *ListSnapshotsRequest, opts ...grpc.CallOption) (*ListSnapshotsResponse, error) { + out := new(ListSnapshotsResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/ListSnapshots", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) OfferSnapshot(ctx context.Context, in *OfferSnapshotRequest, opts ...grpc.CallOption) (*OfferSnapshotResponse, error) { + out := new(OfferSnapshotResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/OfferSnapshot", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) LoadSnapshotChunk(ctx context.Context, in *LoadSnapshotChunkRequest, opts ...grpc.CallOption) (*LoadSnapshotChunkResponse, error) { + out := new(LoadSnapshotChunkResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/LoadSnapshotChunk", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) ApplySnapshotChunk(ctx context.Context, in *ApplySnapshotChunkRequest, opts ...grpc.CallOption) (*ApplySnapshotChunkResponse, error) { + out := new(ApplySnapshotChunkResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/ApplySnapshotChunk", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) PrepareProposal(ctx context.Context, in *PrepareProposalRequest, opts ...grpc.CallOption) (*PrepareProposalResponse, error) { + out := new(PrepareProposalResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/PrepareProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) ProcessProposal(ctx context.Context, in *ProcessProposalRequest, opts ...grpc.CallOption) (*ProcessProposalResponse, error) { + out := new(ProcessProposalResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/ProcessProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) ExtendVote(ctx context.Context, in *ExtendVoteRequest, opts ...grpc.CallOption) (*ExtendVoteResponse, error) { + out := new(ExtendVoteResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/ExtendVote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) VerifyVoteExtension(ctx context.Context, in *VerifyVoteExtensionRequest, opts ...grpc.CallOption) (*VerifyVoteExtensionResponse, error) { + out := new(VerifyVoteExtensionResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/VerifyVoteExtension", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIServiceClient) FinalizeBlock(ctx context.Context, in *FinalizeBlockRequest, opts ...grpc.CallOption) (*FinalizeBlockResponse, error) { + out := new(FinalizeBlockResponse) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1.ABCIService/FinalizeBlock", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ABCIServiceServer is the server API for ABCIService service. +type ABCIServiceServer interface { + // Echo returns back the same message it is sent. + Echo(context.Context, *EchoRequest) (*EchoResponse, error) + // Flush flushes the write buffer. + Flush(context.Context, *FlushRequest) (*FlushResponse, error) + // Info returns information about the application state. + Info(context.Context, *InfoRequest) (*InfoResponse, error) + // CheckTx validates a transaction. + CheckTx(context.Context, *CheckTxRequest) (*CheckTxResponse, error) + // Query queries the application state. + Query(context.Context, *QueryRequest) (*QueryResponse, error) + // Commit commits a block of transactions. + Commit(context.Context, *CommitRequest) (*CommitResponse, error) + // InitChain initializes the blockchain. + InitChain(context.Context, *InitChainRequest) (*InitChainResponse, error) + // ListSnapshots lists all the available snapshots. + ListSnapshots(context.Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error) + // OfferSnapshot sends a snapshot offer. + OfferSnapshot(context.Context, *OfferSnapshotRequest) (*OfferSnapshotResponse, error) + // LoadSnapshotChunk returns a chunk of snapshot. + LoadSnapshotChunk(context.Context, *LoadSnapshotChunkRequest) (*LoadSnapshotChunkResponse, error) + // ApplySnapshotChunk applies a chunk of snapshot. + ApplySnapshotChunk(context.Context, *ApplySnapshotChunkRequest) (*ApplySnapshotChunkResponse, error) + // PrepareProposal returns a proposal for the next block. + PrepareProposal(context.Context, *PrepareProposalRequest) (*PrepareProposalResponse, error) + // ProcessProposal validates a proposal. + ProcessProposal(context.Context, *ProcessProposalRequest) (*ProcessProposalResponse, error) + // ExtendVote extends a vote with application-injected data (vote extensions). + ExtendVote(context.Context, *ExtendVoteRequest) (*ExtendVoteResponse, error) + // VerifyVoteExtension verifies a vote extension. + VerifyVoteExtension(context.Context, *VerifyVoteExtensionRequest) (*VerifyVoteExtensionResponse, error) + // FinalizeBlock finalizes a block. + FinalizeBlock(context.Context, *FinalizeBlockRequest) (*FinalizeBlockResponse, error) +} + +// UnimplementedABCIServiceServer can be embedded to have forward compatible implementations. +type UnimplementedABCIServiceServer struct { +} + +func (*UnimplementedABCIServiceServer) Echo(ctx context.Context, req *EchoRequest) (*EchoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented") +} +func (*UnimplementedABCIServiceServer) Flush(ctx context.Context, req *FlushRequest) (*FlushResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Flush not implemented") +} +func (*UnimplementedABCIServiceServer) Info(ctx context.Context, req *InfoRequest) (*InfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Info not implemented") +} +func (*UnimplementedABCIServiceServer) CheckTx(ctx context.Context, req *CheckTxRequest) (*CheckTxResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CheckTx not implemented") +} +func (*UnimplementedABCIServiceServer) Query(ctx context.Context, req *QueryRequest) (*QueryResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Query not implemented") +} +func (*UnimplementedABCIServiceServer) Commit(ctx context.Context, req *CommitRequest) (*CommitResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Commit not implemented") +} +func (*UnimplementedABCIServiceServer) InitChain(ctx context.Context, req *InitChainRequest) (*InitChainResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method InitChain not implemented") +} +func (*UnimplementedABCIServiceServer) ListSnapshots(ctx context.Context, req *ListSnapshotsRequest) (*ListSnapshotsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented") +} +func (*UnimplementedABCIServiceServer) OfferSnapshot(ctx context.Context, req *OfferSnapshotRequest) (*OfferSnapshotResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method OfferSnapshot not implemented") +} +func (*UnimplementedABCIServiceServer) LoadSnapshotChunk(ctx context.Context, req *LoadSnapshotChunkRequest) (*LoadSnapshotChunkResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method LoadSnapshotChunk not implemented") +} +func (*UnimplementedABCIServiceServer) ApplySnapshotChunk(ctx context.Context, req *ApplySnapshotChunkRequest) (*ApplySnapshotChunkResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ApplySnapshotChunk not implemented") +} +func (*UnimplementedABCIServiceServer) PrepareProposal(ctx context.Context, req *PrepareProposalRequest) (*PrepareProposalResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PrepareProposal not implemented") +} +func (*UnimplementedABCIServiceServer) ProcessProposal(ctx context.Context, req *ProcessProposalRequest) (*ProcessProposalResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProcessProposal not implemented") +} +func (*UnimplementedABCIServiceServer) ExtendVote(ctx context.Context, req *ExtendVoteRequest) (*ExtendVoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExtendVote not implemented") +} +func (*UnimplementedABCIServiceServer) VerifyVoteExtension(ctx context.Context, req *VerifyVoteExtensionRequest) (*VerifyVoteExtensionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VerifyVoteExtension not implemented") +} +func (*UnimplementedABCIServiceServer) FinalizeBlock(ctx context.Context, req *FinalizeBlockRequest) (*FinalizeBlockResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FinalizeBlock not implemented") +} + +func RegisterABCIServiceServer(s grpc1.Server, srv ABCIServiceServer) { + s.RegisterService(&_ABCIService_serviceDesc, srv) +} + +func _ABCIService_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EchoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).Echo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/Echo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).Echo(ctx, req.(*EchoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FlushRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).Flush(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/Flush", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).Flush(ctx, req.(*FlushRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).Info(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/Info", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).Info(ctx, req.(*InfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckTxRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).CheckTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/CheckTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).CheckTx(ctx, req.(*CheckTxRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/Query", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).Query(ctx, req.(*QueryRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CommitRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).Commit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/Commit", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).Commit(ctx, req.(*CommitRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InitChainRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).InitChain(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/InitChain", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).InitChain(ctx, req.(*InitChainRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListSnapshotsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).ListSnapshots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/ListSnapshots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).ListSnapshots(ctx, req.(*ListSnapshotsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_OfferSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(OfferSnapshotRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).OfferSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/OfferSnapshot", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).OfferSnapshot(ctx, req.(*OfferSnapshotRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_LoadSnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LoadSnapshotChunkRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).LoadSnapshotChunk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/LoadSnapshotChunk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).LoadSnapshotChunk(ctx, req.(*LoadSnapshotChunkRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_ApplySnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ApplySnapshotChunkRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).ApplySnapshotChunk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/ApplySnapshotChunk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).ApplySnapshotChunk(ctx, req.(*ApplySnapshotChunkRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_PrepareProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PrepareProposalRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).PrepareProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/PrepareProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).PrepareProposal(ctx, req.(*PrepareProposalRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_ProcessProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ProcessProposalRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).ProcessProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/ProcessProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).ProcessProposal(ctx, req.(*ProcessProposalRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_ExtendVote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExtendVoteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).ExtendVote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/ExtendVote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).ExtendVote(ctx, req.(*ExtendVoteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_VerifyVoteExtension_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VerifyVoteExtensionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).VerifyVoteExtension(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/VerifyVoteExtension", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).VerifyVoteExtension(ctx, req.(*VerifyVoteExtensionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIService_FinalizeBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FinalizeBlockRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServiceServer).FinalizeBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1.ABCIService/FinalizeBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServiceServer).FinalizeBlock(ctx, req.(*FinalizeBlockRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _ABCIService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.abci.v1.ABCIService", + HandlerType: (*ABCIServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Echo", + Handler: _ABCIService_Echo_Handler, + }, + { + MethodName: "Flush", + Handler: _ABCIService_Flush_Handler, + }, + { + MethodName: "Info", + Handler: _ABCIService_Info_Handler, + }, + { + MethodName: "CheckTx", + Handler: _ABCIService_CheckTx_Handler, + }, + { + MethodName: "Query", + Handler: _ABCIService_Query_Handler, + }, + { + MethodName: "Commit", + Handler: _ABCIService_Commit_Handler, + }, + { + MethodName: "InitChain", + Handler: _ABCIService_InitChain_Handler, + }, + { + MethodName: "ListSnapshots", + Handler: _ABCIService_ListSnapshots_Handler, + }, + { + MethodName: "OfferSnapshot", + Handler: _ABCIService_OfferSnapshot_Handler, + }, + { + MethodName: "LoadSnapshotChunk", + Handler: _ABCIService_LoadSnapshotChunk_Handler, + }, + { + MethodName: "ApplySnapshotChunk", + Handler: _ABCIService_ApplySnapshotChunk_Handler, + }, + { + MethodName: "PrepareProposal", + Handler: _ABCIService_PrepareProposal_Handler, + }, + { + MethodName: "ProcessProposal", + Handler: _ABCIService_ProcessProposal_Handler, + }, + { + MethodName: "ExtendVote", + Handler: _ABCIService_ExtendVote_Handler, + }, + { + MethodName: "VerifyVoteExtension", + Handler: _ABCIService_VerifyVoteExtension_Handler, + }, + { + MethodName: "FinalizeBlock", + Handler: _ABCIService_FinalizeBlock_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/abci/v1/service.proto", +} diff --git a/api/cometbft/abci/v1/types.go b/api/cometbft/abci/v1/types.go new file mode 100644 index 00000000000..fd5c873bc37 --- /dev/null +++ b/api/cometbft/abci/v1/types.go @@ -0,0 +1,121 @@ +package v1 + +import ( + "bytes" + + "github.com/cosmos/gogoproto/jsonpb" +) + +const ( + CodeTypeOK uint32 = 0 +) + +// IsOK returns true if Code is OK. +func (r CheckTxResponse) IsOK() bool { + return r.Code == CodeTypeOK +} + +// IsErr returns true if Code is something other than OK. +func (r CheckTxResponse) IsErr() bool { + return r.Code != CodeTypeOK +} + +// IsOK returns true if Code is OK. +func (r QueryResponse) IsOK() bool { + return r.Code == CodeTypeOK +} + +// IsErr returns true if Code is something other than OK. +func (r QueryResponse) IsErr() bool { + return r.Code != CodeTypeOK +} + +// IsAccepted returns true if Code is ACCEPT +func (r ProcessProposalResponse) IsAccepted() bool { + return r.Status == PROCESS_PROPOSAL_STATUS_ACCEPT +} + +// IsStatusUnknown returns true if Code is UNKNOWN +func (r ProcessProposalResponse) IsStatusUnknown() bool { + return r.Status == PROCESS_PROPOSAL_STATUS_UNKNOWN +} + +func (r VerifyVoteExtensionResponse) IsAccepted() bool { + return r.Status == VERIFY_VOTE_EXTENSION_STATUS_ACCEPT +} + +// IsStatusUnknown returns true if Code is Unknown +func (r VerifyVoteExtensionResponse) IsStatusUnknown() bool { + return r.Status == VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN +} + +// IsOK returns true if Code is OK. +func (r ExecTxResult) IsOK() bool { + return r.Code == CodeTypeOK +} + +// IsErr returns true if Code is something other than OK. +func (r ExecTxResult) IsErr() bool { + return r.Code != CodeTypeOK +} + +// --------------------------------------------------------------------------- +// override JSON marshaling so we emit defaults (ie. disable omitempty) + +var ( + jsonpbMarshaller = jsonpb.Marshaler{ + EnumsAsInts: true, + EmitDefaults: true, + } + jsonpbUnmarshaller = jsonpb.Unmarshaler{} +) + +func (r *CheckTxResponse) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *CheckTxResponse) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + +func (r *QueryResponse) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *QueryResponse) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + +func (r *CommitResponse) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *CommitResponse) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + +func (r *EventAttribute) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *EventAttribute) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + +func (r *ExecTxResult) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *ExecTxResult) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} diff --git a/abci/types/types.pb.go b/api/cometbft/abci/v1/types.pb.go similarity index 72% rename from abci/types/types.pb.go rename to api/cometbft/abci/v1/types.pb.go index 804b0a60fde..93a014c5498 100644 --- a/abci/types/types.pb.go +++ b/api/cometbft/abci/v1/types.pb.go @@ -1,21 +1,16 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/abci/types.proto +// source: cometbft/abci/v1/types.proto -package types +package v1 import ( - context "context" fmt "fmt" - crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" - types1 "github.com/cometbft/cometbft/proto/tendermint/types" + v11 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + v1 "github.com/cometbft/cometbft/api/cometbft/types/v1" _ "github.com/cosmos/gogoproto/gogoproto" - grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" _ "github.com/cosmos/gogoproto/types" github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" io "io" math "math" math_bits "math/bits" @@ -34,21 +29,32 @@ var _ = time.Kitchen // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// Type of the transaction check request. +// +// This enumeration is incompatible with the CheckTxType definition in +// cometbft.abci.v1beta1 and therefore shall not be used in encoding with the same +// field number. type CheckTxType int32 const ( - CheckTxType_New CheckTxType = 0 - CheckTxType_Recheck CheckTxType = 1 + // Unknown + CHECK_TX_TYPE_UNKNOWN CheckTxType = 0 + // Recheck (2nd, 3rd, etc.) + CHECK_TX_TYPE_RECHECK CheckTxType = 1 + // Check (1st time) + CHECK_TX_TYPE_CHECK CheckTxType = 2 ) var CheckTxType_name = map[int32]string{ - 0: "NEW", - 1: "RECHECK", + 0: "CHECK_TX_TYPE_UNKNOWN", + 1: "CHECK_TX_TYPE_RECHECK", + 2: "CHECK_TX_TYPE_CHECK", } var CheckTxType_value = map[string]int32{ - "NEW": 0, - "RECHECK": 1, + "CHECK_TX_TYPE_UNKNOWN": 0, + "CHECK_TX_TYPE_RECHECK": 1, + "CHECK_TX_TYPE_CHECK": 2, } func (x CheckTxType) String() string { @@ -56,172 +62,200 @@ func (x CheckTxType) String() string { } func (CheckTxType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{0} + return fileDescriptor_95dd8f7b670b96e3, []int{0} } -type MisbehaviorType int32 +// The result of offering a snapshot. +type OfferSnapshotResult int32 const ( - MisbehaviorType_UNKNOWN MisbehaviorType = 0 - MisbehaviorType_DUPLICATE_VOTE MisbehaviorType = 1 - MisbehaviorType_LIGHT_CLIENT_ATTACK MisbehaviorType = 2 + // Unknown result, abort all snapshot restoration + OFFER_SNAPSHOT_RESULT_UNKNOWN OfferSnapshotResult = 0 + // Snapshot accepted, apply chunks + OFFER_SNAPSHOT_RESULT_ACCEPT OfferSnapshotResult = 1 + // Abort all snapshot restoration + OFFER_SNAPSHOT_RESULT_ABORT OfferSnapshotResult = 2 + // Reject this specific snapshot, try others + OFFER_SNAPSHOT_RESULT_REJECT OfferSnapshotResult = 3 + // Reject all snapshots of this format, try others + OFFER_SNAPSHOT_RESULT_REJECT_FORMAT OfferSnapshotResult = 4 + // Reject all snapshots from the sender(s), try others + OFFER_SNAPSHOT_RESULT_REJECT_SENDER OfferSnapshotResult = 5 ) -var MisbehaviorType_name = map[int32]string{ - 0: "UNKNOWN", - 1: "DUPLICATE_VOTE", - 2: "LIGHT_CLIENT_ATTACK", +var OfferSnapshotResult_name = map[int32]string{ + 0: "OFFER_SNAPSHOT_RESULT_UNKNOWN", + 1: "OFFER_SNAPSHOT_RESULT_ACCEPT", + 2: "OFFER_SNAPSHOT_RESULT_ABORT", + 3: "OFFER_SNAPSHOT_RESULT_REJECT", + 4: "OFFER_SNAPSHOT_RESULT_REJECT_FORMAT", + 5: "OFFER_SNAPSHOT_RESULT_REJECT_SENDER", } -var MisbehaviorType_value = map[string]int32{ - "UNKNOWN": 0, - "DUPLICATE_VOTE": 1, - "LIGHT_CLIENT_ATTACK": 2, +var OfferSnapshotResult_value = map[string]int32{ + "OFFER_SNAPSHOT_RESULT_UNKNOWN": 0, + "OFFER_SNAPSHOT_RESULT_ACCEPT": 1, + "OFFER_SNAPSHOT_RESULT_ABORT": 2, + "OFFER_SNAPSHOT_RESULT_REJECT": 3, + "OFFER_SNAPSHOT_RESULT_REJECT_FORMAT": 4, + "OFFER_SNAPSHOT_RESULT_REJECT_SENDER": 5, } -func (x MisbehaviorType) String() string { - return proto.EnumName(MisbehaviorType_name, int32(x)) +func (x OfferSnapshotResult) String() string { + return proto.EnumName(OfferSnapshotResult_name, int32(x)) } -func (MisbehaviorType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{1} +func (OfferSnapshotResult) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{1} } -type ResponseOfferSnapshot_Result int32 +// The result of applying a snapshot chunk. +type ApplySnapshotChunkResult int32 const ( - ResponseOfferSnapshot_UNKNOWN ResponseOfferSnapshot_Result = 0 - ResponseOfferSnapshot_ACCEPT ResponseOfferSnapshot_Result = 1 - ResponseOfferSnapshot_ABORT ResponseOfferSnapshot_Result = 2 - ResponseOfferSnapshot_REJECT ResponseOfferSnapshot_Result = 3 - ResponseOfferSnapshot_REJECT_FORMAT ResponseOfferSnapshot_Result = 4 - ResponseOfferSnapshot_REJECT_SENDER ResponseOfferSnapshot_Result = 5 + // Unknown result, abort all snapshot restoration + APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN ApplySnapshotChunkResult = 0 + // Chunk successfully accepted + APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT ApplySnapshotChunkResult = 1 + // Abort all snapshot restoration + APPLY_SNAPSHOT_CHUNK_RESULT_ABORT ApplySnapshotChunkResult = 2 + // Retry chunk (combine with refetch and reject) + APPLY_SNAPSHOT_CHUNK_RESULT_RETRY ApplySnapshotChunkResult = 3 + // Retry snapshot (combine with refetch and reject) + APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT ApplySnapshotChunkResult = 4 + // Reject this snapshot, try others + APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT ApplySnapshotChunkResult = 5 ) -var ResponseOfferSnapshot_Result_name = map[int32]string{ - 0: "UNKNOWN", - 1: "ACCEPT", - 2: "ABORT", - 3: "REJECT", - 4: "REJECT_FORMAT", - 5: "REJECT_SENDER", +var ApplySnapshotChunkResult_name = map[int32]string{ + 0: "APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN", + 1: "APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT", + 2: "APPLY_SNAPSHOT_CHUNK_RESULT_ABORT", + 3: "APPLY_SNAPSHOT_CHUNK_RESULT_RETRY", + 4: "APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT", + 5: "APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT", } -var ResponseOfferSnapshot_Result_value = map[string]int32{ - "UNKNOWN": 0, - "ACCEPT": 1, - "ABORT": 2, - "REJECT": 3, - "REJECT_FORMAT": 4, - "REJECT_SENDER": 5, +var ApplySnapshotChunkResult_value = map[string]int32{ + "APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN": 0, + "APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT": 1, + "APPLY_SNAPSHOT_CHUNK_RESULT_ABORT": 2, + "APPLY_SNAPSHOT_CHUNK_RESULT_RETRY": 3, + "APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT": 4, + "APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT": 5, } -func (x ResponseOfferSnapshot_Result) String() string { - return proto.EnumName(ResponseOfferSnapshot_Result_name, int32(x)) +func (x ApplySnapshotChunkResult) String() string { + return proto.EnumName(ApplySnapshotChunkResult_name, int32(x)) } -func (ResponseOfferSnapshot_Result) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{27, 0} +func (ApplySnapshotChunkResult) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{2} } -type ResponseApplySnapshotChunk_Result int32 +// ProcessProposalStatus is the status of the proposal processing. +type ProcessProposalStatus int32 const ( - ResponseApplySnapshotChunk_UNKNOWN ResponseApplySnapshotChunk_Result = 0 - ResponseApplySnapshotChunk_ACCEPT ResponseApplySnapshotChunk_Result = 1 - ResponseApplySnapshotChunk_ABORT ResponseApplySnapshotChunk_Result = 2 - ResponseApplySnapshotChunk_RETRY ResponseApplySnapshotChunk_Result = 3 - ResponseApplySnapshotChunk_RETRY_SNAPSHOT ResponseApplySnapshotChunk_Result = 4 - ResponseApplySnapshotChunk_REJECT_SNAPSHOT ResponseApplySnapshotChunk_Result = 5 + // Unknown + PROCESS_PROPOSAL_STATUS_UNKNOWN ProcessProposalStatus = 0 + // Accepted + PROCESS_PROPOSAL_STATUS_ACCEPT ProcessProposalStatus = 1 + // Rejected + PROCESS_PROPOSAL_STATUS_REJECT ProcessProposalStatus = 2 ) -var ResponseApplySnapshotChunk_Result_name = map[int32]string{ - 0: "UNKNOWN", - 1: "ACCEPT", - 2: "ABORT", - 3: "RETRY", - 4: "RETRY_SNAPSHOT", - 5: "REJECT_SNAPSHOT", +var ProcessProposalStatus_name = map[int32]string{ + 0: "PROCESS_PROPOSAL_STATUS_UNKNOWN", + 1: "PROCESS_PROPOSAL_STATUS_ACCEPT", + 2: "PROCESS_PROPOSAL_STATUS_REJECT", } -var ResponseApplySnapshotChunk_Result_value = map[string]int32{ - "UNKNOWN": 0, - "ACCEPT": 1, - "ABORT": 2, - "RETRY": 3, - "RETRY_SNAPSHOT": 4, - "REJECT_SNAPSHOT": 5, +var ProcessProposalStatus_value = map[string]int32{ + "PROCESS_PROPOSAL_STATUS_UNKNOWN": 0, + "PROCESS_PROPOSAL_STATUS_ACCEPT": 1, + "PROCESS_PROPOSAL_STATUS_REJECT": 2, } -func (x ResponseApplySnapshotChunk_Result) String() string { - return proto.EnumName(ResponseApplySnapshotChunk_Result_name, int32(x)) +func (x ProcessProposalStatus) String() string { + return proto.EnumName(ProcessProposalStatus_name, int32(x)) } -func (ResponseApplySnapshotChunk_Result) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{29, 0} +func (ProcessProposalStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{3} } -type ResponseProcessProposal_ProposalStatus int32 +// VerifyVoteExtensionStatus is the status of the vote extension verification. +type VerifyVoteExtensionStatus int32 const ( - ResponseProcessProposal_UNKNOWN ResponseProcessProposal_ProposalStatus = 0 - ResponseProcessProposal_ACCEPT ResponseProcessProposal_ProposalStatus = 1 - ResponseProcessProposal_REJECT ResponseProcessProposal_ProposalStatus = 2 + // Unknown + VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN VerifyVoteExtensionStatus = 0 + // Accepted + VERIFY_VOTE_EXTENSION_STATUS_ACCEPT VerifyVoteExtensionStatus = 1 + // Rejecting the vote extension will reject the entire precommit by the sender. + // Incorrectly implementing this thus has liveness implications as it may affect + // CometBFT's ability to receive 2/3+ valid votes to finalize the block. + // Honest nodes should never be rejected. + VERIFY_VOTE_EXTENSION_STATUS_REJECT VerifyVoteExtensionStatus = 2 ) -var ResponseProcessProposal_ProposalStatus_name = map[int32]string{ - 0: "UNKNOWN", - 1: "ACCEPT", - 2: "REJECT", +var VerifyVoteExtensionStatus_name = map[int32]string{ + 0: "VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN", + 1: "VERIFY_VOTE_EXTENSION_STATUS_ACCEPT", + 2: "VERIFY_VOTE_EXTENSION_STATUS_REJECT", } -var ResponseProcessProposal_ProposalStatus_value = map[string]int32{ - "UNKNOWN": 0, - "ACCEPT": 1, - "REJECT": 2, +var VerifyVoteExtensionStatus_value = map[string]int32{ + "VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN": 0, + "VERIFY_VOTE_EXTENSION_STATUS_ACCEPT": 1, + "VERIFY_VOTE_EXTENSION_STATUS_REJECT": 2, } -func (x ResponseProcessProposal_ProposalStatus) String() string { - return proto.EnumName(ResponseProcessProposal_ProposalStatus_name, int32(x)) +func (x VerifyVoteExtensionStatus) String() string { + return proto.EnumName(VerifyVoteExtensionStatus_name, int32(x)) } -func (ResponseProcessProposal_ProposalStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{31, 0} +func (VerifyVoteExtensionStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{4} } -type ResponseVerifyVoteExtension_VerifyStatus int32 +// The type of misbehavior committed by a validator. +type MisbehaviorType int32 const ( - ResponseVerifyVoteExtension_UNKNOWN ResponseVerifyVoteExtension_VerifyStatus = 0 - ResponseVerifyVoteExtension_ACCEPT ResponseVerifyVoteExtension_VerifyStatus = 1 - // Rejecting the vote extension will reject the entire precommit by the sender. - // Incorrectly implementing this thus has liveness implications as it may affect - // CometBFT's ability to receive 2/3+ valid votes to finalize the block. - // Honest nodes should never be rejected. - ResponseVerifyVoteExtension_REJECT ResponseVerifyVoteExtension_VerifyStatus = 2 + // Unknown + MISBEHAVIOR_TYPE_UNKNOWN MisbehaviorType = 0 + // Duplicate vote + MISBEHAVIOR_TYPE_DUPLICATE_VOTE MisbehaviorType = 1 + // Light client attack + MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK MisbehaviorType = 2 ) -var ResponseVerifyVoteExtension_VerifyStatus_name = map[int32]string{ - 0: "UNKNOWN", - 1: "ACCEPT", - 2: "REJECT", +var MisbehaviorType_name = map[int32]string{ + 0: "MISBEHAVIOR_TYPE_UNKNOWN", + 1: "MISBEHAVIOR_TYPE_DUPLICATE_VOTE", + 2: "MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK", } -var ResponseVerifyVoteExtension_VerifyStatus_value = map[string]int32{ - "UNKNOWN": 0, - "ACCEPT": 1, - "REJECT": 2, +var MisbehaviorType_value = map[string]int32{ + "MISBEHAVIOR_TYPE_UNKNOWN": 0, + "MISBEHAVIOR_TYPE_DUPLICATE_VOTE": 1, + "MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK": 2, } -func (x ResponseVerifyVoteExtension_VerifyStatus) String() string { - return proto.EnumName(ResponseVerifyVoteExtension_VerifyStatus_name, int32(x)) +func (x MisbehaviorType) String() string { + return proto.EnumName(MisbehaviorType_name, int32(x)) } -func (ResponseVerifyVoteExtension_VerifyStatus) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{33, 0} +func (MisbehaviorType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{5} } +// Request represents a request to the ABCI application. type Request struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Value: // *Request_Echo // *Request_Flush @@ -246,7 +280,7 @@ func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{0} + return fileDescriptor_95dd8f7b670b96e3, []int{0} } func (m *Request) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -282,52 +316,52 @@ type isRequest_Value interface { } type Request_Echo struct { - Echo *RequestEcho `protobuf:"bytes,1,opt,name=echo,proto3,oneof" json:"echo,omitempty"` + Echo *EchoRequest `protobuf:"bytes,1,opt,name=echo,proto3,oneof" json:"echo,omitempty"` } type Request_Flush struct { - Flush *RequestFlush `protobuf:"bytes,2,opt,name=flush,proto3,oneof" json:"flush,omitempty"` + Flush *FlushRequest `protobuf:"bytes,2,opt,name=flush,proto3,oneof" json:"flush,omitempty"` } type Request_Info struct { - Info *RequestInfo `protobuf:"bytes,3,opt,name=info,proto3,oneof" json:"info,omitempty"` + Info *InfoRequest `protobuf:"bytes,3,opt,name=info,proto3,oneof" json:"info,omitempty"` } type Request_InitChain struct { - InitChain *RequestInitChain `protobuf:"bytes,5,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` + InitChain *InitChainRequest `protobuf:"bytes,5,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` } type Request_Query struct { - Query *RequestQuery `protobuf:"bytes,6,opt,name=query,proto3,oneof" json:"query,omitempty"` + Query *QueryRequest `protobuf:"bytes,6,opt,name=query,proto3,oneof" json:"query,omitempty"` } type Request_CheckTx struct { - CheckTx *RequestCheckTx `protobuf:"bytes,8,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` + CheckTx *CheckTxRequest `protobuf:"bytes,8,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` } type Request_Commit struct { - Commit *RequestCommit `protobuf:"bytes,11,opt,name=commit,proto3,oneof" json:"commit,omitempty"` + Commit *CommitRequest `protobuf:"bytes,11,opt,name=commit,proto3,oneof" json:"commit,omitempty"` } type Request_ListSnapshots struct { - ListSnapshots *RequestListSnapshots `protobuf:"bytes,12,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` + ListSnapshots *ListSnapshotsRequest `protobuf:"bytes,12,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` } type Request_OfferSnapshot struct { - OfferSnapshot *RequestOfferSnapshot `protobuf:"bytes,13,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` + OfferSnapshot *OfferSnapshotRequest `protobuf:"bytes,13,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` } type Request_LoadSnapshotChunk struct { - LoadSnapshotChunk *RequestLoadSnapshotChunk `protobuf:"bytes,14,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` + LoadSnapshotChunk *LoadSnapshotChunkRequest `protobuf:"bytes,14,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` } type Request_ApplySnapshotChunk struct { - ApplySnapshotChunk *RequestApplySnapshotChunk `protobuf:"bytes,15,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` + ApplySnapshotChunk *ApplySnapshotChunkRequest `protobuf:"bytes,15,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` } type Request_PrepareProposal struct { - PrepareProposal *RequestPrepareProposal `protobuf:"bytes,16,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` + PrepareProposal *PrepareProposalRequest `protobuf:"bytes,16,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` } type Request_ProcessProposal struct { - ProcessProposal *RequestProcessProposal `protobuf:"bytes,17,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` + ProcessProposal *ProcessProposalRequest `protobuf:"bytes,17,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` } type Request_ExtendVote struct { - ExtendVote *RequestExtendVote `protobuf:"bytes,18,opt,name=extend_vote,json=extendVote,proto3,oneof" json:"extend_vote,omitempty"` + ExtendVote *ExtendVoteRequest `protobuf:"bytes,18,opt,name=extend_vote,json=extendVote,proto3,oneof" json:"extend_vote,omitempty"` } type Request_VerifyVoteExtension struct { - VerifyVoteExtension *RequestVerifyVoteExtension `protobuf:"bytes,19,opt,name=verify_vote_extension,json=verifyVoteExtension,proto3,oneof" json:"verify_vote_extension,omitempty"` + VerifyVoteExtension *VerifyVoteExtensionRequest `protobuf:"bytes,19,opt,name=verify_vote_extension,json=verifyVoteExtension,proto3,oneof" json:"verify_vote_extension,omitempty"` } type Request_FinalizeBlock struct { - FinalizeBlock *RequestFinalizeBlock `protobuf:"bytes,20,opt,name=finalize_block,json=finalizeBlock,proto3,oneof" json:"finalize_block,omitempty"` + FinalizeBlock *FinalizeBlockRequest `protobuf:"bytes,20,opt,name=finalize_block,json=finalizeBlock,proto3,oneof" json:"finalize_block,omitempty"` } func (*Request_Echo) isRequest_Value() {} @@ -354,112 +388,112 @@ func (m *Request) GetValue() isRequest_Value { return nil } -func (m *Request) GetEcho() *RequestEcho { +func (m *Request) GetEcho() *EchoRequest { if x, ok := m.GetValue().(*Request_Echo); ok { return x.Echo } return nil } -func (m *Request) GetFlush() *RequestFlush { +func (m *Request) GetFlush() *FlushRequest { if x, ok := m.GetValue().(*Request_Flush); ok { return x.Flush } return nil } -func (m *Request) GetInfo() *RequestInfo { +func (m *Request) GetInfo() *InfoRequest { if x, ok := m.GetValue().(*Request_Info); ok { return x.Info } return nil } -func (m *Request) GetInitChain() *RequestInitChain { +func (m *Request) GetInitChain() *InitChainRequest { if x, ok := m.GetValue().(*Request_InitChain); ok { return x.InitChain } return nil } -func (m *Request) GetQuery() *RequestQuery { +func (m *Request) GetQuery() *QueryRequest { if x, ok := m.GetValue().(*Request_Query); ok { return x.Query } return nil } -func (m *Request) GetCheckTx() *RequestCheckTx { +func (m *Request) GetCheckTx() *CheckTxRequest { if x, ok := m.GetValue().(*Request_CheckTx); ok { return x.CheckTx } return nil } -func (m *Request) GetCommit() *RequestCommit { +func (m *Request) GetCommit() *CommitRequest { if x, ok := m.GetValue().(*Request_Commit); ok { return x.Commit } return nil } -func (m *Request) GetListSnapshots() *RequestListSnapshots { +func (m *Request) GetListSnapshots() *ListSnapshotsRequest { if x, ok := m.GetValue().(*Request_ListSnapshots); ok { return x.ListSnapshots } return nil } -func (m *Request) GetOfferSnapshot() *RequestOfferSnapshot { +func (m *Request) GetOfferSnapshot() *OfferSnapshotRequest { if x, ok := m.GetValue().(*Request_OfferSnapshot); ok { return x.OfferSnapshot } return nil } -func (m *Request) GetLoadSnapshotChunk() *RequestLoadSnapshotChunk { +func (m *Request) GetLoadSnapshotChunk() *LoadSnapshotChunkRequest { if x, ok := m.GetValue().(*Request_LoadSnapshotChunk); ok { return x.LoadSnapshotChunk } return nil } -func (m *Request) GetApplySnapshotChunk() *RequestApplySnapshotChunk { +func (m *Request) GetApplySnapshotChunk() *ApplySnapshotChunkRequest { if x, ok := m.GetValue().(*Request_ApplySnapshotChunk); ok { return x.ApplySnapshotChunk } return nil } -func (m *Request) GetPrepareProposal() *RequestPrepareProposal { +func (m *Request) GetPrepareProposal() *PrepareProposalRequest { if x, ok := m.GetValue().(*Request_PrepareProposal); ok { return x.PrepareProposal } return nil } -func (m *Request) GetProcessProposal() *RequestProcessProposal { +func (m *Request) GetProcessProposal() *ProcessProposalRequest { if x, ok := m.GetValue().(*Request_ProcessProposal); ok { return x.ProcessProposal } return nil } -func (m *Request) GetExtendVote() *RequestExtendVote { +func (m *Request) GetExtendVote() *ExtendVoteRequest { if x, ok := m.GetValue().(*Request_ExtendVote); ok { return x.ExtendVote } return nil } -func (m *Request) GetVerifyVoteExtension() *RequestVerifyVoteExtension { +func (m *Request) GetVerifyVoteExtension() *VerifyVoteExtensionRequest { if x, ok := m.GetValue().(*Request_VerifyVoteExtension); ok { return x.VerifyVoteExtension } return nil } -func (m *Request) GetFinalizeBlock() *RequestFinalizeBlock { +func (m *Request) GetFinalizeBlock() *FinalizeBlockRequest { if x, ok := m.GetValue().(*Request_FinalizeBlock); ok { return x.FinalizeBlock } @@ -488,22 +522,23 @@ func (*Request) XXX_OneofWrappers() []interface{} { } } -type RequestEcho struct { +// EchoRequest is a request to "echo" the given string. +type EchoRequest struct { Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` } -func (m *RequestEcho) Reset() { *m = RequestEcho{} } -func (m *RequestEcho) String() string { return proto.CompactTextString(m) } -func (*RequestEcho) ProtoMessage() {} -func (*RequestEcho) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{1} +func (m *EchoRequest) Reset() { *m = EchoRequest{} } +func (m *EchoRequest) String() string { return proto.CompactTextString(m) } +func (*EchoRequest) ProtoMessage() {} +func (*EchoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{1} } -func (m *RequestEcho) XXX_Unmarshal(b []byte) error { +func (m *EchoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestEcho) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *EchoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestEcho.Marshal(b, m, deterministic) + return xxx_messageInfo_EchoRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -513,40 +548,41 @@ func (m *RequestEcho) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *RequestEcho) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestEcho.Merge(m, src) +func (m *EchoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_EchoRequest.Merge(m, src) } -func (m *RequestEcho) XXX_Size() int { +func (m *EchoRequest) XXX_Size() int { return m.Size() } -func (m *RequestEcho) XXX_DiscardUnknown() { - xxx_messageInfo_RequestEcho.DiscardUnknown(m) +func (m *EchoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_EchoRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestEcho proto.InternalMessageInfo +var xxx_messageInfo_EchoRequest proto.InternalMessageInfo -func (m *RequestEcho) GetMessage() string { +func (m *EchoRequest) GetMessage() string { if m != nil { return m.Message } return "" } -type RequestFlush struct { +// FlushRequest is a request to flush the write buffer. +type FlushRequest struct { } -func (m *RequestFlush) Reset() { *m = RequestFlush{} } -func (m *RequestFlush) String() string { return proto.CompactTextString(m) } -func (*RequestFlush) ProtoMessage() {} -func (*RequestFlush) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{2} +func (m *FlushRequest) Reset() { *m = FlushRequest{} } +func (m *FlushRequest) String() string { return proto.CompactTextString(m) } +func (*FlushRequest) ProtoMessage() {} +func (*FlushRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{2} } -func (m *RequestFlush) XXX_Unmarshal(b []byte) error { +func (m *FlushRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestFlush) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *FlushRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestFlush.Marshal(b, m, deterministic) + return xxx_messageInfo_FlushRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -556,37 +592,38 @@ func (m *RequestFlush) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *RequestFlush) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestFlush.Merge(m, src) +func (m *FlushRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_FlushRequest.Merge(m, src) } -func (m *RequestFlush) XXX_Size() int { +func (m *FlushRequest) XXX_Size() int { return m.Size() } -func (m *RequestFlush) XXX_DiscardUnknown() { - xxx_messageInfo_RequestFlush.DiscardUnknown(m) +func (m *FlushRequest) XXX_DiscardUnknown() { + xxx_messageInfo_FlushRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestFlush proto.InternalMessageInfo +var xxx_messageInfo_FlushRequest proto.InternalMessageInfo -type RequestInfo struct { +// InfoRequest is a request for the ABCI application version. +type InfoRequest struct { Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` BlockVersion uint64 `protobuf:"varint,2,opt,name=block_version,json=blockVersion,proto3" json:"block_version,omitempty"` P2PVersion uint64 `protobuf:"varint,3,opt,name=p2p_version,json=p2pVersion,proto3" json:"p2p_version,omitempty"` AbciVersion string `protobuf:"bytes,4,opt,name=abci_version,json=abciVersion,proto3" json:"abci_version,omitempty"` } -func (m *RequestInfo) Reset() { *m = RequestInfo{} } -func (m *RequestInfo) String() string { return proto.CompactTextString(m) } -func (*RequestInfo) ProtoMessage() {} -func (*RequestInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{3} +func (m *InfoRequest) Reset() { *m = InfoRequest{} } +func (m *InfoRequest) String() string { return proto.CompactTextString(m) } +func (*InfoRequest) ProtoMessage() {} +func (*InfoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{3} } -func (m *RequestInfo) XXX_Unmarshal(b []byte) error { +func (m *InfoRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *InfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestInfo.Marshal(b, m, deterministic) + return xxx_messageInfo_InfoRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -596,67 +633,68 @@ func (m *RequestInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *RequestInfo) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestInfo.Merge(m, src) +func (m *InfoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_InfoRequest.Merge(m, src) } -func (m *RequestInfo) XXX_Size() int { +func (m *InfoRequest) XXX_Size() int { return m.Size() } -func (m *RequestInfo) XXX_DiscardUnknown() { - xxx_messageInfo_RequestInfo.DiscardUnknown(m) +func (m *InfoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_InfoRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestInfo proto.InternalMessageInfo +var xxx_messageInfo_InfoRequest proto.InternalMessageInfo -func (m *RequestInfo) GetVersion() string { +func (m *InfoRequest) GetVersion() string { if m != nil { return m.Version } return "" } -func (m *RequestInfo) GetBlockVersion() uint64 { +func (m *InfoRequest) GetBlockVersion() uint64 { if m != nil { return m.BlockVersion } return 0 } -func (m *RequestInfo) GetP2PVersion() uint64 { +func (m *InfoRequest) GetP2PVersion() uint64 { if m != nil { return m.P2PVersion } return 0 } -func (m *RequestInfo) GetAbciVersion() string { +func (m *InfoRequest) GetAbciVersion() string { if m != nil { return m.AbciVersion } return "" } -type RequestInitChain struct { - Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"` - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - ConsensusParams *types1.ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` - Validators []ValidatorUpdate `protobuf:"bytes,4,rep,name=validators,proto3" json:"validators"` - AppStateBytes []byte `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"` - InitialHeight int64 `protobuf:"varint,6,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` +// InitChainRequest is a request to initialize the blockchain. +type InitChainRequest struct { + Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ConsensusParams *v1.ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []ValidatorUpdate `protobuf:"bytes,4,rep,name=validators,proto3" json:"validators"` + AppStateBytes []byte `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"` + InitialHeight int64 `protobuf:"varint,6,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` } -func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } -func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } -func (*RequestInitChain) ProtoMessage() {} -func (*RequestInitChain) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{4} +func (m *InitChainRequest) Reset() { *m = InitChainRequest{} } +func (m *InitChainRequest) String() string { return proto.CompactTextString(m) } +func (*InitChainRequest) ProtoMessage() {} +func (*InitChainRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{4} } -func (m *RequestInitChain) XXX_Unmarshal(b []byte) error { +func (m *InitChainRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *InitChainRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestInitChain.Marshal(b, m, deterministic) + return xxx_messageInfo_InitChainRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -666,79 +704,80 @@ func (m *RequestInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, er return b[:n], nil } } -func (m *RequestInitChain) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestInitChain.Merge(m, src) +func (m *InitChainRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_InitChainRequest.Merge(m, src) } -func (m *RequestInitChain) XXX_Size() int { +func (m *InitChainRequest) XXX_Size() int { return m.Size() } -func (m *RequestInitChain) XXX_DiscardUnknown() { - xxx_messageInfo_RequestInitChain.DiscardUnknown(m) +func (m *InitChainRequest) XXX_DiscardUnknown() { + xxx_messageInfo_InitChainRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestInitChain proto.InternalMessageInfo +var xxx_messageInfo_InitChainRequest proto.InternalMessageInfo -func (m *RequestInitChain) GetTime() time.Time { +func (m *InitChainRequest) GetTime() time.Time { if m != nil { return m.Time } return time.Time{} } -func (m *RequestInitChain) GetChainId() string { +func (m *InitChainRequest) GetChainId() string { if m != nil { return m.ChainId } return "" } -func (m *RequestInitChain) GetConsensusParams() *types1.ConsensusParams { +func (m *InitChainRequest) GetConsensusParams() *v1.ConsensusParams { if m != nil { return m.ConsensusParams } return nil } -func (m *RequestInitChain) GetValidators() []ValidatorUpdate { +func (m *InitChainRequest) GetValidators() []ValidatorUpdate { if m != nil { return m.Validators } return nil } -func (m *RequestInitChain) GetAppStateBytes() []byte { +func (m *InitChainRequest) GetAppStateBytes() []byte { if m != nil { return m.AppStateBytes } return nil } -func (m *RequestInitChain) GetInitialHeight() int64 { +func (m *InitChainRequest) GetInitialHeight() int64 { if m != nil { return m.InitialHeight } return 0 } -type RequestQuery struct { +// QueryRequest is a request to query the application state. +type QueryRequest struct { Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` Prove bool `protobuf:"varint,4,opt,name=prove,proto3" json:"prove,omitempty"` } -func (m *RequestQuery) Reset() { *m = RequestQuery{} } -func (m *RequestQuery) String() string { return proto.CompactTextString(m) } -func (*RequestQuery) ProtoMessage() {} -func (*RequestQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{5} +func (m *QueryRequest) Reset() { *m = QueryRequest{} } +func (m *QueryRequest) String() string { return proto.CompactTextString(m) } +func (*QueryRequest) ProtoMessage() {} +func (*QueryRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{5} } -func (m *RequestQuery) XXX_Unmarshal(b []byte) error { +func (m *QueryRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *QueryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestQuery.Marshal(b, m, deterministic) + return xxx_messageInfo_QueryRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -748,63 +787,64 @@ func (m *RequestQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *RequestQuery) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestQuery.Merge(m, src) +func (m *QueryRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryRequest.Merge(m, src) } -func (m *RequestQuery) XXX_Size() int { +func (m *QueryRequest) XXX_Size() int { return m.Size() } -func (m *RequestQuery) XXX_DiscardUnknown() { - xxx_messageInfo_RequestQuery.DiscardUnknown(m) +func (m *QueryRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestQuery proto.InternalMessageInfo +var xxx_messageInfo_QueryRequest proto.InternalMessageInfo -func (m *RequestQuery) GetData() []byte { +func (m *QueryRequest) GetData() []byte { if m != nil { return m.Data } return nil } -func (m *RequestQuery) GetPath() string { +func (m *QueryRequest) GetPath() string { if m != nil { return m.Path } return "" } -func (m *RequestQuery) GetHeight() int64 { +func (m *QueryRequest) GetHeight() int64 { if m != nil { return m.Height } return 0 } -func (m *RequestQuery) GetProve() bool { +func (m *QueryRequest) GetProve() bool { if m != nil { return m.Prove } return false } -type RequestCheckTx struct { +// CheckTxRequest is a request to check that the transaction is valid. +type CheckTxRequest struct { Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` - Type CheckTxType `protobuf:"varint,2,opt,name=type,proto3,enum=tendermint.abci.CheckTxType" json:"type,omitempty"` + Type CheckTxType `protobuf:"varint,3,opt,name=type,proto3,enum=cometbft.abci.v1.CheckTxType" json:"type,omitempty"` } -func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } -func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } -func (*RequestCheckTx) ProtoMessage() {} -func (*RequestCheckTx) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{6} +func (m *CheckTxRequest) Reset() { *m = CheckTxRequest{} } +func (m *CheckTxRequest) String() string { return proto.CompactTextString(m) } +func (*CheckTxRequest) ProtoMessage() {} +func (*CheckTxRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{6} } -func (m *RequestCheckTx) XXX_Unmarshal(b []byte) error { +func (m *CheckTxRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *CheckTxRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestCheckTx.Marshal(b, m, deterministic) + return xxx_messageInfo_CheckTxRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -814,47 +854,48 @@ func (m *RequestCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, erro return b[:n], nil } } -func (m *RequestCheckTx) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestCheckTx.Merge(m, src) +func (m *CheckTxRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CheckTxRequest.Merge(m, src) } -func (m *RequestCheckTx) XXX_Size() int { +func (m *CheckTxRequest) XXX_Size() int { return m.Size() } -func (m *RequestCheckTx) XXX_DiscardUnknown() { - xxx_messageInfo_RequestCheckTx.DiscardUnknown(m) +func (m *CheckTxRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CheckTxRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestCheckTx proto.InternalMessageInfo +var xxx_messageInfo_CheckTxRequest proto.InternalMessageInfo -func (m *RequestCheckTx) GetTx() []byte { +func (m *CheckTxRequest) GetTx() []byte { if m != nil { return m.Tx } return nil } -func (m *RequestCheckTx) GetType() CheckTxType { +func (m *CheckTxRequest) GetType() CheckTxType { if m != nil { return m.Type } - return CheckTxType_New + return CHECK_TX_TYPE_UNKNOWN } -type RequestCommit struct { +// CommitRequest is a request to commit the pending application state. +type CommitRequest struct { } -func (m *RequestCommit) Reset() { *m = RequestCommit{} } -func (m *RequestCommit) String() string { return proto.CompactTextString(m) } -func (*RequestCommit) ProtoMessage() {} -func (*RequestCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{7} +func (m *CommitRequest) Reset() { *m = CommitRequest{} } +func (m *CommitRequest) String() string { return proto.CompactTextString(m) } +func (*CommitRequest) ProtoMessage() {} +func (*CommitRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{7} } -func (m *RequestCommit) XXX_Unmarshal(b []byte) error { +func (m *CommitRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *CommitRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestCommit.Marshal(b, m, deterministic) + return xxx_messageInfo_CommitRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -864,34 +905,34 @@ func (m *RequestCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error return b[:n], nil } } -func (m *RequestCommit) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestCommit.Merge(m, src) +func (m *CommitRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommitRequest.Merge(m, src) } -func (m *RequestCommit) XXX_Size() int { +func (m *CommitRequest) XXX_Size() int { return m.Size() } -func (m *RequestCommit) XXX_DiscardUnknown() { - xxx_messageInfo_RequestCommit.DiscardUnknown(m) +func (m *CommitRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CommitRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestCommit proto.InternalMessageInfo +var xxx_messageInfo_CommitRequest proto.InternalMessageInfo -// lists available snapshots -type RequestListSnapshots struct { +// Request to list available snapshots. +type ListSnapshotsRequest struct { } -func (m *RequestListSnapshots) Reset() { *m = RequestListSnapshots{} } -func (m *RequestListSnapshots) String() string { return proto.CompactTextString(m) } -func (*RequestListSnapshots) ProtoMessage() {} -func (*RequestListSnapshots) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{8} +func (m *ListSnapshotsRequest) Reset() { *m = ListSnapshotsRequest{} } +func (m *ListSnapshotsRequest) String() string { return proto.CompactTextString(m) } +func (*ListSnapshotsRequest) ProtoMessage() {} +func (*ListSnapshotsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{8} } -func (m *RequestListSnapshots) XXX_Unmarshal(b []byte) error { +func (m *ListSnapshotsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestListSnapshots) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ListSnapshotsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestListSnapshots.Marshal(b, m, deterministic) + return xxx_messageInfo_ListSnapshotsRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -901,36 +942,36 @@ func (m *RequestListSnapshots) XXX_Marshal(b []byte, deterministic bool) ([]byte return b[:n], nil } } -func (m *RequestListSnapshots) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestListSnapshots.Merge(m, src) +func (m *ListSnapshotsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListSnapshotsRequest.Merge(m, src) } -func (m *RequestListSnapshots) XXX_Size() int { +func (m *ListSnapshotsRequest) XXX_Size() int { return m.Size() } -func (m *RequestListSnapshots) XXX_DiscardUnknown() { - xxx_messageInfo_RequestListSnapshots.DiscardUnknown(m) +func (m *ListSnapshotsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ListSnapshotsRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestListSnapshots proto.InternalMessageInfo +var xxx_messageInfo_ListSnapshotsRequest proto.InternalMessageInfo -// offers a snapshot to the application -type RequestOfferSnapshot struct { +// Request offering a snapshot to the application. +type OfferSnapshotRequest struct { Snapshot *Snapshot `protobuf:"bytes,1,opt,name=snapshot,proto3" json:"snapshot,omitempty"` AppHash []byte `protobuf:"bytes,2,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } -func (m *RequestOfferSnapshot) Reset() { *m = RequestOfferSnapshot{} } -func (m *RequestOfferSnapshot) String() string { return proto.CompactTextString(m) } -func (*RequestOfferSnapshot) ProtoMessage() {} -func (*RequestOfferSnapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{9} +func (m *OfferSnapshotRequest) Reset() { *m = OfferSnapshotRequest{} } +func (m *OfferSnapshotRequest) String() string { return proto.CompactTextString(m) } +func (*OfferSnapshotRequest) ProtoMessage() {} +func (*OfferSnapshotRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{9} } -func (m *RequestOfferSnapshot) XXX_Unmarshal(b []byte) error { +func (m *OfferSnapshotRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestOfferSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *OfferSnapshotRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestOfferSnapshot.Marshal(b, m, deterministic) + return xxx_messageInfo_OfferSnapshotRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -940,51 +981,51 @@ func (m *RequestOfferSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte return b[:n], nil } } -func (m *RequestOfferSnapshot) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestOfferSnapshot.Merge(m, src) +func (m *OfferSnapshotRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_OfferSnapshotRequest.Merge(m, src) } -func (m *RequestOfferSnapshot) XXX_Size() int { +func (m *OfferSnapshotRequest) XXX_Size() int { return m.Size() } -func (m *RequestOfferSnapshot) XXX_DiscardUnknown() { - xxx_messageInfo_RequestOfferSnapshot.DiscardUnknown(m) +func (m *OfferSnapshotRequest) XXX_DiscardUnknown() { + xxx_messageInfo_OfferSnapshotRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestOfferSnapshot proto.InternalMessageInfo +var xxx_messageInfo_OfferSnapshotRequest proto.InternalMessageInfo -func (m *RequestOfferSnapshot) GetSnapshot() *Snapshot { +func (m *OfferSnapshotRequest) GetSnapshot() *Snapshot { if m != nil { return m.Snapshot } return nil } -func (m *RequestOfferSnapshot) GetAppHash() []byte { +func (m *OfferSnapshotRequest) GetAppHash() []byte { if m != nil { return m.AppHash } return nil } -// loads a snapshot chunk -type RequestLoadSnapshotChunk struct { +// Request to load a snapshot chunk. +type LoadSnapshotChunkRequest struct { Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Format uint32 `protobuf:"varint,2,opt,name=format,proto3" json:"format,omitempty"` Chunk uint32 `protobuf:"varint,3,opt,name=chunk,proto3" json:"chunk,omitempty"` } -func (m *RequestLoadSnapshotChunk) Reset() { *m = RequestLoadSnapshotChunk{} } -func (m *RequestLoadSnapshotChunk) String() string { return proto.CompactTextString(m) } -func (*RequestLoadSnapshotChunk) ProtoMessage() {} -func (*RequestLoadSnapshotChunk) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{10} +func (m *LoadSnapshotChunkRequest) Reset() { *m = LoadSnapshotChunkRequest{} } +func (m *LoadSnapshotChunkRequest) String() string { return proto.CompactTextString(m) } +func (*LoadSnapshotChunkRequest) ProtoMessage() {} +func (*LoadSnapshotChunkRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{10} } -func (m *RequestLoadSnapshotChunk) XXX_Unmarshal(b []byte) error { +func (m *LoadSnapshotChunkRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestLoadSnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *LoadSnapshotChunkRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestLoadSnapshotChunk.Marshal(b, m, deterministic) + return xxx_messageInfo_LoadSnapshotChunkRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -994,58 +1035,58 @@ func (m *RequestLoadSnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([] return b[:n], nil } } -func (m *RequestLoadSnapshotChunk) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestLoadSnapshotChunk.Merge(m, src) +func (m *LoadSnapshotChunkRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_LoadSnapshotChunkRequest.Merge(m, src) } -func (m *RequestLoadSnapshotChunk) XXX_Size() int { +func (m *LoadSnapshotChunkRequest) XXX_Size() int { return m.Size() } -func (m *RequestLoadSnapshotChunk) XXX_DiscardUnknown() { - xxx_messageInfo_RequestLoadSnapshotChunk.DiscardUnknown(m) +func (m *LoadSnapshotChunkRequest) XXX_DiscardUnknown() { + xxx_messageInfo_LoadSnapshotChunkRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestLoadSnapshotChunk proto.InternalMessageInfo +var xxx_messageInfo_LoadSnapshotChunkRequest proto.InternalMessageInfo -func (m *RequestLoadSnapshotChunk) GetHeight() uint64 { +func (m *LoadSnapshotChunkRequest) GetHeight() uint64 { if m != nil { return m.Height } return 0 } -func (m *RequestLoadSnapshotChunk) GetFormat() uint32 { +func (m *LoadSnapshotChunkRequest) GetFormat() uint32 { if m != nil { return m.Format } return 0 } -func (m *RequestLoadSnapshotChunk) GetChunk() uint32 { +func (m *LoadSnapshotChunkRequest) GetChunk() uint32 { if m != nil { return m.Chunk } return 0 } -// Applies a snapshot chunk -type RequestApplySnapshotChunk struct { +// Request to apply a snapshot chunk. +type ApplySnapshotChunkRequest struct { Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` Chunk []byte `protobuf:"bytes,2,opt,name=chunk,proto3" json:"chunk,omitempty"` Sender string `protobuf:"bytes,3,opt,name=sender,proto3" json:"sender,omitempty"` } -func (m *RequestApplySnapshotChunk) Reset() { *m = RequestApplySnapshotChunk{} } -func (m *RequestApplySnapshotChunk) String() string { return proto.CompactTextString(m) } -func (*RequestApplySnapshotChunk) ProtoMessage() {} -func (*RequestApplySnapshotChunk) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{11} +func (m *ApplySnapshotChunkRequest) Reset() { *m = ApplySnapshotChunkRequest{} } +func (m *ApplySnapshotChunkRequest) String() string { return proto.CompactTextString(m) } +func (*ApplySnapshotChunkRequest) ProtoMessage() {} +func (*ApplySnapshotChunkRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{11} } -func (m *RequestApplySnapshotChunk) XXX_Unmarshal(b []byte) error { +func (m *ApplySnapshotChunkRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestApplySnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ApplySnapshotChunkRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestApplySnapshotChunk.Marshal(b, m, deterministic) + return xxx_messageInfo_ApplySnapshotChunkRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1055,40 +1096,42 @@ func (m *RequestApplySnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([ return b[:n], nil } } -func (m *RequestApplySnapshotChunk) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestApplySnapshotChunk.Merge(m, src) +func (m *ApplySnapshotChunkRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApplySnapshotChunkRequest.Merge(m, src) } -func (m *RequestApplySnapshotChunk) XXX_Size() int { +func (m *ApplySnapshotChunkRequest) XXX_Size() int { return m.Size() } -func (m *RequestApplySnapshotChunk) XXX_DiscardUnknown() { - xxx_messageInfo_RequestApplySnapshotChunk.DiscardUnknown(m) +func (m *ApplySnapshotChunkRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ApplySnapshotChunkRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestApplySnapshotChunk proto.InternalMessageInfo +var xxx_messageInfo_ApplySnapshotChunkRequest proto.InternalMessageInfo -func (m *RequestApplySnapshotChunk) GetIndex() uint32 { +func (m *ApplySnapshotChunkRequest) GetIndex() uint32 { if m != nil { return m.Index } return 0 } -func (m *RequestApplySnapshotChunk) GetChunk() []byte { +func (m *ApplySnapshotChunkRequest) GetChunk() []byte { if m != nil { return m.Chunk } return nil } -func (m *RequestApplySnapshotChunk) GetSender() string { +func (m *ApplySnapshotChunkRequest) GetSender() string { if m != nil { return m.Sender } return "" } -type RequestPrepareProposal struct { +// PrepareProposalRequest is a request for the ABCI application to prepare a new +// block proposal. +type PrepareProposalRequest struct { // the modified transactions cannot exceed this size. MaxTxBytes int64 `protobuf:"varint,1,opt,name=max_tx_bytes,json=maxTxBytes,proto3" json:"max_tx_bytes,omitempty"` // txs is an array of transactions that will be included in a block, @@ -1103,18 +1146,18 @@ type RequestPrepareProposal struct { ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` } -func (m *RequestPrepareProposal) Reset() { *m = RequestPrepareProposal{} } -func (m *RequestPrepareProposal) String() string { return proto.CompactTextString(m) } -func (*RequestPrepareProposal) ProtoMessage() {} -func (*RequestPrepareProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{12} +func (m *PrepareProposalRequest) Reset() { *m = PrepareProposalRequest{} } +func (m *PrepareProposalRequest) String() string { return proto.CompactTextString(m) } +func (*PrepareProposalRequest) ProtoMessage() {} +func (*PrepareProposalRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{12} } -func (m *RequestPrepareProposal) XXX_Unmarshal(b []byte) error { +func (m *PrepareProposalRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestPrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *PrepareProposalRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestPrepareProposal.Marshal(b, m, deterministic) + return xxx_messageInfo_PrepareProposalRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1124,79 +1167,81 @@ func (m *RequestPrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]by return b[:n], nil } } -func (m *RequestPrepareProposal) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestPrepareProposal.Merge(m, src) +func (m *PrepareProposalRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PrepareProposalRequest.Merge(m, src) } -func (m *RequestPrepareProposal) XXX_Size() int { +func (m *PrepareProposalRequest) XXX_Size() int { return m.Size() } -func (m *RequestPrepareProposal) XXX_DiscardUnknown() { - xxx_messageInfo_RequestPrepareProposal.DiscardUnknown(m) +func (m *PrepareProposalRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PrepareProposalRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestPrepareProposal proto.InternalMessageInfo +var xxx_messageInfo_PrepareProposalRequest proto.InternalMessageInfo -func (m *RequestPrepareProposal) GetMaxTxBytes() int64 { +func (m *PrepareProposalRequest) GetMaxTxBytes() int64 { if m != nil { return m.MaxTxBytes } return 0 } -func (m *RequestPrepareProposal) GetTxs() [][]byte { +func (m *PrepareProposalRequest) GetTxs() [][]byte { if m != nil { return m.Txs } return nil } -func (m *RequestPrepareProposal) GetLocalLastCommit() ExtendedCommitInfo { +func (m *PrepareProposalRequest) GetLocalLastCommit() ExtendedCommitInfo { if m != nil { return m.LocalLastCommit } return ExtendedCommitInfo{} } -func (m *RequestPrepareProposal) GetMisbehavior() []Misbehavior { +func (m *PrepareProposalRequest) GetMisbehavior() []Misbehavior { if m != nil { return m.Misbehavior } return nil } -func (m *RequestPrepareProposal) GetHeight() int64 { +func (m *PrepareProposalRequest) GetHeight() int64 { if m != nil { return m.Height } return 0 } -func (m *RequestPrepareProposal) GetTime() time.Time { +func (m *PrepareProposalRequest) GetTime() time.Time { if m != nil { return m.Time } return time.Time{} } -func (m *RequestPrepareProposal) GetNextValidatorsHash() []byte { +func (m *PrepareProposalRequest) GetNextValidatorsHash() []byte { if m != nil { return m.NextValidatorsHash } return nil } -func (m *RequestPrepareProposal) GetProposerAddress() []byte { +func (m *PrepareProposalRequest) GetProposerAddress() []byte { if m != nil { return m.ProposerAddress } return nil } -type RequestProcessProposal struct { +// ProcessProposalRequest is a request for the ABCI application to process a proposal +// received from another validator. +type ProcessProposalRequest struct { Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` ProposedLastCommit CommitInfo `protobuf:"bytes,2,opt,name=proposed_last_commit,json=proposedLastCommit,proto3" json:"proposed_last_commit"` Misbehavior []Misbehavior `protobuf:"bytes,3,rep,name=misbehavior,proto3" json:"misbehavior"` - // hash is the merkle root hash of the fields of the proposed block. + // Merkle root hash of the fields of the proposed block. Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` @@ -1205,18 +1250,18 @@ type RequestProcessProposal struct { ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` } -func (m *RequestProcessProposal) Reset() { *m = RequestProcessProposal{} } -func (m *RequestProcessProposal) String() string { return proto.CompactTextString(m) } -func (*RequestProcessProposal) ProtoMessage() {} -func (*RequestProcessProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{13} +func (m *ProcessProposalRequest) Reset() { *m = ProcessProposalRequest{} } +func (m *ProcessProposalRequest) String() string { return proto.CompactTextString(m) } +func (*ProcessProposalRequest) ProtoMessage() {} +func (*ProcessProposalRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{13} } -func (m *RequestProcessProposal) XXX_Unmarshal(b []byte) error { +func (m *ProcessProposalRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ProcessProposalRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestProcessProposal.Marshal(b, m, deterministic) + return xxx_messageInfo_ProcessProposalRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1226,94 +1271,102 @@ func (m *RequestProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]by return b[:n], nil } } -func (m *RequestProcessProposal) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestProcessProposal.Merge(m, src) +func (m *ProcessProposalRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProcessProposalRequest.Merge(m, src) } -func (m *RequestProcessProposal) XXX_Size() int { +func (m *ProcessProposalRequest) XXX_Size() int { return m.Size() } -func (m *RequestProcessProposal) XXX_DiscardUnknown() { - xxx_messageInfo_RequestProcessProposal.DiscardUnknown(m) +func (m *ProcessProposalRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ProcessProposalRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestProcessProposal proto.InternalMessageInfo +var xxx_messageInfo_ProcessProposalRequest proto.InternalMessageInfo -func (m *RequestProcessProposal) GetTxs() [][]byte { +func (m *ProcessProposalRequest) GetTxs() [][]byte { if m != nil { return m.Txs } return nil } -func (m *RequestProcessProposal) GetProposedLastCommit() CommitInfo { +func (m *ProcessProposalRequest) GetProposedLastCommit() CommitInfo { if m != nil { return m.ProposedLastCommit } return CommitInfo{} } -func (m *RequestProcessProposal) GetMisbehavior() []Misbehavior { +func (m *ProcessProposalRequest) GetMisbehavior() []Misbehavior { if m != nil { return m.Misbehavior } return nil } -func (m *RequestProcessProposal) GetHash() []byte { +func (m *ProcessProposalRequest) GetHash() []byte { if m != nil { return m.Hash } return nil } -func (m *RequestProcessProposal) GetHeight() int64 { +func (m *ProcessProposalRequest) GetHeight() int64 { if m != nil { return m.Height } return 0 } -func (m *RequestProcessProposal) GetTime() time.Time { +func (m *ProcessProposalRequest) GetTime() time.Time { if m != nil { return m.Time } return time.Time{} } -func (m *RequestProcessProposal) GetNextValidatorsHash() []byte { +func (m *ProcessProposalRequest) GetNextValidatorsHash() []byte { if m != nil { return m.NextValidatorsHash } return nil } -func (m *RequestProcessProposal) GetProposerAddress() []byte { +func (m *ProcessProposalRequest) GetProposerAddress() []byte { if m != nil { return m.ProposerAddress } return nil } -// Extends a vote with application-injected data -type RequestExtendVote struct { - // the hash of the block that this vote may be referring to +// ExtendVoteRequest extends a precommit vote with application-injected data. +type ExtendVoteRequest struct { + // the hash of the block that this vote may be referring to Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` // the height of the extended vote Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + // info of the block that this vote may be referring to + Time time.Time `protobuf:"bytes,3,opt,name=time,proto3,stdtime" json:"time"` + Txs [][]byte `protobuf:"bytes,4,rep,name=txs,proto3" json:"txs,omitempty"` + ProposedLastCommit CommitInfo `protobuf:"bytes,5,opt,name=proposed_last_commit,json=proposedLastCommit,proto3" json:"proposed_last_commit"` + Misbehavior []Misbehavior `protobuf:"bytes,6,rep,name=misbehavior,proto3" json:"misbehavior"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // address of the public key of the original proposer of the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` } -func (m *RequestExtendVote) Reset() { *m = RequestExtendVote{} } -func (m *RequestExtendVote) String() string { return proto.CompactTextString(m) } -func (*RequestExtendVote) ProtoMessage() {} -func (*RequestExtendVote) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{14} +func (m *ExtendVoteRequest) Reset() { *m = ExtendVoteRequest{} } +func (m *ExtendVoteRequest) String() string { return proto.CompactTextString(m) } +func (*ExtendVoteRequest) ProtoMessage() {} +func (*ExtendVoteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{14} } -func (m *RequestExtendVote) XXX_Unmarshal(b []byte) error { +func (m *ExtendVoteRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestExtendVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ExtendVoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestExtendVote.Marshal(b, m, deterministic) + return xxx_messageInfo_ExtendVoteRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1323,34 +1376,77 @@ func (m *RequestExtendVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, e return b[:n], nil } } -func (m *RequestExtendVote) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestExtendVote.Merge(m, src) +func (m *ExtendVoteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendVoteRequest.Merge(m, src) } -func (m *RequestExtendVote) XXX_Size() int { +func (m *ExtendVoteRequest) XXX_Size() int { return m.Size() } -func (m *RequestExtendVote) XXX_DiscardUnknown() { - xxx_messageInfo_RequestExtendVote.DiscardUnknown(m) +func (m *ExtendVoteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendVoteRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestExtendVote proto.InternalMessageInfo +var xxx_messageInfo_ExtendVoteRequest proto.InternalMessageInfo -func (m *RequestExtendVote) GetHash() []byte { +func (m *ExtendVoteRequest) GetHash() []byte { if m != nil { return m.Hash } return nil } -func (m *RequestExtendVote) GetHeight() int64 { +func (m *ExtendVoteRequest) GetHeight() int64 { if m != nil { return m.Height } return 0 } -// Verify the vote extension -type RequestVerifyVoteExtension struct { +func (m *ExtendVoteRequest) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *ExtendVoteRequest) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *ExtendVoteRequest) GetProposedLastCommit() CommitInfo { + if m != nil { + return m.ProposedLastCommit + } + return CommitInfo{} +} + +func (m *ExtendVoteRequest) GetMisbehavior() []Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *ExtendVoteRequest) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *ExtendVoteRequest) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +// VerifyVoteExtensionRequest is a request for the application to verify a vote extension +// produced by a different validator. +type VerifyVoteExtensionRequest struct { // the hash of the block that this received vote corresponds to Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` // the validator that signed the vote extension @@ -1359,18 +1455,18 @@ type RequestVerifyVoteExtension struct { VoteExtension []byte `protobuf:"bytes,4,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` } -func (m *RequestVerifyVoteExtension) Reset() { *m = RequestVerifyVoteExtension{} } -func (m *RequestVerifyVoteExtension) String() string { return proto.CompactTextString(m) } -func (*RequestVerifyVoteExtension) ProtoMessage() {} -func (*RequestVerifyVoteExtension) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{15} +func (m *VerifyVoteExtensionRequest) Reset() { *m = VerifyVoteExtensionRequest{} } +func (m *VerifyVoteExtensionRequest) String() string { return proto.CompactTextString(m) } +func (*VerifyVoteExtensionRequest) ProtoMessage() {} +func (*VerifyVoteExtensionRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{15} } -func (m *RequestVerifyVoteExtension) XXX_Unmarshal(b []byte) error { +func (m *VerifyVoteExtensionRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestVerifyVoteExtension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *VerifyVoteExtensionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestVerifyVoteExtension.Marshal(b, m, deterministic) + return xxx_messageInfo_VerifyVoteExtensionRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1380,71 +1476,72 @@ func (m *RequestVerifyVoteExtension) XXX_Marshal(b []byte, deterministic bool) ( return b[:n], nil } } -func (m *RequestVerifyVoteExtension) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestVerifyVoteExtension.Merge(m, src) +func (m *VerifyVoteExtensionRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_VerifyVoteExtensionRequest.Merge(m, src) } -func (m *RequestVerifyVoteExtension) XXX_Size() int { +func (m *VerifyVoteExtensionRequest) XXX_Size() int { return m.Size() } -func (m *RequestVerifyVoteExtension) XXX_DiscardUnknown() { - xxx_messageInfo_RequestVerifyVoteExtension.DiscardUnknown(m) +func (m *VerifyVoteExtensionRequest) XXX_DiscardUnknown() { + xxx_messageInfo_VerifyVoteExtensionRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestVerifyVoteExtension proto.InternalMessageInfo +var xxx_messageInfo_VerifyVoteExtensionRequest proto.InternalMessageInfo -func (m *RequestVerifyVoteExtension) GetHash() []byte { +func (m *VerifyVoteExtensionRequest) GetHash() []byte { if m != nil { return m.Hash } return nil } -func (m *RequestVerifyVoteExtension) GetValidatorAddress() []byte { +func (m *VerifyVoteExtensionRequest) GetValidatorAddress() []byte { if m != nil { return m.ValidatorAddress } return nil } -func (m *RequestVerifyVoteExtension) GetHeight() int64 { +func (m *VerifyVoteExtensionRequest) GetHeight() int64 { if m != nil { return m.Height } return 0 } -func (m *RequestVerifyVoteExtension) GetVoteExtension() []byte { +func (m *VerifyVoteExtensionRequest) GetVoteExtension() []byte { if m != nil { return m.VoteExtension } return nil } -type RequestFinalizeBlock struct { +// FinalizeBlockRequest is a request to finalize the block. +type FinalizeBlockRequest struct { Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` DecidedLastCommit CommitInfo `protobuf:"bytes,2,opt,name=decided_last_commit,json=decidedLastCommit,proto3" json:"decided_last_commit"` Misbehavior []Misbehavior `protobuf:"bytes,3,rep,name=misbehavior,proto3" json:"misbehavior"` - // hash is the merkle root hash of the fields of the decided block. + // Merkle root hash of the fields of the decided block. Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` - // proposer_address is the address of the public key of the original proposer of the block. + // address of the public key of the original proposer of the block. ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` } -func (m *RequestFinalizeBlock) Reset() { *m = RequestFinalizeBlock{} } -func (m *RequestFinalizeBlock) String() string { return proto.CompactTextString(m) } -func (*RequestFinalizeBlock) ProtoMessage() {} -func (*RequestFinalizeBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{16} +func (m *FinalizeBlockRequest) Reset() { *m = FinalizeBlockRequest{} } +func (m *FinalizeBlockRequest) String() string { return proto.CompactTextString(m) } +func (*FinalizeBlockRequest) ProtoMessage() {} +func (*FinalizeBlockRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{16} } -func (m *RequestFinalizeBlock) XXX_Unmarshal(b []byte) error { +func (m *FinalizeBlockRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *RequestFinalizeBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *FinalizeBlockRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_RequestFinalizeBlock.Marshal(b, m, deterministic) + return xxx_messageInfo_FinalizeBlockRequest.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1454,75 +1551,78 @@ func (m *RequestFinalizeBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte return b[:n], nil } } -func (m *RequestFinalizeBlock) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestFinalizeBlock.Merge(m, src) +func (m *FinalizeBlockRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_FinalizeBlockRequest.Merge(m, src) } -func (m *RequestFinalizeBlock) XXX_Size() int { +func (m *FinalizeBlockRequest) XXX_Size() int { return m.Size() } -func (m *RequestFinalizeBlock) XXX_DiscardUnknown() { - xxx_messageInfo_RequestFinalizeBlock.DiscardUnknown(m) +func (m *FinalizeBlockRequest) XXX_DiscardUnknown() { + xxx_messageInfo_FinalizeBlockRequest.DiscardUnknown(m) } -var xxx_messageInfo_RequestFinalizeBlock proto.InternalMessageInfo +var xxx_messageInfo_FinalizeBlockRequest proto.InternalMessageInfo -func (m *RequestFinalizeBlock) GetTxs() [][]byte { +func (m *FinalizeBlockRequest) GetTxs() [][]byte { if m != nil { return m.Txs } return nil } -func (m *RequestFinalizeBlock) GetDecidedLastCommit() CommitInfo { +func (m *FinalizeBlockRequest) GetDecidedLastCommit() CommitInfo { if m != nil { return m.DecidedLastCommit } return CommitInfo{} } -func (m *RequestFinalizeBlock) GetMisbehavior() []Misbehavior { +func (m *FinalizeBlockRequest) GetMisbehavior() []Misbehavior { if m != nil { return m.Misbehavior } return nil } -func (m *RequestFinalizeBlock) GetHash() []byte { +func (m *FinalizeBlockRequest) GetHash() []byte { if m != nil { return m.Hash } return nil } -func (m *RequestFinalizeBlock) GetHeight() int64 { +func (m *FinalizeBlockRequest) GetHeight() int64 { if m != nil { return m.Height } return 0 } -func (m *RequestFinalizeBlock) GetTime() time.Time { +func (m *FinalizeBlockRequest) GetTime() time.Time { if m != nil { return m.Time } return time.Time{} } -func (m *RequestFinalizeBlock) GetNextValidatorsHash() []byte { +func (m *FinalizeBlockRequest) GetNextValidatorsHash() []byte { if m != nil { return m.NextValidatorsHash } return nil } -func (m *RequestFinalizeBlock) GetProposerAddress() []byte { +func (m *FinalizeBlockRequest) GetProposerAddress() []byte { if m != nil { return m.ProposerAddress } return nil } +// Response represents a response from the ABCI application. type Response struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Value: // // *Response_Exception @@ -1549,7 +1649,7 @@ func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{17} + return fileDescriptor_95dd8f7b670b96e3, []int{17} } func (m *Response) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1585,55 +1685,55 @@ type isResponse_Value interface { } type Response_Exception struct { - Exception *ResponseException `protobuf:"bytes,1,opt,name=exception,proto3,oneof" json:"exception,omitempty"` + Exception *ExceptionResponse `protobuf:"bytes,1,opt,name=exception,proto3,oneof" json:"exception,omitempty"` } type Response_Echo struct { - Echo *ResponseEcho `protobuf:"bytes,2,opt,name=echo,proto3,oneof" json:"echo,omitempty"` + Echo *EchoResponse `protobuf:"bytes,2,opt,name=echo,proto3,oneof" json:"echo,omitempty"` } type Response_Flush struct { - Flush *ResponseFlush `protobuf:"bytes,3,opt,name=flush,proto3,oneof" json:"flush,omitempty"` + Flush *FlushResponse `protobuf:"bytes,3,opt,name=flush,proto3,oneof" json:"flush,omitempty"` } type Response_Info struct { - Info *ResponseInfo `protobuf:"bytes,4,opt,name=info,proto3,oneof" json:"info,omitempty"` + Info *InfoResponse `protobuf:"bytes,4,opt,name=info,proto3,oneof" json:"info,omitempty"` } type Response_InitChain struct { - InitChain *ResponseInitChain `protobuf:"bytes,6,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` + InitChain *InitChainResponse `protobuf:"bytes,6,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` } type Response_Query struct { - Query *ResponseQuery `protobuf:"bytes,7,opt,name=query,proto3,oneof" json:"query,omitempty"` + Query *QueryResponse `protobuf:"bytes,7,opt,name=query,proto3,oneof" json:"query,omitempty"` } type Response_CheckTx struct { - CheckTx *ResponseCheckTx `protobuf:"bytes,9,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` + CheckTx *CheckTxResponse `protobuf:"bytes,9,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` } type Response_Commit struct { - Commit *ResponseCommit `protobuf:"bytes,12,opt,name=commit,proto3,oneof" json:"commit,omitempty"` + Commit *CommitResponse `protobuf:"bytes,12,opt,name=commit,proto3,oneof" json:"commit,omitempty"` } type Response_ListSnapshots struct { - ListSnapshots *ResponseListSnapshots `protobuf:"bytes,13,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` + ListSnapshots *ListSnapshotsResponse `protobuf:"bytes,13,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` } type Response_OfferSnapshot struct { - OfferSnapshot *ResponseOfferSnapshot `protobuf:"bytes,14,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` + OfferSnapshot *OfferSnapshotResponse `protobuf:"bytes,14,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` } type Response_LoadSnapshotChunk struct { - LoadSnapshotChunk *ResponseLoadSnapshotChunk `protobuf:"bytes,15,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` + LoadSnapshotChunk *LoadSnapshotChunkResponse `protobuf:"bytes,15,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` } type Response_ApplySnapshotChunk struct { - ApplySnapshotChunk *ResponseApplySnapshotChunk `protobuf:"bytes,16,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` + ApplySnapshotChunk *ApplySnapshotChunkResponse `protobuf:"bytes,16,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` } type Response_PrepareProposal struct { - PrepareProposal *ResponsePrepareProposal `protobuf:"bytes,17,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` + PrepareProposal *PrepareProposalResponse `protobuf:"bytes,17,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` } type Response_ProcessProposal struct { - ProcessProposal *ResponseProcessProposal `protobuf:"bytes,18,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` + ProcessProposal *ProcessProposalResponse `protobuf:"bytes,18,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` } type Response_ExtendVote struct { - ExtendVote *ResponseExtendVote `protobuf:"bytes,19,opt,name=extend_vote,json=extendVote,proto3,oneof" json:"extend_vote,omitempty"` + ExtendVote *ExtendVoteResponse `protobuf:"bytes,19,opt,name=extend_vote,json=extendVote,proto3,oneof" json:"extend_vote,omitempty"` } type Response_VerifyVoteExtension struct { - VerifyVoteExtension *ResponseVerifyVoteExtension `protobuf:"bytes,20,opt,name=verify_vote_extension,json=verifyVoteExtension,proto3,oneof" json:"verify_vote_extension,omitempty"` + VerifyVoteExtension *VerifyVoteExtensionResponse `protobuf:"bytes,20,opt,name=verify_vote_extension,json=verifyVoteExtension,proto3,oneof" json:"verify_vote_extension,omitempty"` } type Response_FinalizeBlock struct { - FinalizeBlock *ResponseFinalizeBlock `protobuf:"bytes,21,opt,name=finalize_block,json=finalizeBlock,proto3,oneof" json:"finalize_block,omitempty"` + FinalizeBlock *FinalizeBlockResponse `protobuf:"bytes,21,opt,name=finalize_block,json=finalizeBlock,proto3,oneof" json:"finalize_block,omitempty"` } func (*Response_Exception) isResponse_Value() {} @@ -1661,119 +1761,119 @@ func (m *Response) GetValue() isResponse_Value { return nil } -func (m *Response) GetException() *ResponseException { +func (m *Response) GetException() *ExceptionResponse { if x, ok := m.GetValue().(*Response_Exception); ok { return x.Exception } return nil } -func (m *Response) GetEcho() *ResponseEcho { +func (m *Response) GetEcho() *EchoResponse { if x, ok := m.GetValue().(*Response_Echo); ok { return x.Echo } return nil } -func (m *Response) GetFlush() *ResponseFlush { +func (m *Response) GetFlush() *FlushResponse { if x, ok := m.GetValue().(*Response_Flush); ok { return x.Flush } return nil } -func (m *Response) GetInfo() *ResponseInfo { +func (m *Response) GetInfo() *InfoResponse { if x, ok := m.GetValue().(*Response_Info); ok { return x.Info } return nil } -func (m *Response) GetInitChain() *ResponseInitChain { +func (m *Response) GetInitChain() *InitChainResponse { if x, ok := m.GetValue().(*Response_InitChain); ok { return x.InitChain } return nil } -func (m *Response) GetQuery() *ResponseQuery { +func (m *Response) GetQuery() *QueryResponse { if x, ok := m.GetValue().(*Response_Query); ok { return x.Query } return nil } -func (m *Response) GetCheckTx() *ResponseCheckTx { +func (m *Response) GetCheckTx() *CheckTxResponse { if x, ok := m.GetValue().(*Response_CheckTx); ok { return x.CheckTx } return nil } -func (m *Response) GetCommit() *ResponseCommit { +func (m *Response) GetCommit() *CommitResponse { if x, ok := m.GetValue().(*Response_Commit); ok { return x.Commit } return nil } -func (m *Response) GetListSnapshots() *ResponseListSnapshots { +func (m *Response) GetListSnapshots() *ListSnapshotsResponse { if x, ok := m.GetValue().(*Response_ListSnapshots); ok { return x.ListSnapshots } return nil } -func (m *Response) GetOfferSnapshot() *ResponseOfferSnapshot { +func (m *Response) GetOfferSnapshot() *OfferSnapshotResponse { if x, ok := m.GetValue().(*Response_OfferSnapshot); ok { return x.OfferSnapshot } return nil } -func (m *Response) GetLoadSnapshotChunk() *ResponseLoadSnapshotChunk { +func (m *Response) GetLoadSnapshotChunk() *LoadSnapshotChunkResponse { if x, ok := m.GetValue().(*Response_LoadSnapshotChunk); ok { return x.LoadSnapshotChunk } return nil } -func (m *Response) GetApplySnapshotChunk() *ResponseApplySnapshotChunk { +func (m *Response) GetApplySnapshotChunk() *ApplySnapshotChunkResponse { if x, ok := m.GetValue().(*Response_ApplySnapshotChunk); ok { return x.ApplySnapshotChunk } return nil } -func (m *Response) GetPrepareProposal() *ResponsePrepareProposal { +func (m *Response) GetPrepareProposal() *PrepareProposalResponse { if x, ok := m.GetValue().(*Response_PrepareProposal); ok { return x.PrepareProposal } return nil } -func (m *Response) GetProcessProposal() *ResponseProcessProposal { +func (m *Response) GetProcessProposal() *ProcessProposalResponse { if x, ok := m.GetValue().(*Response_ProcessProposal); ok { return x.ProcessProposal } return nil } -func (m *Response) GetExtendVote() *ResponseExtendVote { +func (m *Response) GetExtendVote() *ExtendVoteResponse { if x, ok := m.GetValue().(*Response_ExtendVote); ok { return x.ExtendVote } return nil } -func (m *Response) GetVerifyVoteExtension() *ResponseVerifyVoteExtension { +func (m *Response) GetVerifyVoteExtension() *VerifyVoteExtensionResponse { if x, ok := m.GetValue().(*Response_VerifyVoteExtension); ok { return x.VerifyVoteExtension } return nil } -func (m *Response) GetFinalizeBlock() *ResponseFinalizeBlock { +func (m *Response) GetFinalizeBlock() *FinalizeBlockResponse { if x, ok := m.GetValue().(*Response_FinalizeBlock); ok { return x.FinalizeBlock } @@ -1804,22 +1904,22 @@ func (*Response) XXX_OneofWrappers() []interface{} { } // nondeterministic -type ResponseException struct { +type ExceptionResponse struct { Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` } -func (m *ResponseException) Reset() { *m = ResponseException{} } -func (m *ResponseException) String() string { return proto.CompactTextString(m) } -func (*ResponseException) ProtoMessage() {} -func (*ResponseException) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{18} +func (m *ExceptionResponse) Reset() { *m = ExceptionResponse{} } +func (m *ExceptionResponse) String() string { return proto.CompactTextString(m) } +func (*ExceptionResponse) ProtoMessage() {} +func (*ExceptionResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{18} } -func (m *ResponseException) XXX_Unmarshal(b []byte) error { +func (m *ExceptionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseException) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ExceptionResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseException.Marshal(b, m, deterministic) + return xxx_messageInfo_ExceptionResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1829,41 +1929,42 @@ func (m *ResponseException) XXX_Marshal(b []byte, deterministic bool) ([]byte, e return b[:n], nil } } -func (m *ResponseException) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseException.Merge(m, src) +func (m *ExceptionResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExceptionResponse.Merge(m, src) } -func (m *ResponseException) XXX_Size() int { +func (m *ExceptionResponse) XXX_Size() int { return m.Size() } -func (m *ResponseException) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseException.DiscardUnknown(m) +func (m *ExceptionResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ExceptionResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseException proto.InternalMessageInfo +var xxx_messageInfo_ExceptionResponse proto.InternalMessageInfo -func (m *ResponseException) GetError() string { +func (m *ExceptionResponse) GetError() string { if m != nil { return m.Error } return "" } -type ResponseEcho struct { +// EchoResponse indicates that the connection is still alive. +type EchoResponse struct { Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` } -func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } -func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } -func (*ResponseEcho) ProtoMessage() {} -func (*ResponseEcho) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{19} +func (m *EchoResponse) Reset() { *m = EchoResponse{} } +func (m *EchoResponse) String() string { return proto.CompactTextString(m) } +func (*EchoResponse) ProtoMessage() {} +func (*EchoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{19} } -func (m *ResponseEcho) XXX_Unmarshal(b []byte) error { +func (m *EchoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseEcho) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *EchoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseEcho.Marshal(b, m, deterministic) + return xxx_messageInfo_EchoResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1873,40 +1974,41 @@ func (m *ResponseEcho) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *ResponseEcho) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseEcho.Merge(m, src) +func (m *EchoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_EchoResponse.Merge(m, src) } -func (m *ResponseEcho) XXX_Size() int { +func (m *EchoResponse) XXX_Size() int { return m.Size() } -func (m *ResponseEcho) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseEcho.DiscardUnknown(m) +func (m *EchoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_EchoResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseEcho proto.InternalMessageInfo +var xxx_messageInfo_EchoResponse proto.InternalMessageInfo -func (m *ResponseEcho) GetMessage() string { +func (m *EchoResponse) GetMessage() string { if m != nil { return m.Message } return "" } -type ResponseFlush struct { +// FlushResponse indicates that the write buffer was flushed. +type FlushResponse struct { } -func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } -func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } -func (*ResponseFlush) ProtoMessage() {} -func (*ResponseFlush) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{20} +func (m *FlushResponse) Reset() { *m = FlushResponse{} } +func (m *FlushResponse) String() string { return proto.CompactTextString(m) } +func (*FlushResponse) ProtoMessage() {} +func (*FlushResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{20} } -func (m *ResponseFlush) XXX_Unmarshal(b []byte) error { +func (m *FlushResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseFlush) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *FlushResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseFlush.Marshal(b, m, deterministic) + return xxx_messageInfo_FlushResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1916,19 +2018,20 @@ func (m *ResponseFlush) XXX_Marshal(b []byte, deterministic bool) ([]byte, error return b[:n], nil } } -func (m *ResponseFlush) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseFlush.Merge(m, src) +func (m *FlushResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_FlushResponse.Merge(m, src) } -func (m *ResponseFlush) XXX_Size() int { +func (m *FlushResponse) XXX_Size() int { return m.Size() } -func (m *ResponseFlush) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseFlush.DiscardUnknown(m) +func (m *FlushResponse) XXX_DiscardUnknown() { + xxx_messageInfo_FlushResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseFlush proto.InternalMessageInfo +var xxx_messageInfo_FlushResponse proto.InternalMessageInfo -type ResponseInfo struct { +// InfoResponse contains the ABCI application version information. +type InfoResponse struct { Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` AppVersion uint64 `protobuf:"varint,3,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` @@ -1936,18 +2039,18 @@ type ResponseInfo struct { LastBlockAppHash []byte `protobuf:"bytes,5,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"` } -func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } -func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } -func (*ResponseInfo) ProtoMessage() {} -func (*ResponseInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{21} +func (m *InfoResponse) Reset() { *m = InfoResponse{} } +func (m *InfoResponse) String() string { return proto.CompactTextString(m) } +func (*InfoResponse) ProtoMessage() {} +func (*InfoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{21} } -func (m *ResponseInfo) XXX_Unmarshal(b []byte) error { +func (m *InfoResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *InfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseInfo.Marshal(b, m, deterministic) + return xxx_messageInfo_InfoResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -1957,71 +2060,73 @@ func (m *ResponseInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } -func (m *ResponseInfo) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseInfo.Merge(m, src) +func (m *InfoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_InfoResponse.Merge(m, src) } -func (m *ResponseInfo) XXX_Size() int { +func (m *InfoResponse) XXX_Size() int { return m.Size() } -func (m *ResponseInfo) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseInfo.DiscardUnknown(m) +func (m *InfoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_InfoResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseInfo proto.InternalMessageInfo +var xxx_messageInfo_InfoResponse proto.InternalMessageInfo -func (m *ResponseInfo) GetData() string { +func (m *InfoResponse) GetData() string { if m != nil { return m.Data } return "" } -func (m *ResponseInfo) GetVersion() string { +func (m *InfoResponse) GetVersion() string { if m != nil { return m.Version } return "" } -func (m *ResponseInfo) GetAppVersion() uint64 { +func (m *InfoResponse) GetAppVersion() uint64 { if m != nil { return m.AppVersion } return 0 } -func (m *ResponseInfo) GetLastBlockHeight() int64 { +func (m *InfoResponse) GetLastBlockHeight() int64 { if m != nil { return m.LastBlockHeight } return 0 } -func (m *ResponseInfo) GetLastBlockAppHash() []byte { +func (m *InfoResponse) GetLastBlockAppHash() []byte { if m != nil { return m.LastBlockAppHash } return nil } -type ResponseInitChain struct { - ConsensusParams *types1.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` - Validators []ValidatorUpdate `protobuf:"bytes,2,rep,name=validators,proto3" json:"validators"` - AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +// InitChainResponse contains the ABCI application's hash and updates to the +// validator set and/or the consensus params, if any. +type InitChainResponse struct { + ConsensusParams *v1.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []ValidatorUpdate `protobuf:"bytes,2,rep,name=validators,proto3" json:"validators"` + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } -func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } -func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } -func (*ResponseInitChain) ProtoMessage() {} -func (*ResponseInitChain) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{22} +func (m *InitChainResponse) Reset() { *m = InitChainResponse{} } +func (m *InitChainResponse) String() string { return proto.CompactTextString(m) } +func (*InitChainResponse) ProtoMessage() {} +func (*InitChainResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{22} } -func (m *ResponseInitChain) XXX_Unmarshal(b []byte) error { +func (m *InitChainResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *InitChainResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseInitChain.Marshal(b, m, deterministic) + return xxx_messageInfo_InitChainResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2031,64 +2136,65 @@ func (m *ResponseInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, e return b[:n], nil } } -func (m *ResponseInitChain) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseInitChain.Merge(m, src) +func (m *InitChainResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_InitChainResponse.Merge(m, src) } -func (m *ResponseInitChain) XXX_Size() int { +func (m *InitChainResponse) XXX_Size() int { return m.Size() } -func (m *ResponseInitChain) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseInitChain.DiscardUnknown(m) +func (m *InitChainResponse) XXX_DiscardUnknown() { + xxx_messageInfo_InitChainResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseInitChain proto.InternalMessageInfo +var xxx_messageInfo_InitChainResponse proto.InternalMessageInfo -func (m *ResponseInitChain) GetConsensusParams() *types1.ConsensusParams { +func (m *InitChainResponse) GetConsensusParams() *v1.ConsensusParams { if m != nil { return m.ConsensusParams } return nil } -func (m *ResponseInitChain) GetValidators() []ValidatorUpdate { +func (m *InitChainResponse) GetValidators() []ValidatorUpdate { if m != nil { return m.Validators } return nil } -func (m *ResponseInitChain) GetAppHash() []byte { +func (m *InitChainResponse) GetAppHash() []byte { if m != nil { return m.AppHash } return nil } -type ResponseQuery struct { +// QueryResponse contains the ABCI application data along with a proof. +type QueryResponse struct { Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // bytes data = 2; // use "value" instead. - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` - Index int64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` - Key []byte `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"` - Value []byte `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"` - ProofOps *crypto.ProofOps `protobuf:"bytes,8,opt,name=proof_ops,json=proofOps,proto3" json:"proof_ops,omitempty"` - Height int64 `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"` - Codespace string `protobuf:"bytes,10,opt,name=codespace,proto3" json:"codespace,omitempty"` -} - -func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } -func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } -func (*ResponseQuery) ProtoMessage() {} -func (*ResponseQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{23} -} -func (m *ResponseQuery) XXX_Unmarshal(b []byte) error { + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + Index int64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` + Key []byte `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"` + ProofOps *v11.ProofOps `protobuf:"bytes,8,opt,name=proof_ops,json=proofOps,proto3" json:"proof_ops,omitempty"` + Height int64 `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"` + Codespace string `protobuf:"bytes,10,opt,name=codespace,proto3" json:"codespace,omitempty"` +} + +func (m *QueryResponse) Reset() { *m = QueryResponse{} } +func (m *QueryResponse) String() string { return proto.CompactTextString(m) } +func (*QueryResponse) ProtoMessage() {} +func (*QueryResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{23} +} +func (m *QueryResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *QueryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseQuery.Marshal(b, m, deterministic) + return xxx_messageInfo_QueryResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2098,82 +2204,84 @@ func (m *ResponseQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error return b[:n], nil } } -func (m *ResponseQuery) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseQuery.Merge(m, src) +func (m *QueryResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryResponse.Merge(m, src) } -func (m *ResponseQuery) XXX_Size() int { +func (m *QueryResponse) XXX_Size() int { return m.Size() } -func (m *ResponseQuery) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseQuery.DiscardUnknown(m) +func (m *QueryResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseQuery proto.InternalMessageInfo +var xxx_messageInfo_QueryResponse proto.InternalMessageInfo -func (m *ResponseQuery) GetCode() uint32 { +func (m *QueryResponse) GetCode() uint32 { if m != nil { return m.Code } return 0 } -func (m *ResponseQuery) GetLog() string { +func (m *QueryResponse) GetLog() string { if m != nil { return m.Log } return "" } -func (m *ResponseQuery) GetInfo() string { +func (m *QueryResponse) GetInfo() string { if m != nil { return m.Info } return "" } -func (m *ResponseQuery) GetIndex() int64 { +func (m *QueryResponse) GetIndex() int64 { if m != nil { return m.Index } return 0 } -func (m *ResponseQuery) GetKey() []byte { +func (m *QueryResponse) GetKey() []byte { if m != nil { return m.Key } return nil } -func (m *ResponseQuery) GetValue() []byte { +func (m *QueryResponse) GetValue() []byte { if m != nil { return m.Value } return nil } -func (m *ResponseQuery) GetProofOps() *crypto.ProofOps { +func (m *QueryResponse) GetProofOps() *v11.ProofOps { if m != nil { return m.ProofOps } return nil } -func (m *ResponseQuery) GetHeight() int64 { +func (m *QueryResponse) GetHeight() int64 { if m != nil { return m.Height } return 0 } -func (m *ResponseQuery) GetCodespace() string { +func (m *QueryResponse) GetCodespace() string { if m != nil { return m.Codespace } return "" } -type ResponseCheckTx struct { +// CheckTxResponse shows if the transaction was deemed valid by the ABCI +// application. +type CheckTxResponse struct { Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` @@ -2184,18 +2292,18 @@ type ResponseCheckTx struct { Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` } -func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } -func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } -func (*ResponseCheckTx) ProtoMessage() {} -func (*ResponseCheckTx) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{24} +func (m *CheckTxResponse) Reset() { *m = CheckTxResponse{} } +func (m *CheckTxResponse) String() string { return proto.CompactTextString(m) } +func (*CheckTxResponse) ProtoMessage() {} +func (*CheckTxResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{24} } -func (m *ResponseCheckTx) XXX_Unmarshal(b []byte) error { +func (m *CheckTxResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *CheckTxResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseCheckTx.Marshal(b, m, deterministic) + return xxx_messageInfo_CheckTxResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2205,90 +2313,91 @@ func (m *ResponseCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, err return b[:n], nil } } -func (m *ResponseCheckTx) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseCheckTx.Merge(m, src) +func (m *CheckTxResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CheckTxResponse.Merge(m, src) } -func (m *ResponseCheckTx) XXX_Size() int { +func (m *CheckTxResponse) XXX_Size() int { return m.Size() } -func (m *ResponseCheckTx) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseCheckTx.DiscardUnknown(m) +func (m *CheckTxResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CheckTxResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseCheckTx proto.InternalMessageInfo +var xxx_messageInfo_CheckTxResponse proto.InternalMessageInfo -func (m *ResponseCheckTx) GetCode() uint32 { +func (m *CheckTxResponse) GetCode() uint32 { if m != nil { return m.Code } return 0 } -func (m *ResponseCheckTx) GetData() []byte { +func (m *CheckTxResponse) GetData() []byte { if m != nil { return m.Data } return nil } -func (m *ResponseCheckTx) GetLog() string { +func (m *CheckTxResponse) GetLog() string { if m != nil { return m.Log } return "" } -func (m *ResponseCheckTx) GetInfo() string { +func (m *CheckTxResponse) GetInfo() string { if m != nil { return m.Info } return "" } -func (m *ResponseCheckTx) GetGasWanted() int64 { +func (m *CheckTxResponse) GetGasWanted() int64 { if m != nil { return m.GasWanted } return 0 } -func (m *ResponseCheckTx) GetGasUsed() int64 { +func (m *CheckTxResponse) GetGasUsed() int64 { if m != nil { return m.GasUsed } return 0 } -func (m *ResponseCheckTx) GetEvents() []Event { +func (m *CheckTxResponse) GetEvents() []Event { if m != nil { return m.Events } return nil } -func (m *ResponseCheckTx) GetCodespace() string { +func (m *CheckTxResponse) GetCodespace() string { if m != nil { return m.Codespace } return "" } -type ResponseCommit struct { +// CommitResponse indicates how much blocks should CometBFT retain. +type CommitResponse struct { RetainHeight int64 `protobuf:"varint,3,opt,name=retain_height,json=retainHeight,proto3" json:"retain_height,omitempty"` } -func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } -func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } -func (*ResponseCommit) ProtoMessage() {} -func (*ResponseCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{25} +func (m *CommitResponse) Reset() { *m = CommitResponse{} } +func (m *CommitResponse) String() string { return proto.CompactTextString(m) } +func (*CommitResponse) ProtoMessage() {} +func (*CommitResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{25} } -func (m *ResponseCommit) XXX_Unmarshal(b []byte) error { +func (m *CommitResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *CommitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseCommit.Marshal(b, m, deterministic) + return xxx_messageInfo_CommitResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2298,41 +2407,42 @@ func (m *ResponseCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, erro return b[:n], nil } } -func (m *ResponseCommit) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseCommit.Merge(m, src) +func (m *CommitResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommitResponse.Merge(m, src) } -func (m *ResponseCommit) XXX_Size() int { +func (m *CommitResponse) XXX_Size() int { return m.Size() } -func (m *ResponseCommit) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseCommit.DiscardUnknown(m) +func (m *CommitResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CommitResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseCommit proto.InternalMessageInfo +var xxx_messageInfo_CommitResponse proto.InternalMessageInfo -func (m *ResponseCommit) GetRetainHeight() int64 { +func (m *CommitResponse) GetRetainHeight() int64 { if m != nil { return m.RetainHeight } return 0 } -type ResponseListSnapshots struct { +// ListSnapshotsResponse contains the list of snapshots. +type ListSnapshotsResponse struct { Snapshots []*Snapshot `protobuf:"bytes,1,rep,name=snapshots,proto3" json:"snapshots,omitempty"` } -func (m *ResponseListSnapshots) Reset() { *m = ResponseListSnapshots{} } -func (m *ResponseListSnapshots) String() string { return proto.CompactTextString(m) } -func (*ResponseListSnapshots) ProtoMessage() {} -func (*ResponseListSnapshots) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{26} +func (m *ListSnapshotsResponse) Reset() { *m = ListSnapshotsResponse{} } +func (m *ListSnapshotsResponse) String() string { return proto.CompactTextString(m) } +func (*ListSnapshotsResponse) ProtoMessage() {} +func (*ListSnapshotsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{26} } -func (m *ResponseListSnapshots) XXX_Unmarshal(b []byte) error { +func (m *ListSnapshotsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseListSnapshots) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ListSnapshotsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseListSnapshots.Marshal(b, m, deterministic) + return xxx_messageInfo_ListSnapshotsResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2342,41 +2452,43 @@ func (m *ResponseListSnapshots) XXX_Marshal(b []byte, deterministic bool) ([]byt return b[:n], nil } } -func (m *ResponseListSnapshots) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseListSnapshots.Merge(m, src) +func (m *ListSnapshotsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ListSnapshotsResponse.Merge(m, src) } -func (m *ResponseListSnapshots) XXX_Size() int { +func (m *ListSnapshotsResponse) XXX_Size() int { return m.Size() } -func (m *ResponseListSnapshots) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseListSnapshots.DiscardUnknown(m) +func (m *ListSnapshotsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ListSnapshotsResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseListSnapshots proto.InternalMessageInfo +var xxx_messageInfo_ListSnapshotsResponse proto.InternalMessageInfo -func (m *ResponseListSnapshots) GetSnapshots() []*Snapshot { +func (m *ListSnapshotsResponse) GetSnapshots() []*Snapshot { if m != nil { return m.Snapshots } return nil } -type ResponseOfferSnapshot struct { - Result ResponseOfferSnapshot_Result `protobuf:"varint,1,opt,name=result,proto3,enum=tendermint.abci.ResponseOfferSnapshot_Result" json:"result,omitempty"` +// OfferSnapshotResponse indicates the ABCI application decision whenever to +// provide a snapshot to the requester or not. +type OfferSnapshotResponse struct { + Result OfferSnapshotResult `protobuf:"varint,1,opt,name=result,proto3,enum=cometbft.abci.v1.OfferSnapshotResult" json:"result,omitempty"` } -func (m *ResponseOfferSnapshot) Reset() { *m = ResponseOfferSnapshot{} } -func (m *ResponseOfferSnapshot) String() string { return proto.CompactTextString(m) } -func (*ResponseOfferSnapshot) ProtoMessage() {} -func (*ResponseOfferSnapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{27} +func (m *OfferSnapshotResponse) Reset() { *m = OfferSnapshotResponse{} } +func (m *OfferSnapshotResponse) String() string { return proto.CompactTextString(m) } +func (*OfferSnapshotResponse) ProtoMessage() {} +func (*OfferSnapshotResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{27} } -func (m *ResponseOfferSnapshot) XXX_Unmarshal(b []byte) error { +func (m *OfferSnapshotResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseOfferSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *OfferSnapshotResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseOfferSnapshot.Marshal(b, m, deterministic) + return xxx_messageInfo_OfferSnapshotResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2386,41 +2498,42 @@ func (m *ResponseOfferSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]byt return b[:n], nil } } -func (m *ResponseOfferSnapshot) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseOfferSnapshot.Merge(m, src) +func (m *OfferSnapshotResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_OfferSnapshotResponse.Merge(m, src) } -func (m *ResponseOfferSnapshot) XXX_Size() int { +func (m *OfferSnapshotResponse) XXX_Size() int { return m.Size() } -func (m *ResponseOfferSnapshot) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseOfferSnapshot.DiscardUnknown(m) +func (m *OfferSnapshotResponse) XXX_DiscardUnknown() { + xxx_messageInfo_OfferSnapshotResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseOfferSnapshot proto.InternalMessageInfo +var xxx_messageInfo_OfferSnapshotResponse proto.InternalMessageInfo -func (m *ResponseOfferSnapshot) GetResult() ResponseOfferSnapshot_Result { +func (m *OfferSnapshotResponse) GetResult() OfferSnapshotResult { if m != nil { return m.Result } - return ResponseOfferSnapshot_UNKNOWN + return OFFER_SNAPSHOT_RESULT_UNKNOWN } -type ResponseLoadSnapshotChunk struct { +// LoadSnapshotChunkResponse returns a snapshot's chunk. +type LoadSnapshotChunkResponse struct { Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"` } -func (m *ResponseLoadSnapshotChunk) Reset() { *m = ResponseLoadSnapshotChunk{} } -func (m *ResponseLoadSnapshotChunk) String() string { return proto.CompactTextString(m) } -func (*ResponseLoadSnapshotChunk) ProtoMessage() {} -func (*ResponseLoadSnapshotChunk) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{28} +func (m *LoadSnapshotChunkResponse) Reset() { *m = LoadSnapshotChunkResponse{} } +func (m *LoadSnapshotChunkResponse) String() string { return proto.CompactTextString(m) } +func (*LoadSnapshotChunkResponse) ProtoMessage() {} +func (*LoadSnapshotChunkResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{28} } -func (m *ResponseLoadSnapshotChunk) XXX_Unmarshal(b []byte) error { +func (m *LoadSnapshotChunkResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseLoadSnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *LoadSnapshotChunkResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseLoadSnapshotChunk.Marshal(b, m, deterministic) + return xxx_messageInfo_LoadSnapshotChunkResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2430,43 +2543,44 @@ func (m *ResponseLoadSnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([ return b[:n], nil } } -func (m *ResponseLoadSnapshotChunk) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseLoadSnapshotChunk.Merge(m, src) +func (m *LoadSnapshotChunkResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_LoadSnapshotChunkResponse.Merge(m, src) } -func (m *ResponseLoadSnapshotChunk) XXX_Size() int { +func (m *LoadSnapshotChunkResponse) XXX_Size() int { return m.Size() } -func (m *ResponseLoadSnapshotChunk) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseLoadSnapshotChunk.DiscardUnknown(m) +func (m *LoadSnapshotChunkResponse) XXX_DiscardUnknown() { + xxx_messageInfo_LoadSnapshotChunkResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseLoadSnapshotChunk proto.InternalMessageInfo +var xxx_messageInfo_LoadSnapshotChunkResponse proto.InternalMessageInfo -func (m *ResponseLoadSnapshotChunk) GetChunk() []byte { +func (m *LoadSnapshotChunkResponse) GetChunk() []byte { if m != nil { return m.Chunk } return nil } -type ResponseApplySnapshotChunk struct { - Result ResponseApplySnapshotChunk_Result `protobuf:"varint,1,opt,name=result,proto3,enum=tendermint.abci.ResponseApplySnapshotChunk_Result" json:"result,omitempty"` - RefetchChunks []uint32 `protobuf:"varint,2,rep,packed,name=refetch_chunks,json=refetchChunks,proto3" json:"refetch_chunks,omitempty"` - RejectSenders []string `protobuf:"bytes,3,rep,name=reject_senders,json=rejectSenders,proto3" json:"reject_senders,omitempty"` +// ApplySnapshotChunkResponse returns a result of applying the specified chunk. +type ApplySnapshotChunkResponse struct { + Result ApplySnapshotChunkResult `protobuf:"varint,1,opt,name=result,proto3,enum=cometbft.abci.v1.ApplySnapshotChunkResult" json:"result,omitempty"` + RefetchChunks []uint32 `protobuf:"varint,2,rep,packed,name=refetch_chunks,json=refetchChunks,proto3" json:"refetch_chunks,omitempty"` + RejectSenders []string `protobuf:"bytes,3,rep,name=reject_senders,json=rejectSenders,proto3" json:"reject_senders,omitempty"` } -func (m *ResponseApplySnapshotChunk) Reset() { *m = ResponseApplySnapshotChunk{} } -func (m *ResponseApplySnapshotChunk) String() string { return proto.CompactTextString(m) } -func (*ResponseApplySnapshotChunk) ProtoMessage() {} -func (*ResponseApplySnapshotChunk) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{29} +func (m *ApplySnapshotChunkResponse) Reset() { *m = ApplySnapshotChunkResponse{} } +func (m *ApplySnapshotChunkResponse) String() string { return proto.CompactTextString(m) } +func (*ApplySnapshotChunkResponse) ProtoMessage() {} +func (*ApplySnapshotChunkResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{29} } -func (m *ResponseApplySnapshotChunk) XXX_Unmarshal(b []byte) error { +func (m *ApplySnapshotChunkResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseApplySnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ApplySnapshotChunkResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseApplySnapshotChunk.Marshal(b, m, deterministic) + return xxx_messageInfo_ApplySnapshotChunkResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2476,55 +2590,56 @@ func (m *ResponseApplySnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ( return b[:n], nil } } -func (m *ResponseApplySnapshotChunk) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseApplySnapshotChunk.Merge(m, src) +func (m *ApplySnapshotChunkResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ApplySnapshotChunkResponse.Merge(m, src) } -func (m *ResponseApplySnapshotChunk) XXX_Size() int { +func (m *ApplySnapshotChunkResponse) XXX_Size() int { return m.Size() } -func (m *ResponseApplySnapshotChunk) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseApplySnapshotChunk.DiscardUnknown(m) +func (m *ApplySnapshotChunkResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ApplySnapshotChunkResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseApplySnapshotChunk proto.InternalMessageInfo +var xxx_messageInfo_ApplySnapshotChunkResponse proto.InternalMessageInfo -func (m *ResponseApplySnapshotChunk) GetResult() ResponseApplySnapshotChunk_Result { +func (m *ApplySnapshotChunkResponse) GetResult() ApplySnapshotChunkResult { if m != nil { return m.Result } - return ResponseApplySnapshotChunk_UNKNOWN + return APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN } -func (m *ResponseApplySnapshotChunk) GetRefetchChunks() []uint32 { +func (m *ApplySnapshotChunkResponse) GetRefetchChunks() []uint32 { if m != nil { return m.RefetchChunks } return nil } -func (m *ResponseApplySnapshotChunk) GetRejectSenders() []string { +func (m *ApplySnapshotChunkResponse) GetRejectSenders() []string { if m != nil { return m.RejectSenders } return nil } -type ResponsePrepareProposal struct { +// PrepareProposalResponse contains a list of transactions, which will form a block. +type PrepareProposalResponse struct { Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` } -func (m *ResponsePrepareProposal) Reset() { *m = ResponsePrepareProposal{} } -func (m *ResponsePrepareProposal) String() string { return proto.CompactTextString(m) } -func (*ResponsePrepareProposal) ProtoMessage() {} -func (*ResponsePrepareProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{30} +func (m *PrepareProposalResponse) Reset() { *m = PrepareProposalResponse{} } +func (m *PrepareProposalResponse) String() string { return proto.CompactTextString(m) } +func (*PrepareProposalResponse) ProtoMessage() {} +func (*PrepareProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{30} } -func (m *ResponsePrepareProposal) XXX_Unmarshal(b []byte) error { +func (m *PrepareProposalResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponsePrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *PrepareProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponsePrepareProposal.Marshal(b, m, deterministic) + return xxx_messageInfo_PrepareProposalResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2534,41 +2649,43 @@ func (m *ResponsePrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]b return b[:n], nil } } -func (m *ResponsePrepareProposal) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponsePrepareProposal.Merge(m, src) +func (m *PrepareProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PrepareProposalResponse.Merge(m, src) } -func (m *ResponsePrepareProposal) XXX_Size() int { +func (m *PrepareProposalResponse) XXX_Size() int { return m.Size() } -func (m *ResponsePrepareProposal) XXX_DiscardUnknown() { - xxx_messageInfo_ResponsePrepareProposal.DiscardUnknown(m) +func (m *PrepareProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PrepareProposalResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponsePrepareProposal proto.InternalMessageInfo +var xxx_messageInfo_PrepareProposalResponse proto.InternalMessageInfo -func (m *ResponsePrepareProposal) GetTxs() [][]byte { +func (m *PrepareProposalResponse) GetTxs() [][]byte { if m != nil { return m.Txs } return nil } -type ResponseProcessProposal struct { - Status ResponseProcessProposal_ProposalStatus `protobuf:"varint,1,opt,name=status,proto3,enum=tendermint.abci.ResponseProcessProposal_ProposalStatus" json:"status,omitempty"` +// ProcessProposalResponse indicates the ABCI application's decision whenever +// the given proposal should be accepted or not. +type ProcessProposalResponse struct { + Status ProcessProposalStatus `protobuf:"varint,1,opt,name=status,proto3,enum=cometbft.abci.v1.ProcessProposalStatus" json:"status,omitempty"` } -func (m *ResponseProcessProposal) Reset() { *m = ResponseProcessProposal{} } -func (m *ResponseProcessProposal) String() string { return proto.CompactTextString(m) } -func (*ResponseProcessProposal) ProtoMessage() {} -func (*ResponseProcessProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{31} +func (m *ProcessProposalResponse) Reset() { *m = ProcessProposalResponse{} } +func (m *ProcessProposalResponse) String() string { return proto.CompactTextString(m) } +func (*ProcessProposalResponse) ProtoMessage() {} +func (*ProcessProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{31} } -func (m *ResponseProcessProposal) XXX_Unmarshal(b []byte) error { +func (m *ProcessProposalResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ProcessProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseProcessProposal.Marshal(b, m, deterministic) + return xxx_messageInfo_ProcessProposalResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2578,41 +2695,43 @@ func (m *ResponseProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]b return b[:n], nil } } -func (m *ResponseProcessProposal) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseProcessProposal.Merge(m, src) +func (m *ProcessProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProcessProposalResponse.Merge(m, src) } -func (m *ResponseProcessProposal) XXX_Size() int { +func (m *ProcessProposalResponse) XXX_Size() int { return m.Size() } -func (m *ResponseProcessProposal) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseProcessProposal.DiscardUnknown(m) +func (m *ProcessProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ProcessProposalResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseProcessProposal proto.InternalMessageInfo +var xxx_messageInfo_ProcessProposalResponse proto.InternalMessageInfo -func (m *ResponseProcessProposal) GetStatus() ResponseProcessProposal_ProposalStatus { +func (m *ProcessProposalResponse) GetStatus() ProcessProposalStatus { if m != nil { return m.Status } - return ResponseProcessProposal_UNKNOWN + return PROCESS_PROPOSAL_STATUS_UNKNOWN } -type ResponseExtendVote struct { +// ExtendVoteResponse contains the vote extension that the application would like to +// attach to its next precommit vote. +type ExtendVoteResponse struct { VoteExtension []byte `protobuf:"bytes,1,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` } -func (m *ResponseExtendVote) Reset() { *m = ResponseExtendVote{} } -func (m *ResponseExtendVote) String() string { return proto.CompactTextString(m) } -func (*ResponseExtendVote) ProtoMessage() {} -func (*ResponseExtendVote) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{32} +func (m *ExtendVoteResponse) Reset() { *m = ExtendVoteResponse{} } +func (m *ExtendVoteResponse) String() string { return proto.CompactTextString(m) } +func (*ExtendVoteResponse) ProtoMessage() {} +func (*ExtendVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{32} } -func (m *ResponseExtendVote) XXX_Unmarshal(b []byte) error { +func (m *ExtendVoteResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseExtendVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *ExtendVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseExtendVote.Marshal(b, m, deterministic) + return xxx_messageInfo_ExtendVoteResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2622,41 +2741,43 @@ func (m *ResponseExtendVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, return b[:n], nil } } -func (m *ResponseExtendVote) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseExtendVote.Merge(m, src) +func (m *ExtendVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendVoteResponse.Merge(m, src) } -func (m *ResponseExtendVote) XXX_Size() int { +func (m *ExtendVoteResponse) XXX_Size() int { return m.Size() } -func (m *ResponseExtendVote) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseExtendVote.DiscardUnknown(m) +func (m *ExtendVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendVoteResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseExtendVote proto.InternalMessageInfo +var xxx_messageInfo_ExtendVoteResponse proto.InternalMessageInfo -func (m *ResponseExtendVote) GetVoteExtension() []byte { +func (m *ExtendVoteResponse) GetVoteExtension() []byte { if m != nil { return m.VoteExtension } return nil } -type ResponseVerifyVoteExtension struct { - Status ResponseVerifyVoteExtension_VerifyStatus `protobuf:"varint,1,opt,name=status,proto3,enum=tendermint.abci.ResponseVerifyVoteExtension_VerifyStatus" json:"status,omitempty"` +// VerifyVoteExtensionResponse indicates the ABCI application's decision +// whenever the vote extension should be accepted or not. +type VerifyVoteExtensionResponse struct { + Status VerifyVoteExtensionStatus `protobuf:"varint,1,opt,name=status,proto3,enum=cometbft.abci.v1.VerifyVoteExtensionStatus" json:"status,omitempty"` } -func (m *ResponseVerifyVoteExtension) Reset() { *m = ResponseVerifyVoteExtension{} } -func (m *ResponseVerifyVoteExtension) String() string { return proto.CompactTextString(m) } -func (*ResponseVerifyVoteExtension) ProtoMessage() {} -func (*ResponseVerifyVoteExtension) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{33} +func (m *VerifyVoteExtensionResponse) Reset() { *m = VerifyVoteExtensionResponse{} } +func (m *VerifyVoteExtensionResponse) String() string { return proto.CompactTextString(m) } +func (*VerifyVoteExtensionResponse) ProtoMessage() {} +func (*VerifyVoteExtensionResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{33} } -func (m *ResponseVerifyVoteExtension) XXX_Unmarshal(b []byte) error { +func (m *VerifyVoteExtensionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseVerifyVoteExtension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *VerifyVoteExtensionResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseVerifyVoteExtension.Marshal(b, m, deterministic) + return xxx_messageInfo_VerifyVoteExtensionResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2666,52 +2787,55 @@ func (m *ResponseVerifyVoteExtension) XXX_Marshal(b []byte, deterministic bool) return b[:n], nil } } -func (m *ResponseVerifyVoteExtension) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseVerifyVoteExtension.Merge(m, src) +func (m *VerifyVoteExtensionResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_VerifyVoteExtensionResponse.Merge(m, src) } -func (m *ResponseVerifyVoteExtension) XXX_Size() int { +func (m *VerifyVoteExtensionResponse) XXX_Size() int { return m.Size() } -func (m *ResponseVerifyVoteExtension) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseVerifyVoteExtension.DiscardUnknown(m) +func (m *VerifyVoteExtensionResponse) XXX_DiscardUnknown() { + xxx_messageInfo_VerifyVoteExtensionResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseVerifyVoteExtension proto.InternalMessageInfo +var xxx_messageInfo_VerifyVoteExtensionResponse proto.InternalMessageInfo -func (m *ResponseVerifyVoteExtension) GetStatus() ResponseVerifyVoteExtension_VerifyStatus { +func (m *VerifyVoteExtensionResponse) GetStatus() VerifyVoteExtensionStatus { if m != nil { return m.Status } - return ResponseVerifyVoteExtension_UNKNOWN + return VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN } -type ResponseFinalizeBlock struct { - // set of block events emmitted as part of executing the block +// FinalizeBlockResponse contains the result of executing the block. +type FinalizeBlockResponse struct { + // set of block events emitted as part of executing the block Events []Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` // the result of executing each transaction including the events - // the particular transction emitted. This should match the order + // the particular transaction emitted. This should match the order // of the transactions delivered in the block itself TxResults []*ExecTxResult `protobuf:"bytes,2,rep,name=tx_results,json=txResults,proto3" json:"tx_results,omitempty"` // a list of updates to the validator set. These will reflect the validator set at current height + 2. ValidatorUpdates []ValidatorUpdate `protobuf:"bytes,3,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` // updates to the consensus params, if any. - ConsensusParamUpdates *types1.ConsensusParams `protobuf:"bytes,4,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` - // app_hash is the hash of the applications' state which is used to confirm that execution of the transactions was deterministic. It is up to the application to decide which algorithm to use. + ConsensusParamUpdates *v1.ConsensusParams `protobuf:"bytes,4,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` + // app_hash is the hash of the applications' state which is used to confirm + // that execution of the transactions was deterministic. + // It is up to the application to decide which algorithm to use. AppHash []byte `protobuf:"bytes,5,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` } -func (m *ResponseFinalizeBlock) Reset() { *m = ResponseFinalizeBlock{} } -func (m *ResponseFinalizeBlock) String() string { return proto.CompactTextString(m) } -func (*ResponseFinalizeBlock) ProtoMessage() {} -func (*ResponseFinalizeBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{34} +func (m *FinalizeBlockResponse) Reset() { *m = FinalizeBlockResponse{} } +func (m *FinalizeBlockResponse) String() string { return proto.CompactTextString(m) } +func (*FinalizeBlockResponse) ProtoMessage() {} +func (*FinalizeBlockResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_95dd8f7b670b96e3, []int{34} } -func (m *ResponseFinalizeBlock) XXX_Unmarshal(b []byte) error { +func (m *FinalizeBlockResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *ResponseFinalizeBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *FinalizeBlockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_ResponseFinalizeBlock.Marshal(b, m, deterministic) + return xxx_messageInfo_FinalizeBlockResponse.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -2721,53 +2845,54 @@ func (m *ResponseFinalizeBlock) XXX_Marshal(b []byte, deterministic bool) ([]byt return b[:n], nil } } -func (m *ResponseFinalizeBlock) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseFinalizeBlock.Merge(m, src) +func (m *FinalizeBlockResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_FinalizeBlockResponse.Merge(m, src) } -func (m *ResponseFinalizeBlock) XXX_Size() int { +func (m *FinalizeBlockResponse) XXX_Size() int { return m.Size() } -func (m *ResponseFinalizeBlock) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseFinalizeBlock.DiscardUnknown(m) +func (m *FinalizeBlockResponse) XXX_DiscardUnknown() { + xxx_messageInfo_FinalizeBlockResponse.DiscardUnknown(m) } -var xxx_messageInfo_ResponseFinalizeBlock proto.InternalMessageInfo +var xxx_messageInfo_FinalizeBlockResponse proto.InternalMessageInfo -func (m *ResponseFinalizeBlock) GetEvents() []Event { +func (m *FinalizeBlockResponse) GetEvents() []Event { if m != nil { return m.Events } return nil } -func (m *ResponseFinalizeBlock) GetTxResults() []*ExecTxResult { +func (m *FinalizeBlockResponse) GetTxResults() []*ExecTxResult { if m != nil { return m.TxResults } return nil } -func (m *ResponseFinalizeBlock) GetValidatorUpdates() []ValidatorUpdate { +func (m *FinalizeBlockResponse) GetValidatorUpdates() []ValidatorUpdate { if m != nil { return m.ValidatorUpdates } return nil } -func (m *ResponseFinalizeBlock) GetConsensusParamUpdates() *types1.ConsensusParams { +func (m *FinalizeBlockResponse) GetConsensusParamUpdates() *v1.ConsensusParams { if m != nil { return m.ConsensusParamUpdates } return nil } -func (m *ResponseFinalizeBlock) GetAppHash() []byte { +func (m *FinalizeBlockResponse) GetAppHash() []byte { if m != nil { return m.AppHash } return nil } +// CommitInfo contains votes for the particular round. type CommitInfo struct { Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` Votes []VoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` @@ -2777,7 +2902,7 @@ func (m *CommitInfo) Reset() { *m = CommitInfo{} } func (m *CommitInfo) String() string { return proto.CompactTextString(m) } func (*CommitInfo) ProtoMessage() {} func (*CommitInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{35} + return fileDescriptor_95dd8f7b670b96e3, []int{35} } func (m *CommitInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2821,7 +2946,7 @@ func (m *CommitInfo) GetVotes() []VoteInfo { } // ExtendedCommitInfo is similar to CommitInfo except that it is only used in -// the PrepareProposal request such that CometBFT can provide vote extensions +// the PrepareProposal request such that Tendermint can provide vote extensions // to the application. type ExtendedCommitInfo struct { // The round at which the block proposer decided in the previous height. @@ -2835,7 +2960,7 @@ func (m *ExtendedCommitInfo) Reset() { *m = ExtendedCommitInfo{} } func (m *ExtendedCommitInfo) String() string { return proto.CompactTextString(m) } func (*ExtendedCommitInfo) ProtoMessage() {} func (*ExtendedCommitInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{36} + return fileDescriptor_95dd8f7b670b96e3, []int{36} } func (m *ExtendedCommitInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2880,6 +3005,8 @@ func (m *ExtendedCommitInfo) GetVotes() []ExtendedVoteInfo { // Event allows application developers to attach additional information to // ResponseFinalizeBlock and ResponseCheckTx. +// Up to 0.37, this could also be used in ResponseBeginBlock, ResponseEndBlock, +// and ResponseDeliverTx. // Later, transactions may be queried using these events. type Event struct { Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` @@ -2890,7 +3017,7 @@ func (m *Event) Reset() { *m = Event{} } func (m *Event) String() string { return proto.CompactTextString(m) } func (*Event) ProtoMessage() {} func (*Event) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{37} + return fileDescriptor_95dd8f7b670b96e3, []int{37} } func (m *Event) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2944,7 +3071,7 @@ func (m *EventAttribute) Reset() { *m = EventAttribute{} } func (m *EventAttribute) String() string { return proto.CompactTextString(m) } func (*EventAttribute) ProtoMessage() {} func (*EventAttribute) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{38} + return fileDescriptor_95dd8f7b670b96e3, []int{38} } func (m *EventAttribute) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3002,8 +3129,8 @@ type ExecTxResult struct { Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` - GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"` - GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` } @@ -3012,7 +3139,7 @@ func (m *ExecTxResult) Reset() { *m = ExecTxResult{} } func (m *ExecTxResult) String() string { return proto.CompactTextString(m) } func (*ExecTxResult) ProtoMessage() {} func (*ExecTxResult) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{39} + return fileDescriptor_95dd8f7b670b96e3, []int{39} } func (m *ExecTxResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3111,7 +3238,7 @@ func (m *TxResult) Reset() { *m = TxResult{} } func (m *TxResult) String() string { return proto.CompactTextString(m) } func (*TxResult) ProtoMessage() {} func (*TxResult) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{40} + return fileDescriptor_95dd8f7b670b96e3, []int{40} } func (m *TxResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3168,6 +3295,7 @@ func (m *TxResult) GetResult() ExecTxResult { return ExecTxResult{} } +// Validator in the validator set. type Validator struct { Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` // PubKey pub_key = 2 [(gogoproto.nullable)=false]; @@ -3178,7 +3306,7 @@ func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} func (*Validator) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{41} + return fileDescriptor_95dd8f7b670b96e3, []int{41} } func (m *Validator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3221,16 +3349,17 @@ func (m *Validator) GetPower() int64 { return 0 } +// ValidatorUpdate is a singular update to a validator set. type ValidatorUpdate struct { - PubKey crypto.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` - Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"` + PubKey v11.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"` } func (m *ValidatorUpdate) Reset() { *m = ValidatorUpdate{} } func (m *ValidatorUpdate) String() string { return proto.CompactTextString(m) } func (*ValidatorUpdate) ProtoMessage() {} func (*ValidatorUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{42} + return fileDescriptor_95dd8f7b670b96e3, []int{42} } func (m *ValidatorUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3259,11 +3388,11 @@ func (m *ValidatorUpdate) XXX_DiscardUnknown() { var xxx_messageInfo_ValidatorUpdate proto.InternalMessageInfo -func (m *ValidatorUpdate) GetPubKey() crypto.PublicKey { +func (m *ValidatorUpdate) GetPubKey() v11.PublicKey { if m != nil { return m.PubKey } - return crypto.PublicKey{} + return v11.PublicKey{} } func (m *ValidatorUpdate) GetPower() int64 { @@ -3273,16 +3402,17 @@ func (m *ValidatorUpdate) GetPower() int64 { return 0 } +// VoteInfo contains the information about the vote. type VoteInfo struct { - Validator Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` - BlockIdFlag types1.BlockIDFlag `protobuf:"varint,3,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=tendermint.types.BlockIDFlag" json:"block_id_flag,omitempty"` + Validator Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` + BlockIdFlag v1.BlockIDFlag `protobuf:"varint,3,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=cometbft.types.v1.BlockIDFlag" json:"block_id_flag,omitempty"` } func (m *VoteInfo) Reset() { *m = VoteInfo{} } func (m *VoteInfo) String() string { return proto.CompactTextString(m) } func (*VoteInfo) ProtoMessage() {} func (*VoteInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{43} + return fileDescriptor_95dd8f7b670b96e3, []int{43} } func (m *VoteInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3318,13 +3448,14 @@ func (m *VoteInfo) GetValidator() Validator { return Validator{} } -func (m *VoteInfo) GetBlockIdFlag() types1.BlockIDFlag { +func (m *VoteInfo) GetBlockIdFlag() v1.BlockIDFlag { if m != nil { return m.BlockIdFlag } - return types1.BlockIDFlagUnknown + return v1.BlockIDFlagUnknown } +// ExtendedVoteInfo extends VoteInfo with the vote extensions (non-deterministic). type ExtendedVoteInfo struct { // The validator that sent the vote. Validator Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` @@ -3333,14 +3464,14 @@ type ExtendedVoteInfo struct { // Vote extension signature created by CometBFT ExtensionSignature []byte `protobuf:"bytes,4,opt,name=extension_signature,json=extensionSignature,proto3" json:"extension_signature,omitempty"` // block_id_flag indicates whether the validator voted for a block, nil, or did not vote at all - BlockIdFlag types1.BlockIDFlag `protobuf:"varint,5,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=tendermint.types.BlockIDFlag" json:"block_id_flag,omitempty"` + BlockIdFlag v1.BlockIDFlag `protobuf:"varint,5,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=cometbft.types.v1.BlockIDFlag" json:"block_id_flag,omitempty"` } func (m *ExtendedVoteInfo) Reset() { *m = ExtendedVoteInfo{} } func (m *ExtendedVoteInfo) String() string { return proto.CompactTextString(m) } func (*ExtendedVoteInfo) ProtoMessage() {} func (*ExtendedVoteInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{44} + return fileDescriptor_95dd8f7b670b96e3, []int{44} } func (m *ExtendedVoteInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3390,15 +3521,16 @@ func (m *ExtendedVoteInfo) GetExtensionSignature() []byte { return nil } -func (m *ExtendedVoteInfo) GetBlockIdFlag() types1.BlockIDFlag { +func (m *ExtendedVoteInfo) GetBlockIdFlag() v1.BlockIDFlag { if m != nil { return m.BlockIdFlag } - return types1.BlockIDFlagUnknown + return v1.BlockIDFlagUnknown } +// Misbehavior is a type of misbehavior committed by a validator. type Misbehavior struct { - Type MisbehaviorType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.abci.MisbehaviorType" json:"type,omitempty"` + Type MisbehaviorType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.abci.v1.MisbehaviorType" json:"type,omitempty"` // The offending validator Validator Validator `protobuf:"bytes,2,opt,name=validator,proto3" json:"validator"` // The height when the offense occurred @@ -3415,7 +3547,7 @@ func (m *Misbehavior) Reset() { *m = Misbehavior{} } func (m *Misbehavior) String() string { return proto.CompactTextString(m) } func (*Misbehavior) ProtoMessage() {} func (*Misbehavior) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{45} + return fileDescriptor_95dd8f7b670b96e3, []int{45} } func (m *Misbehavior) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3448,7 +3580,7 @@ func (m *Misbehavior) GetType() MisbehaviorType { if m != nil { return m.Type } - return MisbehaviorType_UNKNOWN + return MISBEHAVIOR_TYPE_UNKNOWN } func (m *Misbehavior) GetValidator() Validator { @@ -3479,6 +3611,7 @@ func (m *Misbehavior) GetTotalVotingPower() int64 { return 0 } +// Snapshot of the ABCI application state. type Snapshot struct { Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Format uint32 `protobuf:"varint,2,opt,name=format,proto3" json:"format,omitempty"` @@ -3491,7 +3624,7 @@ func (m *Snapshot) Reset() { *m = Snapshot{} } func (m *Snapshot) String() string { return proto.CompactTextString(m) } func (*Snapshot) ProtoMessage() {} func (*Snapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_252557cfdd89a31a, []int{46} + return fileDescriptor_95dd8f7b670b96e3, []int{46} } func (m *Snapshot) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3556,883 +3689,262 @@ func (m *Snapshot) GetMetadata() []byte { } func init() { - proto.RegisterEnum("tendermint.abci.CheckTxType", CheckTxType_name, CheckTxType_value) - proto.RegisterEnum("tendermint.abci.MisbehaviorType", MisbehaviorType_name, MisbehaviorType_value) - proto.RegisterEnum("tendermint.abci.ResponseOfferSnapshot_Result", ResponseOfferSnapshot_Result_name, ResponseOfferSnapshot_Result_value) - proto.RegisterEnum("tendermint.abci.ResponseApplySnapshotChunk_Result", ResponseApplySnapshotChunk_Result_name, ResponseApplySnapshotChunk_Result_value) - proto.RegisterEnum("tendermint.abci.ResponseProcessProposal_ProposalStatus", ResponseProcessProposal_ProposalStatus_name, ResponseProcessProposal_ProposalStatus_value) - proto.RegisterEnum("tendermint.abci.ResponseVerifyVoteExtension_VerifyStatus", ResponseVerifyVoteExtension_VerifyStatus_name, ResponseVerifyVoteExtension_VerifyStatus_value) - proto.RegisterType((*Request)(nil), "tendermint.abci.Request") - proto.RegisterType((*RequestEcho)(nil), "tendermint.abci.RequestEcho") - proto.RegisterType((*RequestFlush)(nil), "tendermint.abci.RequestFlush") - proto.RegisterType((*RequestInfo)(nil), "tendermint.abci.RequestInfo") - proto.RegisterType((*RequestInitChain)(nil), "tendermint.abci.RequestInitChain") - proto.RegisterType((*RequestQuery)(nil), "tendermint.abci.RequestQuery") - proto.RegisterType((*RequestCheckTx)(nil), "tendermint.abci.RequestCheckTx") - proto.RegisterType((*RequestCommit)(nil), "tendermint.abci.RequestCommit") - proto.RegisterType((*RequestListSnapshots)(nil), "tendermint.abci.RequestListSnapshots") - proto.RegisterType((*RequestOfferSnapshot)(nil), "tendermint.abci.RequestOfferSnapshot") - proto.RegisterType((*RequestLoadSnapshotChunk)(nil), "tendermint.abci.RequestLoadSnapshotChunk") - proto.RegisterType((*RequestApplySnapshotChunk)(nil), "tendermint.abci.RequestApplySnapshotChunk") - proto.RegisterType((*RequestPrepareProposal)(nil), "tendermint.abci.RequestPrepareProposal") - proto.RegisterType((*RequestProcessProposal)(nil), "tendermint.abci.RequestProcessProposal") - proto.RegisterType((*RequestExtendVote)(nil), "tendermint.abci.RequestExtendVote") - proto.RegisterType((*RequestVerifyVoteExtension)(nil), "tendermint.abci.RequestVerifyVoteExtension") - proto.RegisterType((*RequestFinalizeBlock)(nil), "tendermint.abci.RequestFinalizeBlock") - proto.RegisterType((*Response)(nil), "tendermint.abci.Response") - proto.RegisterType((*ResponseException)(nil), "tendermint.abci.ResponseException") - proto.RegisterType((*ResponseEcho)(nil), "tendermint.abci.ResponseEcho") - proto.RegisterType((*ResponseFlush)(nil), "tendermint.abci.ResponseFlush") - proto.RegisterType((*ResponseInfo)(nil), "tendermint.abci.ResponseInfo") - proto.RegisterType((*ResponseInitChain)(nil), "tendermint.abci.ResponseInitChain") - proto.RegisterType((*ResponseQuery)(nil), "tendermint.abci.ResponseQuery") - proto.RegisterType((*ResponseCheckTx)(nil), "tendermint.abci.ResponseCheckTx") - proto.RegisterType((*ResponseCommit)(nil), "tendermint.abci.ResponseCommit") - proto.RegisterType((*ResponseListSnapshots)(nil), "tendermint.abci.ResponseListSnapshots") - proto.RegisterType((*ResponseOfferSnapshot)(nil), "tendermint.abci.ResponseOfferSnapshot") - proto.RegisterType((*ResponseLoadSnapshotChunk)(nil), "tendermint.abci.ResponseLoadSnapshotChunk") - proto.RegisterType((*ResponseApplySnapshotChunk)(nil), "tendermint.abci.ResponseApplySnapshotChunk") - proto.RegisterType((*ResponsePrepareProposal)(nil), "tendermint.abci.ResponsePrepareProposal") - proto.RegisterType((*ResponseProcessProposal)(nil), "tendermint.abci.ResponseProcessProposal") - proto.RegisterType((*ResponseExtendVote)(nil), "tendermint.abci.ResponseExtendVote") - proto.RegisterType((*ResponseVerifyVoteExtension)(nil), "tendermint.abci.ResponseVerifyVoteExtension") - proto.RegisterType((*ResponseFinalizeBlock)(nil), "tendermint.abci.ResponseFinalizeBlock") - proto.RegisterType((*CommitInfo)(nil), "tendermint.abci.CommitInfo") - proto.RegisterType((*ExtendedCommitInfo)(nil), "tendermint.abci.ExtendedCommitInfo") - proto.RegisterType((*Event)(nil), "tendermint.abci.Event") - proto.RegisterType((*EventAttribute)(nil), "tendermint.abci.EventAttribute") - proto.RegisterType((*ExecTxResult)(nil), "tendermint.abci.ExecTxResult") - proto.RegisterType((*TxResult)(nil), "tendermint.abci.TxResult") - proto.RegisterType((*Validator)(nil), "tendermint.abci.Validator") - proto.RegisterType((*ValidatorUpdate)(nil), "tendermint.abci.ValidatorUpdate") - proto.RegisterType((*VoteInfo)(nil), "tendermint.abci.VoteInfo") - proto.RegisterType((*ExtendedVoteInfo)(nil), "tendermint.abci.ExtendedVoteInfo") - proto.RegisterType((*Misbehavior)(nil), "tendermint.abci.Misbehavior") - proto.RegisterType((*Snapshot)(nil), "tendermint.abci.Snapshot") -} - -func init() { proto.RegisterFile("tendermint/abci/types.proto", fileDescriptor_252557cfdd89a31a) } - -var fileDescriptor_252557cfdd89a31a = []byte{ - // 3164 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xbb, 0x73, 0x23, 0xc7, - 0xd1, 0xc7, 0xe2, 0x8d, 0xc6, 0x83, 0xcb, 0x21, 0xef, 0x84, 0x83, 0xee, 0x48, 0x6a, 0x55, 0x92, - 0x4e, 0x27, 0x89, 0xd4, 0xc7, 0xfb, 0x4e, 0x8f, 0x3a, 0xe9, 0xfb, 0x0a, 0xc4, 0xe1, 0x3e, 0x90, - 0x47, 0x91, 0xd4, 0x12, 0x3c, 0x95, 0x3e, 0xdb, 0x5a, 0x2d, 0x81, 0x01, 0xb0, 0x3a, 0x00, 0xbb, - 0xda, 0x1d, 0x50, 0xa0, 0x42, 0x3f, 0xaa, 0x5c, 0x8a, 0x54, 0x65, 0x07, 0x0a, 0xac, 0xc0, 0x81, - 0x13, 0xff, 0x05, 0x8e, 0xec, 0xc4, 0x81, 0x02, 0x07, 0x0a, 0x1d, 0xc9, 0x2e, 0x29, 0x53, 0xea, - 0xc0, 0x99, 0xcb, 0x35, 0x8f, 0x7d, 0x01, 0x58, 0x02, 0x3c, 0xa9, 0x5c, 0xe5, 0x2a, 0x67, 0x3b, - 0xbd, 0xdd, 0x3d, 0x33, 0xbd, 0x3d, 0xdd, 0xfd, 0xeb, 0x1d, 0x78, 0x92, 0xe0, 0x61, 0x1b, 0xdb, - 0x03, 0x63, 0x48, 0xb6, 0xf4, 0xd3, 0x96, 0xb1, 0x45, 0xce, 0x2d, 0xec, 0x6c, 0x5a, 0xb6, 0x49, - 0x4c, 0xb4, 0xe4, 0xbf, 0xdc, 0xa4, 0x2f, 0x2b, 0x37, 0x02, 0xdc, 0x2d, 0xfb, 0xdc, 0x22, 0xe6, - 0x96, 0x65, 0x9b, 0x66, 0x87, 0xf3, 0x57, 0xae, 0x4f, 0xbf, 0x7e, 0x84, 0xcf, 0x85, 0xb6, 0x90, - 0x30, 0x9b, 0x65, 0xcb, 0xd2, 0x6d, 0x7d, 0xe0, 0xbe, 0xde, 0x98, 0x7a, 0x7d, 0xa6, 0xf7, 0x8d, - 0xb6, 0x4e, 0x4c, 0x5b, 0x70, 0xac, 0x77, 0x4d, 0xb3, 0xdb, 0xc7, 0x5b, 0x6c, 0x74, 0x3a, 0xea, - 0x6c, 0x11, 0x63, 0x80, 0x1d, 0xa2, 0x0f, 0x2c, 0xc1, 0xb0, 0xda, 0x35, 0xbb, 0x26, 0x7b, 0xdc, - 0xa2, 0x4f, 0x9c, 0xaa, 0xfc, 0x21, 0x07, 0x19, 0x15, 0x7f, 0x38, 0xc2, 0x0e, 0x41, 0xdb, 0x90, - 0xc4, 0xad, 0x9e, 0x59, 0x96, 0x36, 0xa4, 0x9b, 0xf9, 0xed, 0xeb, 0x9b, 0x13, 0x1b, 0xdc, 0x14, - 0x7c, 0xf5, 0x56, 0xcf, 0x6c, 0xc4, 0x54, 0xc6, 0x8b, 0xee, 0x40, 0xaa, 0xd3, 0x1f, 0x39, 0xbd, - 0x72, 0x9c, 0x09, 0xdd, 0x88, 0x12, 0xba, 0x4f, 0x99, 0x1a, 0x31, 0x95, 0x73, 0xd3, 0xa9, 0x8c, - 0x61, 0xc7, 0x2c, 0x27, 0x2e, 0x9e, 0x6a, 0x77, 0xd8, 0x61, 0x53, 0x51, 0x5e, 0xb4, 0x03, 0x60, - 0x0c, 0x0d, 0xa2, 0xb5, 0x7a, 0xba, 0x31, 0x2c, 0xa7, 0x98, 0xe4, 0x53, 0xd1, 0x92, 0x06, 0xa9, - 0x51, 0xc6, 0x46, 0x4c, 0xcd, 0x19, 0xee, 0x80, 0x2e, 0xf7, 0xc3, 0x11, 0xb6, 0xcf, 0xcb, 0xe9, - 0x8b, 0x97, 0xfb, 0x36, 0x65, 0xa2, 0xcb, 0x65, 0xdc, 0xe8, 0x0d, 0xc8, 0xb6, 0x7a, 0xb8, 0xf5, - 0x48, 0x23, 0xe3, 0x72, 0x96, 0x49, 0xae, 0x47, 0x49, 0xd6, 0x28, 0x5f, 0x73, 0xdc, 0x88, 0xa9, - 0x99, 0x16, 0x7f, 0x44, 0xaf, 0x41, 0xba, 0x65, 0x0e, 0x06, 0x06, 0x29, 0xe7, 0x99, 0xec, 0x5a, - 0xa4, 0x2c, 0xe3, 0x6a, 0xc4, 0x54, 0xc1, 0x8f, 0x0e, 0xa0, 0xd4, 0x37, 0x1c, 0xa2, 0x39, 0x43, - 0xdd, 0x72, 0x7a, 0x26, 0x71, 0xca, 0x05, 0xa6, 0xe1, 0x99, 0x28, 0x0d, 0xfb, 0x86, 0x43, 0x8e, - 0x5d, 0xe6, 0x46, 0x4c, 0x2d, 0xf6, 0x83, 0x04, 0xaa, 0xcf, 0xec, 0x74, 0xb0, 0xed, 0x29, 0x2c, - 0x17, 0x2f, 0xd6, 0x77, 0x48, 0xb9, 0x5d, 0x79, 0xaa, 0xcf, 0x0c, 0x12, 0xd0, 0x0f, 0x60, 0xa5, - 0x6f, 0xea, 0x6d, 0x4f, 0x9d, 0xd6, 0xea, 0x8d, 0x86, 0x8f, 0xca, 0x25, 0xa6, 0xf4, 0xf9, 0xc8, - 0x45, 0x9a, 0x7a, 0xdb, 0x55, 0x51, 0xa3, 0x02, 0x8d, 0x98, 0xba, 0xdc, 0x9f, 0x24, 0xa2, 0xf7, - 0x60, 0x55, 0xb7, 0xac, 0xfe, 0xf9, 0xa4, 0xf6, 0x25, 0xa6, 0xfd, 0x56, 0x94, 0xf6, 0x2a, 0x95, - 0x99, 0x54, 0x8f, 0xf4, 0x29, 0x2a, 0x6a, 0x82, 0x6c, 0xd9, 0xd8, 0xd2, 0x6d, 0xac, 0x59, 0xb6, - 0x69, 0x99, 0x8e, 0xde, 0x2f, 0xcb, 0x4c, 0xf7, 0x73, 0x51, 0xba, 0x8f, 0x38, 0xff, 0x91, 0x60, - 0x6f, 0xc4, 0xd4, 0x25, 0x2b, 0x4c, 0xe2, 0x5a, 0xcd, 0x16, 0x76, 0x1c, 0x5f, 0xeb, 0xf2, 0x3c, - 0xad, 0x8c, 0x3f, 0xac, 0x35, 0x44, 0x42, 0x75, 0xc8, 0xe3, 0x31, 0x15, 0xd7, 0xce, 0x4c, 0x82, - 0xcb, 0x88, 0x29, 0x54, 0x22, 0x4f, 0x28, 0x63, 0x7d, 0x68, 0x12, 0xdc, 0x88, 0xa9, 0x80, 0xbd, - 0x11, 0xd2, 0xe1, 0xca, 0x19, 0xb6, 0x8d, 0xce, 0x39, 0x53, 0xa3, 0xb1, 0x37, 0x8e, 0x61, 0x0e, - 0xcb, 0x2b, 0x4c, 0xe1, 0x0b, 0x51, 0x0a, 0x1f, 0x32, 0x21, 0xaa, 0xa2, 0xee, 0x8a, 0x34, 0x62, - 0xea, 0xca, 0xd9, 0x34, 0x99, 0xba, 0x58, 0xc7, 0x18, 0xea, 0x7d, 0xe3, 0x63, 0xac, 0x9d, 0xf6, - 0xcd, 0xd6, 0xa3, 0xf2, 0xea, 0xc5, 0x2e, 0x76, 0x5f, 0x70, 0xef, 0x50, 0x66, 0xea, 0x62, 0x9d, - 0x20, 0x61, 0x27, 0x03, 0xa9, 0x33, 0xbd, 0x3f, 0xc2, 0x7b, 0xc9, 0x6c, 0x52, 0x4e, 0xed, 0x25, - 0xb3, 0x19, 0x39, 0xbb, 0x97, 0xcc, 0xe6, 0x64, 0xd8, 0x4b, 0x66, 0x41, 0xce, 0x2b, 0xcf, 0x41, - 0x3e, 0x10, 0x98, 0x50, 0x19, 0x32, 0x03, 0xec, 0x38, 0x7a, 0x17, 0xb3, 0x38, 0x96, 0x53, 0xdd, - 0xa1, 0x52, 0x82, 0x42, 0x30, 0x18, 0x29, 0x9f, 0x4a, 0x9e, 0x24, 0x8d, 0x33, 0x54, 0xf2, 0x0c, - 0xdb, 0xcc, 0x1c, 0x42, 0x52, 0x0c, 0xd1, 0xd3, 0x50, 0x64, 0x5b, 0xd1, 0xdc, 0xf7, 0x34, 0xd8, - 0x25, 0xd5, 0x02, 0x23, 0x3e, 0x14, 0x4c, 0xeb, 0x90, 0xb7, 0xb6, 0x2d, 0x8f, 0x25, 0xc1, 0x58, - 0xc0, 0xda, 0xb6, 0x5c, 0x86, 0xa7, 0xa0, 0x40, 0xf7, 0xed, 0x71, 0x24, 0xd9, 0x24, 0x79, 0x4a, - 0x13, 0x2c, 0xca, 0x9f, 0xe2, 0x20, 0x4f, 0x06, 0x30, 0xf4, 0x1a, 0x24, 0x69, 0x2c, 0x17, 0x61, - 0xb9, 0xb2, 0xc9, 0x03, 0xfd, 0xa6, 0x1b, 0xe8, 0x37, 0x9b, 0x6e, 0xa0, 0xdf, 0xc9, 0x7e, 0xf1, - 0xd5, 0x7a, 0xec, 0xd3, 0xbf, 0xac, 0x4b, 0x2a, 0x93, 0x40, 0xd7, 0x68, 0xd8, 0xd2, 0x8d, 0xa1, - 0x66, 0xb4, 0xd9, 0x92, 0x73, 0x34, 0x26, 0xe9, 0xc6, 0x70, 0xb7, 0x8d, 0xf6, 0x41, 0x6e, 0x99, - 0x43, 0x07, 0x0f, 0x9d, 0x91, 0xa3, 0xf1, 0x54, 0x23, 0x82, 0x71, 0x28, 0xa4, 0xf2, 0x84, 0x57, - 0x73, 0x39, 0x8f, 0x18, 0xa3, 0xba, 0xd4, 0x0a, 0x13, 0xd0, 0x7d, 0x00, 0x2f, 0x1f, 0x39, 0xe5, - 0xe4, 0x46, 0xe2, 0x66, 0x7e, 0x7b, 0x63, 0xea, 0x83, 0x3f, 0x74, 0x59, 0x4e, 0xac, 0xb6, 0x4e, - 0xf0, 0x4e, 0x92, 0x2e, 0x57, 0x0d, 0x48, 0xa2, 0x67, 0x61, 0x49, 0xb7, 0x2c, 0xcd, 0x21, 0x3a, - 0xc1, 0xda, 0xe9, 0x39, 0xc1, 0x0e, 0x8b, 0xf3, 0x05, 0xb5, 0xa8, 0x5b, 0xd6, 0x31, 0xa5, 0xee, - 0x50, 0x22, 0x7a, 0x06, 0x4a, 0x34, 0xa6, 0x1b, 0x7a, 0x5f, 0xeb, 0x61, 0xa3, 0xdb, 0x23, 0x2c, - 0x9e, 0x27, 0xd4, 0xa2, 0xa0, 0x36, 0x18, 0x51, 0x69, 0x7b, 0x5f, 0x9c, 0xc5, 0x73, 0x84, 0x20, - 0xd9, 0xd6, 0x89, 0xce, 0x2c, 0x59, 0x50, 0xd9, 0x33, 0xa5, 0x59, 0x3a, 0xe9, 0x09, 0xfb, 0xb0, - 0x67, 0x74, 0x15, 0xd2, 0x42, 0x6d, 0x82, 0xa9, 0x15, 0x23, 0xb4, 0x0a, 0x29, 0xcb, 0x36, 0xcf, - 0x30, 0xfb, 0x74, 0x59, 0x95, 0x0f, 0x14, 0x15, 0x4a, 0xe1, 0xd8, 0x8f, 0x4a, 0x10, 0x27, 0x63, - 0x31, 0x4b, 0x9c, 0x8c, 0xd1, 0xcb, 0x90, 0xa4, 0x86, 0x64, 0x73, 0x94, 0x66, 0x64, 0x3b, 0x21, - 0xd7, 0x3c, 0xb7, 0xb0, 0xca, 0x38, 0x95, 0x25, 0x28, 0x86, 0x72, 0x82, 0x72, 0x15, 0x56, 0x67, - 0x85, 0x78, 0xa5, 0xe7, 0xd1, 0x43, 0xa1, 0x1a, 0xdd, 0x81, 0xac, 0x17, 0xe3, 0xb9, 0xe3, 0x5c, - 0x9b, 0x9a, 0xd6, 0x65, 0x56, 0x3d, 0x56, 0xea, 0x31, 0xf4, 0x03, 0xf4, 0x74, 0x91, 0xd1, 0x0b, - 0x6a, 0x46, 0xb7, 0xac, 0x86, 0xee, 0xf4, 0x94, 0xf7, 0xa1, 0x1c, 0x15, 0xbf, 0x03, 0x06, 0x93, - 0x98, 0xdb, 0xbb, 0x06, 0xbb, 0x0a, 0xe9, 0x8e, 0x69, 0x0f, 0x74, 0xc2, 0x94, 0x15, 0x55, 0x31, - 0xa2, 0x86, 0xe4, 0xb1, 0x3c, 0xc1, 0xc8, 0x7c, 0xa0, 0x68, 0x70, 0x2d, 0x32, 0x86, 0x53, 0x11, - 0x63, 0xd8, 0xc6, 0xdc, 0xac, 0x45, 0x95, 0x0f, 0x7c, 0x45, 0x7c, 0xb1, 0x7c, 0x40, 0xa7, 0x75, - 0xd8, 0x5e, 0x99, 0xfe, 0x9c, 0x2a, 0x46, 0xca, 0x67, 0x09, 0xb8, 0x3a, 0x3b, 0x92, 0xa3, 0x0d, - 0x28, 0x0c, 0xf4, 0xb1, 0x46, 0xc6, 0xc2, 0xed, 0x24, 0xf6, 0xe1, 0x61, 0xa0, 0x8f, 0x9b, 0x63, - 0xee, 0x73, 0x32, 0x24, 0xc8, 0xd8, 0x29, 0xc7, 0x37, 0x12, 0x37, 0x0b, 0x2a, 0x7d, 0x44, 0x27, - 0xb0, 0xdc, 0x37, 0x5b, 0x7a, 0x5f, 0xeb, 0xeb, 0x0e, 0xd1, 0x44, 0x8a, 0xe7, 0x87, 0xe8, 0xe9, - 0x29, 0x63, 0xf3, 0x98, 0x8c, 0xdb, 0xfc, 0x7b, 0xd2, 0x80, 0x23, 0xfc, 0x7f, 0x89, 0xe9, 0xd8, - 0xd7, 0xdd, 0x4f, 0x8d, 0xee, 0x41, 0x7e, 0x60, 0x38, 0xa7, 0xb8, 0xa7, 0x9f, 0x19, 0xa6, 0x2d, - 0x4e, 0xd3, 0xb4, 0xd3, 0xbc, 0xe5, 0xf3, 0x08, 0x4d, 0x41, 0xb1, 0xc0, 0x27, 0x49, 0x85, 0x7c, - 0xd8, 0x8d, 0x26, 0xe9, 0x4b, 0x47, 0x93, 0x97, 0x61, 0x75, 0x88, 0xc7, 0x44, 0xf3, 0xcf, 0x2b, - 0xf7, 0x93, 0x0c, 0x33, 0x3d, 0xa2, 0xef, 0xbc, 0x13, 0xee, 0x50, 0x97, 0x41, 0xcf, 0xb3, 0x5c, - 0x68, 0x99, 0x0e, 0xb6, 0x35, 0xbd, 0xdd, 0xb6, 0xb1, 0xe3, 0xb0, 0xf2, 0xa9, 0xc0, 0x12, 0x1c, - 0xa3, 0x57, 0x39, 0x59, 0xf9, 0x79, 0xf0, 0xd3, 0x84, 0x73, 0x9f, 0x30, 0xbc, 0xe4, 0x1b, 0xfe, - 0x18, 0x56, 0x85, 0x7c, 0x3b, 0x64, 0x7b, 0x5e, 0x83, 0x3e, 0x39, 0x7d, 0xbe, 0x26, 0x6d, 0x8e, - 0x5c, 0xf1, 0x68, 0xb3, 0x27, 0x1e, 0xcf, 0xec, 0x08, 0x92, 0xcc, 0x28, 0x49, 0x1e, 0x62, 0xe8, - 0xf3, 0xbf, 0xdb, 0xa7, 0xf8, 0x5f, 0x58, 0x9e, 0xaa, 0x23, 0xbc, 0x7d, 0x49, 0x33, 0xf7, 0x15, - 0x0f, 0xee, 0x4b, 0xf9, 0x95, 0x04, 0x95, 0xe8, 0xc2, 0x61, 0xa6, 0xaa, 0x17, 0x60, 0xd9, 0xdb, - 0x8b, 0xb7, 0x3e, 0x7e, 0xa6, 0x65, 0xef, 0x85, 0x58, 0x60, 0x64, 0x78, 0x7e, 0x06, 0x4a, 0x13, - 0x65, 0x0d, 0xff, 0x0a, 0xc5, 0xb3, 0xe0, 0xfc, 0xca, 0x4f, 0x13, 0x5e, 0xcc, 0x0c, 0xd5, 0x1e, - 0x33, 0x1c, 0xed, 0x6d, 0x58, 0x69, 0xe3, 0x96, 0xd1, 0x7e, 0x5c, 0x3f, 0x5b, 0x16, 0xd2, 0xff, - 0x71, 0xb3, 0x69, 0x37, 0xfb, 0x25, 0x40, 0x56, 0xc5, 0x8e, 0x45, 0x4b, 0x09, 0xb4, 0x03, 0x39, - 0x3c, 0x6e, 0x61, 0x8b, 0xb8, 0xd5, 0xd7, 0xec, 0xea, 0x96, 0x73, 0xd7, 0x5d, 0x4e, 0x8a, 0xed, - 0x3c, 0x31, 0x74, 0x5b, 0xc0, 0xd7, 0x68, 0x24, 0x2a, 0xc4, 0x83, 0xf8, 0xf5, 0x15, 0x17, 0xbf, - 0x26, 0x22, 0xa1, 0x19, 0x97, 0x9a, 0x00, 0xb0, 0xb7, 0x05, 0x80, 0x4d, 0xce, 0x99, 0x2c, 0x84, - 0x60, 0x6b, 0x21, 0x04, 0x9b, 0x9e, 0xb3, 0xcd, 0x08, 0x08, 0xfb, 0x8a, 0x0b, 0x61, 0x33, 0x73, - 0x56, 0x3c, 0x81, 0x61, 0xdf, 0x0c, 0x60, 0xd8, 0x1c, 0x13, 0xdd, 0x88, 0x14, 0x9d, 0x01, 0x62, - 0x5f, 0xf7, 0x40, 0x6c, 0x21, 0x12, 0x00, 0x0b, 0xe1, 0x49, 0x14, 0x7b, 0x38, 0x85, 0x62, 0x39, - 0xea, 0x7c, 0x36, 0x52, 0xc5, 0x1c, 0x18, 0x7b, 0x38, 0x05, 0x63, 0x4b, 0x73, 0x14, 0xce, 0xc1, - 0xb1, 0x3f, 0x9c, 0x8d, 0x63, 0xa3, 0x91, 0xa6, 0x58, 0xe6, 0x62, 0x40, 0x56, 0x8b, 0x00, 0xb2, - 0x72, 0x24, 0xe8, 0xe2, 0xea, 0x17, 0x46, 0xb2, 0x27, 0x33, 0x90, 0x2c, 0xc7, 0x9c, 0x37, 0x23, - 0x95, 0x2f, 0x00, 0x65, 0x4f, 0x66, 0x40, 0x59, 0x34, 0x57, 0xed, 0x5c, 0x2c, 0x7b, 0x3f, 0x8c, - 0x65, 0x57, 0x22, 0x0a, 0x26, 0xff, 0xb4, 0x47, 0x80, 0xd9, 0xd3, 0x28, 0x30, 0xcb, 0x01, 0xe7, - 0x8b, 0x91, 0x1a, 0x2f, 0x81, 0x66, 0x0f, 0xa7, 0xd0, 0xec, 0x95, 0x39, 0x9e, 0xb6, 0x38, 0x9c, - 0x4d, 0xc9, 0xe9, 0xbd, 0x64, 0x36, 0x2b, 0xe7, 0x38, 0x90, 0xdd, 0x4b, 0x66, 0xf3, 0x72, 0x41, - 0x79, 0x9e, 0x66, 0xdf, 0x89, 0x38, 0x47, 0xcb, 0x5c, 0x6c, 0xdb, 0xa6, 0x2d, 0x80, 0x29, 0x1f, - 0x28, 0x37, 0x29, 0xbc, 0xf1, 0x63, 0xda, 0x05, 0xd0, 0x97, 0xc1, 0x89, 0x40, 0x1c, 0x53, 0x7e, - 0x27, 0xf9, 0xb2, 0x0c, 0xfc, 0x06, 0xa1, 0x51, 0x4e, 0x40, 0xa3, 0x00, 0x20, 0x8e, 0x87, 0x01, - 0xf1, 0x3a, 0xe4, 0x29, 0x4c, 0x98, 0xc0, 0xba, 0xba, 0xe5, 0x61, 0xdd, 0x5b, 0xb0, 0xcc, 0x12, - 0x26, 0x87, 0xcd, 0x22, 0x2d, 0x25, 0x59, 0x5a, 0x5a, 0xa2, 0x2f, 0xb8, 0x75, 0x78, 0x7e, 0x7a, - 0x09, 0x56, 0x02, 0xbc, 0x1e, 0xfc, 0xe0, 0xc0, 0x4f, 0xf6, 0xb8, 0xab, 0x02, 0x87, 0xfc, 0x51, - 0xf2, 0x2d, 0xe4, 0x83, 0xe4, 0x59, 0x78, 0x56, 0xfa, 0x9e, 0xf0, 0x6c, 0xfc, 0xb1, 0xf1, 0x6c, - 0x10, 0x4e, 0x25, 0xc2, 0x70, 0xea, 0xef, 0x92, 0xff, 0x4d, 0x3c, 0x74, 0xda, 0x32, 0xdb, 0x58, - 0x00, 0x1c, 0xf6, 0x4c, 0x4b, 0x92, 0xbe, 0xd9, 0x15, 0x30, 0x86, 0x3e, 0x52, 0x2e, 0x2f, 0xf1, - 0xe4, 0x44, 0x5e, 0xf1, 0xb0, 0x11, 0x4f, 0xfc, 0x02, 0x1b, 0xc9, 0x90, 0x78, 0x84, 0x79, 0xa7, - 0xb3, 0xa0, 0xd2, 0x47, 0xca, 0xc7, 0x9c, 0x4f, 0x24, 0x70, 0x3e, 0x40, 0xaf, 0x41, 0x8e, 0xf5, - 0xa9, 0x35, 0xd3, 0x72, 0x44, 0x77, 0x33, 0x54, 0xda, 0xf0, 0x66, 0xf5, 0xe6, 0x11, 0xe5, 0x39, - 0xb4, 0x1c, 0x35, 0x6b, 0x89, 0xa7, 0x40, 0xc5, 0x91, 0x0b, 0x55, 0x1c, 0xd7, 0x21, 0x47, 0x57, - 0xef, 0x58, 0x7a, 0x0b, 0x97, 0x81, 0x2d, 0xd4, 0x27, 0x28, 0xbf, 0x8d, 0xc3, 0xd2, 0x44, 0xa2, - 0x99, 0xb9, 0x77, 0xd7, 0x25, 0xe3, 0x01, 0xb4, 0xbe, 0x98, 0x3d, 0xd6, 0x00, 0xba, 0xba, 0xa3, - 0x7d, 0xa4, 0x0f, 0x09, 0x6e, 0x0b, 0xa3, 0x04, 0x28, 0xa8, 0x02, 0x59, 0x3a, 0x1a, 0x39, 0xb8, - 0x2d, 0x1a, 0x07, 0xde, 0x18, 0x35, 0x20, 0x8d, 0xcf, 0xf0, 0x90, 0x38, 0xe5, 0x0c, 0xfb, 0xec, - 0x57, 0xa7, 0x91, 0x1c, 0x7d, 0xbd, 0x53, 0xa6, 0x1f, 0xfb, 0xdb, 0xaf, 0xd6, 0x65, 0xce, 0xfd, - 0xa2, 0x39, 0x30, 0x08, 0x1e, 0x58, 0xe4, 0x5c, 0x15, 0xf2, 0x61, 0x2b, 0x64, 0x27, 0xac, 0xc0, - 0x5a, 0x58, 0x05, 0x17, 0x99, 0x52, 0x9b, 0x1a, 0xa6, 0x6d, 0x90, 0x73, 0xb5, 0x38, 0xc0, 0x03, - 0xcb, 0x34, 0xfb, 0x1a, 0x3f, 0xe3, 0x55, 0x28, 0x85, 0xf3, 0x2a, 0x7a, 0x1a, 0x8a, 0x36, 0x26, - 0xba, 0x31, 0xd4, 0x42, 0x45, 0x70, 0x81, 0x13, 0xf9, 0x99, 0xda, 0x4b, 0x66, 0x25, 0x39, 0xbe, - 0x97, 0xcc, 0xc6, 0xe5, 0x84, 0x72, 0x04, 0x57, 0x66, 0xe6, 0x55, 0xf4, 0x2a, 0xe4, 0xfc, 0x94, - 0x2c, 0xb1, 0xdd, 0x5e, 0xd0, 0x24, 0xf0, 0x79, 0x95, 0xdf, 0x4b, 0xbe, 0xca, 0x70, 0xdb, 0xa1, - 0x0e, 0x69, 0x1b, 0x3b, 0xa3, 0x3e, 0x6f, 0x04, 0x94, 0xb6, 0x5f, 0x5a, 0x2c, 0x23, 0x53, 0xea, - 0xa8, 0x4f, 0x54, 0x21, 0xac, 0xbc, 0x07, 0x69, 0x4e, 0x41, 0x79, 0xc8, 0x9c, 0x1c, 0x3c, 0x38, - 0x38, 0x7c, 0xe7, 0x40, 0x8e, 0x21, 0x80, 0x74, 0xb5, 0x56, 0xab, 0x1f, 0x35, 0x65, 0x09, 0xe5, - 0x20, 0x55, 0xdd, 0x39, 0x54, 0x9b, 0x72, 0x9c, 0x92, 0xd5, 0xfa, 0x5e, 0xbd, 0xd6, 0x94, 0x13, - 0x68, 0x19, 0x8a, 0xfc, 0x59, 0xbb, 0x7f, 0xa8, 0xbe, 0x55, 0x6d, 0xca, 0xc9, 0x00, 0xe9, 0xb8, - 0x7e, 0x70, 0xaf, 0xae, 0xca, 0x29, 0xe5, 0xbf, 0xe0, 0x5a, 0x64, 0x0e, 0xf7, 0x7b, 0x0a, 0x52, - 0xa0, 0xa7, 0xa0, 0x7c, 0x16, 0xa7, 0xa0, 0x26, 0x2a, 0x31, 0xa3, 0xbd, 0x89, 0x8d, 0x6f, 0x5f, - 0x22, 0xab, 0x4f, 0xec, 0x9e, 0xe2, 0x18, 0x1b, 0x77, 0x30, 0x69, 0xf5, 0x78, 0xa1, 0xc0, 0x23, - 0x50, 0x51, 0x2d, 0x0a, 0x2a, 0x13, 0x72, 0x38, 0xdb, 0x07, 0xb8, 0x45, 0x34, 0xee, 0x44, 0x0e, - 0x03, 0x13, 0x39, 0xca, 0x46, 0xa9, 0xc7, 0x9c, 0xa8, 0xbc, 0x7f, 0x29, 0x5b, 0xe6, 0x20, 0xa5, - 0xd6, 0x9b, 0xea, 0xbb, 0x72, 0x02, 0x21, 0x28, 0xb1, 0x47, 0xed, 0xf8, 0xa0, 0x7a, 0x74, 0xdc, - 0x38, 0xa4, 0xb6, 0x5c, 0x81, 0x25, 0xd7, 0x96, 0x2e, 0x31, 0xa5, 0xbc, 0x00, 0x4f, 0x44, 0x54, - 0x15, 0xd3, 0x90, 0x4a, 0xf9, 0xb5, 0x14, 0xe4, 0x0e, 0x57, 0x06, 0x87, 0x90, 0x76, 0x88, 0x4e, - 0x46, 0x8e, 0x30, 0xe2, 0xab, 0x8b, 0x96, 0x19, 0x9b, 0xee, 0xc3, 0x31, 0x13, 0x57, 0x85, 0x1a, - 0xe5, 0x0e, 0x94, 0xc2, 0x6f, 0xa2, 0x6d, 0xe0, 0x3b, 0x51, 0x5c, 0xb9, 0x0b, 0x68, 0xba, 0xfa, - 0x98, 0x01, 0x2f, 0xa5, 0x59, 0xf0, 0xf2, 0x37, 0x12, 0x3c, 0x79, 0x41, 0xa5, 0x81, 0xde, 0x9e, - 0xd8, 0xe4, 0xeb, 0x97, 0xa9, 0x53, 0x36, 0x39, 0x6d, 0x62, 0x9b, 0xb7, 0xa1, 0x10, 0xa4, 0x2f, - 0xb6, 0xc9, 0x6f, 0xe3, 0xfe, 0x21, 0x0e, 0xe3, 0x60, 0x3f, 0x04, 0x4a, 0xdf, 0x31, 0x04, 0xbe, - 0x01, 0x40, 0xc6, 0x1a, 0x77, 0x6b, 0x37, 0x8f, 0xde, 0x98, 0xd1, 0x1a, 0xc3, 0xad, 0xe6, 0x58, - 0x1c, 0x82, 0x1c, 0x11, 0x4f, 0x0e, 0x3a, 0x0e, 0x36, 0x05, 0x46, 0x2c, 0xc7, 0x3a, 0x02, 0x30, - 0x2f, 0x9a, 0x8c, 0xfd, 0xe6, 0x01, 0x27, 0x3b, 0xe8, 0x5d, 0x78, 0x62, 0xa2, 0x50, 0xf0, 0x54, - 0x27, 0x17, 0xad, 0x17, 0xae, 0x84, 0xeb, 0x05, 0x57, 0x75, 0x30, 0xdb, 0xa7, 0xc2, 0xd9, 0xfe, - 0x5d, 0x00, 0xbf, 0x39, 0x40, 0x23, 0x8c, 0x6d, 0x8e, 0x86, 0x6d, 0xe6, 0x01, 0x29, 0x95, 0x0f, - 0xd0, 0x1d, 0x48, 0x51, 0x4f, 0x72, 0xed, 0x34, 0x1d, 0x8a, 0xa9, 0x27, 0x04, 0x9a, 0x0b, 0x9c, - 0x5b, 0x31, 0x00, 0x4d, 0xf7, 0x16, 0x23, 0xa6, 0x78, 0x33, 0x3c, 0xc5, 0x53, 0x91, 0x5d, 0xca, - 0xd9, 0x53, 0x7d, 0x0c, 0x29, 0xf6, 0xe5, 0x69, 0xd2, 0x65, 0x0d, 0x6d, 0x51, 0x2d, 0xd2, 0x67, - 0xf4, 0x23, 0x00, 0x9d, 0x10, 0xdb, 0x38, 0x1d, 0xf9, 0x13, 0xac, 0xcf, 0xf6, 0x9c, 0xaa, 0xcb, - 0xb7, 0x73, 0x5d, 0xb8, 0xd0, 0xaa, 0x2f, 0x1a, 0x70, 0xa3, 0x80, 0x42, 0xe5, 0x00, 0x4a, 0x61, - 0x59, 0xb7, 0xbe, 0xe1, 0x6b, 0x08, 0xd7, 0x37, 0xbc, 0x5c, 0x15, 0xf5, 0x8d, 0x57, 0x1d, 0x25, - 0x78, 0xd7, 0x9e, 0x0d, 0x94, 0x7f, 0x48, 0x50, 0x08, 0x3a, 0xde, 0xf7, 0x5c, 0x82, 0xdc, 0x98, - 0x51, 0x82, 0xe4, 0xba, 0xba, 0xf3, 0x0e, 0xaf, 0x40, 0xae, 0x4d, 0x55, 0x20, 0x99, 0xae, 0xee, - 0x9c, 0xfc, 0x0b, 0x0b, 0x10, 0xe5, 0x67, 0x12, 0x64, 0xbd, 0xcd, 0x87, 0x1b, 0xf8, 0xa1, 0x3f, - 0x1e, 0xdc, 0x76, 0xf1, 0x60, 0xd7, 0x9d, 0xff, 0xdf, 0x48, 0x78, 0xff, 0x37, 0xee, 0x7a, 0xc9, - 0x2f, 0xaa, 0x1d, 0x12, 0xb4, 0xb4, 0xf0, 0x29, 0x37, 0xd7, 0xdf, 0x85, 0x9c, 0x77, 0x76, 0x29, - 0xe4, 0x70, 0xdb, 0x46, 0x92, 0x38, 0x41, 0xa2, 0xe9, 0xb7, 0x0a, 0x29, 0xcb, 0xfc, 0x48, 0xb4, - 0xf4, 0x13, 0x2a, 0x1f, 0x28, 0x6d, 0x58, 0x9a, 0x38, 0xf8, 0xe8, 0x2e, 0x64, 0xac, 0xd1, 0xa9, - 0xe6, 0xba, 0xc6, 0x44, 0x73, 0xcd, 0x2d, 0x66, 0x47, 0xa7, 0x7d, 0xa3, 0xf5, 0x00, 0x9f, 0xbb, - 0x8b, 0xb1, 0x46, 0xa7, 0x0f, 0xb8, 0x07, 0xf1, 0x59, 0xe2, 0xc1, 0x59, 0x7e, 0x21, 0x41, 0xd6, - 0x3d, 0x11, 0xe8, 0x7f, 0x20, 0xe7, 0x05, 0x15, 0xef, 0x9f, 0x5c, 0x64, 0x34, 0x12, 0xfa, 0x7d, - 0x11, 0x54, 0x75, 0x7f, 0x26, 0x1a, 0x6d, 0xad, 0xd3, 0xd7, 0xb9, 0x27, 0x95, 0xc2, 0x36, 0xe3, - 0x61, 0x87, 0x45, 0xe3, 0xdd, 0x7b, 0xf7, 0xfb, 0x7a, 0x57, 0xcd, 0x33, 0x99, 0xdd, 0x36, 0x1d, - 0x88, 0xba, 0xee, 0x6f, 0x12, 0xc8, 0x93, 0xe7, 0xf5, 0x3b, 0xaf, 0x6e, 0x3a, 0xc9, 0x25, 0x66, - 0x24, 0x39, 0xb4, 0x05, 0x2b, 0x1e, 0x87, 0xe6, 0x18, 0xdd, 0xa1, 0x4e, 0x46, 0x36, 0x16, 0xed, - 0x48, 0xe4, 0xbd, 0x3a, 0x76, 0xdf, 0x4c, 0xef, 0x3a, 0xf5, 0x98, 0xbb, 0xfe, 0x49, 0x1c, 0xf2, - 0x81, 0xe6, 0x28, 0xfa, 0xef, 0x40, 0x28, 0x2a, 0xcd, 0xc8, 0x0b, 0x01, 0x5e, 0xff, 0xff, 0x5a, - 0xd8, 0x4c, 0xf1, 0xcb, 0x9b, 0x29, 0xaa, 0x05, 0xed, 0xf6, 0x5a, 0x93, 0x97, 0xee, 0xb5, 0xbe, - 0x08, 0x88, 0x98, 0x44, 0xef, 0x6b, 0x67, 0x26, 0x31, 0x86, 0x5d, 0x8d, 0xbb, 0x21, 0x0f, 0x1c, - 0x32, 0x7b, 0xf3, 0x90, 0xbd, 0x38, 0x62, 0x1e, 0xf9, 0x63, 0x09, 0xb2, 0x5e, 0xd1, 0x7d, 0xd9, - 0xbf, 0x6f, 0x57, 0x21, 0x2d, 0xea, 0x4a, 0xfe, 0xfb, 0x4d, 0x8c, 0x66, 0x36, 0x95, 0x2b, 0x90, - 0x1d, 0x60, 0xa2, 0xb3, 0x28, 0xc8, 0x73, 0x9a, 0x37, 0xbe, 0xf5, 0x3a, 0xe4, 0x03, 0x7f, 0x2e, - 0x69, 0x60, 0x3c, 0xa8, 0xbf, 0x23, 0xc7, 0x2a, 0x99, 0x4f, 0x3e, 0xdf, 0x48, 0x1c, 0xe0, 0x8f, - 0xe8, 0x69, 0x56, 0xeb, 0xb5, 0x46, 0xbd, 0xf6, 0x40, 0x96, 0x2a, 0xf9, 0x4f, 0x3e, 0xdf, 0xc8, - 0xa8, 0x98, 0xf5, 0x13, 0x6f, 0x3d, 0x80, 0xa5, 0x89, 0x0f, 0x13, 0x2e, 0x5a, 0x10, 0x94, 0xee, - 0x9d, 0x1c, 0xed, 0xef, 0xd6, 0xaa, 0xcd, 0xba, 0xf6, 0xf0, 0xb0, 0x59, 0x97, 0x25, 0xf4, 0x04, - 0xac, 0xec, 0xef, 0xfe, 0x5f, 0xa3, 0xa9, 0xd5, 0xf6, 0x77, 0xeb, 0x07, 0x4d, 0xad, 0xda, 0x6c, - 0x56, 0x6b, 0x0f, 0xe4, 0xf8, 0xf6, 0xe7, 0x79, 0x48, 0x56, 0x77, 0x6a, 0xbb, 0xa8, 0x06, 0x49, - 0xd6, 0x08, 0xb9, 0xf0, 0xea, 0x52, 0xe5, 0xe2, 0xce, 0x30, 0xba, 0x0f, 0x29, 0xd6, 0x23, 0x41, - 0x17, 0xdf, 0x65, 0xaa, 0xcc, 0x69, 0x15, 0xd3, 0xc5, 0xb0, 0x13, 0x79, 0xe1, 0xe5, 0xa6, 0xca, - 0xc5, 0x9d, 0x63, 0xb4, 0x0f, 0x19, 0x17, 0x22, 0xcf, 0xbb, 0x71, 0x54, 0x99, 0xdb, 0xce, 0xa5, - 0x5b, 0xe3, 0xad, 0x86, 0x8b, 0xef, 0x3d, 0x55, 0xe6, 0xf4, 0x94, 0xd1, 0x2e, 0xa4, 0x05, 0x18, - 0x9d, 0x73, 0x95, 0xa9, 0x32, 0xaf, 0x4b, 0x8c, 0x54, 0xc8, 0xf9, 0x4d, 0x9c, 0xf9, 0xb7, 0xb9, - 0x2a, 0x0b, 0xb4, 0xcb, 0xd1, 0x7b, 0x50, 0x0c, 0x03, 0xdd, 0xc5, 0xae, 0x4b, 0x55, 0x16, 0xec, - 0x47, 0x53, 0xfd, 0x61, 0xd4, 0xbb, 0xd8, 0xf5, 0xa9, 0xca, 0x82, 0xed, 0x69, 0xf4, 0x01, 0x2c, - 0x4f, 0xa3, 0xd2, 0xc5, 0x6f, 0x53, 0x55, 0x2e, 0xd1, 0xb0, 0x46, 0x03, 0x40, 0x33, 0xd0, 0xec, - 0x25, 0x2e, 0x57, 0x55, 0x2e, 0xd3, 0xbf, 0x46, 0x6d, 0x58, 0x9a, 0x84, 0x88, 0x8b, 0x5e, 0xb6, - 0xaa, 0x2c, 0xdc, 0xcb, 0xe6, 0xb3, 0x84, 0xa1, 0xe5, 0xa2, 0x97, 0xaf, 0x2a, 0x0b, 0xb7, 0xb6, - 0xd1, 0x09, 0x40, 0x00, 0x1d, 0x2e, 0x70, 0x19, 0xab, 0xb2, 0x48, 0x93, 0x1b, 0x59, 0xb0, 0x32, - 0x0b, 0x36, 0x5e, 0xe6, 0x6e, 0x56, 0xe5, 0x52, 0xbd, 0x6f, 0xea, 0xcf, 0x61, 0x00, 0xb8, 0xd8, - 0x5d, 0xad, 0xca, 0x82, 0x4d, 0xf0, 0x9d, 0xea, 0x17, 0x5f, 0xaf, 0x49, 0x5f, 0x7e, 0xbd, 0x26, - 0xfd, 0xf5, 0xeb, 0x35, 0xe9, 0xd3, 0x6f, 0xd6, 0x62, 0x5f, 0x7e, 0xb3, 0x16, 0xfb, 0xf3, 0x37, - 0x6b, 0xb1, 0xff, 0x7f, 0xae, 0x6b, 0x90, 0xde, 0xe8, 0x74, 0xb3, 0x65, 0x0e, 0xb6, 0x5a, 0xe6, - 0x00, 0x93, 0xd3, 0x0e, 0xf1, 0x1f, 0xfc, 0x2b, 0xb7, 0xa7, 0x69, 0x96, 0x41, 0x6f, 0xff, 0x33, - 0x00, 0x00, 0xff, 0xff, 0x55, 0x7b, 0x1c, 0x1f, 0x92, 0x2b, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// ABCIClient is the client API for ABCI service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type ABCIClient interface { - Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) - Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) - Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) - CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) - Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) - Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) - InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) - ListSnapshots(ctx context.Context, in *RequestListSnapshots, opts ...grpc.CallOption) (*ResponseListSnapshots, error) - OfferSnapshot(ctx context.Context, in *RequestOfferSnapshot, opts ...grpc.CallOption) (*ResponseOfferSnapshot, error) - LoadSnapshotChunk(ctx context.Context, in *RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*ResponseLoadSnapshotChunk, error) - ApplySnapshotChunk(ctx context.Context, in *RequestApplySnapshotChunk, opts ...grpc.CallOption) (*ResponseApplySnapshotChunk, error) - PrepareProposal(ctx context.Context, in *RequestPrepareProposal, opts ...grpc.CallOption) (*ResponsePrepareProposal, error) - ProcessProposal(ctx context.Context, in *RequestProcessProposal, opts ...grpc.CallOption) (*ResponseProcessProposal, error) - ExtendVote(ctx context.Context, in *RequestExtendVote, opts ...grpc.CallOption) (*ResponseExtendVote, error) - VerifyVoteExtension(ctx context.Context, in *RequestVerifyVoteExtension, opts ...grpc.CallOption) (*ResponseVerifyVoteExtension, error) - FinalizeBlock(ctx context.Context, in *RequestFinalizeBlock, opts ...grpc.CallOption) (*ResponseFinalizeBlock, error) -} - -type aBCIClient struct { - cc grpc1.ClientConn -} - -func NewABCIClient(cc grpc1.ClientConn) ABCIClient { - return &aBCIClient{cc} -} - -func (c *aBCIClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) { - out := new(ResponseEcho) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/Echo", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) { - out := new(ResponseFlush) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/Flush", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) { - out := new(ResponseInfo) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/Info", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { - out := new(ResponseCheckTx) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/CheckTx", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) { - out := new(ResponseQuery) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/Query", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { - out := new(ResponseCommit) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/Commit", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { - out := new(ResponseInitChain) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/InitChain", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) ListSnapshots(ctx context.Context, in *RequestListSnapshots, opts ...grpc.CallOption) (*ResponseListSnapshots, error) { - out := new(ResponseListSnapshots) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/ListSnapshots", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) OfferSnapshot(ctx context.Context, in *RequestOfferSnapshot, opts ...grpc.CallOption) (*ResponseOfferSnapshot, error) { - out := new(ResponseOfferSnapshot) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/OfferSnapshot", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) LoadSnapshotChunk(ctx context.Context, in *RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*ResponseLoadSnapshotChunk, error) { - out := new(ResponseLoadSnapshotChunk) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/LoadSnapshotChunk", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) ApplySnapshotChunk(ctx context.Context, in *RequestApplySnapshotChunk, opts ...grpc.CallOption) (*ResponseApplySnapshotChunk, error) { - out := new(ResponseApplySnapshotChunk) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/ApplySnapshotChunk", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) PrepareProposal(ctx context.Context, in *RequestPrepareProposal, opts ...grpc.CallOption) (*ResponsePrepareProposal, error) { - out := new(ResponsePrepareProposal) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/PrepareProposal", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) ProcessProposal(ctx context.Context, in *RequestProcessProposal, opts ...grpc.CallOption) (*ResponseProcessProposal, error) { - out := new(ResponseProcessProposal) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/ProcessProposal", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) ExtendVote(ctx context.Context, in *RequestExtendVote, opts ...grpc.CallOption) (*ResponseExtendVote, error) { - out := new(ResponseExtendVote) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/ExtendVote", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) VerifyVoteExtension(ctx context.Context, in *RequestVerifyVoteExtension, opts ...grpc.CallOption) (*ResponseVerifyVoteExtension, error) { - out := new(ResponseVerifyVoteExtension) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/VerifyVoteExtension", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *aBCIClient) FinalizeBlock(ctx context.Context, in *RequestFinalizeBlock, opts ...grpc.CallOption) (*ResponseFinalizeBlock, error) { - out := new(ResponseFinalizeBlock) - err := c.cc.Invoke(ctx, "/tendermint.abci.ABCI/FinalizeBlock", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// ABCIServer is the server API for ABCI service. -type ABCIServer interface { - Echo(context.Context, *RequestEcho) (*ResponseEcho, error) - Flush(context.Context, *RequestFlush) (*ResponseFlush, error) - Info(context.Context, *RequestInfo) (*ResponseInfo, error) - CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) - Query(context.Context, *RequestQuery) (*ResponseQuery, error) - Commit(context.Context, *RequestCommit) (*ResponseCommit, error) - InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) - ListSnapshots(context.Context, *RequestListSnapshots) (*ResponseListSnapshots, error) - OfferSnapshot(context.Context, *RequestOfferSnapshot) (*ResponseOfferSnapshot, error) - LoadSnapshotChunk(context.Context, *RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) - ApplySnapshotChunk(context.Context, *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) - PrepareProposal(context.Context, *RequestPrepareProposal) (*ResponsePrepareProposal, error) - ProcessProposal(context.Context, *RequestProcessProposal) (*ResponseProcessProposal, error) - ExtendVote(context.Context, *RequestExtendVote) (*ResponseExtendVote, error) - VerifyVoteExtension(context.Context, *RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error) - FinalizeBlock(context.Context, *RequestFinalizeBlock) (*ResponseFinalizeBlock, error) -} - -// UnimplementedABCIServer can be embedded to have forward compatible implementations. -type UnimplementedABCIServer struct { -} - -func (*UnimplementedABCIServer) Echo(ctx context.Context, req *RequestEcho) (*ResponseEcho, error) { - return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented") -} -func (*UnimplementedABCIServer) Flush(ctx context.Context, req *RequestFlush) (*ResponseFlush, error) { - return nil, status.Errorf(codes.Unimplemented, "method Flush not implemented") -} -func (*UnimplementedABCIServer) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { - return nil, status.Errorf(codes.Unimplemented, "method Info not implemented") -} -func (*UnimplementedABCIServer) CheckTx(ctx context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { - return nil, status.Errorf(codes.Unimplemented, "method CheckTx not implemented") -} -func (*UnimplementedABCIServer) Query(ctx context.Context, req *RequestQuery) (*ResponseQuery, error) { - return nil, status.Errorf(codes.Unimplemented, "method Query not implemented") -} -func (*UnimplementedABCIServer) Commit(ctx context.Context, req *RequestCommit) (*ResponseCommit, error) { - return nil, status.Errorf(codes.Unimplemented, "method Commit not implemented") -} -func (*UnimplementedABCIServer) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { - return nil, status.Errorf(codes.Unimplemented, "method InitChain not implemented") -} -func (*UnimplementedABCIServer) ListSnapshots(ctx context.Context, req *RequestListSnapshots) (*ResponseListSnapshots, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented") -} -func (*UnimplementedABCIServer) OfferSnapshot(ctx context.Context, req *RequestOfferSnapshot) (*ResponseOfferSnapshot, error) { - return nil, status.Errorf(codes.Unimplemented, "method OfferSnapshot not implemented") -} -func (*UnimplementedABCIServer) LoadSnapshotChunk(ctx context.Context, req *RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) { - return nil, status.Errorf(codes.Unimplemented, "method LoadSnapshotChunk not implemented") -} -func (*UnimplementedABCIServer) ApplySnapshotChunk(ctx context.Context, req *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) { - return nil, status.Errorf(codes.Unimplemented, "method ApplySnapshotChunk not implemented") -} -func (*UnimplementedABCIServer) PrepareProposal(ctx context.Context, req *RequestPrepareProposal) (*ResponsePrepareProposal, error) { - return nil, status.Errorf(codes.Unimplemented, "method PrepareProposal not implemented") -} -func (*UnimplementedABCIServer) ProcessProposal(ctx context.Context, req *RequestProcessProposal) (*ResponseProcessProposal, error) { - return nil, status.Errorf(codes.Unimplemented, "method ProcessProposal not implemented") -} -func (*UnimplementedABCIServer) ExtendVote(ctx context.Context, req *RequestExtendVote) (*ResponseExtendVote, error) { - return nil, status.Errorf(codes.Unimplemented, "method ExtendVote not implemented") -} -func (*UnimplementedABCIServer) VerifyVoteExtension(ctx context.Context, req *RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error) { - return nil, status.Errorf(codes.Unimplemented, "method VerifyVoteExtension not implemented") -} -func (*UnimplementedABCIServer) FinalizeBlock(ctx context.Context, req *RequestFinalizeBlock) (*ResponseFinalizeBlock, error) { - return nil, status.Errorf(codes.Unimplemented, "method FinalizeBlock not implemented") -} - -func RegisterABCIServer(s grpc1.Server, srv ABCIServer) { - s.RegisterService(&_ABCI_serviceDesc, srv) -} - -func _ABCI_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestEcho) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).Echo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/Echo", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).Echo(ctx, req.(*RequestEcho)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestFlush) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).Flush(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/Flush", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).Flush(ctx, req.(*RequestFlush)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestInfo) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).Info(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/Info", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).Info(ctx, req.(*RequestInfo)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestCheckTx) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).CheckTx(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/CheckTx", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).CheckTx(ctx, req.(*RequestCheckTx)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestQuery) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).Query(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/Query", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).Query(ctx, req.(*RequestQuery)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestCommit) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).Commit(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/Commit", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).Commit(ctx, req.(*RequestCommit)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestInitChain) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).InitChain(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/InitChain", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).InitChain(ctx, req.(*RequestInitChain)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestListSnapshots) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).ListSnapshots(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/ListSnapshots", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).ListSnapshots(ctx, req.(*RequestListSnapshots)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_OfferSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestOfferSnapshot) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).OfferSnapshot(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/OfferSnapshot", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).OfferSnapshot(ctx, req.(*RequestOfferSnapshot)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_LoadSnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestLoadSnapshotChunk) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).LoadSnapshotChunk(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/LoadSnapshotChunk", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).LoadSnapshotChunk(ctx, req.(*RequestLoadSnapshotChunk)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_ApplySnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestApplySnapshotChunk) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).ApplySnapshotChunk(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/ApplySnapshotChunk", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).ApplySnapshotChunk(ctx, req.(*RequestApplySnapshotChunk)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_PrepareProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestPrepareProposal) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).PrepareProposal(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/PrepareProposal", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).PrepareProposal(ctx, req.(*RequestPrepareProposal)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_ProcessProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestProcessProposal) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).ProcessProposal(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/ProcessProposal", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).ProcessProposal(ctx, req.(*RequestProcessProposal)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_ExtendVote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestExtendVote) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).ExtendVote(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/ExtendVote", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).ExtendVote(ctx, req.(*RequestExtendVote)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_VerifyVoteExtension_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestVerifyVoteExtension) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).VerifyVoteExtension(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/VerifyVoteExtension", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).VerifyVoteExtension(ctx, req.(*RequestVerifyVoteExtension)) - } - return interceptor(ctx, in, info, handler) -} - -func _ABCI_FinalizeBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestFinalizeBlock) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ABCIServer).FinalizeBlock(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.abci.ABCI/FinalizeBlock", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIServer).FinalizeBlock(ctx, req.(*RequestFinalizeBlock)) - } - return interceptor(ctx, in, info, handler) -} - -var _ABCI_serviceDesc = grpc.ServiceDesc{ - ServiceName: "tendermint.abci.ABCI", - HandlerType: (*ABCIServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Echo", - Handler: _ABCI_Echo_Handler, - }, - { - MethodName: "Flush", - Handler: _ABCI_Flush_Handler, - }, - { - MethodName: "Info", - Handler: _ABCI_Info_Handler, - }, - { - MethodName: "CheckTx", - Handler: _ABCI_CheckTx_Handler, - }, - { - MethodName: "Query", - Handler: _ABCI_Query_Handler, - }, - { - MethodName: "Commit", - Handler: _ABCI_Commit_Handler, - }, - { - MethodName: "InitChain", - Handler: _ABCI_InitChain_Handler, - }, - { - MethodName: "ListSnapshots", - Handler: _ABCI_ListSnapshots_Handler, - }, - { - MethodName: "OfferSnapshot", - Handler: _ABCI_OfferSnapshot_Handler, - }, - { - MethodName: "LoadSnapshotChunk", - Handler: _ABCI_LoadSnapshotChunk_Handler, - }, - { - MethodName: "ApplySnapshotChunk", - Handler: _ABCI_ApplySnapshotChunk_Handler, - }, - { - MethodName: "PrepareProposal", - Handler: _ABCI_PrepareProposal_Handler, - }, - { - MethodName: "ProcessProposal", - Handler: _ABCI_ProcessProposal_Handler, - }, - { - MethodName: "ExtendVote", - Handler: _ABCI_ExtendVote_Handler, - }, - { - MethodName: "VerifyVoteExtension", - Handler: _ABCI_VerifyVoteExtension_Handler, - }, - { - MethodName: "FinalizeBlock", - Handler: _ABCI_FinalizeBlock_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "tendermint/abci/types.proto", + proto.RegisterEnum("cometbft.abci.v1.CheckTxType", CheckTxType_name, CheckTxType_value) + proto.RegisterEnum("cometbft.abci.v1.OfferSnapshotResult", OfferSnapshotResult_name, OfferSnapshotResult_value) + proto.RegisterEnum("cometbft.abci.v1.ApplySnapshotChunkResult", ApplySnapshotChunkResult_name, ApplySnapshotChunkResult_value) + proto.RegisterEnum("cometbft.abci.v1.ProcessProposalStatus", ProcessProposalStatus_name, ProcessProposalStatus_value) + proto.RegisterEnum("cometbft.abci.v1.VerifyVoteExtensionStatus", VerifyVoteExtensionStatus_name, VerifyVoteExtensionStatus_value) + proto.RegisterEnum("cometbft.abci.v1.MisbehaviorType", MisbehaviorType_name, MisbehaviorType_value) + proto.RegisterType((*Request)(nil), "cometbft.abci.v1.Request") + proto.RegisterType((*EchoRequest)(nil), "cometbft.abci.v1.EchoRequest") + proto.RegisterType((*FlushRequest)(nil), "cometbft.abci.v1.FlushRequest") + proto.RegisterType((*InfoRequest)(nil), "cometbft.abci.v1.InfoRequest") + proto.RegisterType((*InitChainRequest)(nil), "cometbft.abci.v1.InitChainRequest") + proto.RegisterType((*QueryRequest)(nil), "cometbft.abci.v1.QueryRequest") + proto.RegisterType((*CheckTxRequest)(nil), "cometbft.abci.v1.CheckTxRequest") + proto.RegisterType((*CommitRequest)(nil), "cometbft.abci.v1.CommitRequest") + proto.RegisterType((*ListSnapshotsRequest)(nil), "cometbft.abci.v1.ListSnapshotsRequest") + proto.RegisterType((*OfferSnapshotRequest)(nil), "cometbft.abci.v1.OfferSnapshotRequest") + proto.RegisterType((*LoadSnapshotChunkRequest)(nil), "cometbft.abci.v1.LoadSnapshotChunkRequest") + proto.RegisterType((*ApplySnapshotChunkRequest)(nil), "cometbft.abci.v1.ApplySnapshotChunkRequest") + proto.RegisterType((*PrepareProposalRequest)(nil), "cometbft.abci.v1.PrepareProposalRequest") + proto.RegisterType((*ProcessProposalRequest)(nil), "cometbft.abci.v1.ProcessProposalRequest") + proto.RegisterType((*ExtendVoteRequest)(nil), "cometbft.abci.v1.ExtendVoteRequest") + proto.RegisterType((*VerifyVoteExtensionRequest)(nil), "cometbft.abci.v1.VerifyVoteExtensionRequest") + proto.RegisterType((*FinalizeBlockRequest)(nil), "cometbft.abci.v1.FinalizeBlockRequest") + proto.RegisterType((*Response)(nil), "cometbft.abci.v1.Response") + proto.RegisterType((*ExceptionResponse)(nil), "cometbft.abci.v1.ExceptionResponse") + proto.RegisterType((*EchoResponse)(nil), "cometbft.abci.v1.EchoResponse") + proto.RegisterType((*FlushResponse)(nil), "cometbft.abci.v1.FlushResponse") + proto.RegisterType((*InfoResponse)(nil), "cometbft.abci.v1.InfoResponse") + proto.RegisterType((*InitChainResponse)(nil), "cometbft.abci.v1.InitChainResponse") + proto.RegisterType((*QueryResponse)(nil), "cometbft.abci.v1.QueryResponse") + proto.RegisterType((*CheckTxResponse)(nil), "cometbft.abci.v1.CheckTxResponse") + proto.RegisterType((*CommitResponse)(nil), "cometbft.abci.v1.CommitResponse") + proto.RegisterType((*ListSnapshotsResponse)(nil), "cometbft.abci.v1.ListSnapshotsResponse") + proto.RegisterType((*OfferSnapshotResponse)(nil), "cometbft.abci.v1.OfferSnapshotResponse") + proto.RegisterType((*LoadSnapshotChunkResponse)(nil), "cometbft.abci.v1.LoadSnapshotChunkResponse") + proto.RegisterType((*ApplySnapshotChunkResponse)(nil), "cometbft.abci.v1.ApplySnapshotChunkResponse") + proto.RegisterType((*PrepareProposalResponse)(nil), "cometbft.abci.v1.PrepareProposalResponse") + proto.RegisterType((*ProcessProposalResponse)(nil), "cometbft.abci.v1.ProcessProposalResponse") + proto.RegisterType((*ExtendVoteResponse)(nil), "cometbft.abci.v1.ExtendVoteResponse") + proto.RegisterType((*VerifyVoteExtensionResponse)(nil), "cometbft.abci.v1.VerifyVoteExtensionResponse") + proto.RegisterType((*FinalizeBlockResponse)(nil), "cometbft.abci.v1.FinalizeBlockResponse") + proto.RegisterType((*CommitInfo)(nil), "cometbft.abci.v1.CommitInfo") + proto.RegisterType((*ExtendedCommitInfo)(nil), "cometbft.abci.v1.ExtendedCommitInfo") + proto.RegisterType((*Event)(nil), "cometbft.abci.v1.Event") + proto.RegisterType((*EventAttribute)(nil), "cometbft.abci.v1.EventAttribute") + proto.RegisterType((*ExecTxResult)(nil), "cometbft.abci.v1.ExecTxResult") + proto.RegisterType((*TxResult)(nil), "cometbft.abci.v1.TxResult") + proto.RegisterType((*Validator)(nil), "cometbft.abci.v1.Validator") + proto.RegisterType((*ValidatorUpdate)(nil), "cometbft.abci.v1.ValidatorUpdate") + proto.RegisterType((*VoteInfo)(nil), "cometbft.abci.v1.VoteInfo") + proto.RegisterType((*ExtendedVoteInfo)(nil), "cometbft.abci.v1.ExtendedVoteInfo") + proto.RegisterType((*Misbehavior)(nil), "cometbft.abci.v1.Misbehavior") + proto.RegisterType((*Snapshot)(nil), "cometbft.abci.v1.Snapshot") +} + +func init() { proto.RegisterFile("cometbft/abci/v1/types.proto", fileDescriptor_95dd8f7b670b96e3) } + +var fileDescriptor_95dd8f7b670b96e3 = []byte{ + // 3140 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0x4b, 0x73, 0x1b, 0xc7, + 0xb5, 0xd6, 0xe0, 0x41, 0x02, 0x07, 0x00, 0x39, 0x6c, 0x92, 0x12, 0x44, 0xcb, 0x24, 0x35, 0xb4, + 0x2c, 0x59, 0xb2, 0xc9, 0x2b, 0xd9, 0xd7, 0x8f, 0xeb, 0x57, 0x81, 0x10, 0x68, 0x92, 0xa2, 0x08, + 0x78, 0x00, 0xf2, 0x5a, 0xaa, 0x7b, 0x33, 0x1e, 0x00, 0x0d, 0x62, 0x2c, 0x00, 0x33, 0x9e, 0x69, + 0xd0, 0x60, 0xb2, 0x4a, 0x2a, 0x76, 0xa5, 0xbc, 0xf2, 0x26, 0x9b, 0x54, 0x52, 0x95, 0xaa, 0x54, + 0x56, 0xa9, 0xca, 0x3a, 0xbf, 0x20, 0xe5, 0x55, 0xe2, 0x65, 0x56, 0x4e, 0xca, 0xde, 0x65, 0x91, + 0x9d, 0xab, 0xb2, 0x4c, 0xf5, 0x63, 0x5e, 0xc0, 0x0c, 0x49, 0xc9, 0xce, 0x22, 0x95, 0xec, 0xa6, + 0xbb, 0xbf, 0x73, 0xba, 0xfb, 0x74, 0xf7, 0x79, 0x7c, 0x00, 0x5c, 0x69, 0x99, 0x7d, 0x4c, 0x9a, + 0x1d, 0xb2, 0xa1, 0x37, 0x5b, 0xc6, 0xc6, 0xf1, 0xed, 0x0d, 0x72, 0x62, 0x61, 0x67, 0xdd, 0xb2, + 0x4d, 0x62, 0x22, 0xd9, 0x1d, 0x5d, 0xa7, 0xa3, 0xeb, 0xc7, 0xb7, 0x97, 0x9e, 0xf6, 0xf0, 0x2d, + 0xfb, 0xc4, 0x22, 0x26, 0x95, 0x78, 0x84, 0x4f, 0x84, 0xc0, 0xd2, 0x72, 0xc4, 0xb0, 0x65, 0x9b, + 0x66, 0x67, 0x62, 0x9c, 0x4d, 0xc3, 0x86, 0x75, 0x5b, 0xef, 0xbb, 0xf2, 0x57, 0x27, 0xc7, 0x8f, + 0xf5, 0x9e, 0xd1, 0xd6, 0x89, 0x69, 0x0b, 0xc8, 0xc2, 0x91, 0x79, 0x64, 0xb2, 0xcf, 0x0d, 0xfa, + 0x25, 0x7a, 0x57, 0x8e, 0x4c, 0xf3, 0xa8, 0x87, 0x37, 0x58, 0xab, 0x39, 0xec, 0x6c, 0x10, 0xa3, + 0x8f, 0x1d, 0xa2, 0xf7, 0x2d, 0x0e, 0x50, 0xfe, 0x98, 0x85, 0x69, 0x15, 0x7f, 0x38, 0xc4, 0x0e, + 0x41, 0x2f, 0x42, 0x0a, 0xb7, 0xba, 0x66, 0x51, 0x5a, 0x95, 0x6e, 0xe4, 0xee, 0x3c, 0xbd, 0x3e, + 0xbe, 0xcb, 0xf5, 0x4a, 0xab, 0x6b, 0x0a, 0xf0, 0xf6, 0x05, 0x95, 0x81, 0xd1, 0xcb, 0x90, 0xee, + 0xf4, 0x86, 0x4e, 0xb7, 0x98, 0x60, 0x52, 0xcb, 0x93, 0x52, 0x5b, 0x74, 0xd8, 0x17, 0xe3, 0x70, + 0x3a, 0x99, 0x31, 0xe8, 0x98, 0xc5, 0x64, 0xdc, 0x64, 0x3b, 0x83, 0x4e, 0x70, 0x32, 0x0a, 0x46, + 0x65, 0x00, 0x63, 0x60, 0x10, 0xad, 0xd5, 0xd5, 0x8d, 0x41, 0x31, 0xcd, 0x44, 0x95, 0x28, 0x51, + 0x83, 0x94, 0x29, 0xc4, 0x97, 0xcf, 0x1a, 0x6e, 0x1f, 0x5d, 0xf1, 0x87, 0x43, 0x6c, 0x9f, 0x14, + 0xa7, 0xe2, 0x56, 0xfc, 0x2e, 0x1d, 0x0e, 0xac, 0x98, 0xc1, 0xd1, 0x9b, 0x90, 0x69, 0x75, 0x71, + 0xeb, 0x91, 0x46, 0x46, 0xc5, 0x0c, 0x13, 0x5d, 0x9d, 0x14, 0x2d, 0x53, 0x44, 0x63, 0xe4, 0x0b, + 0x4f, 0xb7, 0x78, 0x0f, 0x7a, 0x0d, 0xa6, 0x5a, 0x66, 0xbf, 0x6f, 0x90, 0x62, 0x8e, 0x09, 0xaf, + 0x44, 0x08, 0xb3, 0x71, 0x5f, 0x56, 0x08, 0xa0, 0x2a, 0xcc, 0xf4, 0x0c, 0x87, 0x68, 0xce, 0x40, + 0xb7, 0x9c, 0xae, 0x49, 0x9c, 0x62, 0x9e, 0xa9, 0x78, 0x76, 0x52, 0xc5, 0x9e, 0xe1, 0x90, 0xba, + 0x0b, 0xf3, 0x35, 0x15, 0x7a, 0xc1, 0x7e, 0xaa, 0xd0, 0xec, 0x74, 0xb0, 0xed, 0x69, 0x2c, 0x16, + 0xe2, 0x14, 0x56, 0x29, 0xce, 0x95, 0x0c, 0x28, 0x34, 0x83, 0xfd, 0xe8, 0xff, 0x60, 0xbe, 0x67, + 0xea, 0x6d, 0x4f, 0x9f, 0xd6, 0xea, 0x0e, 0x07, 0x8f, 0x8a, 0x33, 0x4c, 0xeb, 0xcd, 0x88, 0x65, + 0x9a, 0x7a, 0xdb, 0x15, 0x2e, 0x53, 0xa8, 0xaf, 0x79, 0xae, 0x37, 0x3e, 0x86, 0x34, 0x58, 0xd0, + 0x2d, 0xab, 0x77, 0x32, 0xae, 0x7e, 0x96, 0xa9, 0xbf, 0x35, 0xa9, 0xbe, 0x44, 0xd1, 0x31, 0xfa, + 0x91, 0x3e, 0x31, 0x88, 0x0e, 0x40, 0xb6, 0x6c, 0x6c, 0xe9, 0x36, 0xd6, 0x2c, 0xdb, 0xb4, 0x4c, + 0x47, 0xef, 0x15, 0x65, 0xa6, 0xfc, 0xc6, 0xa4, 0xf2, 0x1a, 0x47, 0xd6, 0x04, 0xd0, 0xd7, 0x3c, + 0x6b, 0x85, 0x47, 0xb8, 0x5a, 0xb3, 0x85, 0x1d, 0xc7, 0x57, 0x3b, 0x17, 0xaf, 0x96, 0x21, 0x23, + 0xd5, 0x86, 0x46, 0xd0, 0x16, 0xe4, 0xf0, 0x88, 0xe0, 0x41, 0x5b, 0x3b, 0x36, 0x09, 0x2e, 0x22, + 0xa6, 0x71, 0x2d, 0xe2, 0xb9, 0x32, 0xd0, 0xa1, 0x49, 0xb0, 0xaf, 0x0c, 0xb0, 0xd7, 0x89, 0x9a, + 0xb0, 0x78, 0x8c, 0x6d, 0xa3, 0x73, 0xc2, 0xf4, 0x68, 0x6c, 0xc4, 0x31, 0xcc, 0x41, 0x71, 0x9e, + 0x69, 0x7c, 0x7e, 0x52, 0xe3, 0x21, 0x83, 0x53, 0xe1, 0x8a, 0x0b, 0xf6, 0x55, 0xcf, 0x1f, 0x4f, + 0x8e, 0xd2, 0x9b, 0xd6, 0x31, 0x06, 0x7a, 0xcf, 0xf8, 0x3e, 0xd6, 0x9a, 0x3d, 0xb3, 0xf5, 0xa8, + 0xb8, 0x10, 0x77, 0xd3, 0xb6, 0x04, 0x6e, 0x93, 0xc2, 0x02, 0x37, 0xad, 0x13, 0xec, 0xdf, 0x9c, + 0x86, 0xf4, 0xb1, 0xde, 0x1b, 0xe2, 0xdd, 0x54, 0x26, 0x25, 0xa7, 0x77, 0x53, 0x99, 0x69, 0x39, + 0xb3, 0x9b, 0xca, 0x64, 0x65, 0xd8, 0x4d, 0x65, 0x40, 0xce, 0x29, 0xd7, 0x21, 0x17, 0xf0, 0x53, + 0xa8, 0x08, 0xd3, 0x7d, 0xec, 0x38, 0xfa, 0x11, 0x66, 0x7e, 0x2d, 0xab, 0xba, 0x4d, 0x65, 0x06, + 0xf2, 0x41, 0xd7, 0xa4, 0x7c, 0x26, 0x41, 0x2e, 0xe0, 0x74, 0xa8, 0xe4, 0x31, 0xb6, 0x99, 0x41, + 0x84, 0xa4, 0x68, 0xa2, 0x35, 0x28, 0xb0, 0xbd, 0x68, 0xee, 0x38, 0xf5, 0x7d, 0x29, 0x35, 0xcf, + 0x3a, 0x0f, 0x05, 0x68, 0x05, 0x72, 0xd6, 0x1d, 0xcb, 0x83, 0x24, 0x19, 0x04, 0xac, 0x3b, 0x96, + 0x0b, 0xb8, 0x0a, 0x79, 0xba, 0x75, 0x0f, 0x91, 0x62, 0x93, 0xe4, 0x68, 0x9f, 0x80, 0x28, 0x7f, + 0x48, 0x80, 0x3c, 0xee, 0xcc, 0xd0, 0xab, 0x90, 0xa2, 0x5e, 0x5c, 0xb8, 0xe9, 0xa5, 0x75, 0xee, + 0xe2, 0xd7, 0x5d, 0x17, 0xbf, 0xde, 0x70, 0x5d, 0xfc, 0x66, 0xe6, 0xf3, 0x2f, 0x57, 0x2e, 0x7c, + 0xf6, 0xe7, 0x15, 0x49, 0x65, 0x12, 0xe8, 0x32, 0xf5, 0x60, 0xba, 0x31, 0xd0, 0x8c, 0x36, 0x5b, + 0x72, 0x96, 0x7a, 0x27, 0xdd, 0x18, 0xec, 0xb4, 0xd1, 0x7d, 0x90, 0x5b, 0xe6, 0xc0, 0xc1, 0x03, + 0x67, 0xe8, 0x68, 0x3c, 0xf6, 0x08, 0xd7, 0x1c, 0xf0, 0xaf, 0x3c, 0x06, 0x32, 0x47, 0x25, 0xa0, + 0x35, 0x86, 0x54, 0x67, 0x5b, 0xe1, 0x0e, 0xf4, 0x0e, 0x80, 0x17, 0xa0, 0x9c, 0x62, 0x6a, 0x35, + 0x79, 0x23, 0x77, 0xe7, 0x6a, 0xc4, 0x7d, 0x72, 0x31, 0x07, 0x56, 0x5b, 0x27, 0x78, 0x33, 0x45, + 0x17, 0xac, 0x06, 0x44, 0xd1, 0xb3, 0x30, 0xab, 0x5b, 0x96, 0xe6, 0x10, 0x9d, 0x60, 0xad, 0x79, + 0x42, 0xb0, 0xc3, 0xdc, 0x7e, 0x5e, 0x2d, 0xe8, 0x96, 0x55, 0xa7, 0xbd, 0x9b, 0xb4, 0x13, 0x5d, + 0x83, 0x19, 0xea, 0xe1, 0x0d, 0xbd, 0xa7, 0x75, 0xb1, 0x71, 0xd4, 0x25, 0xcc, 0xbb, 0x27, 0xd5, + 0x82, 0xe8, 0xdd, 0x66, 0x9d, 0x4a, 0x1b, 0xf2, 0x41, 0xe7, 0x8e, 0x10, 0xa4, 0xda, 0x3a, 0xd1, + 0x99, 0x2d, 0xf3, 0x2a, 0xfb, 0xa6, 0x7d, 0x96, 0x4e, 0xba, 0xc2, 0x42, 0xec, 0x1b, 0x5d, 0x84, + 0x29, 0xa1, 0x36, 0xc9, 0xd4, 0x8a, 0x16, 0x5a, 0x80, 0xb4, 0x65, 0x9b, 0xc7, 0x98, 0x1d, 0x5e, + 0x46, 0xe5, 0x0d, 0xe5, 0x01, 0xcc, 0x84, 0xe3, 0x00, 0x9a, 0x81, 0x04, 0x19, 0x89, 0x59, 0x12, + 0x64, 0x84, 0x6e, 0x43, 0x8a, 0x1a, 0x93, 0x69, 0x9b, 0x89, 0x8a, 0x7e, 0x42, 0xbe, 0x71, 0x62, + 0x61, 0x95, 0x41, 0x77, 0x53, 0x99, 0x84, 0x9c, 0x54, 0x66, 0xa1, 0x10, 0x8a, 0x12, 0xca, 0x45, + 0x58, 0x88, 0xf2, 0xf9, 0x8a, 0x01, 0x0b, 0x51, 0xae, 0x1b, 0xbd, 0x0c, 0x19, 0xcf, 0xe9, 0xbb, + 0x37, 0x68, 0x62, 0x76, 0x4f, 0xc8, 0xc3, 0xd2, 0xbb, 0x43, 0x0f, 0xa2, 0xab, 0x8b, 0x50, 0x9f, + 0x57, 0xa7, 0x75, 0xcb, 0xda, 0xd6, 0x9d, 0xae, 0xf2, 0x3e, 0x14, 0xe3, 0xfc, 0x79, 0xc0, 0x70, + 0x12, 0x7b, 0x00, 0xae, 0xe1, 0x2e, 0xc2, 0x54, 0xc7, 0xb4, 0xfb, 0x3a, 0x61, 0xca, 0x0a, 0xaa, + 0x68, 0x51, 0x83, 0x72, 0xdf, 0x9e, 0x64, 0xdd, 0xbc, 0xa1, 0x68, 0x70, 0x39, 0xd6, 0xa5, 0x53, + 0x11, 0x63, 0xd0, 0xc6, 0xdc, 0xbc, 0x05, 0x95, 0x37, 0x7c, 0x45, 0x7c, 0xb1, 0xbc, 0x41, 0xa7, + 0x75, 0xf0, 0xa0, 0x8d, 0x6d, 0xa6, 0x3f, 0xab, 0x8a, 0x96, 0xf2, 0xb3, 0x24, 0x5c, 0x8c, 0xf6, + 0xeb, 0x68, 0x15, 0xf2, 0x7d, 0x7d, 0xa4, 0x91, 0x91, 0xb8, 0x7e, 0x12, 0xbb, 0x00, 0xd0, 0xd7, + 0x47, 0x8d, 0x11, 0xbf, 0x7b, 0x32, 0x24, 0xc9, 0xc8, 0x29, 0x26, 0x56, 0x93, 0x37, 0xf2, 0x2a, + 0xfd, 0x44, 0x87, 0x30, 0xd7, 0x33, 0x5b, 0x7a, 0x4f, 0xeb, 0xe9, 0x0e, 0xd1, 0x44, 0xd8, 0xe7, + 0xcf, 0xe9, 0x99, 0x38, 0x3f, 0x8d, 0xdb, 0xfc, 0x60, 0xa9, 0x0b, 0x12, 0x0f, 0x61, 0x96, 0x29, + 0xd9, 0xd3, 0x1d, 0xc2, 0x87, 0x50, 0x05, 0x72, 0x7d, 0xc3, 0x69, 0xe2, 0xae, 0x7e, 0x6c, 0x98, + 0xb6, 0x78, 0x57, 0x11, 0xb7, 0xe7, 0xbe, 0x0f, 0x12, 0xaa, 0x82, 0x72, 0x81, 0x43, 0x49, 0x87, + 0x6e, 0xb3, 0xeb, 0x59, 0xa6, 0x1e, 0xdb, 0xb3, 0xfc, 0x17, 0x2c, 0x0c, 0xf0, 0x88, 0x68, 0xfe, + 0xcb, 0xe5, 0x37, 0x65, 0x9a, 0x19, 0x1f, 0xd1, 0x31, 0xef, 0xad, 0x3b, 0xf4, 0xd2, 0xa0, 0xe7, + 0x58, 0x6c, 0xb4, 0x4c, 0x07, 0xdb, 0x9a, 0xde, 0x6e, 0xdb, 0xd8, 0x71, 0x58, 0x56, 0x95, 0x67, + 0xf1, 0x8e, 0xf5, 0x97, 0x78, 0xb7, 0xf2, 0x29, 0x3b, 0x9c, 0xa8, 0xe8, 0xe8, 0x9a, 0x5e, 0xf2, + 0x4d, 0xdf, 0x80, 0x05, 0x21, 0xdf, 0x0e, 0x59, 0x9f, 0xa7, 0xa7, 0x57, 0xe2, 0x92, 0xae, 0x80, + 0xd5, 0x91, 0x2b, 0x1f, 0x6f, 0xf8, 0xe4, 0x13, 0x1a, 0x1e, 0x41, 0x8a, 0x99, 0x25, 0xc5, 0xdd, + 0x0d, 0xfd, 0xfe, 0x57, 0x3b, 0x8c, 0x8f, 0x93, 0x30, 0x37, 0x91, 0x58, 0x78, 0x1b, 0x93, 0x22, + 0x37, 0x96, 0x88, 0xdc, 0x58, 0xf2, 0xb1, 0x37, 0x26, 0x4e, 0x3b, 0x75, 0xf6, 0x69, 0xa7, 0xbf, + 0xcb, 0xd3, 0x9e, 0x7a, 0xc2, 0xd3, 0xfe, 0xa7, 0x9e, 0xc3, 0xcf, 0x25, 0x58, 0x8a, 0x4f, 0xc7, + 0x22, 0x0f, 0xe4, 0x16, 0xcc, 0x79, 0x4b, 0xf1, 0xd4, 0x73, 0xf7, 0x28, 0x7b, 0x03, 0x42, 0x7f, + 0x6c, 0xc4, 0xbb, 0x06, 0x33, 0x63, 0xd9, 0x22, 0xbf, 0xcc, 0x85, 0xe3, 0xe0, 0x32, 0x94, 0x4f, + 0x92, 0xb0, 0x10, 0x95, 0xd0, 0x45, 0xbc, 0x58, 0x15, 0xe6, 0xdb, 0xb8, 0x65, 0xb4, 0x9f, 0xf8, + 0xc1, 0xce, 0x09, 0xf1, 0xff, 0xbc, 0xd7, 0x88, 0x7b, 0xf2, 0x6b, 0x80, 0x8c, 0x8a, 0x1d, 0x8b, + 0x26, 0x68, 0xa8, 0x0c, 0x59, 0x3c, 0x6a, 0x61, 0x8b, 0xb8, 0x49, 0x6d, 0x4c, 0xdd, 0x20, 0x20, + 0xae, 0x1c, 0xad, 0x9f, 0x3d, 0x39, 0xf4, 0x92, 0xa0, 0x09, 0x62, 0x0b, 0x7e, 0x9e, 0x7e, 0x7b, + 0xa2, 0x9c, 0x27, 0x78, 0xc5, 0xe5, 0x09, 0x92, 0x71, 0xd5, 0xaf, 0x48, 0xc6, 0x3d, 0x39, 0x41, + 0x14, 0xbc, 0x24, 0x88, 0x82, 0x54, 0xdc, 0x74, 0x3c, 0x67, 0xf7, 0xa7, 0x63, 0x4c, 0xc1, 0xdd, + 0x10, 0x53, 0x30, 0x15, 0xb7, 0xd5, 0x40, 0x72, 0xed, 0x6f, 0xd5, 0xa7, 0x0a, 0x5e, 0x71, 0xa9, + 0x82, 0xe9, 0xb8, 0x45, 0x8b, 0x6c, 0xd2, 0x5f, 0x34, 0xe7, 0x0a, 0xde, 0x0a, 0x70, 0x05, 0x59, + 0x26, 0x7b, 0xf5, 0x14, 0xae, 0xc0, 0x93, 0xf6, 0xc8, 0x82, 0xff, 0xf1, 0xc8, 0x82, 0x7c, 0x2c, + 0xd3, 0x20, 0xd2, 0x40, 0x4f, 0xd8, 0x65, 0x0b, 0x6a, 0x13, 0x6c, 0x01, 0x2f, 0xee, 0xaf, 0x9f, + 0xc9, 0x16, 0x78, 0xaa, 0xc6, 0xe8, 0x82, 0xda, 0x04, 0x5d, 0x30, 0x13, 0xa7, 0x71, 0x2c, 0xe7, + 0xf4, 0x35, 0x86, 0xf9, 0x82, 0xff, 0x8f, 0xe6, 0x0b, 0x62, 0x0b, 0xfa, 0x88, 0xfc, 0xd2, 0x53, + 0x1d, 0x41, 0x18, 0xbc, 0x1f, 0x43, 0x18, 0xc8, 0x71, 0x85, 0x6d, 0x54, 0x76, 0xe9, 0x4d, 0x10, + 0xc5, 0x18, 0x1c, 0x46, 0x30, 0x06, 0xbc, 0xb4, 0x7f, 0xee, 0x1c, 0x8c, 0x81, 0xa7, 0x7a, 0x82, + 0x32, 0x38, 0x8c, 0xa0, 0x0c, 0x50, 0xbc, 0xde, 0xb1, 0xa4, 0x28, 0xa8, 0x37, 0xcc, 0x19, 0xbc, + 0x13, 0xe6, 0x0c, 0xe6, 0x4f, 0xcf, 0x45, 0x79, 0x68, 0xf7, 0xb4, 0x05, 0x49, 0x83, 0x56, 0x1c, + 0x69, 0xc0, 0xeb, 0xfa, 0x17, 0xce, 0x49, 0x1a, 0x78, 0xba, 0x23, 0x59, 0x83, 0xda, 0x04, 0x6b, + 0xb0, 0x18, 0x77, 0xe1, 0xc6, 0x82, 0x8c, 0x7f, 0xe1, 0x62, 0x69, 0x83, 0xb4, 0x3c, 0xb5, 0x9b, + 0xca, 0x64, 0xe4, 0x2c, 0x27, 0x0c, 0x76, 0x53, 0x99, 0x9c, 0x9c, 0x57, 0x9e, 0xa3, 0x69, 0xcd, + 0x98, 0xdf, 0xa3, 0x45, 0x04, 0xb6, 0x6d, 0xd3, 0x16, 0x04, 0x00, 0x6f, 0x28, 0x37, 0x20, 0x1f, + 0x74, 0x71, 0xa7, 0x50, 0x0c, 0xb3, 0x50, 0x08, 0x79, 0x35, 0xe5, 0x77, 0x12, 0xe4, 0x83, 0xfe, + 0x2a, 0x54, 0x80, 0x66, 0x45, 0x01, 0x1a, 0x20, 0x1e, 0x12, 0x61, 0xe2, 0x61, 0x05, 0x72, 0xb4, + 0x08, 0x1b, 0xe3, 0x14, 0x74, 0xcb, 0xe3, 0x14, 0x6e, 0xc2, 0x1c, 0x8b, 0xa1, 0x9c, 0x9e, 0x10, + 0x71, 0x2a, 0xc5, 0xe2, 0xd4, 0x2c, 0x1d, 0x60, 0xc6, 0xe0, 0xb5, 0x30, 0x7a, 0x01, 0xe6, 0x03, + 0x58, 0xaf, 0xb8, 0xe3, 0xe5, 0xb5, 0xec, 0xa1, 0x4b, 0xa2, 0xca, 0xfb, 0xbd, 0x04, 0x73, 0x13, + 0xee, 0x32, 0x92, 0x37, 0x90, 0xbe, 0x2b, 0xde, 0x20, 0xf1, 0xe4, 0xbc, 0x41, 0xb0, 0x5c, 0x4d, + 0x86, 0xcb, 0xd5, 0xbf, 0x4b, 0x50, 0x08, 0xb9, 0x6d, 0x7a, 0x08, 0x2d, 0xb3, 0x8d, 0x45, 0x01, + 0xc9, 0xbe, 0x69, 0x9e, 0xd2, 0x33, 0x8f, 0x44, 0x99, 0x48, 0x3f, 0x29, 0xca, 0x0b, 0x44, 0x59, + 0x11, 0x66, 0xbc, 0xda, 0x93, 0xe7, 0x02, 0xa2, 0xf6, 0x94, 0x21, 0xf9, 0x08, 0x73, 0x7e, 0x39, + 0xaf, 0xd2, 0x4f, 0x8a, 0x63, 0xd7, 0x4f, 0xc4, 0x74, 0xde, 0x40, 0xaf, 0x41, 0x96, 0xfd, 0x0a, + 0xa0, 0x99, 0x96, 0x23, 0x28, 0xe5, 0x40, 0xbe, 0xc3, 0x7f, 0x2a, 0x10, 0xef, 0xdc, 0xec, 0x54, + 0x2d, 0x47, 0xcd, 0x58, 0xe2, 0x2b, 0x90, 0x85, 0x64, 0x43, 0x59, 0xc8, 0x15, 0xc8, 0xd2, 0xe5, + 0x3b, 0x96, 0xde, 0xc2, 0x45, 0x60, 0x2b, 0xf5, 0x3b, 0x94, 0xdf, 0x24, 0x60, 0x76, 0x2c, 0xea, + 0x44, 0x6e, 0xde, 0xbd, 0x95, 0x89, 0x00, 0x2d, 0x72, 0x3e, 0x83, 0x2c, 0x03, 0x1c, 0xe9, 0x8e, + 0xf6, 0x91, 0x3e, 0x20, 0xb8, 0x2d, 0xac, 0x12, 0xe8, 0x41, 0x4b, 0x90, 0xa1, 0xad, 0xa1, 0x83, + 0xdb, 0x82, 0xa1, 0xf1, 0xda, 0x68, 0x07, 0xa6, 0xf0, 0x31, 0x1e, 0x10, 0xa7, 0x38, 0xcd, 0x0e, + 0xfe, 0x52, 0x84, 0x7b, 0xa2, 0xe3, 0x9b, 0x45, 0x7a, 0xdc, 0x7f, 0xfd, 0x72, 0x45, 0xe6, 0xf0, + 0xe7, 0xcd, 0xbe, 0x41, 0x70, 0xdf, 0x22, 0x27, 0xaa, 0x50, 0x10, 0x36, 0x43, 0x66, 0xcc, 0x0c, + 0x8c, 0x2e, 0xcc, 0xbb, 0xb5, 0x3f, 0x35, 0xaa, 0x61, 0xda, 0x06, 0x39, 0x51, 0x0b, 0x7d, 0xdc, + 0xb7, 0x4c, 0xb3, 0xa7, 0xf1, 0x77, 0x5e, 0x82, 0x99, 0x70, 0x90, 0x45, 0x6b, 0x50, 0xb0, 0x31, + 0xd1, 0x8d, 0x81, 0x16, 0xca, 0x8d, 0xf3, 0xbc, 0x93, 0xbf, 0xab, 0xdd, 0x54, 0x46, 0x92, 0x13, + 0x82, 0xae, 0x79, 0x17, 0x16, 0x23, 0x63, 0x2c, 0x7a, 0x15, 0xb2, 0x7e, 0x7c, 0x96, 0xd8, 0x76, + 0x4f, 0xe3, 0x61, 0x7c, 0xb0, 0x72, 0x08, 0x8b, 0x91, 0x41, 0x16, 0xbd, 0x09, 0x53, 0x36, 0x76, + 0x86, 0x3d, 0x4e, 0xb5, 0xcc, 0xdc, 0xb9, 0x76, 0x76, 0x74, 0x1e, 0xf6, 0x88, 0x2a, 0x84, 0x94, + 0xdb, 0x70, 0x39, 0x36, 0xca, 0xfa, 0x6c, 0x8a, 0x14, 0x60, 0x53, 0x94, 0xdf, 0x4a, 0xb0, 0x14, + 0x1f, 0x39, 0xd1, 0xe6, 0xd8, 0x82, 0x6e, 0x9e, 0x33, 0xee, 0x06, 0x56, 0x45, 0xcb, 0x0d, 0x1b, + 0x77, 0x30, 0x69, 0x75, 0x79, 0x08, 0xe7, 0x4e, 0xa1, 0xa0, 0x16, 0x44, 0x2f, 0x93, 0x71, 0x38, + 0xec, 0x03, 0xdc, 0x22, 0x1a, 0x3f, 0x54, 0x87, 0xa5, 0xfc, 0x59, 0x0a, 0xa3, 0xbd, 0x75, 0xde, + 0xa9, 0xdc, 0x82, 0x4b, 0x31, 0xb1, 0x78, 0xb2, 0x2e, 0x51, 0x1e, 0x52, 0x70, 0x64, 0x80, 0x45, + 0x6f, 0xc3, 0x94, 0x43, 0x74, 0x32, 0x74, 0xc4, 0xce, 0xae, 0x9f, 0x19, 0x9b, 0xeb, 0x0c, 0xae, + 0x0a, 0x31, 0xe5, 0x75, 0x40, 0x93, 0x91, 0x36, 0xa2, 0xb6, 0x92, 0xa2, 0x6a, 0xab, 0x26, 0x3c, + 0x75, 0x4a, 0x4c, 0x45, 0xe5, 0xb1, 0xc5, 0xdd, 0x3a, 0x57, 0x48, 0x1e, 0x5b, 0xe0, 0xdf, 0x12, + 0xb0, 0x18, 0x19, 0x5a, 0x03, 0xaf, 0x54, 0xfa, 0xb6, 0xaf, 0xf4, 0x4d, 0x00, 0x32, 0xd2, 0xf8, + 0x49, 0xbb, 0xde, 0x3e, 0xaa, 0x9e, 0x18, 0xe1, 0x16, 0x73, 0x58, 0xf4, 0x62, 0x64, 0x89, 0xf8, + 0xa2, 0xc5, 0x7f, 0xa0, 0x9e, 0x1d, 0xb2, 0x48, 0xe0, 0x88, 0x52, 0xef, 0xdc, 0x31, 0xc3, 0x2f, + 0x7c, 0x79, 0xb7, 0x83, 0x1e, 0xc2, 0xa5, 0xb1, 0x88, 0xe6, 0xe9, 0x4e, 0x9d, 0x3b, 0xb0, 0x2d, + 0x86, 0x03, 0x9b, 0xab, 0x3b, 0x18, 0x95, 0xd2, 0xe1, 0xa8, 0xf4, 0x10, 0xc0, 0x2f, 0x6c, 0xe9, + 0x7b, 0xb3, 0xcd, 0xe1, 0xa0, 0xcd, 0x8e, 0x30, 0xad, 0xf2, 0x06, 0x7a, 0x19, 0xd2, 0xf4, 0x26, + 0xb8, 0xa6, 0x8a, 0x70, 0x18, 0xf4, 0x48, 0x03, 0x95, 0x31, 0x87, 0x2b, 0x1f, 0xb8, 0xb7, 0x2d, + 0xc8, 0x31, 0xc6, 0xcc, 0xf1, 0x56, 0x78, 0x0e, 0x25, 0x9e, 0xae, 0x8c, 0x9e, 0xeb, 0x07, 0x90, + 0x66, 0xc7, 0x4f, 0xa3, 0x03, 0xa3, 0xb8, 0x45, 0x66, 0x43, 0xbf, 0xd1, 0xf7, 0x00, 0x74, 0x42, + 0x6c, 0xa3, 0x39, 0xf4, 0x67, 0x58, 0x8d, 0xb9, 0x3f, 0x25, 0x17, 0xb8, 0x79, 0x45, 0x5c, 0xa4, + 0x05, 0x5f, 0x36, 0x70, 0x99, 0x02, 0x1a, 0x95, 0x7d, 0x98, 0x09, 0xcb, 0xba, 0xa1, 0x98, 0x2f, + 0x22, 0x1c, 0x8a, 0x79, 0x6e, 0x25, 0x42, 0xb1, 0x17, 0xc8, 0x93, 0x9c, 0xc8, 0x67, 0x0d, 0xe5, + 0x87, 0x09, 0xc8, 0x07, 0x6f, 0xdf, 0xbf, 0x61, 0xb0, 0x54, 0x3e, 0x91, 0x20, 0xe3, 0xed, 0x3f, + 0x4c, 0xe7, 0x87, 0x7e, 0x07, 0xe1, 0xe6, 0x4b, 0x04, 0x39, 0x78, 0xfe, 0xab, 0x47, 0xd2, 0xfb, + 0xd5, 0xe3, 0x0d, 0x2f, 0x20, 0xc4, 0x16, 0xf3, 0x41, 0x6b, 0x8b, 0x8b, 0xe5, 0x06, 0xa8, 0xd7, + 0x21, 0xeb, 0xbd, 0x61, 0x9a, 0x23, 0xbb, 0xc4, 0x87, 0x24, 0x1e, 0x92, 0x20, 0xae, 0x16, 0x20, + 0x6d, 0x99, 0x1f, 0x09, 0x86, 0x3f, 0xa9, 0xf2, 0x86, 0x82, 0x61, 0x76, 0xcc, 0x01, 0xa0, 0x37, + 0x60, 0xda, 0x1a, 0x36, 0x35, 0xf7, 0x7a, 0x84, 0xf8, 0xa1, 0x40, 0xee, 0x35, 0x6c, 0xf6, 0x8c, + 0xd6, 0x3d, 0x7c, 0xe2, 0xae, 0xc6, 0x1a, 0x36, 0xef, 0xf1, 0x6b, 0xc4, 0xa7, 0x49, 0x04, 0xa7, + 0xf9, 0xa9, 0x04, 0x19, 0xf7, 0x5d, 0xa0, 0xb7, 0x21, 0xeb, 0x79, 0x17, 0x31, 0xc5, 0x53, 0xa7, + 0xf8, 0x25, 0x31, 0x81, 0x2f, 0x83, 0x36, 0xdd, 0xdf, 0x19, 0x8d, 0xb6, 0xd6, 0xe9, 0xe9, 0x47, + 0xe2, 0xe7, 0xa2, 0xe5, 0x08, 0x07, 0xc4, 0x7c, 0xf4, 0xce, 0xdd, 0xad, 0x9e, 0x7e, 0xa4, 0xe6, + 0x98, 0xd0, 0x4e, 0x9b, 0x36, 0x44, 0x1e, 0xf2, 0x8d, 0x04, 0xf2, 0xf8, 0xbb, 0xfd, 0xf6, 0xeb, + 0x9b, 0x8c, 0x57, 0xc9, 0x88, 0x78, 0x85, 0x36, 0x60, 0xde, 0x43, 0x68, 0x8e, 0x71, 0x34, 0xd0, + 0xc9, 0xd0, 0xc6, 0x82, 0x54, 0x43, 0xde, 0x50, 0xdd, 0x1d, 0x99, 0xdc, 0x77, 0xfa, 0x49, 0xf7, + 0xfd, 0x71, 0x02, 0x72, 0x01, 0x8e, 0x0f, 0xfd, 0x77, 0xc0, 0x29, 0xcd, 0x44, 0x45, 0x89, 0x00, + 0xd8, 0xff, 0xed, 0x2d, 0x6c, 0xa9, 0xc4, 0x13, 0x58, 0x2a, 0x8e, 0x4d, 0x75, 0x49, 0xc3, 0xd4, + 0x63, 0x93, 0x86, 0xcf, 0x03, 0x22, 0x26, 0xd1, 0x7b, 0xb4, 0x0c, 0x37, 0x06, 0x47, 0x1a, 0xbf, + 0x8c, 0xdc, 0x87, 0xc8, 0x6c, 0xe4, 0x90, 0x0d, 0xd4, 0xd8, 0xbd, 0xfc, 0x91, 0x04, 0x19, 0x8f, + 0x7c, 0x79, 0xdc, 0xdf, 0xe4, 0x2e, 0xc2, 0x94, 0xc8, 0xbd, 0xf8, 0x8f, 0x72, 0xa2, 0x15, 0xc9, + 0x8e, 0x2e, 0x41, 0xa6, 0x8f, 0x89, 0xce, 0x1c, 0x22, 0x8f, 0x70, 0x5e, 0xfb, 0x66, 0x13, 0x72, + 0x81, 0x9f, 0x35, 0xd1, 0x65, 0x58, 0x2c, 0x6f, 0x57, 0xca, 0xf7, 0xb4, 0xc6, 0x7b, 0x5a, 0xe3, + 0x41, 0xad, 0xa2, 0x1d, 0xec, 0xdf, 0xdb, 0xaf, 0xfe, 0xef, 0xbe, 0x7c, 0x61, 0x72, 0x48, 0xad, + 0xb0, 0xb6, 0x2c, 0xa1, 0x4b, 0x30, 0x1f, 0x1e, 0xe2, 0x03, 0x89, 0xa5, 0xd4, 0x4f, 0x7e, 0xb5, + 0x7c, 0xe1, 0xe6, 0x37, 0x12, 0xcc, 0x47, 0x64, 0xb9, 0xe8, 0x2a, 0x3c, 0x5d, 0xdd, 0xda, 0xaa, + 0xa8, 0x5a, 0x7d, 0xbf, 0x54, 0xab, 0x6f, 0x57, 0x1b, 0x9a, 0x5a, 0xa9, 0x1f, 0xec, 0x35, 0x02, + 0x93, 0xae, 0xc2, 0x95, 0x68, 0x48, 0xa9, 0x5c, 0xae, 0xd4, 0x1a, 0xb2, 0x84, 0x56, 0xe0, 0xa9, + 0x18, 0xc4, 0x66, 0x55, 0x6d, 0xc8, 0x89, 0x78, 0x15, 0x6a, 0x65, 0xb7, 0x52, 0x6e, 0xc8, 0x49, + 0x74, 0x1d, 0xd6, 0x4e, 0x43, 0x68, 0x5b, 0x55, 0xf5, 0x7e, 0xa9, 0x21, 0xa7, 0xce, 0x04, 0xd6, + 0x2b, 0xfb, 0x77, 0x2b, 0xaa, 0x9c, 0x16, 0xfb, 0xfe, 0x65, 0x02, 0x8a, 0x71, 0xc9, 0x34, 0xd5, + 0x55, 0xaa, 0xd5, 0xf6, 0x1e, 0xf8, 0xba, 0xca, 0xdb, 0x07, 0xfb, 0xf7, 0x26, 0x4d, 0xf0, 0x2c, + 0x28, 0xa7, 0x01, 0x3d, 0x43, 0x5c, 0x83, 0xab, 0xa7, 0xe2, 0x84, 0x39, 0xce, 0x80, 0xa9, 0x95, + 0x86, 0xfa, 0x40, 0x4e, 0xa2, 0x75, 0xb8, 0x79, 0x26, 0xcc, 0x1b, 0x93, 0x53, 0x68, 0x03, 0x6e, + 0x9d, 0x8e, 0xe7, 0x06, 0x72, 0x05, 0x5c, 0x13, 0x7d, 0x2a, 0xc1, 0x62, 0x64, 0x56, 0x8e, 0xd6, + 0x60, 0xa5, 0xa6, 0x56, 0xcb, 0x95, 0x7a, 0x5d, 0xab, 0xa9, 0xd5, 0x5a, 0xb5, 0x5e, 0xda, 0xd3, + 0xea, 0x8d, 0x52, 0xe3, 0xa0, 0x1e, 0xb0, 0x8d, 0x02, 0xcb, 0x71, 0x20, 0xcf, 0x2e, 0xa7, 0x60, + 0xc4, 0x0d, 0x70, 0xef, 0xe9, 0x2f, 0x24, 0xb8, 0x1c, 0x9b, 0x85, 0xa3, 0x1b, 0xf0, 0xcc, 0x61, + 0x45, 0xdd, 0xd9, 0x7a, 0xa0, 0x1d, 0x56, 0x1b, 0x15, 0xad, 0xf2, 0x5e, 0xa3, 0xb2, 0x5f, 0xdf, + 0xa9, 0xee, 0x4f, 0xae, 0xea, 0x3a, 0xac, 0x9d, 0x8a, 0xf4, 0x96, 0x76, 0x16, 0x70, 0x6c, 0x7d, + 0x3f, 0x96, 0x60, 0x76, 0xcc, 0x17, 0xa2, 0x2b, 0x50, 0xbc, 0xbf, 0x53, 0xdf, 0xac, 0x6c, 0x97, + 0x0e, 0x77, 0xaa, 0xea, 0xf8, 0x9b, 0x5d, 0x83, 0x95, 0x89, 0xd1, 0xbb, 0x07, 0xb5, 0xbd, 0x9d, + 0x72, 0xa9, 0x51, 0x61, 0x93, 0xca, 0x12, 0xdd, 0xd8, 0x04, 0x68, 0x6f, 0xe7, 0x9d, 0xed, 0x86, + 0x56, 0xde, 0xdb, 0xa9, 0xec, 0x37, 0xb4, 0x52, 0xa3, 0x51, 0xf2, 0x9f, 0xf3, 0xe6, 0xbd, 0xcf, + 0xbf, 0x5a, 0x96, 0xbe, 0xf8, 0x6a, 0x59, 0xfa, 0xcb, 0x57, 0xcb, 0xd2, 0x67, 0x5f, 0x2f, 0x5f, + 0xf8, 0xe2, 0xeb, 0xe5, 0x0b, 0x7f, 0xfa, 0x7a, 0xf9, 0xc2, 0xc3, 0xdb, 0x47, 0x06, 0xe9, 0x0e, + 0x9b, 0xd4, 0x0b, 0x6f, 0xf8, 0xff, 0xae, 0xf4, 0xfe, 0xb5, 0x69, 0x19, 0x1b, 0xe3, 0x7f, 0xe1, + 0x6c, 0x4e, 0x31, 0xb7, 0xfa, 0xe2, 0x3f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe3, 0x41, 0x56, 0x8d, + 0xdd, 0x29, 0x00, 0x00, } func (m *Request) Marshal() (dAtA []byte, err error) { @@ -4813,7 +4325,7 @@ func (m *Request_FinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } -func (m *RequestEcho) Marshal() (dAtA []byte, err error) { +func (m *EchoRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4823,12 +4335,12 @@ func (m *RequestEcho) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestEcho) MarshalTo(dAtA []byte) (int, error) { +func (m *EchoRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestEcho) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *EchoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -4843,7 +4355,7 @@ func (m *RequestEcho) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestFlush) Marshal() (dAtA []byte, err error) { +func (m *FlushRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4853,12 +4365,12 @@ func (m *RequestFlush) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestFlush) MarshalTo(dAtA []byte) (int, error) { +func (m *FlushRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestFlush) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *FlushRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -4866,7 +4378,7 @@ func (m *RequestFlush) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestInfo) Marshal() (dAtA []byte, err error) { +func (m *InfoRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4876,12 +4388,12 @@ func (m *RequestInfo) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestInfo) MarshalTo(dAtA []byte) (int, error) { +func (m *InfoRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *InfoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -4913,7 +4425,7 @@ func (m *RequestInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestInitChain) Marshal() (dAtA []byte, err error) { +func (m *InitChainRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4923,12 +4435,12 @@ func (m *RequestInitChain) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestInitChain) MarshalTo(dAtA []byte) (int, error) { +func (m *InitChainRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *InitChainRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -4989,7 +4501,7 @@ func (m *RequestInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestQuery) Marshal() (dAtA []byte, err error) { +func (m *QueryRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4999,12 +4511,12 @@ func (m *RequestQuery) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestQuery) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5041,7 +4553,7 @@ func (m *RequestQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestCheckTx) Marshal() (dAtA []byte, err error) { +func (m *CheckTxRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5051,12 +4563,12 @@ func (m *RequestCheckTx) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestCheckTx) MarshalTo(dAtA []byte) (int, error) { +func (m *CheckTxRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *CheckTxRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5064,7 +4576,7 @@ func (m *RequestCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { if m.Type != 0 { i = encodeVarintTypes(dAtA, i, uint64(m.Type)) i-- - dAtA[i] = 0x10 + dAtA[i] = 0x18 } if len(m.Tx) > 0 { i -= len(m.Tx) @@ -5076,7 +4588,7 @@ func (m *RequestCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestCommit) Marshal() (dAtA []byte, err error) { +func (m *CommitRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5086,12 +4598,12 @@ func (m *RequestCommit) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestCommit) MarshalTo(dAtA []byte) (int, error) { +func (m *CommitRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *CommitRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5099,7 +4611,7 @@ func (m *RequestCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestListSnapshots) Marshal() (dAtA []byte, err error) { +func (m *ListSnapshotsRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5109,12 +4621,12 @@ func (m *RequestListSnapshots) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestListSnapshots) MarshalTo(dAtA []byte) (int, error) { +func (m *ListSnapshotsRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ListSnapshotsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5122,7 +4634,7 @@ func (m *RequestListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestOfferSnapshot) Marshal() (dAtA []byte, err error) { +func (m *OfferSnapshotRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5132,12 +4644,12 @@ func (m *RequestOfferSnapshot) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestOfferSnapshot) MarshalTo(dAtA []byte) (int, error) { +func (m *OfferSnapshotRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestOfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *OfferSnapshotRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5164,7 +4676,7 @@ func (m *RequestOfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestLoadSnapshotChunk) Marshal() (dAtA []byte, err error) { +func (m *LoadSnapshotChunkRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5174,12 +4686,12 @@ func (m *RequestLoadSnapshotChunk) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestLoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { +func (m *LoadSnapshotChunkRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestLoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *LoadSnapshotChunkRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5202,7 +4714,7 @@ func (m *RequestLoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } -func (m *RequestApplySnapshotChunk) Marshal() (dAtA []byte, err error) { +func (m *ApplySnapshotChunkRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5212,12 +4724,12 @@ func (m *RequestApplySnapshotChunk) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { +func (m *ApplySnapshotChunkRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ApplySnapshotChunkRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5244,7 +4756,7 @@ func (m *RequestApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } -func (m *RequestPrepareProposal) Marshal() (dAtA []byte, err error) { +func (m *PrepareProposalRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5254,12 +4766,12 @@ func (m *RequestPrepareProposal) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestPrepareProposal) MarshalTo(dAtA []byte) (int, error) { +func (m *PrepareProposalRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestPrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *PrepareProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5332,7 +4844,7 @@ func (m *RequestPrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } -func (m *RequestProcessProposal) Marshal() (dAtA []byte, err error) { +func (m *ProcessProposalRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5342,12 +4854,12 @@ func (m *RequestProcessProposal) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestProcessProposal) MarshalTo(dAtA []byte) (int, error) { +func (m *ProcessProposalRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ProcessProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5384,7 +4896,77 @@ func (m *RequestProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) copy(dAtA[i:], m.Hash) i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) i-- - dAtA[i] = 0x22 + dAtA[i] = 0x22 + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.ProposedLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ExtendVoteRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExtendVoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExtendVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a } if len(m.Misbehavior) > 0 { for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { @@ -5397,7 +4979,7 @@ func (m *RequestProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) i = encodeVarintTypes(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x1a + dAtA[i] = 0x32 } } { @@ -5409,39 +4991,24 @@ func (m *RequestProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) i = encodeVarintTypes(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x12 + dAtA[i] = 0x2a if len(m.Txs) > 0 { for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Txs[iNdEx]) copy(dAtA[i:], m.Txs[iNdEx]) i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) i-- - dAtA[i] = 0xa + dAtA[i] = 0x22 } } - return len(dAtA) - i, nil -} - -func (m *RequestExtendVote) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err + n25, err25 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err25 != nil { + return 0, err25 } - return dAtA[:n], nil -} - -func (m *RequestExtendVote) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *RequestExtendVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l + i -= n25 + i = encodeVarintTypes(dAtA, i, uint64(n25)) + i-- + dAtA[i] = 0x1a if m.Height != 0 { i = encodeVarintTypes(dAtA, i, uint64(m.Height)) i-- @@ -5457,7 +5024,7 @@ func (m *RequestExtendVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RequestVerifyVoteExtension) Marshal() (dAtA []byte, err error) { +func (m *VerifyVoteExtensionRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5467,12 +5034,12 @@ func (m *RequestVerifyVoteExtension) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestVerifyVoteExtension) MarshalTo(dAtA []byte) (int, error) { +func (m *VerifyVoteExtensionRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestVerifyVoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *VerifyVoteExtensionRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5506,7 +5073,7 @@ func (m *RequestVerifyVoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } -func (m *RequestFinalizeBlock) Marshal() (dAtA []byte, err error) { +func (m *FinalizeBlockRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -5516,12 +5083,12 @@ func (m *RequestFinalizeBlock) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RequestFinalizeBlock) MarshalTo(dAtA []byte) (int, error) { +func (m *FinalizeBlockRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RequestFinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *FinalizeBlockRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -5540,12 +5107,12 @@ func (m *RequestFinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x3a } - n24, err24 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) - if err24 != nil { - return 0, err24 + n26, err26 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err26 != nil { + return 0, err26 } - i -= n24 - i = encodeVarintTypes(dAtA, i, uint64(n24)) + i -= n26 + i = encodeVarintTypes(dAtA, i, uint64(n26)) i-- dAtA[i] = 0x32 if m.Height != 0 { @@ -5997,7 +5564,7 @@ func (m *Response_FinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) } return len(dAtA) - i, nil } -func (m *ResponseException) Marshal() (dAtA []byte, err error) { +func (m *ExceptionResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6007,12 +5574,12 @@ func (m *ResponseException) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseException) MarshalTo(dAtA []byte) (int, error) { +func (m *ExceptionResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseException) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ExceptionResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6027,7 +5594,7 @@ func (m *ResponseException) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseEcho) Marshal() (dAtA []byte, err error) { +func (m *EchoResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6037,12 +5604,12 @@ func (m *ResponseEcho) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseEcho) MarshalTo(dAtA []byte) (int, error) { +func (m *EchoResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseEcho) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *EchoResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6057,7 +5624,7 @@ func (m *ResponseEcho) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseFlush) Marshal() (dAtA []byte, err error) { +func (m *FlushResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6067,12 +5634,12 @@ func (m *ResponseFlush) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseFlush) MarshalTo(dAtA []byte) (int, error) { +func (m *FlushResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseFlush) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *FlushResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6080,7 +5647,7 @@ func (m *ResponseFlush) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseInfo) Marshal() (dAtA []byte, err error) { +func (m *InfoResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6090,12 +5657,12 @@ func (m *ResponseInfo) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseInfo) MarshalTo(dAtA []byte) (int, error) { +func (m *InfoResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *InfoResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6134,7 +5701,7 @@ func (m *ResponseInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseInitChain) Marshal() (dAtA []byte, err error) { +func (m *InitChainResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6144,12 +5711,12 @@ func (m *ResponseInitChain) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseInitChain) MarshalTo(dAtA []byte) (int, error) { +func (m *InitChainResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *InitChainResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6190,7 +5757,7 @@ func (m *ResponseInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseQuery) Marshal() (dAtA []byte, err error) { +func (m *QueryResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6200,12 +5767,12 @@ func (m *ResponseQuery) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseQuery) MarshalTo(dAtA []byte) (int, error) { +func (m *QueryResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *QueryResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6275,7 +5842,7 @@ func (m *ResponseQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseCheckTx) Marshal() (dAtA []byte, err error) { +func (m *CheckTxResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6285,12 +5852,12 @@ func (m *ResponseCheckTx) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseCheckTx) MarshalTo(dAtA []byte) (int, error) { +func (m *CheckTxResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *CheckTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6355,7 +5922,7 @@ func (m *ResponseCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseCommit) Marshal() (dAtA []byte, err error) { +func (m *CommitResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6365,12 +5932,12 @@ func (m *ResponseCommit) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseCommit) MarshalTo(dAtA []byte) (int, error) { +func (m *CommitResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *CommitResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6383,7 +5950,7 @@ func (m *ResponseCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseListSnapshots) Marshal() (dAtA []byte, err error) { +func (m *ListSnapshotsResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6393,12 +5960,12 @@ func (m *ResponseListSnapshots) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseListSnapshots) MarshalTo(dAtA []byte) (int, error) { +func (m *ListSnapshotsResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ListSnapshotsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6420,7 +5987,7 @@ func (m *ResponseListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseOfferSnapshot) Marshal() (dAtA []byte, err error) { +func (m *OfferSnapshotResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6430,12 +5997,12 @@ func (m *ResponseOfferSnapshot) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseOfferSnapshot) MarshalTo(dAtA []byte) (int, error) { +func (m *OfferSnapshotResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseOfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *OfferSnapshotResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6448,7 +6015,7 @@ func (m *ResponseOfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseLoadSnapshotChunk) Marshal() (dAtA []byte, err error) { +func (m *LoadSnapshotChunkResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6458,12 +6025,12 @@ func (m *ResponseLoadSnapshotChunk) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseLoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { +func (m *LoadSnapshotChunkResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseLoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *LoadSnapshotChunkResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6478,7 +6045,7 @@ func (m *ResponseLoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } -func (m *ResponseApplySnapshotChunk) Marshal() (dAtA []byte, err error) { +func (m *ApplySnapshotChunkResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6488,12 +6055,12 @@ func (m *ResponseApplySnapshotChunk) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { +func (m *ApplySnapshotChunkResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ApplySnapshotChunkResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6508,20 +6075,20 @@ func (m *ResponseApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, err } } if len(m.RefetchChunks) > 0 { - dAtA46 := make([]byte, len(m.RefetchChunks)*10) - var j45 int + dAtA48 := make([]byte, len(m.RefetchChunks)*10) + var j47 int for _, num := range m.RefetchChunks { for num >= 1<<7 { - dAtA46[j45] = uint8(uint64(num)&0x7f | 0x80) + dAtA48[j47] = uint8(uint64(num)&0x7f | 0x80) num >>= 7 - j45++ + j47++ } - dAtA46[j45] = uint8(num) - j45++ + dAtA48[j47] = uint8(num) + j47++ } - i -= j45 - copy(dAtA[i:], dAtA46[:j45]) - i = encodeVarintTypes(dAtA, i, uint64(j45)) + i -= j47 + copy(dAtA[i:], dAtA48[:j47]) + i = encodeVarintTypes(dAtA, i, uint64(j47)) i-- dAtA[i] = 0x12 } @@ -6533,7 +6100,7 @@ func (m *ResponseApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, err return len(dAtA) - i, nil } -func (m *ResponsePrepareProposal) Marshal() (dAtA []byte, err error) { +func (m *PrepareProposalResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6543,12 +6110,12 @@ func (m *ResponsePrepareProposal) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponsePrepareProposal) MarshalTo(dAtA []byte) (int, error) { +func (m *PrepareProposalResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponsePrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *PrepareProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6565,7 +6132,7 @@ func (m *ResponsePrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } -func (m *ResponseProcessProposal) Marshal() (dAtA []byte, err error) { +func (m *ProcessProposalResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6575,12 +6142,12 @@ func (m *ResponseProcessProposal) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseProcessProposal) MarshalTo(dAtA []byte) (int, error) { +func (m *ProcessProposalResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ProcessProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6593,7 +6160,7 @@ func (m *ResponseProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } -func (m *ResponseExtendVote) Marshal() (dAtA []byte, err error) { +func (m *ExtendVoteResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6603,12 +6170,12 @@ func (m *ResponseExtendVote) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseExtendVote) MarshalTo(dAtA []byte) (int, error) { +func (m *ExtendVoteResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseExtendVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ExtendVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6623,7 +6190,7 @@ func (m *ResponseExtendVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ResponseVerifyVoteExtension) Marshal() (dAtA []byte, err error) { +func (m *VerifyVoteExtensionResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6633,12 +6200,12 @@ func (m *ResponseVerifyVoteExtension) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseVerifyVoteExtension) MarshalTo(dAtA []byte) (int, error) { +func (m *VerifyVoteExtensionResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseVerifyVoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *VerifyVoteExtensionResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -6651,7 +6218,7 @@ func (m *ResponseVerifyVoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } -func (m *ResponseFinalizeBlock) Marshal() (dAtA []byte, err error) { +func (m *FinalizeBlockResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -6661,12 +6228,12 @@ func (m *ResponseFinalizeBlock) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ResponseFinalizeBlock) MarshalTo(dAtA []byte) (int, error) { +func (m *FinalizeBlockResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ResponseFinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *FinalizeBlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -7228,12 +6795,12 @@ func (m *Misbehavior) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x28 } - n52, err52 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) - if err52 != nil { - return 0, err52 + n54, err54 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err54 != nil { + return 0, err54 } - i -= n52 - i = encodeVarintTypes(dAtA, i, uint64(n52)) + i -= n54 + i = encodeVarintTypes(dAtA, i, uint64(n54)) i-- dAtA[i] = 0x22 if m.Height != 0 { @@ -7526,7 +7093,7 @@ func (m *Request_FinalizeBlock) Size() (n int) { } return n } -func (m *RequestEcho) Size() (n int) { +func (m *EchoRequest) Size() (n int) { if m == nil { return 0 } @@ -7539,7 +7106,7 @@ func (m *RequestEcho) Size() (n int) { return n } -func (m *RequestFlush) Size() (n int) { +func (m *FlushRequest) Size() (n int) { if m == nil { return 0 } @@ -7548,7 +7115,7 @@ func (m *RequestFlush) Size() (n int) { return n } -func (m *RequestInfo) Size() (n int) { +func (m *InfoRequest) Size() (n int) { if m == nil { return 0 } @@ -7571,7 +7138,7 @@ func (m *RequestInfo) Size() (n int) { return n } -func (m *RequestInitChain) Size() (n int) { +func (m *InitChainRequest) Size() (n int) { if m == nil { return 0 } @@ -7603,7 +7170,7 @@ func (m *RequestInitChain) Size() (n int) { return n } -func (m *RequestQuery) Size() (n int) { +func (m *QueryRequest) Size() (n int) { if m == nil { return 0 } @@ -7626,7 +7193,7 @@ func (m *RequestQuery) Size() (n int) { return n } -func (m *RequestCheckTx) Size() (n int) { +func (m *CheckTxRequest) Size() (n int) { if m == nil { return 0 } @@ -7642,7 +7209,7 @@ func (m *RequestCheckTx) Size() (n int) { return n } -func (m *RequestCommit) Size() (n int) { +func (m *CommitRequest) Size() (n int) { if m == nil { return 0 } @@ -7651,7 +7218,7 @@ func (m *RequestCommit) Size() (n int) { return n } -func (m *RequestListSnapshots) Size() (n int) { +func (m *ListSnapshotsRequest) Size() (n int) { if m == nil { return 0 } @@ -7660,7 +7227,7 @@ func (m *RequestListSnapshots) Size() (n int) { return n } -func (m *RequestOfferSnapshot) Size() (n int) { +func (m *OfferSnapshotRequest) Size() (n int) { if m == nil { return 0 } @@ -7677,7 +7244,7 @@ func (m *RequestOfferSnapshot) Size() (n int) { return n } -func (m *RequestLoadSnapshotChunk) Size() (n int) { +func (m *LoadSnapshotChunkRequest) Size() (n int) { if m == nil { return 0 } @@ -7695,7 +7262,7 @@ func (m *RequestLoadSnapshotChunk) Size() (n int) { return n } -func (m *RequestApplySnapshotChunk) Size() (n int) { +func (m *ApplySnapshotChunkRequest) Size() (n int) { if m == nil { return 0 } @@ -7715,7 +7282,7 @@ func (m *RequestApplySnapshotChunk) Size() (n int) { return n } -func (m *RequestPrepareProposal) Size() (n int) { +func (m *PrepareProposalRequest) Size() (n int) { if m == nil { return 0 } @@ -7754,7 +7321,7 @@ func (m *RequestPrepareProposal) Size() (n int) { return n } -func (m *RequestProcessProposal) Size() (n int) { +func (m *ProcessProposalRequest) Size() (n int) { if m == nil { return 0 } @@ -7794,7 +7361,7 @@ func (m *RequestProcessProposal) Size() (n int) { return n } -func (m *RequestExtendVote) Size() (n int) { +func (m *ExtendVoteRequest) Size() (n int) { if m == nil { return 0 } @@ -7807,10 +7374,34 @@ func (m *RequestExtendVote) Size() (n int) { if m.Height != 0 { n += 1 + sovTypes(uint64(m.Height)) } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.ProposedLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } return n } -func (m *RequestVerifyVoteExtension) Size() (n int) { +func (m *VerifyVoteExtensionRequest) Size() (n int) { if m == nil { return 0 } @@ -7834,7 +7425,7 @@ func (m *RequestVerifyVoteExtension) Size() (n int) { return n } -func (m *RequestFinalizeBlock) Size() (n int) { +func (m *FinalizeBlockRequest) Size() (n int) { if m == nil { return 0 } @@ -8090,7 +7681,7 @@ func (m *Response_FinalizeBlock) Size() (n int) { } return n } -func (m *ResponseException) Size() (n int) { +func (m *ExceptionResponse) Size() (n int) { if m == nil { return 0 } @@ -8103,7 +7694,7 @@ func (m *ResponseException) Size() (n int) { return n } -func (m *ResponseEcho) Size() (n int) { +func (m *EchoResponse) Size() (n int) { if m == nil { return 0 } @@ -8116,7 +7707,7 @@ func (m *ResponseEcho) Size() (n int) { return n } -func (m *ResponseFlush) Size() (n int) { +func (m *FlushResponse) Size() (n int) { if m == nil { return 0 } @@ -8125,7 +7716,7 @@ func (m *ResponseFlush) Size() (n int) { return n } -func (m *ResponseInfo) Size() (n int) { +func (m *InfoResponse) Size() (n int) { if m == nil { return 0 } @@ -8152,7 +7743,7 @@ func (m *ResponseInfo) Size() (n int) { return n } -func (m *ResponseInitChain) Size() (n int) { +func (m *InitChainResponse) Size() (n int) { if m == nil { return 0 } @@ -8175,7 +7766,7 @@ func (m *ResponseInitChain) Size() (n int) { return n } -func (m *ResponseQuery) Size() (n int) { +func (m *QueryResponse) Size() (n int) { if m == nil { return 0 } @@ -8217,7 +7808,7 @@ func (m *ResponseQuery) Size() (n int) { return n } -func (m *ResponseCheckTx) Size() (n int) { +func (m *CheckTxResponse) Size() (n int) { if m == nil { return 0 } @@ -8257,7 +7848,7 @@ func (m *ResponseCheckTx) Size() (n int) { return n } -func (m *ResponseCommit) Size() (n int) { +func (m *CommitResponse) Size() (n int) { if m == nil { return 0 } @@ -8269,7 +7860,7 @@ func (m *ResponseCommit) Size() (n int) { return n } -func (m *ResponseListSnapshots) Size() (n int) { +func (m *ListSnapshotsResponse) Size() (n int) { if m == nil { return 0 } @@ -8284,7 +7875,7 @@ func (m *ResponseListSnapshots) Size() (n int) { return n } -func (m *ResponseOfferSnapshot) Size() (n int) { +func (m *OfferSnapshotResponse) Size() (n int) { if m == nil { return 0 } @@ -8296,7 +7887,7 @@ func (m *ResponseOfferSnapshot) Size() (n int) { return n } -func (m *ResponseLoadSnapshotChunk) Size() (n int) { +func (m *LoadSnapshotChunkResponse) Size() (n int) { if m == nil { return 0 } @@ -8309,7 +7900,7 @@ func (m *ResponseLoadSnapshotChunk) Size() (n int) { return n } -func (m *ResponseApplySnapshotChunk) Size() (n int) { +func (m *ApplySnapshotChunkResponse) Size() (n int) { if m == nil { return 0 } @@ -8334,7 +7925,7 @@ func (m *ResponseApplySnapshotChunk) Size() (n int) { return n } -func (m *ResponsePrepareProposal) Size() (n int) { +func (m *PrepareProposalResponse) Size() (n int) { if m == nil { return 0 } @@ -8349,7 +7940,7 @@ func (m *ResponsePrepareProposal) Size() (n int) { return n } -func (m *ResponseProcessProposal) Size() (n int) { +func (m *ProcessProposalResponse) Size() (n int) { if m == nil { return 0 } @@ -8361,7 +7952,7 @@ func (m *ResponseProcessProposal) Size() (n int) { return n } -func (m *ResponseExtendVote) Size() (n int) { +func (m *ExtendVoteResponse) Size() (n int) { if m == nil { return 0 } @@ -8374,7 +7965,7 @@ func (m *ResponseExtendVote) Size() (n int) { return n } -func (m *ResponseVerifyVoteExtension) Size() (n int) { +func (m *VerifyVoteExtensionResponse) Size() (n int) { if m == nil { return 0 } @@ -8386,7 +7977,7 @@ func (m *ResponseVerifyVoteExtension) Size() (n int) { return n } -func (m *ResponseFinalizeBlock) Size() (n int) { +func (m *FinalizeBlockResponse) Size() (n int) { if m == nil { return 0 } @@ -8735,7 +8326,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestEcho{} + v := &EchoRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -8770,7 +8361,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestFlush{} + v := &FlushRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -8805,7 +8396,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestInfo{} + v := &InfoRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -8840,7 +8431,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestInitChain{} + v := &InitChainRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -8875,7 +8466,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestQuery{} + v := &QueryRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -8910,7 +8501,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestCheckTx{} + v := &CheckTxRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -8945,7 +8536,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestCommit{} + v := &CommitRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -8980,7 +8571,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestListSnapshots{} + v := &ListSnapshotsRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9015,7 +8606,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestOfferSnapshot{} + v := &OfferSnapshotRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9050,7 +8641,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestLoadSnapshotChunk{} + v := &LoadSnapshotChunkRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9085,7 +8676,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestApplySnapshotChunk{} + v := &ApplySnapshotChunkRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9120,7 +8711,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestPrepareProposal{} + v := &PrepareProposalRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9155,7 +8746,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestProcessProposal{} + v := &ProcessProposalRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9190,7 +8781,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestExtendVote{} + v := &ExtendVoteRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9225,7 +8816,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestVerifyVoteExtension{} + v := &VerifyVoteExtensionRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9260,7 +8851,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &RequestFinalizeBlock{} + v := &FinalizeBlockRequest{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -9287,7 +8878,7 @@ func (m *Request) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestEcho) Unmarshal(dAtA []byte) error { +func (m *EchoRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -9310,10 +8901,10 @@ func (m *RequestEcho) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestEcho: wiretype end group for non-group") + return fmt.Errorf("proto: EchoRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestEcho: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: EchoRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -9369,7 +8960,7 @@ func (m *RequestEcho) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestFlush) Unmarshal(dAtA []byte) error { +func (m *FlushRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -9392,10 +8983,10 @@ func (m *RequestFlush) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestFlush: wiretype end group for non-group") + return fmt.Errorf("proto: FlushRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestFlush: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: FlushRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -9419,7 +9010,7 @@ func (m *RequestFlush) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestInfo) Unmarshal(dAtA []byte) error { +func (m *InfoRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -9442,10 +9033,10 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestInfo: wiretype end group for non-group") + return fmt.Errorf("proto: InfoRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestInfo: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: InfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -9571,7 +9162,7 @@ func (m *RequestInfo) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestInitChain) Unmarshal(dAtA []byte) error { +func (m *InitChainRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -9594,10 +9185,10 @@ func (m *RequestInitChain) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestInitChain: wiretype end group for non-group") + return fmt.Errorf("proto: InitChainRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: InitChainRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -9695,7 +9286,7 @@ func (m *RequestInitChain) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ConsensusParams == nil { - m.ConsensusParams = &types1.ConsensusParams{} + m.ConsensusParams = &v1.ConsensusParams{} } if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -9809,7 +9400,7 @@ func (m *RequestInitChain) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestQuery) Unmarshal(dAtA []byte) error { +func (m *QueryRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -9832,10 +9423,10 @@ func (m *RequestQuery) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestQuery: wiretype end group for non-group") + return fmt.Errorf("proto: QueryRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestQuery: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -9964,7 +9555,7 @@ func (m *RequestQuery) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestCheckTx) Unmarshal(dAtA []byte) error { +func (m *CheckTxRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -9987,10 +9578,10 @@ func (m *RequestCheckTx) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestCheckTx: wiretype end group for non-group") + return fmt.Errorf("proto: CheckTxRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestCheckTx: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CheckTxRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -10027,7 +9618,7 @@ func (m *RequestCheckTx) Unmarshal(dAtA []byte) error { m.Tx = []byte{} } iNdEx = postIndex - case 2: + case 3: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) } @@ -10067,7 +9658,7 @@ func (m *RequestCheckTx) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestCommit) Unmarshal(dAtA []byte) error { +func (m *CommitRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -10090,10 +9681,10 @@ func (m *RequestCommit) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestCommit: wiretype end group for non-group") + return fmt.Errorf("proto: CommitRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestCommit: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CommitRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -10117,7 +9708,7 @@ func (m *RequestCommit) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestListSnapshots) Unmarshal(dAtA []byte) error { +func (m *ListSnapshotsRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -10140,10 +9731,10 @@ func (m *RequestListSnapshots) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestListSnapshots: wiretype end group for non-group") + return fmt.Errorf("proto: ListSnapshotsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestListSnapshots: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ListSnapshotsRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -10167,7 +9758,7 @@ func (m *RequestListSnapshots) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestOfferSnapshot) Unmarshal(dAtA []byte) error { +func (m *OfferSnapshotRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -10190,10 +9781,10 @@ func (m *RequestOfferSnapshot) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestOfferSnapshot: wiretype end group for non-group") + return fmt.Errorf("proto: OfferSnapshotRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestOfferSnapshot: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: OfferSnapshotRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -10287,7 +9878,7 @@ func (m *RequestOfferSnapshot) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestLoadSnapshotChunk) Unmarshal(dAtA []byte) error { +func (m *LoadSnapshotChunkRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -10310,10 +9901,10 @@ func (m *RequestLoadSnapshotChunk) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestLoadSnapshotChunk: wiretype end group for non-group") + return fmt.Errorf("proto: LoadSnapshotChunkRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestLoadSnapshotChunk: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: LoadSnapshotChunkRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -10394,7 +9985,7 @@ func (m *RequestLoadSnapshotChunk) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestApplySnapshotChunk) Unmarshal(dAtA []byte) error { +func (m *ApplySnapshotChunkRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -10417,10 +10008,10 @@ func (m *RequestApplySnapshotChunk) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestApplySnapshotChunk: wiretype end group for non-group") + return fmt.Errorf("proto: ApplySnapshotChunkRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestApplySnapshotChunk: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ApplySnapshotChunkRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -10529,7 +10120,7 @@ func (m *RequestApplySnapshotChunk) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { +func (m *PrepareProposalRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -10552,10 +10143,10 @@ func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestPrepareProposal: wiretype end group for non-group") + return fmt.Errorf("proto: PrepareProposalRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestPrepareProposal: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: PrepareProposalRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -10817,7 +10408,7 @@ func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestProcessProposal) Unmarshal(dAtA []byte) error { +func (m *ProcessProposalRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -10840,10 +10431,10 @@ func (m *RequestProcessProposal) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestProcessProposal: wiretype end group for non-group") + return fmt.Errorf("proto: ProcessProposalRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ProcessProposalRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -11120,7 +10711,7 @@ func (m *RequestProcessProposal) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestExtendVote) Unmarshal(dAtA []byte) error { +func (m *ExtendVoteRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -11143,10 +10734,10 @@ func (m *RequestExtendVote) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestExtendVote: wiretype end group for non-group") + return fmt.Errorf("proto: ExtendVoteRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestExtendVote: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExtendVoteRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -11202,6 +10793,206 @@ func (m *RequestExtendVote) Unmarshal(dAtA []byte) error { break } } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposedLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ProposedLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -11223,7 +11014,7 @@ func (m *RequestExtendVote) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestVerifyVoteExtension) Unmarshal(dAtA []byte) error { +func (m *VerifyVoteExtensionRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -11246,10 +11037,10 @@ func (m *RequestVerifyVoteExtension) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestVerifyVoteExtension: wiretype end group for non-group") + return fmt.Errorf("proto: VerifyVoteExtensionRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestVerifyVoteExtension: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: VerifyVoteExtensionRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -11394,7 +11185,7 @@ func (m *RequestVerifyVoteExtension) Unmarshal(dAtA []byte) error { } return nil } -func (m *RequestFinalizeBlock) Unmarshal(dAtA []byte) error { +func (m *FinalizeBlockRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -11417,10 +11208,10 @@ func (m *RequestFinalizeBlock) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: RequestFinalizeBlock: wiretype end group for non-group") + return fmt.Errorf("proto: FinalizeBlockRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: RequestFinalizeBlock: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: FinalizeBlockRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -11755,7 +11546,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseException{} + v := &ExceptionResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -11790,7 +11581,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseEcho{} + v := &EchoResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -11825,7 +11616,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseFlush{} + v := &FlushResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -11860,7 +11651,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseInfo{} + v := &InfoResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -11895,7 +11686,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseInitChain{} + v := &InitChainResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -11930,7 +11721,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseQuery{} + v := &QueryResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -11965,7 +11756,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseCheckTx{} + v := &CheckTxResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12000,7 +11791,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseCommit{} + v := &CommitResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12035,7 +11826,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseListSnapshots{} + v := &ListSnapshotsResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12070,7 +11861,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseOfferSnapshot{} + v := &OfferSnapshotResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12105,7 +11896,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseLoadSnapshotChunk{} + v := &LoadSnapshotChunkResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12140,7 +11931,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseApplySnapshotChunk{} + v := &ApplySnapshotChunkResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12175,7 +11966,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponsePrepareProposal{} + v := &PrepareProposalResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12210,7 +12001,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseProcessProposal{} + v := &ProcessProposalResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12245,7 +12036,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseExtendVote{} + v := &ExtendVoteResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12280,7 +12071,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseVerifyVoteExtension{} + v := &VerifyVoteExtensionResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12315,7 +12106,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &ResponseFinalizeBlock{} + v := &FinalizeBlockResponse{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -12342,7 +12133,7 @@ func (m *Response) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseException) Unmarshal(dAtA []byte) error { +func (m *ExceptionResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -12365,10 +12156,10 @@ func (m *ResponseException) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseException: wiretype end group for non-group") + return fmt.Errorf("proto: ExceptionResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseException: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExceptionResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -12424,7 +12215,7 @@ func (m *ResponseException) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseEcho) Unmarshal(dAtA []byte) error { +func (m *EchoResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -12447,10 +12238,10 @@ func (m *ResponseEcho) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseEcho: wiretype end group for non-group") + return fmt.Errorf("proto: EchoResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseEcho: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: EchoResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -12506,7 +12297,7 @@ func (m *ResponseEcho) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseFlush) Unmarshal(dAtA []byte) error { +func (m *FlushResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -12529,10 +12320,10 @@ func (m *ResponseFlush) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseFlush: wiretype end group for non-group") + return fmt.Errorf("proto: FlushResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseFlush: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: FlushResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { default: @@ -12556,7 +12347,7 @@ func (m *ResponseFlush) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseInfo) Unmarshal(dAtA []byte) error { +func (m *InfoResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -12579,10 +12370,10 @@ func (m *ResponseInfo) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseInfo: wiretype end group for non-group") + return fmt.Errorf("proto: InfoResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseInfo: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: InfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -12742,7 +12533,7 @@ func (m *ResponseInfo) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { +func (m *InitChainResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -12765,10 +12556,10 @@ func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseInitChain: wiretype end group for non-group") + return fmt.Errorf("proto: InitChainResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: InitChainResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -12801,7 +12592,7 @@ func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ConsensusParams == nil { - m.ConsensusParams = &types1.ConsensusParams{} + m.ConsensusParams = &v1.ConsensusParams{} } if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -12896,7 +12687,7 @@ func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseQuery) Unmarshal(dAtA []byte) error { +func (m *QueryResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -12919,10 +12710,10 @@ func (m *ResponseQuery) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseQuery: wiretype end group for non-group") + return fmt.Errorf("proto: QueryResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseQuery: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -13125,7 +12916,7 @@ func (m *ResponseQuery) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ProofOps == nil { - m.ProofOps = &crypto.ProofOps{} + m.ProofOps = &v11.ProofOps{} } if err := m.ProofOps.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -13203,7 +12994,7 @@ func (m *ResponseQuery) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error { +func (m *CheckTxResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13226,10 +13017,10 @@ func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseCheckTx: wiretype end group for non-group") + return fmt.Errorf("proto: CheckTxResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseCheckTx: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CheckTxResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -13474,7 +13265,7 @@ func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseCommit) Unmarshal(dAtA []byte) error { +func (m *CommitResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13497,10 +13288,10 @@ func (m *ResponseCommit) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseCommit: wiretype end group for non-group") + return fmt.Errorf("proto: CommitResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseCommit: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: CommitResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 3: @@ -13543,7 +13334,7 @@ func (m *ResponseCommit) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseListSnapshots) Unmarshal(dAtA []byte) error { +func (m *ListSnapshotsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13566,10 +13357,10 @@ func (m *ResponseListSnapshots) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseListSnapshots: wiretype end group for non-group") + return fmt.Errorf("proto: ListSnapshotsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseListSnapshots: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ListSnapshotsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -13627,7 +13418,7 @@ func (m *ResponseListSnapshots) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseOfferSnapshot) Unmarshal(dAtA []byte) error { +func (m *OfferSnapshotResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13650,10 +13441,10 @@ func (m *ResponseOfferSnapshot) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseOfferSnapshot: wiretype end group for non-group") + return fmt.Errorf("proto: OfferSnapshotResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseOfferSnapshot: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: OfferSnapshotResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -13670,7 +13461,7 @@ func (m *ResponseOfferSnapshot) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Result |= ResponseOfferSnapshot_Result(b&0x7F) << shift + m.Result |= OfferSnapshotResult(b&0x7F) << shift if b < 0x80 { break } @@ -13696,7 +13487,7 @@ func (m *ResponseOfferSnapshot) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseLoadSnapshotChunk) Unmarshal(dAtA []byte) error { +func (m *LoadSnapshotChunkResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13719,10 +13510,10 @@ func (m *ResponseLoadSnapshotChunk) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseLoadSnapshotChunk: wiretype end group for non-group") + return fmt.Errorf("proto: LoadSnapshotChunkResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseLoadSnapshotChunk: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: LoadSnapshotChunkResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -13780,7 +13571,7 @@ func (m *ResponseLoadSnapshotChunk) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseApplySnapshotChunk) Unmarshal(dAtA []byte) error { +func (m *ApplySnapshotChunkResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13803,10 +13594,10 @@ func (m *ResponseApplySnapshotChunk) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseApplySnapshotChunk: wiretype end group for non-group") + return fmt.Errorf("proto: ApplySnapshotChunkResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseApplySnapshotChunk: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ApplySnapshotChunkResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -13823,7 +13614,7 @@ func (m *ResponseApplySnapshotChunk) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Result |= ResponseApplySnapshotChunk_Result(b&0x7F) << shift + m.Result |= ApplySnapshotChunkResult(b&0x7F) << shift if b < 0x80 { break } @@ -13957,7 +13748,7 @@ func (m *ResponseApplySnapshotChunk) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponsePrepareProposal) Unmarshal(dAtA []byte) error { +func (m *PrepareProposalResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -13980,10 +13771,10 @@ func (m *ResponsePrepareProposal) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponsePrepareProposal: wiretype end group for non-group") + return fmt.Errorf("proto: PrepareProposalResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponsePrepareProposal: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: PrepareProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -14039,7 +13830,7 @@ func (m *ResponsePrepareProposal) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { +func (m *ProcessProposalResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -14062,10 +13853,10 @@ func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseProcessProposal: wiretype end group for non-group") + return fmt.Errorf("proto: ProcessProposalResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ProcessProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -14082,7 +13873,7 @@ func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Status |= ResponseProcessProposal_ProposalStatus(b&0x7F) << shift + m.Status |= ProcessProposalStatus(b&0x7F) << shift if b < 0x80 { break } @@ -14108,7 +13899,7 @@ func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseExtendVote) Unmarshal(dAtA []byte) error { +func (m *ExtendVoteResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -14131,10 +13922,10 @@ func (m *ResponseExtendVote) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseExtendVote: wiretype end group for non-group") + return fmt.Errorf("proto: ExtendVoteResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseExtendVote: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ExtendVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -14192,7 +13983,7 @@ func (m *ResponseExtendVote) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseVerifyVoteExtension) Unmarshal(dAtA []byte) error { +func (m *VerifyVoteExtensionResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -14215,10 +14006,10 @@ func (m *ResponseVerifyVoteExtension) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseVerifyVoteExtension: wiretype end group for non-group") + return fmt.Errorf("proto: VerifyVoteExtensionResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseVerifyVoteExtension: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: VerifyVoteExtensionResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -14235,7 +14026,7 @@ func (m *ResponseVerifyVoteExtension) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Status |= ResponseVerifyVoteExtension_VerifyStatus(b&0x7F) << shift + m.Status |= VerifyVoteExtensionStatus(b&0x7F) << shift if b < 0x80 { break } @@ -14261,7 +14052,7 @@ func (m *ResponseVerifyVoteExtension) Unmarshal(dAtA []byte) error { } return nil } -func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { +func (m *FinalizeBlockResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -14284,10 +14075,10 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ResponseFinalizeBlock: wiretype end group for non-group") + return fmt.Errorf("proto: FinalizeBlockResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseFinalizeBlock: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: FinalizeBlockResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -14422,7 +14213,7 @@ func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ConsensusParamUpdates == nil { - m.ConsensusParamUpdates = &types1.ConsensusParams{} + m.ConsensusParamUpdates = &v1.ConsensusParams{} } if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -15646,7 +15437,7 @@ func (m *VoteInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.BlockIdFlag |= types1.BlockIDFlag(b&0x7F) << shift + m.BlockIdFlag |= v1.BlockIDFlag(b&0x7F) << shift if b < 0x80 { break } @@ -15816,7 +15607,7 @@ func (m *ExtendedVoteInfo) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.BlockIdFlag |= types1.BlockIDFlag(b&0x7F) << shift + m.BlockIdFlag |= v1.BlockIDFlag(b&0x7F) << shift if b < 0x80 { break } diff --git a/api/cometbft/abci/v1beta1/types.go b/api/cometbft/abci/v1beta1/types.go new file mode 100644 index 00000000000..d069a705447 --- /dev/null +++ b/api/cometbft/abci/v1beta1/types.go @@ -0,0 +1,42 @@ +package v1beta1 + +import ( + "bytes" + + "github.com/cosmos/gogoproto/jsonpb" +) + +const ( + CodeTypeOK uint32 = 0 +) + +// IsOK returns true if Code is OK. +func (r ResponseQuery) IsOK() bool { + return r.Code == CodeTypeOK +} + +// IsErr returns true if Code is something other than OK. +func (r ResponseQuery) IsErr() bool { + return r.Code != CodeTypeOK +} + +// --------------------------------------------------------------------------- +// override JSON marshaling so we emit defaults (ie. disable omitempty) + +var ( + jsonpbMarshaller = jsonpb.Marshaler{ + EnumsAsInts: true, + EmitDefaults: true, + } + jsonpbUnmarshaller = jsonpb.Unmarshaler{} +) + +func (r *ResponseQuery) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *ResponseQuery) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} diff --git a/api/cometbft/abci/v1beta1/types.pb.go b/api/cometbft/abci/v1beta1/types.pb.go new file mode 100644 index 00000000000..2817cbd048e --- /dev/null +++ b/api/cometbft/abci/v1beta1/types.pb.go @@ -0,0 +1,14662 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/abci/v1beta1/types.proto + +package v1beta1 + +import ( + context "context" + fmt "fmt" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Type of the transaction check request. +type CheckTxType int32 + +const ( + // New + CheckTxType_New CheckTxType = 0 + // Recheck (2nd, 3rd, etc.) + CheckTxType_Recheck CheckTxType = 1 +) + +var CheckTxType_name = map[int32]string{ + 0: "NEW", + 1: "RECHECK", +} + +var CheckTxType_value = map[string]int32{ + "NEW": 0, + "RECHECK": 1, +} + +func (x CheckTxType) String() string { + return proto.EnumName(CheckTxType_name, int32(x)) +} + +func (CheckTxType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{0} +} + +// The type of evidence. +type EvidenceType int32 + +const ( + // Unknown + EvidenceType_UNKNOWN EvidenceType = 0 + // Duplicate vote + EvidenceType_DUPLICATE_VOTE EvidenceType = 1 + // Light client attack + EvidenceType_LIGHT_CLIENT_ATTACK EvidenceType = 2 +) + +var EvidenceType_name = map[int32]string{ + 0: "UNKNOWN", + 1: "DUPLICATE_VOTE", + 2: "LIGHT_CLIENT_ATTACK", +} + +var EvidenceType_value = map[string]int32{ + "UNKNOWN": 0, + "DUPLICATE_VOTE": 1, + "LIGHT_CLIENT_ATTACK": 2, +} + +func (x EvidenceType) String() string { + return proto.EnumName(EvidenceType_name, int32(x)) +} + +func (EvidenceType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{1} +} + +// The status code. +type ResponseOfferSnapshot_Result int32 + +const ( + // Unknown result, abort all snapshot restoration + ResponseOfferSnapshot_UNKNOWN ResponseOfferSnapshot_Result = 0 + // Snapshot accepted, apply chunks + ResponseOfferSnapshot_ACCEPT ResponseOfferSnapshot_Result = 1 + // Abort all snapshot restoration + ResponseOfferSnapshot_ABORT ResponseOfferSnapshot_Result = 2 + // Reject this specific snapshot, try others + ResponseOfferSnapshot_REJECT ResponseOfferSnapshot_Result = 3 + // Reject all snapshots of this format, try others + ResponseOfferSnapshot_REJECT_FORMAT ResponseOfferSnapshot_Result = 4 + // Reject all snapshots from the sender(s), try others + ResponseOfferSnapshot_REJECT_SENDER ResponseOfferSnapshot_Result = 5 +) + +var ResponseOfferSnapshot_Result_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ACCEPT", + 2: "ABORT", + 3: "REJECT", + 4: "REJECT_FORMAT", + 5: "REJECT_SENDER", +} + +var ResponseOfferSnapshot_Result_value = map[string]int32{ + "UNKNOWN": 0, + "ACCEPT": 1, + "ABORT": 2, + "REJECT": 3, + "REJECT_FORMAT": 4, + "REJECT_SENDER": 5, +} + +func (x ResponseOfferSnapshot_Result) String() string { + return proto.EnumName(ResponseOfferSnapshot_Result_name, int32(x)) +} + +func (ResponseOfferSnapshot_Result) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{30, 0} +} + +// The status code. +type ResponseApplySnapshotChunk_Result int32 + +const ( + // Unknown result, abort all snapshot restoration + ResponseApplySnapshotChunk_UNKNOWN ResponseApplySnapshotChunk_Result = 0 + // Chunk successfully accepted + ResponseApplySnapshotChunk_ACCEPT ResponseApplySnapshotChunk_Result = 1 + // Abort all snapshot restoration + ResponseApplySnapshotChunk_ABORT ResponseApplySnapshotChunk_Result = 2 + // Retry chunk (combine with refetch and reject) + ResponseApplySnapshotChunk_RETRY ResponseApplySnapshotChunk_Result = 3 + // Retry snapshot (combine with refetch and reject) + ResponseApplySnapshotChunk_RETRY_SNAPSHOT ResponseApplySnapshotChunk_Result = 4 + // Reject this snapshot, try others + ResponseApplySnapshotChunk_REJECT_SNAPSHOT ResponseApplySnapshotChunk_Result = 5 +) + +var ResponseApplySnapshotChunk_Result_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ACCEPT", + 2: "ABORT", + 3: "RETRY", + 4: "RETRY_SNAPSHOT", + 5: "REJECT_SNAPSHOT", +} + +var ResponseApplySnapshotChunk_Result_value = map[string]int32{ + "UNKNOWN": 0, + "ACCEPT": 1, + "ABORT": 2, + "RETRY": 3, + "RETRY_SNAPSHOT": 4, + "REJECT_SNAPSHOT": 5, +} + +func (x ResponseApplySnapshotChunk_Result) String() string { + return proto.EnumName(ResponseApplySnapshotChunk_Result_name, int32(x)) +} + +func (ResponseApplySnapshotChunk_Result) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{32, 0} +} + +// Request represents a request to the ABCI application. +type Request struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Value: + // *Request_Echo + // *Request_Flush + // *Request_Info + // *Request_SetOption + // *Request_InitChain + // *Request_Query + // *Request_BeginBlock + // *Request_CheckTx + // *Request_DeliverTx + // *Request_EndBlock + // *Request_Commit + // *Request_ListSnapshots + // *Request_OfferSnapshot + // *Request_LoadSnapshotChunk + // *Request_ApplySnapshotChunk + Value isRequest_Value `protobuf_oneof:"value"` +} + +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} +func (*Request) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{0} +} +func (m *Request) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Request.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Request) XXX_Merge(src proto.Message) { + xxx_messageInfo_Request.Merge(m, src) +} +func (m *Request) XXX_Size() int { + return m.Size() +} +func (m *Request) XXX_DiscardUnknown() { + xxx_messageInfo_Request.DiscardUnknown(m) +} + +var xxx_messageInfo_Request proto.InternalMessageInfo + +type isRequest_Value interface { + isRequest_Value() + MarshalTo([]byte) (int, error) + Size() int +} + +type Request_Echo struct { + Echo *RequestEcho `protobuf:"bytes,1,opt,name=echo,proto3,oneof" json:"echo,omitempty"` +} +type Request_Flush struct { + Flush *RequestFlush `protobuf:"bytes,2,opt,name=flush,proto3,oneof" json:"flush,omitempty"` +} +type Request_Info struct { + Info *RequestInfo `protobuf:"bytes,3,opt,name=info,proto3,oneof" json:"info,omitempty"` +} +type Request_SetOption struct { + SetOption *RequestSetOption `protobuf:"bytes,4,opt,name=set_option,json=setOption,proto3,oneof" json:"set_option,omitempty"` +} +type Request_InitChain struct { + InitChain *RequestInitChain `protobuf:"bytes,5,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` +} +type Request_Query struct { + Query *RequestQuery `protobuf:"bytes,6,opt,name=query,proto3,oneof" json:"query,omitempty"` +} +type Request_BeginBlock struct { + BeginBlock *RequestBeginBlock `protobuf:"bytes,7,opt,name=begin_block,json=beginBlock,proto3,oneof" json:"begin_block,omitempty"` +} +type Request_CheckTx struct { + CheckTx *RequestCheckTx `protobuf:"bytes,8,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` +} +type Request_DeliverTx struct { + DeliverTx *RequestDeliverTx `protobuf:"bytes,9,opt,name=deliver_tx,json=deliverTx,proto3,oneof" json:"deliver_tx,omitempty"` +} +type Request_EndBlock struct { + EndBlock *RequestEndBlock `protobuf:"bytes,10,opt,name=end_block,json=endBlock,proto3,oneof" json:"end_block,omitempty"` +} +type Request_Commit struct { + Commit *RequestCommit `protobuf:"bytes,11,opt,name=commit,proto3,oneof" json:"commit,omitempty"` +} +type Request_ListSnapshots struct { + ListSnapshots *RequestListSnapshots `protobuf:"bytes,12,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` +} +type Request_OfferSnapshot struct { + OfferSnapshot *RequestOfferSnapshot `protobuf:"bytes,13,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` +} +type Request_LoadSnapshotChunk struct { + LoadSnapshotChunk *RequestLoadSnapshotChunk `protobuf:"bytes,14,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` +} +type Request_ApplySnapshotChunk struct { + ApplySnapshotChunk *RequestApplySnapshotChunk `protobuf:"bytes,15,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` +} + +func (*Request_Echo) isRequest_Value() {} +func (*Request_Flush) isRequest_Value() {} +func (*Request_Info) isRequest_Value() {} +func (*Request_SetOption) isRequest_Value() {} +func (*Request_InitChain) isRequest_Value() {} +func (*Request_Query) isRequest_Value() {} +func (*Request_BeginBlock) isRequest_Value() {} +func (*Request_CheckTx) isRequest_Value() {} +func (*Request_DeliverTx) isRequest_Value() {} +func (*Request_EndBlock) isRequest_Value() {} +func (*Request_Commit) isRequest_Value() {} +func (*Request_ListSnapshots) isRequest_Value() {} +func (*Request_OfferSnapshot) isRequest_Value() {} +func (*Request_LoadSnapshotChunk) isRequest_Value() {} +func (*Request_ApplySnapshotChunk) isRequest_Value() {} + +func (m *Request) GetValue() isRequest_Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *Request) GetEcho() *RequestEcho { + if x, ok := m.GetValue().(*Request_Echo); ok { + return x.Echo + } + return nil +} + +func (m *Request) GetFlush() *RequestFlush { + if x, ok := m.GetValue().(*Request_Flush); ok { + return x.Flush + } + return nil +} + +func (m *Request) GetInfo() *RequestInfo { + if x, ok := m.GetValue().(*Request_Info); ok { + return x.Info + } + return nil +} + +func (m *Request) GetSetOption() *RequestSetOption { + if x, ok := m.GetValue().(*Request_SetOption); ok { + return x.SetOption + } + return nil +} + +func (m *Request) GetInitChain() *RequestInitChain { + if x, ok := m.GetValue().(*Request_InitChain); ok { + return x.InitChain + } + return nil +} + +func (m *Request) GetQuery() *RequestQuery { + if x, ok := m.GetValue().(*Request_Query); ok { + return x.Query + } + return nil +} + +func (m *Request) GetBeginBlock() *RequestBeginBlock { + if x, ok := m.GetValue().(*Request_BeginBlock); ok { + return x.BeginBlock + } + return nil +} + +func (m *Request) GetCheckTx() *RequestCheckTx { + if x, ok := m.GetValue().(*Request_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Request) GetDeliverTx() *RequestDeliverTx { + if x, ok := m.GetValue().(*Request_DeliverTx); ok { + return x.DeliverTx + } + return nil +} + +func (m *Request) GetEndBlock() *RequestEndBlock { + if x, ok := m.GetValue().(*Request_EndBlock); ok { + return x.EndBlock + } + return nil +} + +func (m *Request) GetCommit() *RequestCommit { + if x, ok := m.GetValue().(*Request_Commit); ok { + return x.Commit + } + return nil +} + +func (m *Request) GetListSnapshots() *RequestListSnapshots { + if x, ok := m.GetValue().(*Request_ListSnapshots); ok { + return x.ListSnapshots + } + return nil +} + +func (m *Request) GetOfferSnapshot() *RequestOfferSnapshot { + if x, ok := m.GetValue().(*Request_OfferSnapshot); ok { + return x.OfferSnapshot + } + return nil +} + +func (m *Request) GetLoadSnapshotChunk() *RequestLoadSnapshotChunk { + if x, ok := m.GetValue().(*Request_LoadSnapshotChunk); ok { + return x.LoadSnapshotChunk + } + return nil +} + +func (m *Request) GetApplySnapshotChunk() *RequestApplySnapshotChunk { + if x, ok := m.GetValue().(*Request_ApplySnapshotChunk); ok { + return x.ApplySnapshotChunk + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Request) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Request_Echo)(nil), + (*Request_Flush)(nil), + (*Request_Info)(nil), + (*Request_SetOption)(nil), + (*Request_InitChain)(nil), + (*Request_Query)(nil), + (*Request_BeginBlock)(nil), + (*Request_CheckTx)(nil), + (*Request_DeliverTx)(nil), + (*Request_EndBlock)(nil), + (*Request_Commit)(nil), + (*Request_ListSnapshots)(nil), + (*Request_OfferSnapshot)(nil), + (*Request_LoadSnapshotChunk)(nil), + (*Request_ApplySnapshotChunk)(nil), + } +} + +// RequestEcho is a request to "echo" the given string. +type RequestEcho struct { + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (m *RequestEcho) Reset() { *m = RequestEcho{} } +func (m *RequestEcho) String() string { return proto.CompactTextString(m) } +func (*RequestEcho) ProtoMessage() {} +func (*RequestEcho) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{1} +} +func (m *RequestEcho) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestEcho) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestEcho.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestEcho) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestEcho.Merge(m, src) +} +func (m *RequestEcho) XXX_Size() int { + return m.Size() +} +func (m *RequestEcho) XXX_DiscardUnknown() { + xxx_messageInfo_RequestEcho.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestEcho proto.InternalMessageInfo + +func (m *RequestEcho) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +// RequestFlush is a request to flush the write buffer. +type RequestFlush struct { +} + +func (m *RequestFlush) Reset() { *m = RequestFlush{} } +func (m *RequestFlush) String() string { return proto.CompactTextString(m) } +func (*RequestFlush) ProtoMessage() {} +func (*RequestFlush) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{2} +} +func (m *RequestFlush) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestFlush) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestFlush.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestFlush) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestFlush.Merge(m, src) +} +func (m *RequestFlush) XXX_Size() int { + return m.Size() +} +func (m *RequestFlush) XXX_DiscardUnknown() { + xxx_messageInfo_RequestFlush.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestFlush proto.InternalMessageInfo + +// RequestInfo is a request for the ABCI application version. +type RequestInfo struct { + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + BlockVersion uint64 `protobuf:"varint,2,opt,name=block_version,json=blockVersion,proto3" json:"block_version,omitempty"` + P2PVersion uint64 `protobuf:"varint,3,opt,name=p2p_version,json=p2pVersion,proto3" json:"p2p_version,omitempty"` +} + +func (m *RequestInfo) Reset() { *m = RequestInfo{} } +func (m *RequestInfo) String() string { return proto.CompactTextString(m) } +func (*RequestInfo) ProtoMessage() {} +func (*RequestInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{3} +} +func (m *RequestInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestInfo.Merge(m, src) +} +func (m *RequestInfo) XXX_Size() int { + return m.Size() +} +func (m *RequestInfo) XXX_DiscardUnknown() { + xxx_messageInfo_RequestInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestInfo proto.InternalMessageInfo + +func (m *RequestInfo) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +func (m *RequestInfo) GetBlockVersion() uint64 { + if m != nil { + return m.BlockVersion + } + return 0 +} + +func (m *RequestInfo) GetP2PVersion() uint64 { + if m != nil { + return m.P2PVersion + } + return 0 +} + +// nondeterministic +type RequestSetOption struct { + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *RequestSetOption) Reset() { *m = RequestSetOption{} } +func (m *RequestSetOption) String() string { return proto.CompactTextString(m) } +func (*RequestSetOption) ProtoMessage() {} +func (*RequestSetOption) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{4} +} +func (m *RequestSetOption) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestSetOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestSetOption.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestSetOption) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestSetOption.Merge(m, src) +} +func (m *RequestSetOption) XXX_Size() int { + return m.Size() +} +func (m *RequestSetOption) XXX_DiscardUnknown() { + xxx_messageInfo_RequestSetOption.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestSetOption proto.InternalMessageInfo + +func (m *RequestSetOption) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *RequestSetOption) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// RequestInitChain is a request to initialize the blockchain. +type RequestInitChain struct { + Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ConsensusParams *ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []ValidatorUpdate `protobuf:"bytes,4,rep,name=validators,proto3" json:"validators"` + AppStateBytes []byte `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"` + InitialHeight int64 `protobuf:"varint,6,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` +} + +func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } +func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } +func (*RequestInitChain) ProtoMessage() {} +func (*RequestInitChain) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{5} +} +func (m *RequestInitChain) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestInitChain.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestInitChain) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestInitChain.Merge(m, src) +} +func (m *RequestInitChain) XXX_Size() int { + return m.Size() +} +func (m *RequestInitChain) XXX_DiscardUnknown() { + xxx_messageInfo_RequestInitChain.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestInitChain proto.InternalMessageInfo + +func (m *RequestInitChain) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestInitChain) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *RequestInitChain) GetConsensusParams() *ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return nil +} + +func (m *RequestInitChain) GetValidators() []ValidatorUpdate { + if m != nil { + return m.Validators + } + return nil +} + +func (m *RequestInitChain) GetAppStateBytes() []byte { + if m != nil { + return m.AppStateBytes + } + return nil +} + +func (m *RequestInitChain) GetInitialHeight() int64 { + if m != nil { + return m.InitialHeight + } + return 0 +} + +// RequestQuery is a request to query the application state. +type RequestQuery struct { + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + Prove bool `protobuf:"varint,4,opt,name=prove,proto3" json:"prove,omitempty"` +} + +func (m *RequestQuery) Reset() { *m = RequestQuery{} } +func (m *RequestQuery) String() string { return proto.CompactTextString(m) } +func (*RequestQuery) ProtoMessage() {} +func (*RequestQuery) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{6} +} +func (m *RequestQuery) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestQuery.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestQuery) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestQuery.Merge(m, src) +} +func (m *RequestQuery) XXX_Size() int { + return m.Size() +} +func (m *RequestQuery) XXX_DiscardUnknown() { + xxx_messageInfo_RequestQuery.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestQuery proto.InternalMessageInfo + +func (m *RequestQuery) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *RequestQuery) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *RequestQuery) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestQuery) GetProve() bool { + if m != nil { + return m.Prove + } + return false +} + +// RequestBeginBlock indicates the beginning of committing the block. +type RequestBeginBlock struct { + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Header v1beta1.Header `protobuf:"bytes,2,opt,name=header,proto3" json:"header"` + LastCommitInfo LastCommitInfo `protobuf:"bytes,3,opt,name=last_commit_info,json=lastCommitInfo,proto3" json:"last_commit_info"` + ByzantineValidators []Evidence `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators,proto3" json:"byzantine_validators"` +} + +func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } +func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } +func (*RequestBeginBlock) ProtoMessage() {} +func (*RequestBeginBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{7} +} +func (m *RequestBeginBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestBeginBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestBeginBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestBeginBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestBeginBlock.Merge(m, src) +} +func (m *RequestBeginBlock) XXX_Size() int { + return m.Size() +} +func (m *RequestBeginBlock) XXX_DiscardUnknown() { + xxx_messageInfo_RequestBeginBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestBeginBlock proto.InternalMessageInfo + +func (m *RequestBeginBlock) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *RequestBeginBlock) GetHeader() v1beta1.Header { + if m != nil { + return m.Header + } + return v1beta1.Header{} +} + +func (m *RequestBeginBlock) GetLastCommitInfo() LastCommitInfo { + if m != nil { + return m.LastCommitInfo + } + return LastCommitInfo{} +} + +func (m *RequestBeginBlock) GetByzantineValidators() []Evidence { + if m != nil { + return m.ByzantineValidators + } + return nil +} + +// RequestCheckTx is a request to check the transaction. +type RequestCheckTx struct { + Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` + Type CheckTxType `protobuf:"varint,2,opt,name=type,proto3,enum=cometbft.abci.v1beta1.CheckTxType" json:"type,omitempty"` +} + +func (m *RequestCheckTx) Reset() { *m = RequestCheckTx{} } +func (m *RequestCheckTx) String() string { return proto.CompactTextString(m) } +func (*RequestCheckTx) ProtoMessage() {} +func (*RequestCheckTx) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{8} +} +func (m *RequestCheckTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestCheckTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestCheckTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestCheckTx.Merge(m, src) +} +func (m *RequestCheckTx) XXX_Size() int { + return m.Size() +} +func (m *RequestCheckTx) XXX_DiscardUnknown() { + xxx_messageInfo_RequestCheckTx.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestCheckTx proto.InternalMessageInfo + +func (m *RequestCheckTx) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + +func (m *RequestCheckTx) GetType() CheckTxType { + if m != nil { + return m.Type + } + return CheckTxType_New +} + +// RequestDeliverTx is a request to apply the transaction. +type RequestDeliverTx struct { + Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` +} + +func (m *RequestDeliverTx) Reset() { *m = RequestDeliverTx{} } +func (m *RequestDeliverTx) String() string { return proto.CompactTextString(m) } +func (*RequestDeliverTx) ProtoMessage() {} +func (*RequestDeliverTx) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{9} +} +func (m *RequestDeliverTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestDeliverTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestDeliverTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestDeliverTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestDeliverTx.Merge(m, src) +} +func (m *RequestDeliverTx) XXX_Size() int { + return m.Size() +} +func (m *RequestDeliverTx) XXX_DiscardUnknown() { + xxx_messageInfo_RequestDeliverTx.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestDeliverTx proto.InternalMessageInfo + +func (m *RequestDeliverTx) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + +// RequestEndBlock indicates the end of committing the block. +type RequestEndBlock struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *RequestEndBlock) Reset() { *m = RequestEndBlock{} } +func (m *RequestEndBlock) String() string { return proto.CompactTextString(m) } +func (*RequestEndBlock) ProtoMessage() {} +func (*RequestEndBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{10} +} +func (m *RequestEndBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestEndBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestEndBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestEndBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestEndBlock.Merge(m, src) +} +func (m *RequestEndBlock) XXX_Size() int { + return m.Size() +} +func (m *RequestEndBlock) XXX_DiscardUnknown() { + xxx_messageInfo_RequestEndBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestEndBlock proto.InternalMessageInfo + +func (m *RequestEndBlock) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +// RequestCommit is a request to commit the pending application state. +type RequestCommit struct { +} + +func (m *RequestCommit) Reset() { *m = RequestCommit{} } +func (m *RequestCommit) String() string { return proto.CompactTextString(m) } +func (*RequestCommit) ProtoMessage() {} +func (*RequestCommit) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{11} +} +func (m *RequestCommit) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestCommit.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestCommit) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestCommit.Merge(m, src) +} +func (m *RequestCommit) XXX_Size() int { + return m.Size() +} +func (m *RequestCommit) XXX_DiscardUnknown() { + xxx_messageInfo_RequestCommit.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestCommit proto.InternalMessageInfo + +// lists available snapshots +type RequestListSnapshots struct { +} + +func (m *RequestListSnapshots) Reset() { *m = RequestListSnapshots{} } +func (m *RequestListSnapshots) String() string { return proto.CompactTextString(m) } +func (*RequestListSnapshots) ProtoMessage() {} +func (*RequestListSnapshots) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{12} +} +func (m *RequestListSnapshots) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestListSnapshots) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestListSnapshots.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestListSnapshots) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestListSnapshots.Merge(m, src) +} +func (m *RequestListSnapshots) XXX_Size() int { + return m.Size() +} +func (m *RequestListSnapshots) XXX_DiscardUnknown() { + xxx_messageInfo_RequestListSnapshots.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestListSnapshots proto.InternalMessageInfo + +// offers a snapshot to the application +type RequestOfferSnapshot struct { + Snapshot *Snapshot `protobuf:"bytes,1,opt,name=snapshot,proto3" json:"snapshot,omitempty"` + AppHash []byte `protobuf:"bytes,2,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *RequestOfferSnapshot) Reset() { *m = RequestOfferSnapshot{} } +func (m *RequestOfferSnapshot) String() string { return proto.CompactTextString(m) } +func (*RequestOfferSnapshot) ProtoMessage() {} +func (*RequestOfferSnapshot) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{13} +} +func (m *RequestOfferSnapshot) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestOfferSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestOfferSnapshot.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestOfferSnapshot) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestOfferSnapshot.Merge(m, src) +} +func (m *RequestOfferSnapshot) XXX_Size() int { + return m.Size() +} +func (m *RequestOfferSnapshot) XXX_DiscardUnknown() { + xxx_messageInfo_RequestOfferSnapshot.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestOfferSnapshot proto.InternalMessageInfo + +func (m *RequestOfferSnapshot) GetSnapshot() *Snapshot { + if m != nil { + return m.Snapshot + } + return nil +} + +func (m *RequestOfferSnapshot) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +// loads a snapshot chunk +type RequestLoadSnapshotChunk struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Format uint32 `protobuf:"varint,2,opt,name=format,proto3" json:"format,omitempty"` + Chunk uint32 `protobuf:"varint,3,opt,name=chunk,proto3" json:"chunk,omitempty"` +} + +func (m *RequestLoadSnapshotChunk) Reset() { *m = RequestLoadSnapshotChunk{} } +func (m *RequestLoadSnapshotChunk) String() string { return proto.CompactTextString(m) } +func (*RequestLoadSnapshotChunk) ProtoMessage() {} +func (*RequestLoadSnapshotChunk) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{14} +} +func (m *RequestLoadSnapshotChunk) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestLoadSnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestLoadSnapshotChunk.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestLoadSnapshotChunk) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestLoadSnapshotChunk.Merge(m, src) +} +func (m *RequestLoadSnapshotChunk) XXX_Size() int { + return m.Size() +} +func (m *RequestLoadSnapshotChunk) XXX_DiscardUnknown() { + xxx_messageInfo_RequestLoadSnapshotChunk.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestLoadSnapshotChunk proto.InternalMessageInfo + +func (m *RequestLoadSnapshotChunk) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestLoadSnapshotChunk) GetFormat() uint32 { + if m != nil { + return m.Format + } + return 0 +} + +func (m *RequestLoadSnapshotChunk) GetChunk() uint32 { + if m != nil { + return m.Chunk + } + return 0 +} + +// Applies a snapshot chunk +type RequestApplySnapshotChunk struct { + Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Chunk []byte `protobuf:"bytes,2,opt,name=chunk,proto3" json:"chunk,omitempty"` + Sender string `protobuf:"bytes,3,opt,name=sender,proto3" json:"sender,omitempty"` +} + +func (m *RequestApplySnapshotChunk) Reset() { *m = RequestApplySnapshotChunk{} } +func (m *RequestApplySnapshotChunk) String() string { return proto.CompactTextString(m) } +func (*RequestApplySnapshotChunk) ProtoMessage() {} +func (*RequestApplySnapshotChunk) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{15} +} +func (m *RequestApplySnapshotChunk) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestApplySnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestApplySnapshotChunk.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestApplySnapshotChunk) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestApplySnapshotChunk.Merge(m, src) +} +func (m *RequestApplySnapshotChunk) XXX_Size() int { + return m.Size() +} +func (m *RequestApplySnapshotChunk) XXX_DiscardUnknown() { + xxx_messageInfo_RequestApplySnapshotChunk.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestApplySnapshotChunk proto.InternalMessageInfo + +func (m *RequestApplySnapshotChunk) GetIndex() uint32 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *RequestApplySnapshotChunk) GetChunk() []byte { + if m != nil { + return m.Chunk + } + return nil +} + +func (m *RequestApplySnapshotChunk) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +// Response represents a response from the ABCI application. +type Response struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Value: + // + // *Response_Exception + // *Response_Echo + // *Response_Flush + // *Response_Info + // *Response_SetOption + // *Response_InitChain + // *Response_Query + // *Response_BeginBlock + // *Response_CheckTx + // *Response_DeliverTx + // *Response_EndBlock + // *Response_Commit + // *Response_ListSnapshots + // *Response_OfferSnapshot + // *Response_LoadSnapshotChunk + // *Response_ApplySnapshotChunk + Value isResponse_Value `protobuf_oneof:"value"` +} + +func (m *Response) Reset() { *m = Response{} } +func (m *Response) String() string { return proto.CompactTextString(m) } +func (*Response) ProtoMessage() {} +func (*Response) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{16} +} +func (m *Response) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Response.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Response) XXX_Merge(src proto.Message) { + xxx_messageInfo_Response.Merge(m, src) +} +func (m *Response) XXX_Size() int { + return m.Size() +} +func (m *Response) XXX_DiscardUnknown() { + xxx_messageInfo_Response.DiscardUnknown(m) +} + +var xxx_messageInfo_Response proto.InternalMessageInfo + +type isResponse_Value interface { + isResponse_Value() + MarshalTo([]byte) (int, error) + Size() int +} + +type Response_Exception struct { + Exception *ResponseException `protobuf:"bytes,1,opt,name=exception,proto3,oneof" json:"exception,omitempty"` +} +type Response_Echo struct { + Echo *ResponseEcho `protobuf:"bytes,2,opt,name=echo,proto3,oneof" json:"echo,omitempty"` +} +type Response_Flush struct { + Flush *ResponseFlush `protobuf:"bytes,3,opt,name=flush,proto3,oneof" json:"flush,omitempty"` +} +type Response_Info struct { + Info *ResponseInfo `protobuf:"bytes,4,opt,name=info,proto3,oneof" json:"info,omitempty"` +} +type Response_SetOption struct { + SetOption *ResponseSetOption `protobuf:"bytes,5,opt,name=set_option,json=setOption,proto3,oneof" json:"set_option,omitempty"` +} +type Response_InitChain struct { + InitChain *ResponseInitChain `protobuf:"bytes,6,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` +} +type Response_Query struct { + Query *ResponseQuery `protobuf:"bytes,7,opt,name=query,proto3,oneof" json:"query,omitempty"` +} +type Response_BeginBlock struct { + BeginBlock *ResponseBeginBlock `protobuf:"bytes,8,opt,name=begin_block,json=beginBlock,proto3,oneof" json:"begin_block,omitempty"` +} +type Response_CheckTx struct { + CheckTx *ResponseCheckTx `protobuf:"bytes,9,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` +} +type Response_DeliverTx struct { + DeliverTx *ResponseDeliverTx `protobuf:"bytes,10,opt,name=deliver_tx,json=deliverTx,proto3,oneof" json:"deliver_tx,omitempty"` +} +type Response_EndBlock struct { + EndBlock *ResponseEndBlock `protobuf:"bytes,11,opt,name=end_block,json=endBlock,proto3,oneof" json:"end_block,omitempty"` +} +type Response_Commit struct { + Commit *ResponseCommit `protobuf:"bytes,12,opt,name=commit,proto3,oneof" json:"commit,omitempty"` +} +type Response_ListSnapshots struct { + ListSnapshots *ResponseListSnapshots `protobuf:"bytes,13,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` +} +type Response_OfferSnapshot struct { + OfferSnapshot *ResponseOfferSnapshot `protobuf:"bytes,14,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` +} +type Response_LoadSnapshotChunk struct { + LoadSnapshotChunk *ResponseLoadSnapshotChunk `protobuf:"bytes,15,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` +} +type Response_ApplySnapshotChunk struct { + ApplySnapshotChunk *ResponseApplySnapshotChunk `protobuf:"bytes,16,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` +} + +func (*Response_Exception) isResponse_Value() {} +func (*Response_Echo) isResponse_Value() {} +func (*Response_Flush) isResponse_Value() {} +func (*Response_Info) isResponse_Value() {} +func (*Response_SetOption) isResponse_Value() {} +func (*Response_InitChain) isResponse_Value() {} +func (*Response_Query) isResponse_Value() {} +func (*Response_BeginBlock) isResponse_Value() {} +func (*Response_CheckTx) isResponse_Value() {} +func (*Response_DeliverTx) isResponse_Value() {} +func (*Response_EndBlock) isResponse_Value() {} +func (*Response_Commit) isResponse_Value() {} +func (*Response_ListSnapshots) isResponse_Value() {} +func (*Response_OfferSnapshot) isResponse_Value() {} +func (*Response_LoadSnapshotChunk) isResponse_Value() {} +func (*Response_ApplySnapshotChunk) isResponse_Value() {} + +func (m *Response) GetValue() isResponse_Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *Response) GetException() *ResponseException { + if x, ok := m.GetValue().(*Response_Exception); ok { + return x.Exception + } + return nil +} + +func (m *Response) GetEcho() *ResponseEcho { + if x, ok := m.GetValue().(*Response_Echo); ok { + return x.Echo + } + return nil +} + +func (m *Response) GetFlush() *ResponseFlush { + if x, ok := m.GetValue().(*Response_Flush); ok { + return x.Flush + } + return nil +} + +func (m *Response) GetInfo() *ResponseInfo { + if x, ok := m.GetValue().(*Response_Info); ok { + return x.Info + } + return nil +} + +func (m *Response) GetSetOption() *ResponseSetOption { + if x, ok := m.GetValue().(*Response_SetOption); ok { + return x.SetOption + } + return nil +} + +func (m *Response) GetInitChain() *ResponseInitChain { + if x, ok := m.GetValue().(*Response_InitChain); ok { + return x.InitChain + } + return nil +} + +func (m *Response) GetQuery() *ResponseQuery { + if x, ok := m.GetValue().(*Response_Query); ok { + return x.Query + } + return nil +} + +func (m *Response) GetBeginBlock() *ResponseBeginBlock { + if x, ok := m.GetValue().(*Response_BeginBlock); ok { + return x.BeginBlock + } + return nil +} + +func (m *Response) GetCheckTx() *ResponseCheckTx { + if x, ok := m.GetValue().(*Response_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Response) GetDeliverTx() *ResponseDeliverTx { + if x, ok := m.GetValue().(*Response_DeliverTx); ok { + return x.DeliverTx + } + return nil +} + +func (m *Response) GetEndBlock() *ResponseEndBlock { + if x, ok := m.GetValue().(*Response_EndBlock); ok { + return x.EndBlock + } + return nil +} + +func (m *Response) GetCommit() *ResponseCommit { + if x, ok := m.GetValue().(*Response_Commit); ok { + return x.Commit + } + return nil +} + +func (m *Response) GetListSnapshots() *ResponseListSnapshots { + if x, ok := m.GetValue().(*Response_ListSnapshots); ok { + return x.ListSnapshots + } + return nil +} + +func (m *Response) GetOfferSnapshot() *ResponseOfferSnapshot { + if x, ok := m.GetValue().(*Response_OfferSnapshot); ok { + return x.OfferSnapshot + } + return nil +} + +func (m *Response) GetLoadSnapshotChunk() *ResponseLoadSnapshotChunk { + if x, ok := m.GetValue().(*Response_LoadSnapshotChunk); ok { + return x.LoadSnapshotChunk + } + return nil +} + +func (m *Response) GetApplySnapshotChunk() *ResponseApplySnapshotChunk { + if x, ok := m.GetValue().(*Response_ApplySnapshotChunk); ok { + return x.ApplySnapshotChunk + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Response) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Response_Exception)(nil), + (*Response_Echo)(nil), + (*Response_Flush)(nil), + (*Response_Info)(nil), + (*Response_SetOption)(nil), + (*Response_InitChain)(nil), + (*Response_Query)(nil), + (*Response_BeginBlock)(nil), + (*Response_CheckTx)(nil), + (*Response_DeliverTx)(nil), + (*Response_EndBlock)(nil), + (*Response_Commit)(nil), + (*Response_ListSnapshots)(nil), + (*Response_OfferSnapshot)(nil), + (*Response_LoadSnapshotChunk)(nil), + (*Response_ApplySnapshotChunk)(nil), + } +} + +// nondeterministic +type ResponseException struct { + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *ResponseException) Reset() { *m = ResponseException{} } +func (m *ResponseException) String() string { return proto.CompactTextString(m) } +func (*ResponseException) ProtoMessage() {} +func (*ResponseException) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{17} +} +func (m *ResponseException) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseException) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseException.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseException) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseException.Merge(m, src) +} +func (m *ResponseException) XXX_Size() int { + return m.Size() +} +func (m *ResponseException) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseException.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseException proto.InternalMessageInfo + +func (m *ResponseException) GetError() string { + if m != nil { + return m.Error + } + return "" +} + +// ResponseEcho indicates that the connection is still alive. +type ResponseEcho struct { + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (m *ResponseEcho) Reset() { *m = ResponseEcho{} } +func (m *ResponseEcho) String() string { return proto.CompactTextString(m) } +func (*ResponseEcho) ProtoMessage() {} +func (*ResponseEcho) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{18} +} +func (m *ResponseEcho) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseEcho) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseEcho.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseEcho) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseEcho.Merge(m, src) +} +func (m *ResponseEcho) XXX_Size() int { + return m.Size() +} +func (m *ResponseEcho) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseEcho.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseEcho proto.InternalMessageInfo + +func (m *ResponseEcho) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +// ResponseFlush indicates that the ABCI application state was flushed? +type ResponseFlush struct { +} + +func (m *ResponseFlush) Reset() { *m = ResponseFlush{} } +func (m *ResponseFlush) String() string { return proto.CompactTextString(m) } +func (*ResponseFlush) ProtoMessage() {} +func (*ResponseFlush) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{19} +} +func (m *ResponseFlush) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseFlush) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseFlush.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseFlush) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseFlush.Merge(m, src) +} +func (m *ResponseFlush) XXX_Size() int { + return m.Size() +} +func (m *ResponseFlush) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseFlush.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseFlush proto.InternalMessageInfo + +// ResponseInfo contains the ABCI application version information. +type ResponseInfo struct { + Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + AppVersion uint64 `protobuf:"varint,3,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` + LastBlockHeight int64 `protobuf:"varint,4,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` + LastBlockAppHash []byte `protobuf:"bytes,5,opt,name=last_block_app_hash,json=lastBlockAppHash,proto3" json:"last_block_app_hash,omitempty"` +} + +func (m *ResponseInfo) Reset() { *m = ResponseInfo{} } +func (m *ResponseInfo) String() string { return proto.CompactTextString(m) } +func (*ResponseInfo) ProtoMessage() {} +func (*ResponseInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{20} +} +func (m *ResponseInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseInfo.Merge(m, src) +} +func (m *ResponseInfo) XXX_Size() int { + return m.Size() +} +func (m *ResponseInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseInfo proto.InternalMessageInfo + +func (m *ResponseInfo) GetData() string { + if m != nil { + return m.Data + } + return "" +} + +func (m *ResponseInfo) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +func (m *ResponseInfo) GetAppVersion() uint64 { + if m != nil { + return m.AppVersion + } + return 0 +} + +func (m *ResponseInfo) GetLastBlockHeight() int64 { + if m != nil { + return m.LastBlockHeight + } + return 0 +} + +func (m *ResponseInfo) GetLastBlockAppHash() []byte { + if m != nil { + return m.LastBlockAppHash + } + return nil +} + +// nondeterministic +type ResponseSetOption struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + // bytes data = 2; + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` +} + +func (m *ResponseSetOption) Reset() { *m = ResponseSetOption{} } +func (m *ResponseSetOption) String() string { return proto.CompactTextString(m) } +func (*ResponseSetOption) ProtoMessage() {} +func (*ResponseSetOption) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{21} +} +func (m *ResponseSetOption) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseSetOption) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseSetOption.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseSetOption) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseSetOption.Merge(m, src) +} +func (m *ResponseSetOption) XXX_Size() int { + return m.Size() +} +func (m *ResponseSetOption) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseSetOption.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseSetOption proto.InternalMessageInfo + +func (m *ResponseSetOption) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseSetOption) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseSetOption) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + +// ResponseInitChain contains the ABCI application's hash and updates to the +// validator set and/or the consensus params, if any. +type ResponseInitChain struct { + ConsensusParams *ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []ValidatorUpdate `protobuf:"bytes,2,rep,name=validators,proto3" json:"validators"` + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } +func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } +func (*ResponseInitChain) ProtoMessage() {} +func (*ResponseInitChain) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{22} +} +func (m *ResponseInitChain) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseInitChain.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseInitChain) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseInitChain.Merge(m, src) +} +func (m *ResponseInitChain) XXX_Size() int { + return m.Size() +} +func (m *ResponseInitChain) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseInitChain.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseInitChain proto.InternalMessageInfo + +func (m *ResponseInitChain) GetConsensusParams() *ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return nil +} + +func (m *ResponseInitChain) GetValidators() []ValidatorUpdate { + if m != nil { + return m.Validators + } + return nil +} + +func (m *ResponseInitChain) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +// ResponseQuery contains the ABCI application data along with a proof. +type ResponseQuery struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + // bytes data = 2; // use "value" instead. + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + Index int64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` + Key []byte `protobuf:"bytes,6,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"` + ProofOps *v1.ProofOps `protobuf:"bytes,8,opt,name=proof_ops,json=proofOps,proto3" json:"proof_ops,omitempty"` + Height int64 `protobuf:"varint,9,opt,name=height,proto3" json:"height,omitempty"` + Codespace string `protobuf:"bytes,10,opt,name=codespace,proto3" json:"codespace,omitempty"` +} + +func (m *ResponseQuery) Reset() { *m = ResponseQuery{} } +func (m *ResponseQuery) String() string { return proto.CompactTextString(m) } +func (*ResponseQuery) ProtoMessage() {} +func (*ResponseQuery) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{23} +} +func (m *ResponseQuery) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseQuery.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseQuery) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseQuery.Merge(m, src) +} +func (m *ResponseQuery) XXX_Size() int { + return m.Size() +} +func (m *ResponseQuery) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseQuery.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseQuery proto.InternalMessageInfo + +func (m *ResponseQuery) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseQuery) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseQuery) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + +func (m *ResponseQuery) GetIndex() int64 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *ResponseQuery) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *ResponseQuery) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *ResponseQuery) GetProofOps() *v1.ProofOps { + if m != nil { + return m.ProofOps + } + return nil +} + +func (m *ResponseQuery) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *ResponseQuery) GetCodespace() string { + if m != nil { + return m.Codespace + } + return "" +} + +// ResponseBeginBlock contains a list of block-level events. +type ResponseBeginBlock struct { + Events []Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` +} + +func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } +func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseBeginBlock) ProtoMessage() {} +func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{24} +} +func (m *ResponseBeginBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseBeginBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseBeginBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseBeginBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseBeginBlock.Merge(m, src) +} +func (m *ResponseBeginBlock) XXX_Size() int { + return m.Size() +} +func (m *ResponseBeginBlock) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseBeginBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseBeginBlock proto.InternalMessageInfo + +func (m *ResponseBeginBlock) GetEvents() []Event { + if m != nil { + return m.Events + } + return nil +} + +// ResponseCheckTx shows if the transaction was deemed valid by the ABCI +// application. +type ResponseCheckTx struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` + Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` + Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` + Sender string `protobuf:"bytes,9,opt,name=sender,proto3" json:"sender,omitempty"` + Priority int64 `protobuf:"varint,10,opt,name=priority,proto3" json:"priority,omitempty"` + // mempool_error is set by CometBFT. + // ABCI applications creating a ResponseCheckTX should not set mempool_error. + MempoolError string `protobuf:"bytes,11,opt,name=mempool_error,json=mempoolError,proto3" json:"mempool_error,omitempty"` +} + +func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } +func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } +func (*ResponseCheckTx) ProtoMessage() {} +func (*ResponseCheckTx) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{25} +} +func (m *ResponseCheckTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseCheckTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseCheckTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseCheckTx.Merge(m, src) +} +func (m *ResponseCheckTx) XXX_Size() int { + return m.Size() +} +func (m *ResponseCheckTx) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseCheckTx.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseCheckTx proto.InternalMessageInfo + +func (m *ResponseCheckTx) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseCheckTx) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseCheckTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseCheckTx) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + +func (m *ResponseCheckTx) GetGasWanted() int64 { + if m != nil { + return m.GasWanted + } + return 0 +} + +func (m *ResponseCheckTx) GetGasUsed() int64 { + if m != nil { + return m.GasUsed + } + return 0 +} + +func (m *ResponseCheckTx) GetEvents() []Event { + if m != nil { + return m.Events + } + return nil +} + +func (m *ResponseCheckTx) GetCodespace() string { + if m != nil { + return m.Codespace + } + return "" +} + +func (m *ResponseCheckTx) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *ResponseCheckTx) GetPriority() int64 { + if m != nil { + return m.Priority + } + return 0 +} + +func (m *ResponseCheckTx) GetMempoolError() string { + if m != nil { + return m.MempoolError + } + return "" +} + +// ResponseDeliverTx contains a result of committing the given transaction and a +// list of events. +type ResponseDeliverTx struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` + Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` + Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` +} + +func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } +func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } +func (*ResponseDeliverTx) ProtoMessage() {} +func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{26} +} +func (m *ResponseDeliverTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseDeliverTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseDeliverTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseDeliverTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseDeliverTx.Merge(m, src) +} +func (m *ResponseDeliverTx) XXX_Size() int { + return m.Size() +} +func (m *ResponseDeliverTx) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseDeliverTx.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseDeliverTx proto.InternalMessageInfo + +func (m *ResponseDeliverTx) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseDeliverTx) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseDeliverTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseDeliverTx) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + +func (m *ResponseDeliverTx) GetGasWanted() int64 { + if m != nil { + return m.GasWanted + } + return 0 +} + +func (m *ResponseDeliverTx) GetGasUsed() int64 { + if m != nil { + return m.GasUsed + } + return 0 +} + +func (m *ResponseDeliverTx) GetEvents() []Event { + if m != nil { + return m.Events + } + return nil +} + +func (m *ResponseDeliverTx) GetCodespace() string { + if m != nil { + return m.Codespace + } + return "" +} + +// ResponseEndBlock contains updates to consensus params and/or validator set changes, if any. +type ResponseEndBlock struct { + ValidatorUpdates []ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` + ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` + Events []Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` +} + +func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } +func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseEndBlock) ProtoMessage() {} +func (*ResponseEndBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{27} +} +func (m *ResponseEndBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseEndBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseEndBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseEndBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseEndBlock.Merge(m, src) +} +func (m *ResponseEndBlock) XXX_Size() int { + return m.Size() +} +func (m *ResponseEndBlock) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseEndBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseEndBlock proto.InternalMessageInfo + +func (m *ResponseEndBlock) GetValidatorUpdates() []ValidatorUpdate { + if m != nil { + return m.ValidatorUpdates + } + return nil +} + +func (m *ResponseEndBlock) GetConsensusParamUpdates() *ConsensusParams { + if m != nil { + return m.ConsensusParamUpdates + } + return nil +} + +func (m *ResponseEndBlock) GetEvents() []Event { + if m != nil { + return m.Events + } + return nil +} + +// ResponseCommit indicates how much blocks should CometBFT retain. +type ResponseCommit struct { + // reserve 1 + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + RetainHeight int64 `protobuf:"varint,3,opt,name=retain_height,json=retainHeight,proto3" json:"retain_height,omitempty"` +} + +func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } +func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } +func (*ResponseCommit) ProtoMessage() {} +func (*ResponseCommit) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{28} +} +func (m *ResponseCommit) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseCommit.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseCommit) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseCommit.Merge(m, src) +} +func (m *ResponseCommit) XXX_Size() int { + return m.Size() +} +func (m *ResponseCommit) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseCommit.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseCommit proto.InternalMessageInfo + +func (m *ResponseCommit) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseCommit) GetRetainHeight() int64 { + if m != nil { + return m.RetainHeight + } + return 0 +} + +// ResponseListSnapshots contains the list of snapshots. +type ResponseListSnapshots struct { + Snapshots []*Snapshot `protobuf:"bytes,1,rep,name=snapshots,proto3" json:"snapshots,omitempty"` +} + +func (m *ResponseListSnapshots) Reset() { *m = ResponseListSnapshots{} } +func (m *ResponseListSnapshots) String() string { return proto.CompactTextString(m) } +func (*ResponseListSnapshots) ProtoMessage() {} +func (*ResponseListSnapshots) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{29} +} +func (m *ResponseListSnapshots) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseListSnapshots) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseListSnapshots.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseListSnapshots) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseListSnapshots.Merge(m, src) +} +func (m *ResponseListSnapshots) XXX_Size() int { + return m.Size() +} +func (m *ResponseListSnapshots) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseListSnapshots.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseListSnapshots proto.InternalMessageInfo + +func (m *ResponseListSnapshots) GetSnapshots() []*Snapshot { + if m != nil { + return m.Snapshots + } + return nil +} + +// ResponseOfferSnapshot indicates the ABCI application decision whenever to +// provide a snapshot to the requester or not. +type ResponseOfferSnapshot struct { + Result ResponseOfferSnapshot_Result `protobuf:"varint,1,opt,name=result,proto3,enum=cometbft.abci.v1beta1.ResponseOfferSnapshot_Result" json:"result,omitempty"` +} + +func (m *ResponseOfferSnapshot) Reset() { *m = ResponseOfferSnapshot{} } +func (m *ResponseOfferSnapshot) String() string { return proto.CompactTextString(m) } +func (*ResponseOfferSnapshot) ProtoMessage() {} +func (*ResponseOfferSnapshot) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{30} +} +func (m *ResponseOfferSnapshot) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseOfferSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseOfferSnapshot.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseOfferSnapshot) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseOfferSnapshot.Merge(m, src) +} +func (m *ResponseOfferSnapshot) XXX_Size() int { + return m.Size() +} +func (m *ResponseOfferSnapshot) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseOfferSnapshot.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseOfferSnapshot proto.InternalMessageInfo + +func (m *ResponseOfferSnapshot) GetResult() ResponseOfferSnapshot_Result { + if m != nil { + return m.Result + } + return ResponseOfferSnapshot_UNKNOWN +} + +// ResponseLoadSnapshotChunk returns a snapshot's chunk. +type ResponseLoadSnapshotChunk struct { + Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"` +} + +func (m *ResponseLoadSnapshotChunk) Reset() { *m = ResponseLoadSnapshotChunk{} } +func (m *ResponseLoadSnapshotChunk) String() string { return proto.CompactTextString(m) } +func (*ResponseLoadSnapshotChunk) ProtoMessage() {} +func (*ResponseLoadSnapshotChunk) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{31} +} +func (m *ResponseLoadSnapshotChunk) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseLoadSnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseLoadSnapshotChunk.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseLoadSnapshotChunk) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseLoadSnapshotChunk.Merge(m, src) +} +func (m *ResponseLoadSnapshotChunk) XXX_Size() int { + return m.Size() +} +func (m *ResponseLoadSnapshotChunk) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseLoadSnapshotChunk.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseLoadSnapshotChunk proto.InternalMessageInfo + +func (m *ResponseLoadSnapshotChunk) GetChunk() []byte { + if m != nil { + return m.Chunk + } + return nil +} + +// ResponseApplySnapshotChunk returns a result of applying the specified chunk. +type ResponseApplySnapshotChunk struct { + Result ResponseApplySnapshotChunk_Result `protobuf:"varint,1,opt,name=result,proto3,enum=cometbft.abci.v1beta1.ResponseApplySnapshotChunk_Result" json:"result,omitempty"` + RefetchChunks []uint32 `protobuf:"varint,2,rep,packed,name=refetch_chunks,json=refetchChunks,proto3" json:"refetch_chunks,omitempty"` + RejectSenders []string `protobuf:"bytes,3,rep,name=reject_senders,json=rejectSenders,proto3" json:"reject_senders,omitempty"` +} + +func (m *ResponseApplySnapshotChunk) Reset() { *m = ResponseApplySnapshotChunk{} } +func (m *ResponseApplySnapshotChunk) String() string { return proto.CompactTextString(m) } +func (*ResponseApplySnapshotChunk) ProtoMessage() {} +func (*ResponseApplySnapshotChunk) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{32} +} +func (m *ResponseApplySnapshotChunk) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseApplySnapshotChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseApplySnapshotChunk.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseApplySnapshotChunk) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseApplySnapshotChunk.Merge(m, src) +} +func (m *ResponseApplySnapshotChunk) XXX_Size() int { + return m.Size() +} +func (m *ResponseApplySnapshotChunk) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseApplySnapshotChunk.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseApplySnapshotChunk proto.InternalMessageInfo + +func (m *ResponseApplySnapshotChunk) GetResult() ResponseApplySnapshotChunk_Result { + if m != nil { + return m.Result + } + return ResponseApplySnapshotChunk_UNKNOWN +} + +func (m *ResponseApplySnapshotChunk) GetRefetchChunks() []uint32 { + if m != nil { + return m.RefetchChunks + } + return nil +} + +func (m *ResponseApplySnapshotChunk) GetRejectSenders() []string { + if m != nil { + return m.RejectSenders + } + return nil +} + +// ConsensusParams contains all consensus-relevant parameters +// that can be adjusted by the abci app +type ConsensusParams struct { + Block *BlockParams `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Evidence *v1beta1.EvidenceParams `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence,omitempty"` + Validator *v1beta1.ValidatorParams `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator,omitempty"` + Version *v1beta1.VersionParams `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` +} + +func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } +func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } +func (*ConsensusParams) ProtoMessage() {} +func (*ConsensusParams) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{33} +} +func (m *ConsensusParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsensusParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsensusParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsensusParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsensusParams.Merge(m, src) +} +func (m *ConsensusParams) XXX_Size() int { + return m.Size() +} +func (m *ConsensusParams) XXX_DiscardUnknown() { + xxx_messageInfo_ConsensusParams.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsensusParams proto.InternalMessageInfo + +func (m *ConsensusParams) GetBlock() *BlockParams { + if m != nil { + return m.Block + } + return nil +} + +func (m *ConsensusParams) GetEvidence() *v1beta1.EvidenceParams { + if m != nil { + return m.Evidence + } + return nil +} + +func (m *ConsensusParams) GetValidator() *v1beta1.ValidatorParams { + if m != nil { + return m.Validator + } + return nil +} + +func (m *ConsensusParams) GetVersion() *v1beta1.VersionParams { + if m != nil { + return m.Version + } + return nil +} + +// BlockParams contains limits on the block size. +type BlockParams struct { + // Note: must be greater than 0 + MaxBytes int64 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` + // Note: must be greater or equal to -1 + MaxGas int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` +} + +func (m *BlockParams) Reset() { *m = BlockParams{} } +func (m *BlockParams) String() string { return proto.CompactTextString(m) } +func (*BlockParams) ProtoMessage() {} +func (*BlockParams) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{34} +} +func (m *BlockParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockParams.Merge(m, src) +} +func (m *BlockParams) XXX_Size() int { + return m.Size() +} +func (m *BlockParams) XXX_DiscardUnknown() { + xxx_messageInfo_BlockParams.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockParams proto.InternalMessageInfo + +func (m *BlockParams) GetMaxBytes() int64 { + if m != nil { + return m.MaxBytes + } + return 0 +} + +func (m *BlockParams) GetMaxGas() int64 { + if m != nil { + return m.MaxGas + } + return 0 +} + +// LastCommitInfo contains votes for the particular round. +type LastCommitInfo struct { + Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` + Votes []VoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` +} + +func (m *LastCommitInfo) Reset() { *m = LastCommitInfo{} } +func (m *LastCommitInfo) String() string { return proto.CompactTextString(m) } +func (*LastCommitInfo) ProtoMessage() {} +func (*LastCommitInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{35} +} +func (m *LastCommitInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LastCommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LastCommitInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LastCommitInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_LastCommitInfo.Merge(m, src) +} +func (m *LastCommitInfo) XXX_Size() int { + return m.Size() +} +func (m *LastCommitInfo) XXX_DiscardUnknown() { + xxx_messageInfo_LastCommitInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_LastCommitInfo proto.InternalMessageInfo + +func (m *LastCommitInfo) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *LastCommitInfo) GetVotes() []VoteInfo { + if m != nil { + return m.Votes + } + return nil +} + +// Event allows application developers to attach additional information to +// ResponseBeginBlock, ResponseEndBlock, ResponseCheckTx and ResponseDeliverTx. +// Later, transactions may be queried using these events. +type Event struct { + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Attributes []EventAttribute `protobuf:"bytes,2,rep,name=attributes,proto3" json:"attributes,omitempty"` +} + +func (m *Event) Reset() { *m = Event{} } +func (m *Event) String() string { return proto.CompactTextString(m) } +func (*Event) ProtoMessage() {} +func (*Event) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{36} +} +func (m *Event) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Event) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Event.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Event) XXX_Merge(src proto.Message) { + xxx_messageInfo_Event.Merge(m, src) +} +func (m *Event) XXX_Size() int { + return m.Size() +} +func (m *Event) XXX_DiscardUnknown() { + xxx_messageInfo_Event.DiscardUnknown(m) +} + +var xxx_messageInfo_Event proto.InternalMessageInfo + +func (m *Event) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *Event) GetAttributes() []EventAttribute { + if m != nil { + return m.Attributes + } + return nil +} + +// EventAttribute is a single key-value pair, associated with an event. +type EventAttribute struct { + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + Index bool `protobuf:"varint,3,opt,name=index,proto3" json:"index,omitempty"` +} + +func (m *EventAttribute) Reset() { *m = EventAttribute{} } +func (m *EventAttribute) String() string { return proto.CompactTextString(m) } +func (*EventAttribute) ProtoMessage() {} +func (*EventAttribute) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{37} +} +func (m *EventAttribute) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventAttribute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventAttribute.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventAttribute) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventAttribute.Merge(m, src) +} +func (m *EventAttribute) XXX_Size() int { + return m.Size() +} +func (m *EventAttribute) XXX_DiscardUnknown() { + xxx_messageInfo_EventAttribute.DiscardUnknown(m) +} + +var xxx_messageInfo_EventAttribute proto.InternalMessageInfo + +func (m *EventAttribute) GetKey() []byte { + if m != nil { + return m.Key + } + return nil +} + +func (m *EventAttribute) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *EventAttribute) GetIndex() bool { + if m != nil { + return m.Index + } + return false +} + +// TxResult contains results of executing the transaction. +// +// One usage is indexing transaction results. +type TxResult struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Index uint32 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` + Tx []byte `protobuf:"bytes,3,opt,name=tx,proto3" json:"tx,omitempty"` + Result ResponseDeliverTx `protobuf:"bytes,4,opt,name=result,proto3" json:"result"` +} + +func (m *TxResult) Reset() { *m = TxResult{} } +func (m *TxResult) String() string { return proto.CompactTextString(m) } +func (*TxResult) ProtoMessage() {} +func (*TxResult) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{38} +} +func (m *TxResult) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TxResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TxResult.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TxResult) XXX_Merge(src proto.Message) { + xxx_messageInfo_TxResult.Merge(m, src) +} +func (m *TxResult) XXX_Size() int { + return m.Size() +} +func (m *TxResult) XXX_DiscardUnknown() { + xxx_messageInfo_TxResult.DiscardUnknown(m) +} + +var xxx_messageInfo_TxResult proto.InternalMessageInfo + +func (m *TxResult) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *TxResult) GetIndex() uint32 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *TxResult) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + +func (m *TxResult) GetResult() ResponseDeliverTx { + if m != nil { + return m.Result + } + return ResponseDeliverTx{} +} + +// Validator in the validator set. +type Validator struct { + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // PubKey pub_key = 2 [(gogoproto.nullable)=false]; + Power int64 `protobuf:"varint,3,opt,name=power,proto3" json:"power,omitempty"` +} + +func (m *Validator) Reset() { *m = Validator{} } +func (m *Validator) String() string { return proto.CompactTextString(m) } +func (*Validator) ProtoMessage() {} +func (*Validator) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{39} +} +func (m *Validator) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Validator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Validator.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Validator) XXX_Merge(src proto.Message) { + xxx_messageInfo_Validator.Merge(m, src) +} +func (m *Validator) XXX_Size() int { + return m.Size() +} +func (m *Validator) XXX_DiscardUnknown() { + xxx_messageInfo_Validator.DiscardUnknown(m) +} + +var xxx_messageInfo_Validator proto.InternalMessageInfo + +func (m *Validator) GetAddress() []byte { + if m != nil { + return m.Address + } + return nil +} + +func (m *Validator) GetPower() int64 { + if m != nil { + return m.Power + } + return 0 +} + +// ValidatorUpdate is a singular update to a validator set. +type ValidatorUpdate struct { + PubKey v1.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"` +} + +func (m *ValidatorUpdate) Reset() { *m = ValidatorUpdate{} } +func (m *ValidatorUpdate) String() string { return proto.CompactTextString(m) } +func (*ValidatorUpdate) ProtoMessage() {} +func (*ValidatorUpdate) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{40} +} +func (m *ValidatorUpdate) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ValidatorUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ValidatorUpdate.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ValidatorUpdate) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidatorUpdate.Merge(m, src) +} +func (m *ValidatorUpdate) XXX_Size() int { + return m.Size() +} +func (m *ValidatorUpdate) XXX_DiscardUnknown() { + xxx_messageInfo_ValidatorUpdate.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidatorUpdate proto.InternalMessageInfo + +func (m *ValidatorUpdate) GetPubKey() v1.PublicKey { + if m != nil { + return m.PubKey + } + return v1.PublicKey{} +} + +func (m *ValidatorUpdate) GetPower() int64 { + if m != nil { + return m.Power + } + return 0 +} + +// VoteInfo contains the information about the vote. +type VoteInfo struct { + Validator Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` + SignedLastBlock bool `protobuf:"varint,2,opt,name=signed_last_block,json=signedLastBlock,proto3" json:"signed_last_block,omitempty"` +} + +func (m *VoteInfo) Reset() { *m = VoteInfo{} } +func (m *VoteInfo) String() string { return proto.CompactTextString(m) } +func (*VoteInfo) ProtoMessage() {} +func (*VoteInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{41} +} +func (m *VoteInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VoteInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VoteInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *VoteInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_VoteInfo.Merge(m, src) +} +func (m *VoteInfo) XXX_Size() int { + return m.Size() +} +func (m *VoteInfo) XXX_DiscardUnknown() { + xxx_messageInfo_VoteInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_VoteInfo proto.InternalMessageInfo + +func (m *VoteInfo) GetValidator() Validator { + if m != nil { + return m.Validator + } + return Validator{} +} + +func (m *VoteInfo) GetSignedLastBlock() bool { + if m != nil { + return m.SignedLastBlock + } + return false +} + +// Evidence of a misbehavior committed by a validator. +type Evidence struct { + Type EvidenceType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.abci.v1beta1.EvidenceType" json:"type,omitempty"` + // The offending validator + Validator Validator `protobuf:"bytes,2,opt,name=validator,proto3" json:"validator"` + // The height when the offense occurred + Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + // The corresponding time where the offense occurred + Time time.Time `protobuf:"bytes,4,opt,name=time,proto3,stdtime" json:"time"` + // Total voting power of the validator set in case the ABCI application does + // not store historical validators. + // https://github.com/tendermint/tendermint/issues/4581 + TotalVotingPower int64 `protobuf:"varint,5,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` +} + +func (m *Evidence) Reset() { *m = Evidence{} } +func (m *Evidence) String() string { return proto.CompactTextString(m) } +func (*Evidence) ProtoMessage() {} +func (*Evidence) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{42} +} +func (m *Evidence) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Evidence.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Evidence) XXX_Merge(src proto.Message) { + xxx_messageInfo_Evidence.Merge(m, src) +} +func (m *Evidence) XXX_Size() int { + return m.Size() +} +func (m *Evidence) XXX_DiscardUnknown() { + xxx_messageInfo_Evidence.DiscardUnknown(m) +} + +var xxx_messageInfo_Evidence proto.InternalMessageInfo + +func (m *Evidence) GetType() EvidenceType { + if m != nil { + return m.Type + } + return EvidenceType_UNKNOWN +} + +func (m *Evidence) GetValidator() Validator { + if m != nil { + return m.Validator + } + return Validator{} +} + +func (m *Evidence) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Evidence) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *Evidence) GetTotalVotingPower() int64 { + if m != nil { + return m.TotalVotingPower + } + return 0 +} + +// Snapshot of the ABCI application state. +type Snapshot struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Format uint32 `protobuf:"varint,2,opt,name=format,proto3" json:"format,omitempty"` + Chunks uint32 `protobuf:"varint,3,opt,name=chunks,proto3" json:"chunks,omitempty"` + Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` + Metadata []byte `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (m *Snapshot) Reset() { *m = Snapshot{} } +func (m *Snapshot) String() string { return proto.CompactTextString(m) } +func (*Snapshot) ProtoMessage() {} +func (*Snapshot) Descriptor() ([]byte, []int) { + return fileDescriptor_916eac2194a40aed, []int{43} +} +func (m *Snapshot) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Snapshot.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Snapshot) XXX_Merge(src proto.Message) { + xxx_messageInfo_Snapshot.Merge(m, src) +} +func (m *Snapshot) XXX_Size() int { + return m.Size() +} +func (m *Snapshot) XXX_DiscardUnknown() { + xxx_messageInfo_Snapshot.DiscardUnknown(m) +} + +var xxx_messageInfo_Snapshot proto.InternalMessageInfo + +func (m *Snapshot) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Snapshot) GetFormat() uint32 { + if m != nil { + return m.Format + } + return 0 +} + +func (m *Snapshot) GetChunks() uint32 { + if m != nil { + return m.Chunks + } + return 0 +} + +func (m *Snapshot) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *Snapshot) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +func init() { + proto.RegisterEnum("cometbft.abci.v1beta1.CheckTxType", CheckTxType_name, CheckTxType_value) + proto.RegisterEnum("cometbft.abci.v1beta1.EvidenceType", EvidenceType_name, EvidenceType_value) + proto.RegisterEnum("cometbft.abci.v1beta1.ResponseOfferSnapshot_Result", ResponseOfferSnapshot_Result_name, ResponseOfferSnapshot_Result_value) + proto.RegisterEnum("cometbft.abci.v1beta1.ResponseApplySnapshotChunk_Result", ResponseApplySnapshotChunk_Result_name, ResponseApplySnapshotChunk_Result_value) + proto.RegisterType((*Request)(nil), "cometbft.abci.v1beta1.Request") + proto.RegisterType((*RequestEcho)(nil), "cometbft.abci.v1beta1.RequestEcho") + proto.RegisterType((*RequestFlush)(nil), "cometbft.abci.v1beta1.RequestFlush") + proto.RegisterType((*RequestInfo)(nil), "cometbft.abci.v1beta1.RequestInfo") + proto.RegisterType((*RequestSetOption)(nil), "cometbft.abci.v1beta1.RequestSetOption") + proto.RegisterType((*RequestInitChain)(nil), "cometbft.abci.v1beta1.RequestInitChain") + proto.RegisterType((*RequestQuery)(nil), "cometbft.abci.v1beta1.RequestQuery") + proto.RegisterType((*RequestBeginBlock)(nil), "cometbft.abci.v1beta1.RequestBeginBlock") + proto.RegisterType((*RequestCheckTx)(nil), "cometbft.abci.v1beta1.RequestCheckTx") + proto.RegisterType((*RequestDeliverTx)(nil), "cometbft.abci.v1beta1.RequestDeliverTx") + proto.RegisterType((*RequestEndBlock)(nil), "cometbft.abci.v1beta1.RequestEndBlock") + proto.RegisterType((*RequestCommit)(nil), "cometbft.abci.v1beta1.RequestCommit") + proto.RegisterType((*RequestListSnapshots)(nil), "cometbft.abci.v1beta1.RequestListSnapshots") + proto.RegisterType((*RequestOfferSnapshot)(nil), "cometbft.abci.v1beta1.RequestOfferSnapshot") + proto.RegisterType((*RequestLoadSnapshotChunk)(nil), "cometbft.abci.v1beta1.RequestLoadSnapshotChunk") + proto.RegisterType((*RequestApplySnapshotChunk)(nil), "cometbft.abci.v1beta1.RequestApplySnapshotChunk") + proto.RegisterType((*Response)(nil), "cometbft.abci.v1beta1.Response") + proto.RegisterType((*ResponseException)(nil), "cometbft.abci.v1beta1.ResponseException") + proto.RegisterType((*ResponseEcho)(nil), "cometbft.abci.v1beta1.ResponseEcho") + proto.RegisterType((*ResponseFlush)(nil), "cometbft.abci.v1beta1.ResponseFlush") + proto.RegisterType((*ResponseInfo)(nil), "cometbft.abci.v1beta1.ResponseInfo") + proto.RegisterType((*ResponseSetOption)(nil), "cometbft.abci.v1beta1.ResponseSetOption") + proto.RegisterType((*ResponseInitChain)(nil), "cometbft.abci.v1beta1.ResponseInitChain") + proto.RegisterType((*ResponseQuery)(nil), "cometbft.abci.v1beta1.ResponseQuery") + proto.RegisterType((*ResponseBeginBlock)(nil), "cometbft.abci.v1beta1.ResponseBeginBlock") + proto.RegisterType((*ResponseCheckTx)(nil), "cometbft.abci.v1beta1.ResponseCheckTx") + proto.RegisterType((*ResponseDeliverTx)(nil), "cometbft.abci.v1beta1.ResponseDeliverTx") + proto.RegisterType((*ResponseEndBlock)(nil), "cometbft.abci.v1beta1.ResponseEndBlock") + proto.RegisterType((*ResponseCommit)(nil), "cometbft.abci.v1beta1.ResponseCommit") + proto.RegisterType((*ResponseListSnapshots)(nil), "cometbft.abci.v1beta1.ResponseListSnapshots") + proto.RegisterType((*ResponseOfferSnapshot)(nil), "cometbft.abci.v1beta1.ResponseOfferSnapshot") + proto.RegisterType((*ResponseLoadSnapshotChunk)(nil), "cometbft.abci.v1beta1.ResponseLoadSnapshotChunk") + proto.RegisterType((*ResponseApplySnapshotChunk)(nil), "cometbft.abci.v1beta1.ResponseApplySnapshotChunk") + proto.RegisterType((*ConsensusParams)(nil), "cometbft.abci.v1beta1.ConsensusParams") + proto.RegisterType((*BlockParams)(nil), "cometbft.abci.v1beta1.BlockParams") + proto.RegisterType((*LastCommitInfo)(nil), "cometbft.abci.v1beta1.LastCommitInfo") + proto.RegisterType((*Event)(nil), "cometbft.abci.v1beta1.Event") + proto.RegisterType((*EventAttribute)(nil), "cometbft.abci.v1beta1.EventAttribute") + proto.RegisterType((*TxResult)(nil), "cometbft.abci.v1beta1.TxResult") + proto.RegisterType((*Validator)(nil), "cometbft.abci.v1beta1.Validator") + proto.RegisterType((*ValidatorUpdate)(nil), "cometbft.abci.v1beta1.ValidatorUpdate") + proto.RegisterType((*VoteInfo)(nil), "cometbft.abci.v1beta1.VoteInfo") + proto.RegisterType((*Evidence)(nil), "cometbft.abci.v1beta1.Evidence") + proto.RegisterType((*Snapshot)(nil), "cometbft.abci.v1beta1.Snapshot") +} + +func init() { proto.RegisterFile("cometbft/abci/v1beta1/types.proto", fileDescriptor_916eac2194a40aed) } + +var fileDescriptor_916eac2194a40aed = []byte{ + // 2819 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4b, 0x73, 0xe3, 0xc6, + 0xf1, 0xe7, 0xfb, 0xd1, 0x14, 0x29, 0x6a, 0x76, 0xbd, 0xa6, 0xf9, 0xb7, 0xa5, 0xfd, 0x63, 0xb3, + 0x7e, 0x6c, 0x1c, 0x29, 0xbb, 0xae, 0x72, 0xbc, 0xd9, 0x4d, 0x5c, 0x22, 0x97, 0x6b, 0x2a, 0x92, + 0x25, 0x19, 0xa2, 0x64, 0x3b, 0xa9, 0x32, 0x3c, 0x04, 0x46, 0x24, 0xbc, 0x24, 0x00, 0x13, 0x43, + 0x5a, 0x4c, 0xe5, 0x90, 0xca, 0x2d, 0xce, 0xc5, 0xa7, 0xe4, 0xe4, 0x7c, 0x8d, 0xe4, 0x03, 0x24, + 0x55, 0xbe, 0xc5, 0xb7, 0xe4, 0xe4, 0xa4, 0xd6, 0xb7, 0xe4, 0x0b, 0xe4, 0x98, 0x9a, 0x07, 0x5e, + 0x14, 0x29, 0x82, 0x8e, 0x6f, 0xb9, 0x61, 0x1a, 0xdd, 0x3d, 0x98, 0xc6, 0xcc, 0xaf, 0x7f, 0xdd, + 0x00, 0xfc, 0xbf, 0x6e, 0x0f, 0x09, 0xed, 0x9e, 0xd3, 0x1d, 0xdc, 0xd5, 0xcd, 0x9d, 0xc9, 0xdd, + 0x2e, 0xa1, 0xf8, 0xee, 0x0e, 0x9d, 0x3a, 0xc4, 0xdd, 0x76, 0x46, 0x36, 0xb5, 0xd1, 0x33, 0x9e, + 0xca, 0x36, 0x53, 0xd9, 0x96, 0x2a, 0xf5, 0x17, 0x7c, 0x4b, 0x7d, 0x34, 0x75, 0xa8, 0xbd, 0x33, + 0xb9, 0xbb, 0xf3, 0x84, 0x4c, 0xa5, 0x55, 0x7d, 0x73, 0xce, 0x6d, 0x67, 0x64, 0xdb, 0xe7, 0xf2, + 0xfe, 0x2d, 0xff, 0x3e, 0x9f, 0xcb, 0x9f, 0xd9, 0xc1, 0x23, 0x3c, 0xf4, 0x9c, 0x28, 0x0b, 0x94, + 0x42, 0x8f, 0x57, 0xbf, 0xde, 0xb3, 0x7b, 0x36, 0xbf, 0xdc, 0x61, 0x57, 0x52, 0xba, 0xd5, 0xb3, + 0xed, 0xde, 0x80, 0xec, 0xf0, 0x51, 0x77, 0x7c, 0xbe, 0x43, 0xcd, 0x21, 0x71, 0x29, 0x1e, 0x3a, + 0x42, 0x41, 0xf9, 0x57, 0x01, 0xf2, 0x2a, 0xf9, 0x78, 0x4c, 0x5c, 0x8a, 0xde, 0x80, 0x0c, 0xd1, + 0xfb, 0x76, 0x2d, 0x79, 0x33, 0xf9, 0x72, 0xe9, 0x9e, 0xb2, 0x3d, 0x77, 0xc1, 0xdb, 0x52, 0xbb, + 0xa5, 0xf7, 0xed, 0x76, 0x42, 0xe5, 0x16, 0xe8, 0x01, 0x64, 0xcf, 0x07, 0x63, 0xb7, 0x5f, 0x4b, + 0x71, 0xd3, 0x5b, 0x57, 0x9b, 0x3e, 0x66, 0xaa, 0xed, 0x84, 0x2a, 0x6c, 0xd8, 0xb4, 0xa6, 0x75, + 0x6e, 0xd7, 0xd2, 0x71, 0xa6, 0xdd, 0xb3, 0xce, 0xf9, 0xb4, 0xcc, 0x02, 0xb5, 0x01, 0x5c, 0x42, + 0x35, 0xdb, 0xa1, 0xa6, 0x6d, 0xd5, 0x32, 0xdc, 0xfe, 0xa5, 0xab, 0xed, 0x4f, 0x08, 0x3d, 0xe2, + 0xea, 0xed, 0x84, 0x5a, 0x74, 0xbd, 0x01, 0xf3, 0x64, 0x5a, 0x26, 0xd5, 0xf4, 0x3e, 0x36, 0xad, + 0x5a, 0x36, 0x8e, 0xa7, 0x3d, 0xcb, 0xa4, 0x4d, 0xa6, 0xce, 0x3c, 0x99, 0xde, 0x80, 0x85, 0xe2, + 0xe3, 0x31, 0x19, 0x4d, 0x6b, 0xb9, 0x38, 0xa1, 0x78, 0x87, 0xa9, 0xb2, 0x50, 0x70, 0x1b, 0xb4, + 0x0f, 0xa5, 0x2e, 0xe9, 0x99, 0x96, 0xd6, 0x1d, 0xd8, 0xfa, 0x93, 0x5a, 0x9e, 0xbb, 0x78, 0xf9, + 0x6a, 0x17, 0x0d, 0x66, 0xd0, 0x60, 0xfa, 0xed, 0x84, 0x0a, 0x5d, 0x7f, 0x84, 0x1a, 0x50, 0xd0, + 0xfb, 0x44, 0x7f, 0xa2, 0xd1, 0x8b, 0x5a, 0x81, 0x7b, 0xba, 0x7d, 0xb5, 0xa7, 0x26, 0xd3, 0xee, + 0x5c, 0xb4, 0x13, 0x6a, 0x5e, 0x17, 0x97, 0x2c, 0x2e, 0x06, 0x19, 0x98, 0x13, 0x32, 0x62, 0x5e, + 0x8a, 0x71, 0xe2, 0xf2, 0x48, 0xe8, 0x73, 0x3f, 0x45, 0xc3, 0x1b, 0xa0, 0x16, 0x14, 0x89, 0x65, + 0xc8, 0x85, 0x01, 0x77, 0xf4, 0xe2, 0x92, 0x1d, 0x66, 0x19, 0xde, 0xb2, 0x0a, 0x44, 0x5e, 0xa3, + 0x1f, 0x43, 0x4e, 0xb7, 0x87, 0x43, 0x93, 0xd6, 0x4a, 0xdc, 0xc7, 0x77, 0x96, 0x2c, 0x89, 0xeb, + 0xb6, 0x13, 0xaa, 0xb4, 0x42, 0x1d, 0xa8, 0x0c, 0x4c, 0x97, 0x6a, 0xae, 0x85, 0x1d, 0xb7, 0x6f, + 0x53, 0xb7, 0xb6, 0xc6, 0xfd, 0x7c, 0xf7, 0x6a, 0x3f, 0x07, 0xa6, 0x4b, 0x4f, 0x3c, 0x93, 0x76, + 0x42, 0x2d, 0x0f, 0xc2, 0x02, 0xe6, 0xd5, 0x3e, 0x3f, 0x27, 0x23, 0xdf, 0x6d, 0xad, 0x1c, 0xc7, + 0xeb, 0x11, 0xb3, 0xf1, 0xbc, 0x30, 0xaf, 0x76, 0x58, 0x80, 0x30, 0x5c, 0x1b, 0xd8, 0xd8, 0xf0, + 0x9d, 0x6a, 0x7a, 0x7f, 0x6c, 0x3d, 0xa9, 0x55, 0xb8, 0xeb, 0x9d, 0x25, 0x0f, 0x6c, 0x63, 0xc3, + 0x73, 0xd4, 0x64, 0x66, 0xed, 0x84, 0xba, 0x31, 0x98, 0x15, 0x22, 0x03, 0xae, 0x63, 0xc7, 0x19, + 0x4c, 0x67, 0xe7, 0x58, 0xe7, 0x73, 0x7c, 0xff, 0xea, 0x39, 0x76, 0x99, 0xe5, 0xec, 0x24, 0x08, + 0x5f, 0x92, 0x36, 0xf2, 0x90, 0x9d, 0xe0, 0xc1, 0x98, 0x28, 0x2f, 0x41, 0x29, 0x04, 0x1f, 0xa8, + 0x06, 0xf9, 0x21, 0x71, 0x5d, 0xdc, 0x23, 0x1c, 0x73, 0x8a, 0xaa, 0x37, 0x54, 0x2a, 0xb0, 0x16, + 0x06, 0x0b, 0x65, 0xe8, 0x1b, 0x32, 0x00, 0x60, 0x86, 0x13, 0x32, 0x72, 0xd9, 0xa9, 0x97, 0x86, + 0x72, 0x88, 0x6e, 0x41, 0x99, 0x6f, 0x31, 0xcd, 0xbb, 0xcf, 0x10, 0x29, 0xa3, 0xae, 0x71, 0xe1, + 0x99, 0x54, 0xda, 0x82, 0x92, 0x73, 0xcf, 0xf1, 0x55, 0xd2, 0x5c, 0x05, 0x9c, 0x7b, 0x8e, 0x54, + 0x50, 0x7e, 0x08, 0xd5, 0x59, 0xbc, 0x40, 0x55, 0x48, 0x3f, 0x21, 0x53, 0x39, 0x1f, 0xbb, 0x44, + 0xd7, 0xe5, 0xb2, 0xf8, 0x1c, 0x45, 0x55, 0xae, 0xf1, 0xaf, 0x29, 0xdf, 0xd8, 0x87, 0x08, 0x86, + 0x71, 0x0c, 0x79, 0x25, 0xb4, 0xd6, 0xb7, 0x05, 0x2c, 0x6f, 0x7b, 0xb0, 0xbc, 0xdd, 0xf1, 0x60, + 0xb9, 0x51, 0xf8, 0xe2, 0xab, 0xad, 0xc4, 0x67, 0x7f, 0xdf, 0x4a, 0xaa, 0xdc, 0x02, 0x3d, 0xc7, + 0x4e, 0x31, 0x36, 0x2d, 0xcd, 0x34, 0xe4, 0x3c, 0x79, 0x3e, 0xde, 0x33, 0xd0, 0x3b, 0x50, 0xd5, + 0x6d, 0xcb, 0x25, 0x96, 0x3b, 0x76, 0x35, 0x91, 0x30, 0x24, 0x88, 0x2e, 0x3a, 0x59, 0x4d, 0x4f, + 0xfd, 0x98, 0x6b, 0xab, 0xeb, 0x7a, 0x54, 0x80, 0x0e, 0x00, 0x26, 0x78, 0x60, 0x1a, 0x98, 0xda, + 0x23, 0xb7, 0x96, 0xb9, 0x99, 0xbe, 0xc2, 0xd9, 0x99, 0xa7, 0x78, 0xea, 0x18, 0x98, 0x92, 0x46, + 0x86, 0x3d, 0xb9, 0x1a, 0xb2, 0x47, 0x2f, 0xc2, 0x3a, 0x76, 0x1c, 0xcd, 0xa5, 0x98, 0x12, 0xad, + 0x3b, 0xa5, 0xc4, 0xe5, 0xd0, 0xba, 0xa6, 0x96, 0xb1, 0xe3, 0x9c, 0x30, 0x69, 0x83, 0x09, 0xd1, + 0x6d, 0xa8, 0x30, 0x00, 0x35, 0xf1, 0x40, 0xeb, 0x13, 0xb3, 0xd7, 0xa7, 0x1c, 0x3c, 0xd3, 0x6a, + 0x59, 0x4a, 0xdb, 0x5c, 0xa8, 0x18, 0xfe, 0xa6, 0xe0, 0xb0, 0x89, 0x10, 0x64, 0x0c, 0x4c, 0x31, + 0x0f, 0xea, 0x9a, 0xca, 0xaf, 0x99, 0xcc, 0xc1, 0xb4, 0x2f, 0x43, 0xc5, 0xaf, 0xd1, 0x0d, 0xc8, + 0x49, 0xb7, 0x69, 0xee, 0x56, 0x8e, 0xd8, 0xfb, 0x73, 0x46, 0xf6, 0x84, 0xf0, 0xcc, 0x51, 0x50, + 0xc5, 0x40, 0xf9, 0x6d, 0x0a, 0x36, 0x2e, 0x41, 0x2b, 0xf3, 0xdb, 0xc7, 0x6e, 0xdf, 0x9b, 0x8b, + 0x5d, 0xa3, 0x87, 0xcc, 0x2f, 0x36, 0xc8, 0x48, 0xa6, 0xbd, 0xcd, 0x20, 0x50, 0x22, 0x33, 0x7b, + 0x91, 0x6a, 0x73, 0x2d, 0x19, 0x20, 0x69, 0x83, 0x4e, 0xa1, 0x3a, 0xc0, 0x2e, 0xd5, 0x04, 0x30, + 0x69, 0xa1, 0x14, 0xb8, 0x08, 0xa6, 0x0f, 0xb0, 0x07, 0x68, 0xec, 0x10, 0x48, 0x77, 0x95, 0x41, + 0x44, 0x8a, 0xde, 0x83, 0xeb, 0xdd, 0xe9, 0xcf, 0xb1, 0x45, 0x4d, 0x8b, 0x68, 0x97, 0xde, 0xe5, + 0xd6, 0x02, 0xd7, 0xad, 0x89, 0x69, 0x10, 0x4b, 0xf7, 0x5e, 0xe2, 0x35, 0xdf, 0x85, 0xff, 0x92, + 0x5d, 0xe5, 0x3d, 0xa8, 0x44, 0x13, 0x05, 0xaa, 0x40, 0x8a, 0x5e, 0xc8, 0x90, 0xa4, 0xe8, 0x05, + 0x7a, 0x1d, 0x32, 0x6c, 0xe1, 0x3c, 0x1c, 0x95, 0x85, 0x99, 0x5c, 0x5a, 0x77, 0xa6, 0x0e, 0x51, + 0xb9, 0xbe, 0xa2, 0xf8, 0x27, 0xc6, 0x4f, 0x1e, 0xb3, 0xbe, 0x95, 0x57, 0x60, 0x7d, 0x26, 0x2f, + 0x84, 0xde, 0x6b, 0x32, 0xfc, 0x5e, 0x95, 0x75, 0x28, 0x47, 0xe0, 0x5f, 0xb9, 0x01, 0xd7, 0xe7, + 0xe1, 0xb8, 0x62, 0xf9, 0xf2, 0x08, 0x12, 0xa3, 0x07, 0x50, 0xf0, 0x81, 0x5c, 0x9c, 0xd8, 0x45, + 0x71, 0xf3, 0x4c, 0x54, 0xdf, 0x80, 0x1d, 0x58, 0xb6, 0xe9, 0xf9, 0x6e, 0x49, 0xf1, 0xc7, 0xcf, + 0x63, 0xc7, 0x69, 0x63, 0xb7, 0xaf, 0x7c, 0x08, 0xb5, 0x45, 0xf0, 0x3c, 0xb3, 0x98, 0x8c, 0xbf, + 0x49, 0x6f, 0x40, 0xee, 0xdc, 0x1e, 0x0d, 0x31, 0xe5, 0xce, 0xca, 0xaa, 0x1c, 0xb1, 0xcd, 0x2b, + 0xa0, 0x3a, 0xcd, 0xc5, 0x62, 0xa0, 0x68, 0xf0, 0xdc, 0x42, 0x70, 0x66, 0x26, 0xa6, 0x65, 0x10, + 0x11, 0xd5, 0xb2, 0x2a, 0x06, 0x81, 0x23, 0xf1, 0xb0, 0x62, 0xc0, 0xa6, 0x75, 0x89, 0xc5, 0xf6, + 0x76, 0x9a, 0x9f, 0x24, 0x39, 0x52, 0xfe, 0x5c, 0x84, 0x82, 0x4a, 0x5c, 0x87, 0xe1, 0x06, 0x6a, + 0x43, 0x91, 0x5c, 0xe8, 0x44, 0xd0, 0xaf, 0xe4, 0x12, 0xb2, 0x22, 0x6c, 0x5a, 0x9e, 0x3e, 0x63, + 0x07, 0xbe, 0x31, 0xba, 0x2f, 0xa9, 0xe7, 0x32, 0xfe, 0x28, 0x9d, 0x84, 0xb9, 0xe7, 0x43, 0x8f, + 0x7b, 0xa6, 0x97, 0x10, 0x02, 0x61, 0x3b, 0x43, 0x3e, 0xef, 0x4b, 0xf2, 0x99, 0x89, 0x35, 0x71, + 0x84, 0x7d, 0xee, 0x45, 0xd8, 0x67, 0x36, 0xd6, 0xf2, 0x17, 0xd0, 0xcf, 0xbd, 0x08, 0xfd, 0xcc, + 0xc5, 0x72, 0xb5, 0x80, 0x7f, 0x3e, 0xf4, 0xf8, 0x67, 0x3e, 0x56, 0x38, 0x66, 0x08, 0xe8, 0x41, + 0x94, 0x80, 0x0a, 0xda, 0xf8, 0xca, 0x12, 0x1f, 0x0b, 0x19, 0x68, 0x33, 0xc4, 0x40, 0x8b, 0x4b, + 0x28, 0x9f, 0x70, 0x35, 0x87, 0x82, 0xee, 0x45, 0x28, 0x28, 0xc4, 0x8a, 0xcd, 0x02, 0x0e, 0xfa, + 0x38, 0xcc, 0x41, 0x4b, 0x4b, 0xc8, 0xac, 0xdc, 0x6a, 0xf3, 0x48, 0xe8, 0x9b, 0x3e, 0x09, 0x5d, + 0x5b, 0xc2, 0xab, 0xe5, 0xaa, 0x66, 0x59, 0xe8, 0xe9, 0x25, 0x16, 0x2a, 0xf8, 0xe2, 0xab, 0x4b, + 0x1c, 0x2d, 0xa1, 0xa1, 0xa7, 0x97, 0x68, 0x68, 0x25, 0x96, 0xdb, 0x25, 0x3c, 0xb4, 0x3b, 0x9f, + 0x87, 0x2e, 0xe3, 0x88, 0xf2, 0x91, 0xe3, 0x11, 0x51, 0xb2, 0x80, 0x88, 0x56, 0xf9, 0x24, 0x77, + 0x97, 0x4c, 0xb2, 0x3a, 0x13, 0x7d, 0x85, 0x25, 0xf9, 0x19, 0x48, 0x62, 0x50, 0x48, 0x46, 0x23, + 0x7b, 0x24, 0x49, 0x9e, 0x18, 0x28, 0x2f, 0x33, 0xda, 0x11, 0x00, 0xcf, 0x15, 0xac, 0x95, 0x27, + 0x9e, 0x10, 0xcc, 0x28, 0x7f, 0x4c, 0x06, 0xb6, 0x3c, 0x3b, 0x87, 0x29, 0x4b, 0x51, 0x52, 0x96, + 0x10, 0x99, 0x4d, 0x45, 0xc9, 0xec, 0x16, 0x94, 0x58, 0x2a, 0x99, 0xe1, 0xa9, 0xd8, 0xf1, 0x78, + 0x2a, 0xba, 0x03, 0x1b, 0x9c, 0x43, 0x08, 0xca, 0x2b, 0xf3, 0x47, 0x86, 0x27, 0xc3, 0x75, 0x76, + 0x43, 0x6c, 0x5d, 0x91, 0x48, 0xbe, 0x07, 0xd7, 0x42, 0xba, 0x7e, 0x8a, 0x12, 0x84, 0xac, 0xea, + 0x6b, 0xef, 0xca, 0x5c, 0xf5, 0x76, 0x10, 0xa0, 0x80, 0x03, 0x23, 0xc8, 0xe8, 0xb6, 0x41, 0x64, + 0x02, 0xe1, 0xd7, 0x8c, 0x17, 0x0f, 0xec, 0x9e, 0x4c, 0x13, 0xec, 0x92, 0x69, 0xf9, 0x98, 0x5a, + 0x14, 0x60, 0xa9, 0xfc, 0x25, 0x19, 0xf8, 0x0b, 0x68, 0xf1, 0x3c, 0x06, 0x9b, 0xfc, 0x36, 0x19, + 0x6c, 0xea, 0xbf, 0x64, 0xb0, 0xe1, 0x64, 0x9e, 0x8e, 0x26, 0xf3, 0x7f, 0x27, 0x83, 0xb7, 0xed, + 0xf3, 0xd1, 0x6f, 0x16, 0x9d, 0x20, 0x33, 0x67, 0xf9, 0xbb, 0x93, 0x99, 0x59, 0x56, 0x1c, 0x39, + 0x3e, 0x6f, 0xb4, 0xe2, 0xc8, 0x8b, 0x5c, 0xcd, 0x07, 0xe8, 0x3e, 0x14, 0x79, 0x4b, 0x49, 0xb3, + 0x1d, 0x57, 0x42, 0xf6, 0xf3, 0xc1, 0x8a, 0x45, 0xdf, 0x69, 0x7b, 0x72, 0x77, 0xfb, 0x98, 0x29, + 0x1d, 0x39, 0xae, 0x5a, 0x70, 0xe4, 0x55, 0x88, 0x75, 0x14, 0x23, 0xd4, 0xf8, 0x79, 0x28, 0xb2, + 0xc7, 0x77, 0x1d, 0xac, 0x13, 0x8e, 0xb9, 0x45, 0x35, 0x10, 0x28, 0x06, 0xa0, 0xcb, 0xd8, 0x8f, + 0x0e, 0x21, 0x47, 0x26, 0xc4, 0xa2, 0xec, 0x15, 0xa6, 0xa3, 0xcf, 0x30, 0xc3, 0x35, 0x89, 0x45, + 0x1b, 0x35, 0x16, 0xeb, 0x7f, 0x7e, 0xb5, 0x55, 0x15, 0x36, 0xaf, 0xda, 0x43, 0x93, 0x92, 0xa1, + 0x43, 0xa7, 0xaa, 0xf4, 0xa2, 0x3c, 0x4d, 0x31, 0xca, 0x17, 0xc9, 0x0b, 0x73, 0x43, 0xec, 0x9d, + 0xa9, 0x54, 0xa8, 0x0c, 0x88, 0x17, 0xf6, 0x4d, 0x80, 0x1e, 0x76, 0xb5, 0x4f, 0xb0, 0x45, 0x89, + 0x21, 0x63, 0x1f, 0x92, 0xa0, 0x3a, 0x14, 0xd8, 0x68, 0xec, 0x12, 0x43, 0x56, 0x24, 0xfe, 0x38, + 0xb4, 0xda, 0xfc, 0xb7, 0xb1, 0xda, 0x68, 0xc4, 0x0b, 0x33, 0x11, 0x0f, 0xd1, 0xb1, 0x62, 0x98, + 0x8e, 0xb1, 0x27, 0x74, 0x46, 0xa6, 0x3d, 0x32, 0xe9, 0x94, 0xbf, 0xa6, 0xb4, 0xea, 0x8f, 0x59, + 0x29, 0x3c, 0x24, 0x43, 0xc7, 0xb6, 0x07, 0x9a, 0x40, 0xb5, 0x12, 0x37, 0x5d, 0x93, 0xc2, 0x16, + 0x07, 0xb7, 0xdf, 0xa4, 0x82, 0x73, 0x19, 0x90, 0xef, 0xff, 0xd1, 0x30, 0x2b, 0x9f, 0xf3, 0xda, + 0x3d, 0x9a, 0xf9, 0xd1, 0xfb, 0xb0, 0xe1, 0x23, 0x82, 0x36, 0xe6, 0x48, 0xe1, 0x6d, 0xf1, 0xd5, + 0x80, 0xa5, 0x3a, 0x89, 0x8a, 0x5d, 0xf4, 0x01, 0x3c, 0x3b, 0x83, 0x7f, 0xfe, 0x04, 0xa9, 0x95, + 0x60, 0xf0, 0x99, 0x28, 0x0c, 0x7a, 0xfe, 0x83, 0xe8, 0xa5, 0xbf, 0x95, 0x23, 0xb9, 0xc7, 0x4a, + 0xc0, 0x30, 0xa7, 0x99, 0xbb, 0x2b, 0x6e, 0x41, 0x79, 0x44, 0x28, 0x36, 0x2d, 0x2d, 0x52, 0x76, + 0xaf, 0x09, 0xa1, 0x2c, 0xe6, 0xcf, 0xe0, 0x99, 0xb9, 0xac, 0x06, 0xfd, 0x08, 0x8a, 0x01, 0x2d, + 0x4a, 0x5e, 0x59, 0xb5, 0xfa, 0xd5, 0x57, 0x60, 0xa1, 0xfc, 0x29, 0x19, 0x38, 0x8e, 0x56, 0x75, + 0xfb, 0x90, 0x1b, 0x11, 0x77, 0x3c, 0x10, 0x15, 0x56, 0xe5, 0xde, 0x6b, 0xab, 0xb0, 0x22, 0x26, + 0x1d, 0x0f, 0xa8, 0x2a, 0x5d, 0x28, 0x1f, 0x40, 0x4e, 0x48, 0x50, 0x09, 0xf2, 0xa7, 0x87, 0xfb, + 0x87, 0x47, 0xef, 0x1e, 0x56, 0x13, 0x08, 0x20, 0xb7, 0xdb, 0x6c, 0xb6, 0x8e, 0x3b, 0xd5, 0x24, + 0x2a, 0x42, 0x76, 0xb7, 0x71, 0xa4, 0x76, 0xaa, 0x29, 0x26, 0x56, 0x5b, 0x3f, 0x69, 0x35, 0x3b, + 0xd5, 0x34, 0xda, 0x80, 0xb2, 0xb8, 0xd6, 0x1e, 0x1f, 0xa9, 0x6f, 0xef, 0x76, 0xaa, 0x99, 0x90, + 0xe8, 0xa4, 0x75, 0xf8, 0xa8, 0xa5, 0x56, 0xb3, 0xca, 0x5d, 0x56, 0xc8, 0x2d, 0x60, 0x50, 0x41, + 0xc9, 0x96, 0x0c, 0x95, 0x6c, 0xca, 0xef, 0x53, 0x50, 0x5f, 0x4c, 0x88, 0xd0, 0xf1, 0xcc, 0xf2, + 0xdf, 0x58, 0x99, 0x53, 0xcd, 0xc4, 0x00, 0xdd, 0x86, 0xca, 0x88, 0x9c, 0x13, 0xaa, 0xf7, 0x05, + 0x59, 0x13, 0xe9, 0xb6, 0xac, 0x96, 0xa5, 0x94, 0x1b, 0xb9, 0x42, 0xed, 0x23, 0xa2, 0x53, 0x4d, + 0x80, 0x96, 0xd8, 0x8c, 0x45, 0xa6, 0xc6, 0xa4, 0x27, 0x42, 0xa8, 0x7c, 0xb8, 0x52, 0x44, 0x8b, + 0x90, 0x55, 0x5b, 0x1d, 0xf5, 0xfd, 0x6a, 0x1a, 0x21, 0xa8, 0xf0, 0x4b, 0xed, 0xe4, 0x70, 0xf7, + 0xf8, 0xa4, 0x7d, 0xc4, 0x22, 0x7a, 0x0d, 0xd6, 0xbd, 0x88, 0x7a, 0xc2, 0xac, 0xf2, 0xbb, 0x14, + 0xac, 0xcf, 0x1c, 0x1c, 0xf4, 0x06, 0x64, 0x45, 0x39, 0x70, 0xf5, 0x47, 0x0f, 0x8e, 0x04, 0xf2, + 0xac, 0x09, 0x03, 0xd4, 0x80, 0x02, 0x91, 0x5d, 0x93, 0xcb, 0x87, 0x35, 0xda, 0xff, 0xf1, 0xba, + 0x2b, 0xd2, 0x81, 0x6f, 0x87, 0x5a, 0x50, 0xf4, 0x31, 0x41, 0xd6, 0xaf, 0x2f, 0x2d, 0x72, 0xe2, + 0x63, 0x8a, 0xf4, 0x12, 0x58, 0xa2, 0x37, 0x03, 0x06, 0x99, 0x99, 0x2d, 0x48, 0x66, 0x9c, 0x08, + 0x35, 0xe9, 0xc2, 0xb3, 0x52, 0x9a, 0x50, 0x0a, 0xad, 0x10, 0xfd, 0x1f, 0x14, 0x87, 0xf8, 0x42, + 0x76, 0xec, 0x44, 0x6f, 0xa5, 0x30, 0xc4, 0x17, 0xa2, 0x59, 0xf7, 0x2c, 0xe4, 0xd9, 0xcd, 0x1e, + 0x16, 0x18, 0x95, 0x56, 0x73, 0x43, 0x7c, 0xf1, 0x16, 0x76, 0x15, 0x1d, 0x2a, 0xd1, 0x0e, 0x15, + 0xdb, 0xa7, 0x23, 0x7b, 0x6c, 0x19, 0xdc, 0x47, 0x56, 0x15, 0x03, 0xf4, 0x00, 0xb2, 0x13, 0x5b, + 0x40, 0xdc, 0x55, 0x87, 0xfb, 0xcc, 0xa6, 0x24, 0xd4, 0xe7, 0x12, 0x36, 0xca, 0x2f, 0x93, 0x90, + 0xe5, 0x68, 0xc5, 0x90, 0x87, 0x37, 0x9b, 0x24, 0x95, 0x66, 0xd7, 0x48, 0x07, 0xc0, 0x94, 0x8e, + 0xcc, 0xee, 0x38, 0xf0, 0x7f, 0xfb, 0x2a, 0xcc, 0xdb, 0xf5, 0xb4, 0x1b, 0xcf, 0x4b, 0xf0, 0xbb, + 0x1e, 0x38, 0x08, 0x01, 0x60, 0xc8, 0xad, 0x72, 0x08, 0x95, 0xa8, 0x6d, 0xb8, 0x35, 0xbc, 0x36, + 0xa7, 0x35, 0xec, 0x13, 0x35, 0x9f, 0xe6, 0xa5, 0x45, 0xc3, 0x91, 0x0f, 0x94, 0xcf, 0x92, 0x50, + 0xe8, 0x5c, 0xc8, 0xbd, 0xbf, 0xa0, 0xa7, 0x15, 0x98, 0xa6, 0xc2, 0xbd, 0x1b, 0xd1, 0x24, 0x4b, + 0xfb, 0x0d, 0xb8, 0xc7, 0xfe, 0x19, 0xcf, 0xac, 0x56, 0x27, 0x7b, 0xbd, 0x49, 0x89, 0x6e, 0x0f, + 0xa0, 0xe8, 0x6f, 0x37, 0x56, 0x9f, 0x60, 0xc3, 0x18, 0x11, 0xd7, 0x95, 0x2b, 0xf4, 0x86, 0xbc, + 0x81, 0x6a, 0x7f, 0x22, 0x7b, 0x44, 0x69, 0x55, 0x0c, 0x14, 0x02, 0xeb, 0x33, 0xf9, 0x0f, 0x3d, + 0x84, 0xbc, 0x33, 0xee, 0x6a, 0x5e, 0x90, 0x4a, 0xf7, 0x5e, 0x98, 0xcb, 0x4f, 0xc7, 0xdd, 0x81, + 0xa9, 0xef, 0x93, 0xa9, 0xf7, 0x34, 0xce, 0xb8, 0xbb, 0x2f, 0x82, 0x29, 0xa6, 0x49, 0x85, 0xa7, + 0xf9, 0x05, 0x14, 0xbc, 0x2d, 0x82, 0x1e, 0x85, 0xcf, 0x91, 0x98, 0xe1, 0xe6, 0xb2, 0xd4, 0x2c, + 0x27, 0x09, 0x1d, 0xa3, 0x3b, 0xb0, 0xe1, 0x9a, 0x3d, 0x8b, 0x18, 0x5a, 0x50, 0x28, 0xf1, 0x39, + 0x0b, 0xea, 0xba, 0xb8, 0x71, 0xe0, 0x55, 0x49, 0xca, 0xaf, 0x53, 0x50, 0xf0, 0x8e, 0x35, 0xfa, + 0x41, 0x68, 0x2b, 0x56, 0x16, 0x36, 0x91, 0x3c, 0xf5, 0xa0, 0xf1, 0x19, 0x7d, 0xee, 0xd4, 0x37, + 0x7d, 0xee, 0x45, 0xfd, 0x6d, 0xef, 0xa3, 0x43, 0x66, 0xe5, 0x8f, 0x0e, 0xaf, 0x02, 0xa2, 0x36, + 0xc5, 0x03, 0x6d, 0x62, 0x53, 0xd3, 0xea, 0x69, 0x22, 0xfc, 0x82, 0xb9, 0x55, 0xf9, 0x9d, 0x33, + 0x7e, 0xe3, 0x98, 0xbf, 0x89, 0x5f, 0x25, 0xa1, 0xe0, 0x67, 0xd9, 0x55, 0xfb, 0x98, 0x37, 0x20, + 0x27, 0x93, 0x87, 0x68, 0x64, 0xca, 0x91, 0xdf, 0x70, 0xcf, 0x84, 0x1a, 0xee, 0x75, 0x28, 0x0c, + 0x09, 0xc5, 0x9c, 0x70, 0x88, 0xba, 0xd5, 0x1f, 0xdf, 0xb9, 0x0f, 0xa5, 0x50, 0x63, 0x99, 0x1d, + 0xc9, 0xc3, 0xd6, 0xbb, 0xd5, 0x44, 0x3d, 0xff, 0xe9, 0xe7, 0x37, 0xd3, 0x87, 0xe4, 0x13, 0xb6, + 0x8d, 0xd5, 0x56, 0xb3, 0xdd, 0x6a, 0xee, 0x57, 0x93, 0xf5, 0xd2, 0xa7, 0x9f, 0xdf, 0xcc, 0xab, + 0x84, 0xf7, 0x98, 0xee, 0xb4, 0x61, 0x2d, 0xfc, 0x6e, 0xa2, 0xf9, 0x07, 0x41, 0xe5, 0xd1, 0xe9, + 0xf1, 0xc1, 0x5e, 0x73, 0xb7, 0xd3, 0xd2, 0xce, 0x8e, 0x3a, 0xad, 0x6a, 0x12, 0x3d, 0x0b, 0xd7, + 0x0e, 0xf6, 0xde, 0x6a, 0x77, 0xb4, 0xe6, 0xc1, 0x5e, 0xeb, 0xb0, 0xa3, 0xed, 0x76, 0x3a, 0xbb, + 0xcd, 0xfd, 0x6a, 0xea, 0xde, 0x1f, 0x4a, 0xb0, 0xbe, 0xdb, 0x68, 0xee, 0xb1, 0xdc, 0x69, 0xea, + 0x98, 0xd7, 0xcc, 0x47, 0x90, 0xe1, 0x6d, 0x83, 0x18, 0xdf, 0xd3, 0xeb, 0x71, 0x1a, 0x9f, 0x48, + 0x85, 0x2c, 0xef, 0x2e, 0xa0, 0x38, 0x9f, 0xd9, 0xeb, 0xb1, 0xfa, 0xa1, 0xec, 0x21, 0xf9, 0x41, + 0x8a, 0xf1, 0xf5, 0xbd, 0x1e, 0xa7, 0x49, 0x8a, 0x3e, 0x80, 0x62, 0xd0, 0x36, 0x88, 0xfb, 0x4d, + 0xbe, 0x1e, 0xbb, 0x7d, 0xca, 0xfc, 0x07, 0xe5, 0x4a, 0xdc, 0x2f, 0xd2, 0xf5, 0xd8, 0x78, 0x88, + 0xde, 0x83, 0xbc, 0x57, 0x73, 0xc6, 0xfb, 0x6a, 0x5e, 0x8f, 0xd9, 0xda, 0x64, 0xaf, 0x4f, 0xb4, + 0x0b, 0xe2, 0xfc, 0x1a, 0x50, 0x8f, 0xd5, 0xbf, 0x45, 0xa7, 0x90, 0x93, 0x7c, 0x3c, 0xd6, 0xf7, + 0xf0, 0x7a, 0xbc, 0x86, 0x25, 0x0b, 0x72, 0xd0, 0xab, 0x89, 0xfb, 0x3b, 0x44, 0x3d, 0x76, 0xe3, + 0x1a, 0x61, 0x80, 0x50, 0xff, 0x20, 0xf6, 0x7f, 0x0e, 0xf5, 0xf8, 0x0d, 0x69, 0xf4, 0x33, 0x28, + 0xf8, 0x85, 0x5c, 0xcc, 0xff, 0x0d, 0xea, 0x71, 0x7b, 0xc2, 0xe8, 0x23, 0x28, 0x47, 0x6b, 0x97, + 0x55, 0xfe, 0x22, 0xa8, 0xaf, 0xd4, 0xec, 0x65, 0x73, 0x45, 0xcb, 0x99, 0x55, 0xfe, 0x2d, 0xa8, + 0xaf, 0xd4, 0x01, 0x46, 0x13, 0xd8, 0xb8, 0x5c, 0x74, 0xac, 0xfa, 0xc3, 0x41, 0x7d, 0xe5, 0xce, + 0x30, 0x9a, 0x02, 0x9a, 0x53, 0xb8, 0xac, 0xfc, 0x17, 0x42, 0x7d, 0xf5, 0x76, 0x71, 0xe3, 0xf8, + 0x8b, 0xa7, 0x9b, 0xc9, 0x2f, 0x9f, 0x6e, 0x26, 0xff, 0xf1, 0x74, 0x33, 0xf9, 0xd9, 0xd7, 0x9b, + 0x89, 0x2f, 0xbf, 0xde, 0x4c, 0xfc, 0xed, 0xeb, 0xcd, 0xc4, 0x4f, 0x5f, 0xef, 0x99, 0xb4, 0x3f, + 0xee, 0x32, 0x97, 0x3b, 0xc1, 0xcf, 0x5c, 0xfe, 0xef, 0x62, 0x8e, 0xb9, 0x33, 0xf7, 0xdf, 0xb1, + 0x6e, 0x8e, 0xe7, 0xd9, 0xd7, 0xfe, 0x13, 0x00, 0x00, 0xff, 0xff, 0x56, 0x6f, 0xb3, 0x98, 0x5b, + 0x26, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// ABCIApplicationClient is the client API for ABCIApplication service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type ABCIApplicationClient interface { + // Echo returns back the same message it is sent. + Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) + // Flush flushes the write buffer. + Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) + // Info returns information about the application state. + Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) + // SetOption sets a parameter in the application. + SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) + // DeliverTx applies a transaction. + DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) + // CheckTx validates a transaction. + CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) + // Query queries the application state. + Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) + // Commit commits a block of transactions. + Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) + // InitChain initializes the blockchain. + InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) + // BeginBlock signals the beginning of a block. + BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) + // EndBlock signals the end of a block, returns changes to the validator set. + EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) + // ListSnapshots lists all the available snapshots. + ListSnapshots(ctx context.Context, in *RequestListSnapshots, opts ...grpc.CallOption) (*ResponseListSnapshots, error) + // OfferSnapshot sends a snapshot offer. + OfferSnapshot(ctx context.Context, in *RequestOfferSnapshot, opts ...grpc.CallOption) (*ResponseOfferSnapshot, error) + // LoadSnapshotChunk returns a chunk of snapshot. + LoadSnapshotChunk(ctx context.Context, in *RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*ResponseLoadSnapshotChunk, error) + // ApplySnapshotChunk applies a chunk of snapshot. + ApplySnapshotChunk(ctx context.Context, in *RequestApplySnapshotChunk, opts ...grpc.CallOption) (*ResponseApplySnapshotChunk, error) +} + +type aBCIApplicationClient struct { + cc grpc1.ClientConn +} + +func NewABCIApplicationClient(cc grpc1.ClientConn) ABCIApplicationClient { + return &aBCIApplicationClient{cc} +} + +func (c *aBCIApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) { + out := new(ResponseEcho) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/Echo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) { + out := new(ResponseFlush) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/Flush", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) { + out := new(ResponseInfo) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/Info", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) { + out := new(ResponseSetOption) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/SetOption", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { + out := new(ResponseDeliverTx) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/DeliverTx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { + out := new(ResponseCheckTx) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/CheckTx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) { + out := new(ResponseQuery) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/Query", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { + out := new(ResponseCommit) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/Commit", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { + out := new(ResponseInitChain) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/InitChain", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) { + out := new(ResponseBeginBlock) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/BeginBlock", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) { + out := new(ResponseEndBlock) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/EndBlock", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) ListSnapshots(ctx context.Context, in *RequestListSnapshots, opts ...grpc.CallOption) (*ResponseListSnapshots, error) { + out := new(ResponseListSnapshots) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/ListSnapshots", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) OfferSnapshot(ctx context.Context, in *RequestOfferSnapshot, opts ...grpc.CallOption) (*ResponseOfferSnapshot, error) { + out := new(ResponseOfferSnapshot) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/OfferSnapshot", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) LoadSnapshotChunk(ctx context.Context, in *RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*ResponseLoadSnapshotChunk, error) { + out := new(ResponseLoadSnapshotChunk) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/LoadSnapshotChunk", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) ApplySnapshotChunk(ctx context.Context, in *RequestApplySnapshotChunk, opts ...grpc.CallOption) (*ResponseApplySnapshotChunk, error) { + out := new(ResponseApplySnapshotChunk) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta1.ABCIApplication/ApplySnapshotChunk", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ABCIApplicationServer is the server API for ABCIApplication service. +type ABCIApplicationServer interface { + // Echo returns back the same message it is sent. + Echo(context.Context, *RequestEcho) (*ResponseEcho, error) + // Flush flushes the write buffer. + Flush(context.Context, *RequestFlush) (*ResponseFlush, error) + // Info returns information about the application state. + Info(context.Context, *RequestInfo) (*ResponseInfo, error) + // SetOption sets a parameter in the application. + SetOption(context.Context, *RequestSetOption) (*ResponseSetOption, error) + // DeliverTx applies a transaction. + DeliverTx(context.Context, *RequestDeliverTx) (*ResponseDeliverTx, error) + // CheckTx validates a transaction. + CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) + // Query queries the application state. + Query(context.Context, *RequestQuery) (*ResponseQuery, error) + // Commit commits a block of transactions. + Commit(context.Context, *RequestCommit) (*ResponseCommit, error) + // InitChain initializes the blockchain. + InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) + // BeginBlock signals the beginning of a block. + BeginBlock(context.Context, *RequestBeginBlock) (*ResponseBeginBlock, error) + // EndBlock signals the end of a block, returns changes to the validator set. + EndBlock(context.Context, *RequestEndBlock) (*ResponseEndBlock, error) + // ListSnapshots lists all the available snapshots. + ListSnapshots(context.Context, *RequestListSnapshots) (*ResponseListSnapshots, error) + // OfferSnapshot sends a snapshot offer. + OfferSnapshot(context.Context, *RequestOfferSnapshot) (*ResponseOfferSnapshot, error) + // LoadSnapshotChunk returns a chunk of snapshot. + LoadSnapshotChunk(context.Context, *RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) + // ApplySnapshotChunk applies a chunk of snapshot. + ApplySnapshotChunk(context.Context, *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) +} + +// UnimplementedABCIApplicationServer can be embedded to have forward compatible implementations. +type UnimplementedABCIApplicationServer struct { +} + +func (*UnimplementedABCIApplicationServer) Echo(ctx context.Context, req *RequestEcho) (*ResponseEcho, error) { + return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented") +} +func (*UnimplementedABCIApplicationServer) Flush(ctx context.Context, req *RequestFlush) (*ResponseFlush, error) { + return nil, status.Errorf(codes.Unimplemented, "method Flush not implemented") +} +func (*UnimplementedABCIApplicationServer) Info(ctx context.Context, req *RequestInfo) (*ResponseInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method Info not implemented") +} +func (*UnimplementedABCIApplicationServer) SetOption(ctx context.Context, req *RequestSetOption) (*ResponseSetOption, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetOption not implemented") +} +func (*UnimplementedABCIApplicationServer) DeliverTx(ctx context.Context, req *RequestDeliverTx) (*ResponseDeliverTx, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeliverTx not implemented") +} +func (*UnimplementedABCIApplicationServer) CheckTx(ctx context.Context, req *RequestCheckTx) (*ResponseCheckTx, error) { + return nil, status.Errorf(codes.Unimplemented, "method CheckTx not implemented") +} +func (*UnimplementedABCIApplicationServer) Query(ctx context.Context, req *RequestQuery) (*ResponseQuery, error) { + return nil, status.Errorf(codes.Unimplemented, "method Query not implemented") +} +func (*UnimplementedABCIApplicationServer) Commit(ctx context.Context, req *RequestCommit) (*ResponseCommit, error) { + return nil, status.Errorf(codes.Unimplemented, "method Commit not implemented") +} +func (*UnimplementedABCIApplicationServer) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { + return nil, status.Errorf(codes.Unimplemented, "method InitChain not implemented") +} +func (*UnimplementedABCIApplicationServer) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { + return nil, status.Errorf(codes.Unimplemented, "method BeginBlock not implemented") +} +func (*UnimplementedABCIApplicationServer) EndBlock(ctx context.Context, req *RequestEndBlock) (*ResponseEndBlock, error) { + return nil, status.Errorf(codes.Unimplemented, "method EndBlock not implemented") +} +func (*UnimplementedABCIApplicationServer) ListSnapshots(ctx context.Context, req *RequestListSnapshots) (*ResponseListSnapshots, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented") +} +func (*UnimplementedABCIApplicationServer) OfferSnapshot(ctx context.Context, req *RequestOfferSnapshot) (*ResponseOfferSnapshot, error) { + return nil, status.Errorf(codes.Unimplemented, "method OfferSnapshot not implemented") +} +func (*UnimplementedABCIApplicationServer) LoadSnapshotChunk(ctx context.Context, req *RequestLoadSnapshotChunk) (*ResponseLoadSnapshotChunk, error) { + return nil, status.Errorf(codes.Unimplemented, "method LoadSnapshotChunk not implemented") +} +func (*UnimplementedABCIApplicationServer) ApplySnapshotChunk(ctx context.Context, req *RequestApplySnapshotChunk) (*ResponseApplySnapshotChunk, error) { + return nil, status.Errorf(codes.Unimplemented, "method ApplySnapshotChunk not implemented") +} + +func RegisterABCIApplicationServer(s grpc1.Server, srv ABCIApplicationServer) { + s.RegisterService(&_ABCIApplication_serviceDesc, srv) +} + +func _ABCIApplication_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestEcho) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Echo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/Echo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Echo(ctx, req.(*RequestEcho)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestFlush) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Flush(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/Flush", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Flush(ctx, req.(*RequestFlush)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Info(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/Info", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Info(ctx, req.(*RequestInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_SetOption_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestSetOption) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).SetOption(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/SetOption", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).SetOption(ctx, req.(*RequestSetOption)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_DeliverTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestDeliverTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).DeliverTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/DeliverTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).DeliverTx(ctx, req.(*RequestDeliverTx)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestCheckTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).CheckTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/CheckTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).CheckTx(ctx, req.(*RequestCheckTx)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestQuery) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/Query", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Query(ctx, req.(*RequestQuery)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestCommit) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Commit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/Commit", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Commit(ctx, req.(*RequestCommit)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInitChain) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).InitChain(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/InitChain", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).InitChain(ctx, req.(*RequestInitChain)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_BeginBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestBeginBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).BeginBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/BeginBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).BeginBlock(ctx, req.(*RequestBeginBlock)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_EndBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestEndBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).EndBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/EndBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).EndBlock(ctx, req.(*RequestEndBlock)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestListSnapshots) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).ListSnapshots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/ListSnapshots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).ListSnapshots(ctx, req.(*RequestListSnapshots)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_OfferSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestOfferSnapshot) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).OfferSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/OfferSnapshot", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).OfferSnapshot(ctx, req.(*RequestOfferSnapshot)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_LoadSnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestLoadSnapshotChunk) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).LoadSnapshotChunk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/LoadSnapshotChunk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).LoadSnapshotChunk(ctx, req.(*RequestLoadSnapshotChunk)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_ApplySnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestApplySnapshotChunk) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).ApplySnapshotChunk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta1.ABCIApplication/ApplySnapshotChunk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).ApplySnapshotChunk(ctx, req.(*RequestApplySnapshotChunk)) + } + return interceptor(ctx, in, info, handler) +} + +var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.abci.v1beta1.ABCIApplication", + HandlerType: (*ABCIApplicationServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Echo", + Handler: _ABCIApplication_Echo_Handler, + }, + { + MethodName: "Flush", + Handler: _ABCIApplication_Flush_Handler, + }, + { + MethodName: "Info", + Handler: _ABCIApplication_Info_Handler, + }, + { + MethodName: "SetOption", + Handler: _ABCIApplication_SetOption_Handler, + }, + { + MethodName: "DeliverTx", + Handler: _ABCIApplication_DeliverTx_Handler, + }, + { + MethodName: "CheckTx", + Handler: _ABCIApplication_CheckTx_Handler, + }, + { + MethodName: "Query", + Handler: _ABCIApplication_Query_Handler, + }, + { + MethodName: "Commit", + Handler: _ABCIApplication_Commit_Handler, + }, + { + MethodName: "InitChain", + Handler: _ABCIApplication_InitChain_Handler, + }, + { + MethodName: "BeginBlock", + Handler: _ABCIApplication_BeginBlock_Handler, + }, + { + MethodName: "EndBlock", + Handler: _ABCIApplication_EndBlock_Handler, + }, + { + MethodName: "ListSnapshots", + Handler: _ABCIApplication_ListSnapshots_Handler, + }, + { + MethodName: "OfferSnapshot", + Handler: _ABCIApplication_OfferSnapshot_Handler, + }, + { + MethodName: "LoadSnapshotChunk", + Handler: _ABCIApplication_LoadSnapshotChunk_Handler, + }, + { + MethodName: "ApplySnapshotChunk", + Handler: _ABCIApplication_ApplySnapshotChunk_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/abci/v1beta1/types.proto", +} + +func (m *Request) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Request) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != nil { + { + size := m.Value.Size() + i -= size + if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Request_Echo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Echo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Echo != nil { + { + size, err := m.Echo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Request_Flush) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Flush) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Flush != nil { + { + size, err := m.Flush.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Request_Info) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Info) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Request_SetOption) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_SetOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SetOption != nil { + { + size, err := m.SetOption.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Request_InitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_InitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.InitChain != nil { + { + size, err := m.InitChain.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *Request_Query) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Query != nil { + { + size, err := m.Query.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Request_BeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_BeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BeginBlock != nil { + { + size, err := m.BeginBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Request_CheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_CheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.CheckTx != nil { + { + size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *Request_DeliverTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_DeliverTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.DeliverTx != nil { + { + size, err := m.DeliverTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *Request_EndBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_EndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.EndBlock != nil { + { + size, err := m.EndBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + return len(dAtA) - i, nil +} +func (m *Request_Commit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Commit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Commit != nil { + { + size, err := m.Commit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + return len(dAtA) - i, nil +} +func (m *Request_ListSnapshots) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ListSnapshots != nil { + { + size, err := m.ListSnapshots.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } + return len(dAtA) - i, nil +} +func (m *Request_OfferSnapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_OfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.OfferSnapshot != nil { + { + size, err := m.OfferSnapshot.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + return len(dAtA) - i, nil +} +func (m *Request_LoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_LoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LoadSnapshotChunk != nil { + { + size, err := m.LoadSnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + return len(dAtA) - i, nil +} +func (m *Request_ApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ApplySnapshotChunk != nil { + { + size, err := m.ApplySnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } + return len(dAtA) - i, nil +} +func (m *RequestEcho) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestEcho) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestEcho) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Message) > 0 { + i -= len(m.Message) + copy(dAtA[i:], m.Message) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Message))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestFlush) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestFlush) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestFlush) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *RequestInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.P2PVersion != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.P2PVersion)) + i-- + dAtA[i] = 0x18 + } + if m.BlockVersion != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.BlockVersion)) + i-- + dAtA[i] = 0x10 + } + if len(m.Version) > 0 { + i -= len(m.Version) + copy(dAtA[i:], m.Version) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Version))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestSetOption) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestSetOption) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestSetOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0x12 + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestInitChain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestInitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.InitialHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.InitialHeight)) + i-- + dAtA[i] = 0x30 + } + if len(m.AppStateBytes) > 0 { + i -= len(m.AppStateBytes) + copy(dAtA[i:], m.AppStateBytes) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppStateBytes))) + i-- + dAtA[i] = 0x2a + } + if len(m.Validators) > 0 { + for iNdEx := len(m.Validators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Validators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if m.ConsensusParams != nil { + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0x12 + } + n17, err17 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err17 != nil { + return 0, err17 + } + i -= n17 + i = encodeVarintTypes(dAtA, i, uint64(n17)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *RequestQuery) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestQuery) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Prove { + i-- + if m.Prove { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x18 + } + if len(m.Path) > 0 { + i -= len(m.Path) + copy(dAtA[i:], m.Path) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Path))) + i-- + dAtA[i] = 0x12 + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestBeginBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestBeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestBeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ByzantineValidators) > 0 { + for iNdEx := len(m.ByzantineValidators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ByzantineValidators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + { + size, err := m.LastCommitInfo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.Header.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestCheckTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestCheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Type != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x10 + } + if len(m.Tx) > 0 { + i -= len(m.Tx) + copy(dAtA[i:], m.Tx) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestDeliverTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestDeliverTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestDeliverTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Tx) > 0 { + i -= len(m.Tx) + copy(dAtA[i:], m.Tx) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestEndBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestEndBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestEndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *RequestCommit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestCommit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *RequestListSnapshots) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestListSnapshots) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *RequestOfferSnapshot) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestOfferSnapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestOfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x12 + } + if m.Snapshot != nil { + { + size, err := m.Snapshot.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestLoadSnapshotChunk) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestLoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestLoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Chunk != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Chunk)) + i-- + dAtA[i] = 0x18 + } + if m.Format != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Format)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *RequestApplySnapshotChunk) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x1a + } + if len(m.Chunk) > 0 { + i -= len(m.Chunk) + copy(dAtA[i:], m.Chunk) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Chunk))) + i-- + dAtA[i] = 0x12 + } + if m.Index != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Response) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Response) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != nil { + { + size := m.Value.Size() + i -= size + if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Response_Exception) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Exception) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Exception != nil { + { + size, err := m.Exception.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Response_Echo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Echo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Echo != nil { + { + size, err := m.Echo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Response_Flush) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Flush) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Flush != nil { + { + size, err := m.Flush.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Response_Info) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Info) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Response_SetOption) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_SetOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SetOption != nil { + { + size, err := m.SetOption.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *Response_InitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_InitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.InitChain != nil { + { + size, err := m.InitChain.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Response_Query) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Query != nil { + { + size, err := m.Query.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Response_BeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_BeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BeginBlock != nil { + { + size, err := m.BeginBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *Response_CheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_CheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.CheckTx != nil { + { + size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *Response_DeliverTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_DeliverTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.DeliverTx != nil { + { + size, err := m.DeliverTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + return len(dAtA) - i, nil +} +func (m *Response_EndBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_EndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.EndBlock != nil { + { + size, err := m.EndBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + return len(dAtA) - i, nil +} +func (m *Response_Commit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Commit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Commit != nil { + { + size, err := m.Commit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } + return len(dAtA) - i, nil +} +func (m *Response_ListSnapshots) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ListSnapshots != nil { + { + size, err := m.ListSnapshots.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + return len(dAtA) - i, nil +} +func (m *Response_OfferSnapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_OfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.OfferSnapshot != nil { + { + size, err := m.OfferSnapshot.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + return len(dAtA) - i, nil +} +func (m *Response_LoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_LoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LoadSnapshotChunk != nil { + { + size, err := m.LoadSnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } + return len(dAtA) - i, nil +} +func (m *Response_ApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ApplySnapshotChunk != nil { + { + size, err := m.ApplySnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } + return len(dAtA) - i, nil +} +func (m *ResponseException) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseException) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseException) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Error) > 0 { + i -= len(m.Error) + copy(dAtA[i:], m.Error) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Error))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ResponseEcho) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseEcho) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseEcho) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Message) > 0 { + i -= len(m.Message) + copy(dAtA[i:], m.Message) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Message))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ResponseFlush) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseFlush) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseFlush) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *ResponseInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.LastBlockAppHash) > 0 { + i -= len(m.LastBlockAppHash) + copy(dAtA[i:], m.LastBlockAppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.LastBlockAppHash))) + i-- + dAtA[i] = 0x2a + } + if m.LastBlockHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastBlockHeight)) + i-- + dAtA[i] = 0x20 + } + if m.AppVersion != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.AppVersion)) + i-- + dAtA[i] = 0x18 + } + if len(m.Version) > 0 { + i -= len(m.Version) + copy(dAtA[i:], m.Version) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Version))) + i-- + dAtA[i] = 0x12 + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ResponseSetOption) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseSetOption) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseSetOption) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Info) > 0 { + i -= len(m.Info) + copy(dAtA[i:], m.Info) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i-- + dAtA[i] = 0x22 + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x1a + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseInitChain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseInitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x1a + } + if len(m.Validators) > 0 { + for iNdEx := len(m.Validators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Validators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.ConsensusParams != nil { + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ResponseQuery) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseQuery) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Codespace) > 0 { + i -= len(m.Codespace) + copy(dAtA[i:], m.Codespace) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Codespace))) + i-- + dAtA[i] = 0x52 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x48 + } + if m.ProofOps != nil { + { + size, err := m.ProofOps.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0x3a + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0x32 + } + if m.Index != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x28 + } + if len(m.Info) > 0 { + i -= len(m.Info) + copy(dAtA[i:], m.Info) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i-- + dAtA[i] = 0x22 + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x1a + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseBeginBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseBeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseBeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResponseCheckTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseCheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MempoolError) > 0 { + i -= len(m.MempoolError) + copy(dAtA[i:], m.MempoolError) + i = encodeVarintTypes(dAtA, i, uint64(len(m.MempoolError))) + i-- + dAtA[i] = 0x5a + } + if m.Priority != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Priority)) + i-- + dAtA[i] = 0x50 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x4a + } + if len(m.Codespace) > 0 { + i -= len(m.Codespace) + copy(dAtA[i:], m.Codespace) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Codespace))) + i-- + dAtA[i] = 0x42 + } + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if m.GasUsed != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + i-- + dAtA[i] = 0x30 + } + if m.GasWanted != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + i-- + dAtA[i] = 0x28 + } + if len(m.Info) > 0 { + i -= len(m.Info) + copy(dAtA[i:], m.Info) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i-- + dAtA[i] = 0x22 + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x1a + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseDeliverTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseDeliverTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseDeliverTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Codespace) > 0 { + i -= len(m.Codespace) + copy(dAtA[i:], m.Codespace) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Codespace))) + i-- + dAtA[i] = 0x42 + } + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if m.GasUsed != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + i-- + dAtA[i] = 0x30 + } + if m.GasWanted != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + i-- + dAtA[i] = 0x28 + } + if len(m.Info) > 0 { + i -= len(m.Info) + copy(dAtA[i:], m.Info) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i-- + dAtA[i] = 0x22 + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x1a + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseEndBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseEndBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseEndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.ConsensusParamUpdates != nil { + { + size, err := m.ConsensusParamUpdates.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.ValidatorUpdates) > 0 { + for iNdEx := len(m.ValidatorUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ValidatorUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResponseCommit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseCommit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.RetainHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.RetainHeight)) + i-- + dAtA[i] = 0x18 + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} + +func (m *ResponseListSnapshots) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseListSnapshots) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Snapshots) > 0 { + for iNdEx := len(m.Snapshots) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Snapshots[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResponseOfferSnapshot) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseOfferSnapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseOfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Result != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Result)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseLoadSnapshotChunk) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseLoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseLoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Chunk) > 0 { + i -= len(m.Chunk) + copy(dAtA[i:], m.Chunk) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Chunk))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ResponseApplySnapshotChunk) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.RejectSenders) > 0 { + for iNdEx := len(m.RejectSenders) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.RejectSenders[iNdEx]) + copy(dAtA[i:], m.RejectSenders[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.RejectSenders[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.RefetchChunks) > 0 { + dAtA41 := make([]byte, len(m.RefetchChunks)*10) + var j40 int + for _, num := range m.RefetchChunks { + for num >= 1<<7 { + dAtA41[j40] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j40++ + } + dAtA41[j40] = uint8(num) + j40++ + } + i -= j40 + copy(dAtA[i:], dAtA41[:j40]) + i = encodeVarintTypes(dAtA, i, uint64(j40)) + i-- + dAtA[i] = 0x12 + } + if m.Result != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Result)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ConsensusParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsensusParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsensusParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Version != nil { + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.Validator != nil { + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Evidence != nil { + { + size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Block != nil { + { + size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *BlockParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BlockParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MaxGas != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.MaxGas)) + i-- + dAtA[i] = 0x10 + } + if m.MaxBytes != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.MaxBytes)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *LastCommitInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LastCommitInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LastCommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Event) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Event) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Event) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Attributes) > 0 { + for iNdEx := len(m.Attributes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Attributes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Type) > 0 { + i -= len(m.Type) + copy(dAtA[i:], m.Type) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Type))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventAttribute) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventAttribute) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventAttribute) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Index { + i-- + if m.Index { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0x12 + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TxResult) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TxResult) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TxResult) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Result.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.Tx) > 0 { + i -= len(m.Tx) + copy(dAtA[i:], m.Tx) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) + i-- + dAtA[i] = 0x1a + } + if m.Index != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Validator) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Validator) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Validator) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Power != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Power)) + i-- + dAtA[i] = 0x18 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ValidatorUpdate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorUpdate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ValidatorUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Power != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Power)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *VoteInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VoteInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SignedLastBlock { + i-- + if m.SignedLastBlock { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Evidence) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Evidence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Evidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TotalVotingPower != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.TotalVotingPower)) + i-- + dAtA[i] = 0x28 + } + n49, err49 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err49 != nil { + return 0, err49 + } + i -= n49 + i = encodeVarintTypes(dAtA, i, uint64(n49)) + i-- + dAtA[i] = 0x22 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x18 + } + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.Type != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Snapshot) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Snapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Snapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x2a + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0x22 + } + if m.Chunks != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Chunks)) + i-- + dAtA[i] = 0x18 + } + if m.Format != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Format)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Request) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != nil { + n += m.Value.Size() + } + return n +} + +func (m *Request_Echo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Echo != nil { + l = m.Echo.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Flush) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Flush != nil { + l = m.Flush.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Info) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_SetOption) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SetOption != nil { + l = m.SetOption.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_InitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.InitChain != nil { + l = m.InitChain.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Query) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Query != nil { + l = m.Query.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_BeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_CheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_DeliverTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DeliverTx != nil { + l = m.DeliverTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_EndBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Commit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ListSnapshots) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ListSnapshots != nil { + l = m.ListSnapshots.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_OfferSnapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.OfferSnapshot != nil { + l = m.OfferSnapshot.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_LoadSnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LoadSnapshotChunk != nil { + l = m.LoadSnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ApplySnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ApplySnapshotChunk != nil { + l = m.ApplySnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *RequestEcho) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Message) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestFlush) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *RequestInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Version) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.BlockVersion != 0 { + n += 1 + sovTypes(uint64(m.BlockVersion)) + } + if m.P2PVersion != 0 { + n += 1 + sovTypes(uint64(m.P2PVersion)) + } + return n +} + +func (m *RequestSetOption) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestInitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.ConsensusParams != nil { + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.AppStateBytes) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.InitialHeight != 0 { + n += 1 + sovTypes(uint64(m.InitialHeight)) + } + return n +} + +func (m *RequestQuery) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Path) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Prove { + n += 2 + } + return n +} + +func (m *RequestBeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Header.Size() + n += 1 + l + sovTypes(uint64(l)) + l = m.LastCommitInfo.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.ByzantineValidators) > 0 { + for _, e := range m.ByzantineValidators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *RequestCheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Tx) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Type != 0 { + n += 1 + sovTypes(uint64(m.Type)) + } + return n +} + +func (m *RequestDeliverTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Tx) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestEndBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *RequestCommit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *RequestListSnapshots) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *RequestOfferSnapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Snapshot != nil { + l = m.Snapshot.Size() + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestLoadSnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Format != 0 { + n += 1 + sovTypes(uint64(m.Format)) + } + if m.Chunk != 0 { + n += 1 + sovTypes(uint64(m.Chunk)) + } + return n +} + +func (m *RequestApplySnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Index != 0 { + n += 1 + sovTypes(uint64(m.Index)) + } + l = len(m.Chunk) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Response) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != nil { + n += m.Value.Size() + } + return n +} + +func (m *Response_Exception) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Exception != nil { + l = m.Exception.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Echo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Echo != nil { + l = m.Echo.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Flush) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Flush != nil { + l = m.Flush.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Info) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_SetOption) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SetOption != nil { + l = m.SetOption.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_InitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.InitChain != nil { + l = m.InitChain.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Query) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Query != nil { + l = m.Query.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_BeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_CheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_DeliverTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DeliverTx != nil { + l = m.DeliverTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_EndBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Commit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ListSnapshots) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ListSnapshots != nil { + l = m.ListSnapshots.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_OfferSnapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.OfferSnapshot != nil { + l = m.OfferSnapshot.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_LoadSnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LoadSnapshotChunk != nil { + l = m.LoadSnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ApplySnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ApplySnapshotChunk != nil { + l = m.ApplySnapshotChunk.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *ResponseException) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Error) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseEcho) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Message) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseFlush) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *ResponseInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Version) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.AppVersion != 0 { + n += 1 + sovTypes(uint64(m.AppVersion)) + } + if m.LastBlockHeight != 0 { + n += 1 + sovTypes(uint64(m.LastBlockHeight)) + } + l = len(m.LastBlockAppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseSetOption) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseInitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ConsensusParams != nil { + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseQuery) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Index != 0 { + n += 1 + sovTypes(uint64(m.Index)) + } + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.ProofOps != nil { + l = m.ProofOps.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = len(m.Codespace) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseBeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseCheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Codespace) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Priority != 0 { + n += 1 + sovTypes(uint64(m.Priority)) + } + l = len(m.MempoolError) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseDeliverTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Codespace) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseEndBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ValidatorUpdates) > 0 { + for _, e := range m.ValidatorUpdates { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.ConsensusParamUpdates != nil { + l = m.ConsensusParamUpdates.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseCommit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.RetainHeight != 0 { + n += 1 + sovTypes(uint64(m.RetainHeight)) + } + return n +} + +func (m *ResponseListSnapshots) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Snapshots) > 0 { + for _, e := range m.Snapshots { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseOfferSnapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Result != 0 { + n += 1 + sovTypes(uint64(m.Result)) + } + return n +} + +func (m *ResponseLoadSnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Chunk) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseApplySnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Result != 0 { + n += 1 + sovTypes(uint64(m.Result)) + } + if len(m.RefetchChunks) > 0 { + l = 0 + for _, e := range m.RefetchChunks { + l += sovTypes(uint64(e)) + } + n += 1 + sovTypes(uint64(l)) + l + } + if len(m.RejectSenders) > 0 { + for _, s := range m.RejectSenders { + l = len(s) + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ConsensusParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Block != nil { + l = m.Block.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Evidence != nil { + l = m.Evidence.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Validator != nil { + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Version != nil { + l = m.Version.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *BlockParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxBytes != 0 { + n += 1 + sovTypes(uint64(m.MaxBytes)) + } + if m.MaxGas != 0 { + n += 1 + sovTypes(uint64(m.MaxGas)) + } + return n +} + +func (m *LastCommitInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *Event) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Type) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Attributes) > 0 { + for _, e := range m.Attributes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *EventAttribute) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Index { + n += 2 + } + return n +} + +func (m *TxResult) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Index != 0 { + n += 1 + sovTypes(uint64(m.Index)) + } + l = len(m.Tx) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Result.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *Validator) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Power != 0 { + n += 1 + sovTypes(uint64(m.Power)) + } + return n +} + +func (m *ValidatorUpdate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.PubKey.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Power != 0 { + n += 1 + sovTypes(uint64(m.Power)) + } + return n +} + +func (m *VoteInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.SignedLastBlock { + n += 2 + } + return n +} + +func (m *Evidence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovTypes(uint64(m.Type)) + } + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + if m.TotalVotingPower != 0 { + n += 1 + sovTypes(uint64(m.TotalVotingPower)) + } + return n +} + +func (m *Snapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Format != 0 { + n += 1 + sovTypes(uint64(m.Format)) + } + if m.Chunks != 0 { + n += 1 + sovTypes(uint64(m.Chunks)) + } + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Request) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Request: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Request: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Echo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestEcho{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Echo{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Flush", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestFlush{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Flush{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Info{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SetOption", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestSetOption{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_SetOption{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestInitChain{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_InitChain{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestQuery{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Query{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestBeginBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_BeginBlock{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestCheckTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_CheckTx{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestDeliverTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_DeliverTx{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestEndBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_EndBlock{v} + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestCommit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Commit{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListSnapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestListSnapshots{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ListSnapshots{v} + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OfferSnapshot", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestOfferSnapshot{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_OfferSnapshot{v} + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LoadSnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestLoadSnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_LoadSnapshotChunk{v} + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplySnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestApplySnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ApplySnapshotChunk{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestEcho) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestEcho: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestEcho: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Message = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestFlush) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestFlush: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestFlush: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Version = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockVersion", wireType) + } + m.BlockVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field P2PVersion", wireType) + } + m.P2PVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.P2PVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestSetOption) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestSetOption: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestSetOption: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestInitChain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestInitChain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParams == nil { + m.ConsensusParams = &ConsensusParams{} + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, ValidatorUpdate{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppStateBytes", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppStateBytes = append(m.AppStateBytes[:0], dAtA[iNdEx:postIndex]...) + if m.AppStateBytes == nil { + m.AppStateBytes = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialHeight", wireType) + } + m.InitialHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestQuery) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestQuery: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestQuery: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Path = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Prove", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Prove = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestBeginBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestBeginBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastCommitInfo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastCommitInfo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ByzantineValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ByzantineValidators = append(m.ByzantineValidators, Evidence{}) + if err := m.ByzantineValidators[len(m.ByzantineValidators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestCheckTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestCheckTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestCheckTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tx", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) + if m.Tx == nil { + m.Tx = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= CheckTxType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestDeliverTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestDeliverTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestDeliverTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tx", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) + if m.Tx == nil { + m.Tx = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestEndBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestEndBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestEndBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestCommit) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestCommit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestCommit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestListSnapshots) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestListSnapshots: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestListSnapshots: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestOfferSnapshot) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestOfferSnapshot: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestOfferSnapshot: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Snapshot", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Snapshot == nil { + m.Snapshot = &Snapshot{} + } + if err := m.Snapshot.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestLoadSnapshotChunk) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestLoadSnapshotChunk: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestLoadSnapshotChunk: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType) + } + m.Format = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Format |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Chunk", wireType) + } + m.Chunk = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Chunk |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestApplySnapshotChunk) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestApplySnapshotChunk: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestApplySnapshotChunk: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Chunk", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Chunk = append(m.Chunk[:0], dAtA[iNdEx:postIndex]...) + if m.Chunk == nil { + m.Chunk = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Response) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Response: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Response: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Exception", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseException{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Exception{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Echo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseEcho{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Echo{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Flush", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseFlush{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Flush{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Info{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SetOption", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseSetOption{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_SetOption{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseInitChain{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_InitChain{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseQuery{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Query{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseBeginBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_BeginBlock{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseCheckTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_CheckTx{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseDeliverTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_DeliverTx{v} + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseEndBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_EndBlock{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseCommit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Commit{v} + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListSnapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseListSnapshots{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ListSnapshots{v} + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OfferSnapshot", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseOfferSnapshot{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_OfferSnapshot{v} + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LoadSnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseLoadSnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_LoadSnapshotChunk{v} + iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplySnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseApplySnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ApplySnapshotChunk{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseException) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseException: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseException: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseEcho) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseEcho: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseEcho: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Message = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseFlush) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseFlush: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseFlush: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Version = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AppVersion", wireType) + } + m.AppVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.AppVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockHeight", wireType) + } + m.LastBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastBlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockAppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastBlockAppHash = append(m.LastBlockAppHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastBlockAppHash == nil { + m.LastBlockAppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseSetOption) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseSetOption: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseSetOption: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseInitChain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParams == nil { + m.ConsensusParams = &ConsensusParams{} + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, ValidatorUpdate{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseQuery) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseQuery: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseQuery: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...) + if m.Value == nil { + m.Value = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProofOps", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ProofOps == nil { + m.ProofOps = &v1.ProofOps{} + } + if err := m.ProofOps.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Codespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Codespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseBeginBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseBeginBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseBeginBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseCheckTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseCheckTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Codespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Codespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) + } + m.Priority = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Priority |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MempoolError", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MempoolError = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseDeliverTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseDeliverTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseDeliverTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Codespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Codespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseEndBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseEndBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorUpdates = append(m.ValidatorUpdates, ValidatorUpdate{}) + if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParamUpdates == nil { + m.ConsensusParamUpdates = &ConsensusParams{} + } + if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseCommit) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseCommit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseCommit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RetainHeight", wireType) + } + m.RetainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RetainHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseListSnapshots) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseListSnapshots: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseListSnapshots: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Snapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Snapshots = append(m.Snapshots, &Snapshot{}) + if err := m.Snapshots[len(m.Snapshots)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseOfferSnapshot) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseOfferSnapshot: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseOfferSnapshot: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + m.Result = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Result |= ResponseOfferSnapshot_Result(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseLoadSnapshotChunk) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseLoadSnapshotChunk: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseLoadSnapshotChunk: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Chunk", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Chunk = append(m.Chunk[:0], dAtA[iNdEx:postIndex]...) + if m.Chunk == nil { + m.Chunk = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseApplySnapshotChunk) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseApplySnapshotChunk: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseApplySnapshotChunk: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + m.Result = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Result |= ResponseApplySnapshotChunk_Result(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType == 0 { + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.RefetchChunks = append(m.RefetchChunks, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + var count int + for _, integer := range dAtA[iNdEx:postIndex] { + if integer < 128 { + count++ + } + } + elementCount = count + if elementCount != 0 && len(m.RefetchChunks) == 0 { + m.RefetchChunks = make([]uint32, 0, elementCount) + } + for iNdEx < postIndex { + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.RefetchChunks = append(m.RefetchChunks, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field RefetchChunks", wireType) + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RejectSenders", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RejectSenders = append(m.RejectSenders, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConsensusParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsensusParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Block == nil { + m.Block = &BlockParams{} + } + if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Evidence == nil { + m.Evidence = &v1beta1.EvidenceParams{} + } + if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Validator == nil { + m.Validator = &v1beta1.ValidatorParams{} + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Version == nil { + m.Version = &v1beta1.VersionParams{} + } + if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxBytes", wireType) + } + m.MaxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxGas", wireType) + } + m.MaxGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxGas |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LastCommitInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LastCommitInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LastCommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, VoteInfo{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Event) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Event: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Event: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Attributes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Attributes = append(m.Attributes, EventAttribute{}) + if err := m.Attributes[len(m.Attributes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventAttribute) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventAttribute: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventAttribute: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...) + if m.Value == nil { + m.Value = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Index = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TxResult) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TxResult: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TxResult: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tx", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) + if m.Tx == nil { + m.Tx = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Result.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Validator) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Validator: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Validator: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Power", wireType) + } + m.Power = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Power |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ValidatorUpdate) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ValidatorUpdate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorUpdate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Power", wireType) + } + m.Power = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Power |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VoteInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VoteInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VoteInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedLastBlock", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SignedLastBlock = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Evidence) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Evidence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Evidence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= EvidenceType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalVotingPower", wireType) + } + m.TotalVotingPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalVotingPower |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Snapshot) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Snapshot: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Snapshot: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType) + } + m.Format = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Format |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Chunks", wireType) + } + m.Chunks = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Chunks |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/abci/v1beta2/types.go b/api/cometbft/abci/v1beta2/types.go new file mode 100644 index 00000000000..8ef412c2d71 --- /dev/null +++ b/api/cometbft/abci/v1beta2/types.go @@ -0,0 +1,38 @@ +package v1beta2 + +import ( + "bytes" + + "github.com/cosmos/gogoproto/jsonpb" +) + +// IsAccepted returns true if Code is ACCEPT +func (r ResponseProcessProposal) IsAccepted() bool { + return r.Status == ResponseProcessProposal_ACCEPT +} + +// IsStatusUnknown returns true if Code is UNKNOWN +func (r ResponseProcessProposal) IsStatusUnknown() bool { + return r.Status == ResponseProcessProposal_UNKNOWN +} + +// --------------------------------------------------------------------------- +// override JSON marshaling so we emit defaults (ie. disable omitempty) + +var ( + jsonpbMarshaller = jsonpb.Marshaler{ + EnumsAsInts: true, + EmitDefaults: true, + } + jsonpbUnmarshaller = jsonpb.Unmarshaler{} +) + +func (r *EventAttribute) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *EventAttribute) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} diff --git a/api/cometbft/abci/v1beta2/types.pb.go b/api/cometbft/abci/v1beta2/types.pb.go new file mode 100644 index 00000000000..b6086ee2d7e --- /dev/null +++ b/api/cometbft/abci/v1beta2/types.pb.go @@ -0,0 +1,9911 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/abci/v1beta2/types.proto + +package v1beta2 + +import ( + context "context" + fmt "fmt" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta1" + v1beta11 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + v1beta2 "github.com/cometbft/cometbft/api/cometbft/types/v1beta2" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// The type of misbehavior committed by a validator. +type MisbehaviorType int32 + +const ( + // Unknown + MisbehaviorType_UNKNOWN MisbehaviorType = 0 + // Duplicate vote + MisbehaviorType_DUPLICATE_VOTE MisbehaviorType = 1 + // Light client attack + MisbehaviorType_LIGHT_CLIENT_ATTACK MisbehaviorType = 2 +) + +var MisbehaviorType_name = map[int32]string{ + 0: "UNKNOWN", + 1: "DUPLICATE_VOTE", + 2: "LIGHT_CLIENT_ATTACK", +} + +var MisbehaviorType_value = map[string]int32{ + "UNKNOWN": 0, + "DUPLICATE_VOTE": 1, + "LIGHT_CLIENT_ATTACK": 2, +} + +func (x MisbehaviorType) String() string { + return proto.EnumName(MisbehaviorType_name, int32(x)) +} + +func (MisbehaviorType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{0} +} + +// The status. +type ResponseProcessProposal_ProposalStatus int32 + +const ( + // Unknown + ResponseProcessProposal_UNKNOWN ResponseProcessProposal_ProposalStatus = 0 + // Accepted + ResponseProcessProposal_ACCEPT ResponseProcessProposal_ProposalStatus = 1 + // Rejected + ResponseProcessProposal_REJECT ResponseProcessProposal_ProposalStatus = 2 +) + +var ResponseProcessProposal_ProposalStatus_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ACCEPT", + 2: "REJECT", +} + +var ResponseProcessProposal_ProposalStatus_value = map[string]int32{ + "UNKNOWN": 0, + "ACCEPT": 1, + "REJECT": 2, +} + +func (x ResponseProcessProposal_ProposalStatus) String() string { + return proto.EnumName(ResponseProcessProposal_ProposalStatus_name, int32(x)) +} + +func (ResponseProcessProposal_ProposalStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{13, 0} +} + +// Request represents a request to the ABCI application. +type Request struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Value: + // *Request_Echo + // *Request_Flush + // *Request_Info + // *Request_InitChain + // *Request_Query + // *Request_BeginBlock + // *Request_CheckTx + // *Request_DeliverTx + // *Request_EndBlock + // *Request_Commit + // *Request_ListSnapshots + // *Request_OfferSnapshot + // *Request_LoadSnapshotChunk + // *Request_ApplySnapshotChunk + // *Request_PrepareProposal + // *Request_ProcessProposal + Value isRequest_Value `protobuf_oneof:"value"` +} + +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} +func (*Request) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{0} +} +func (m *Request) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Request.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Request) XXX_Merge(src proto.Message) { + xxx_messageInfo_Request.Merge(m, src) +} +func (m *Request) XXX_Size() int { + return m.Size() +} +func (m *Request) XXX_DiscardUnknown() { + xxx_messageInfo_Request.DiscardUnknown(m) +} + +var xxx_messageInfo_Request proto.InternalMessageInfo + +type isRequest_Value interface { + isRequest_Value() + MarshalTo([]byte) (int, error) + Size() int +} + +type Request_Echo struct { + Echo *v1beta1.RequestEcho `protobuf:"bytes,1,opt,name=echo,proto3,oneof" json:"echo,omitempty"` +} +type Request_Flush struct { + Flush *v1beta1.RequestFlush `protobuf:"bytes,2,opt,name=flush,proto3,oneof" json:"flush,omitempty"` +} +type Request_Info struct { + Info *RequestInfo `protobuf:"bytes,3,opt,name=info,proto3,oneof" json:"info,omitempty"` +} +type Request_InitChain struct { + InitChain *RequestInitChain `protobuf:"bytes,5,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` +} +type Request_Query struct { + Query *v1beta1.RequestQuery `protobuf:"bytes,6,opt,name=query,proto3,oneof" json:"query,omitempty"` +} +type Request_BeginBlock struct { + BeginBlock *RequestBeginBlock `protobuf:"bytes,7,opt,name=begin_block,json=beginBlock,proto3,oneof" json:"begin_block,omitempty"` +} +type Request_CheckTx struct { + CheckTx *v1beta1.RequestCheckTx `protobuf:"bytes,8,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` +} +type Request_DeliverTx struct { + DeliverTx *v1beta1.RequestDeliverTx `protobuf:"bytes,9,opt,name=deliver_tx,json=deliverTx,proto3,oneof" json:"deliver_tx,omitempty"` +} +type Request_EndBlock struct { + EndBlock *v1beta1.RequestEndBlock `protobuf:"bytes,10,opt,name=end_block,json=endBlock,proto3,oneof" json:"end_block,omitempty"` +} +type Request_Commit struct { + Commit *v1beta1.RequestCommit `protobuf:"bytes,11,opt,name=commit,proto3,oneof" json:"commit,omitempty"` +} +type Request_ListSnapshots struct { + ListSnapshots *v1beta1.RequestListSnapshots `protobuf:"bytes,12,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` +} +type Request_OfferSnapshot struct { + OfferSnapshot *v1beta1.RequestOfferSnapshot `protobuf:"bytes,13,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` +} +type Request_LoadSnapshotChunk struct { + LoadSnapshotChunk *v1beta1.RequestLoadSnapshotChunk `protobuf:"bytes,14,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` +} +type Request_ApplySnapshotChunk struct { + ApplySnapshotChunk *v1beta1.RequestApplySnapshotChunk `protobuf:"bytes,15,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` +} +type Request_PrepareProposal struct { + PrepareProposal *RequestPrepareProposal `protobuf:"bytes,16,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` +} +type Request_ProcessProposal struct { + ProcessProposal *RequestProcessProposal `protobuf:"bytes,17,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` +} + +func (*Request_Echo) isRequest_Value() {} +func (*Request_Flush) isRequest_Value() {} +func (*Request_Info) isRequest_Value() {} +func (*Request_InitChain) isRequest_Value() {} +func (*Request_Query) isRequest_Value() {} +func (*Request_BeginBlock) isRequest_Value() {} +func (*Request_CheckTx) isRequest_Value() {} +func (*Request_DeliverTx) isRequest_Value() {} +func (*Request_EndBlock) isRequest_Value() {} +func (*Request_Commit) isRequest_Value() {} +func (*Request_ListSnapshots) isRequest_Value() {} +func (*Request_OfferSnapshot) isRequest_Value() {} +func (*Request_LoadSnapshotChunk) isRequest_Value() {} +func (*Request_ApplySnapshotChunk) isRequest_Value() {} +func (*Request_PrepareProposal) isRequest_Value() {} +func (*Request_ProcessProposal) isRequest_Value() {} + +func (m *Request) GetValue() isRequest_Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *Request) GetEcho() *v1beta1.RequestEcho { + if x, ok := m.GetValue().(*Request_Echo); ok { + return x.Echo + } + return nil +} + +func (m *Request) GetFlush() *v1beta1.RequestFlush { + if x, ok := m.GetValue().(*Request_Flush); ok { + return x.Flush + } + return nil +} + +func (m *Request) GetInfo() *RequestInfo { + if x, ok := m.GetValue().(*Request_Info); ok { + return x.Info + } + return nil +} + +func (m *Request) GetInitChain() *RequestInitChain { + if x, ok := m.GetValue().(*Request_InitChain); ok { + return x.InitChain + } + return nil +} + +func (m *Request) GetQuery() *v1beta1.RequestQuery { + if x, ok := m.GetValue().(*Request_Query); ok { + return x.Query + } + return nil +} + +func (m *Request) GetBeginBlock() *RequestBeginBlock { + if x, ok := m.GetValue().(*Request_BeginBlock); ok { + return x.BeginBlock + } + return nil +} + +func (m *Request) GetCheckTx() *v1beta1.RequestCheckTx { + if x, ok := m.GetValue().(*Request_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Request) GetDeliverTx() *v1beta1.RequestDeliverTx { + if x, ok := m.GetValue().(*Request_DeliverTx); ok { + return x.DeliverTx + } + return nil +} + +func (m *Request) GetEndBlock() *v1beta1.RequestEndBlock { + if x, ok := m.GetValue().(*Request_EndBlock); ok { + return x.EndBlock + } + return nil +} + +func (m *Request) GetCommit() *v1beta1.RequestCommit { + if x, ok := m.GetValue().(*Request_Commit); ok { + return x.Commit + } + return nil +} + +func (m *Request) GetListSnapshots() *v1beta1.RequestListSnapshots { + if x, ok := m.GetValue().(*Request_ListSnapshots); ok { + return x.ListSnapshots + } + return nil +} + +func (m *Request) GetOfferSnapshot() *v1beta1.RequestOfferSnapshot { + if x, ok := m.GetValue().(*Request_OfferSnapshot); ok { + return x.OfferSnapshot + } + return nil +} + +func (m *Request) GetLoadSnapshotChunk() *v1beta1.RequestLoadSnapshotChunk { + if x, ok := m.GetValue().(*Request_LoadSnapshotChunk); ok { + return x.LoadSnapshotChunk + } + return nil +} + +func (m *Request) GetApplySnapshotChunk() *v1beta1.RequestApplySnapshotChunk { + if x, ok := m.GetValue().(*Request_ApplySnapshotChunk); ok { + return x.ApplySnapshotChunk + } + return nil +} + +func (m *Request) GetPrepareProposal() *RequestPrepareProposal { + if x, ok := m.GetValue().(*Request_PrepareProposal); ok { + return x.PrepareProposal + } + return nil +} + +func (m *Request) GetProcessProposal() *RequestProcessProposal { + if x, ok := m.GetValue().(*Request_ProcessProposal); ok { + return x.ProcessProposal + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Request) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Request_Echo)(nil), + (*Request_Flush)(nil), + (*Request_Info)(nil), + (*Request_InitChain)(nil), + (*Request_Query)(nil), + (*Request_BeginBlock)(nil), + (*Request_CheckTx)(nil), + (*Request_DeliverTx)(nil), + (*Request_EndBlock)(nil), + (*Request_Commit)(nil), + (*Request_ListSnapshots)(nil), + (*Request_OfferSnapshot)(nil), + (*Request_LoadSnapshotChunk)(nil), + (*Request_ApplySnapshotChunk)(nil), + (*Request_PrepareProposal)(nil), + (*Request_ProcessProposal)(nil), + } +} + +// RequestInfo is a request for the ABCI application version. +type RequestInfo struct { + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + BlockVersion uint64 `protobuf:"varint,2,opt,name=block_version,json=blockVersion,proto3" json:"block_version,omitempty"` + P2PVersion uint64 `protobuf:"varint,3,opt,name=p2p_version,json=p2pVersion,proto3" json:"p2p_version,omitempty"` + AbciVersion string `protobuf:"bytes,4,opt,name=abci_version,json=abciVersion,proto3" json:"abci_version,omitempty"` +} + +func (m *RequestInfo) Reset() { *m = RequestInfo{} } +func (m *RequestInfo) String() string { return proto.CompactTextString(m) } +func (*RequestInfo) ProtoMessage() {} +func (*RequestInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{1} +} +func (m *RequestInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestInfo.Merge(m, src) +} +func (m *RequestInfo) XXX_Size() int { + return m.Size() +} +func (m *RequestInfo) XXX_DiscardUnknown() { + xxx_messageInfo_RequestInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestInfo proto.InternalMessageInfo + +func (m *RequestInfo) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + +func (m *RequestInfo) GetBlockVersion() uint64 { + if m != nil { + return m.BlockVersion + } + return 0 +} + +func (m *RequestInfo) GetP2PVersion() uint64 { + if m != nil { + return m.P2PVersion + } + return 0 +} + +func (m *RequestInfo) GetAbciVersion() string { + if m != nil { + return m.AbciVersion + } + return "" +} + +// RequestInitChain is a request to initialize the blockchain. +type RequestInitChain struct { + Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ConsensusParams *v1beta2.ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []v1beta1.ValidatorUpdate `protobuf:"bytes,4,rep,name=validators,proto3" json:"validators"` + AppStateBytes []byte `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"` + InitialHeight int64 `protobuf:"varint,6,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` +} + +func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } +func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } +func (*RequestInitChain) ProtoMessage() {} +func (*RequestInitChain) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{2} +} +func (m *RequestInitChain) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestInitChain.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestInitChain) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestInitChain.Merge(m, src) +} +func (m *RequestInitChain) XXX_Size() int { + return m.Size() +} +func (m *RequestInitChain) XXX_DiscardUnknown() { + xxx_messageInfo_RequestInitChain.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestInitChain proto.InternalMessageInfo + +func (m *RequestInitChain) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestInitChain) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *RequestInitChain) GetConsensusParams() *v1beta2.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return nil +} + +func (m *RequestInitChain) GetValidators() []v1beta1.ValidatorUpdate { + if m != nil { + return m.Validators + } + return nil +} + +func (m *RequestInitChain) GetAppStateBytes() []byte { + if m != nil { + return m.AppStateBytes + } + return nil +} + +func (m *RequestInitChain) GetInitialHeight() int64 { + if m != nil { + return m.InitialHeight + } + return 0 +} + +// RequestBeginBlock indicates the beginning of committing the block. +type RequestBeginBlock struct { + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Header v1beta11.Header `protobuf:"bytes,2,opt,name=header,proto3" json:"header"` + LastCommitInfo CommitInfo `protobuf:"bytes,3,opt,name=last_commit_info,json=lastCommitInfo,proto3" json:"last_commit_info"` + ByzantineValidators []Misbehavior `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators,proto3" json:"byzantine_validators"` +} + +func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} } +func (m *RequestBeginBlock) String() string { return proto.CompactTextString(m) } +func (*RequestBeginBlock) ProtoMessage() {} +func (*RequestBeginBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{3} +} +func (m *RequestBeginBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestBeginBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestBeginBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestBeginBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestBeginBlock.Merge(m, src) +} +func (m *RequestBeginBlock) XXX_Size() int { + return m.Size() +} +func (m *RequestBeginBlock) XXX_DiscardUnknown() { + xxx_messageInfo_RequestBeginBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestBeginBlock proto.InternalMessageInfo + +func (m *RequestBeginBlock) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *RequestBeginBlock) GetHeader() v1beta11.Header { + if m != nil { + return m.Header + } + return v1beta11.Header{} +} + +func (m *RequestBeginBlock) GetLastCommitInfo() CommitInfo { + if m != nil { + return m.LastCommitInfo + } + return CommitInfo{} +} + +func (m *RequestBeginBlock) GetByzantineValidators() []Misbehavior { + if m != nil { + return m.ByzantineValidators + } + return nil +} + +// RequestPrepareProposal is a request for the ABCI application to prepare a new +// block proposal. +type RequestPrepareProposal struct { + // the modified transactions cannot exceed this size. + MaxTxBytes int64 `protobuf:"varint,1,opt,name=max_tx_bytes,json=maxTxBytes,proto3" json:"max_tx_bytes,omitempty"` + // txs is an array of transactions that will be included in a block, + // sent to the app for possible modifications. + Txs [][]byte `protobuf:"bytes,2,rep,name=txs,proto3" json:"txs,omitempty"` + LocalLastCommit ExtendedCommitInfo `protobuf:"bytes,3,opt,name=local_last_commit,json=localLastCommit,proto3" json:"local_last_commit"` + Misbehavior []Misbehavior `protobuf:"bytes,4,rep,name=misbehavior,proto3" json:"misbehavior"` + Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // address of the public key of the validator proposing the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *RequestPrepareProposal) Reset() { *m = RequestPrepareProposal{} } +func (m *RequestPrepareProposal) String() string { return proto.CompactTextString(m) } +func (*RequestPrepareProposal) ProtoMessage() {} +func (*RequestPrepareProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{4} +} +func (m *RequestPrepareProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestPrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestPrepareProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestPrepareProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestPrepareProposal.Merge(m, src) +} +func (m *RequestPrepareProposal) XXX_Size() int { + return m.Size() +} +func (m *RequestPrepareProposal) XXX_DiscardUnknown() { + xxx_messageInfo_RequestPrepareProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestPrepareProposal proto.InternalMessageInfo + +func (m *RequestPrepareProposal) GetMaxTxBytes() int64 { + if m != nil { + return m.MaxTxBytes + } + return 0 +} + +func (m *RequestPrepareProposal) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *RequestPrepareProposal) GetLocalLastCommit() ExtendedCommitInfo { + if m != nil { + return m.LocalLastCommit + } + return ExtendedCommitInfo{} +} + +func (m *RequestPrepareProposal) GetMisbehavior() []Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *RequestPrepareProposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestPrepareProposal) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestPrepareProposal) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *RequestPrepareProposal) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +// RequestProcessProposal is a request for the ABCI application to process proposal. +type RequestProcessProposal struct { + Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` + ProposedLastCommit CommitInfo `protobuf:"bytes,2,opt,name=proposed_last_commit,json=proposedLastCommit,proto3" json:"proposed_last_commit"` + Misbehavior []Misbehavior `protobuf:"bytes,3,rep,name=misbehavior,proto3" json:"misbehavior"` + // hash is the merkle root hash of the fields of the proposed block. + Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` + Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // address of the public key of the original proposer of the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *RequestProcessProposal) Reset() { *m = RequestProcessProposal{} } +func (m *RequestProcessProposal) String() string { return proto.CompactTextString(m) } +func (*RequestProcessProposal) ProtoMessage() {} +func (*RequestProcessProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{5} +} +func (m *RequestProcessProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestProcessProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestProcessProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestProcessProposal.Merge(m, src) +} +func (m *RequestProcessProposal) XXX_Size() int { + return m.Size() +} +func (m *RequestProcessProposal) XXX_DiscardUnknown() { + xxx_messageInfo_RequestProcessProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestProcessProposal proto.InternalMessageInfo + +func (m *RequestProcessProposal) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *RequestProcessProposal) GetProposedLastCommit() CommitInfo { + if m != nil { + return m.ProposedLastCommit + } + return CommitInfo{} +} + +func (m *RequestProcessProposal) GetMisbehavior() []Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *RequestProcessProposal) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *RequestProcessProposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestProcessProposal) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestProcessProposal) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *RequestProcessProposal) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +// Response represents a response from the ABCI application. +type Response struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Value: + // *Response_Exception + // *Response_Echo + // *Response_Flush + // *Response_Info + // *Response_InitChain + // *Response_Query + // *Response_BeginBlock + // *Response_CheckTx + // *Response_DeliverTx + // *Response_EndBlock + // *Response_Commit + // *Response_ListSnapshots + // *Response_OfferSnapshot + // *Response_LoadSnapshotChunk + // *Response_ApplySnapshotChunk + // *Response_PrepareProposal + // *Response_ProcessProposal + Value isResponse_Value `protobuf_oneof:"value"` +} + +func (m *Response) Reset() { *m = Response{} } +func (m *Response) String() string { return proto.CompactTextString(m) } +func (*Response) ProtoMessage() {} +func (*Response) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{6} +} +func (m *Response) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Response.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Response) XXX_Merge(src proto.Message) { + xxx_messageInfo_Response.Merge(m, src) +} +func (m *Response) XXX_Size() int { + return m.Size() +} +func (m *Response) XXX_DiscardUnknown() { + xxx_messageInfo_Response.DiscardUnknown(m) +} + +var xxx_messageInfo_Response proto.InternalMessageInfo + +type isResponse_Value interface { + isResponse_Value() + MarshalTo([]byte) (int, error) + Size() int +} + +type Response_Exception struct { + Exception *v1beta1.ResponseException `protobuf:"bytes,1,opt,name=exception,proto3,oneof" json:"exception,omitempty"` +} +type Response_Echo struct { + Echo *v1beta1.ResponseEcho `protobuf:"bytes,2,opt,name=echo,proto3,oneof" json:"echo,omitempty"` +} +type Response_Flush struct { + Flush *v1beta1.ResponseFlush `protobuf:"bytes,3,opt,name=flush,proto3,oneof" json:"flush,omitempty"` +} +type Response_Info struct { + Info *v1beta1.ResponseInfo `protobuf:"bytes,4,opt,name=info,proto3,oneof" json:"info,omitempty"` +} +type Response_InitChain struct { + InitChain *ResponseInitChain `protobuf:"bytes,6,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` +} +type Response_Query struct { + Query *v1beta1.ResponseQuery `protobuf:"bytes,7,opt,name=query,proto3,oneof" json:"query,omitempty"` +} +type Response_BeginBlock struct { + BeginBlock *ResponseBeginBlock `protobuf:"bytes,8,opt,name=begin_block,json=beginBlock,proto3,oneof" json:"begin_block,omitempty"` +} +type Response_CheckTx struct { + CheckTx *ResponseCheckTx `protobuf:"bytes,9,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` +} +type Response_DeliverTx struct { + DeliverTx *ResponseDeliverTx `protobuf:"bytes,10,opt,name=deliver_tx,json=deliverTx,proto3,oneof" json:"deliver_tx,omitempty"` +} +type Response_EndBlock struct { + EndBlock *ResponseEndBlock `protobuf:"bytes,11,opt,name=end_block,json=endBlock,proto3,oneof" json:"end_block,omitempty"` +} +type Response_Commit struct { + Commit *v1beta1.ResponseCommit `protobuf:"bytes,12,opt,name=commit,proto3,oneof" json:"commit,omitempty"` +} +type Response_ListSnapshots struct { + ListSnapshots *v1beta1.ResponseListSnapshots `protobuf:"bytes,13,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` +} +type Response_OfferSnapshot struct { + OfferSnapshot *v1beta1.ResponseOfferSnapshot `protobuf:"bytes,14,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` +} +type Response_LoadSnapshotChunk struct { + LoadSnapshotChunk *v1beta1.ResponseLoadSnapshotChunk `protobuf:"bytes,15,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` +} +type Response_ApplySnapshotChunk struct { + ApplySnapshotChunk *v1beta1.ResponseApplySnapshotChunk `protobuf:"bytes,16,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` +} +type Response_PrepareProposal struct { + PrepareProposal *ResponsePrepareProposal `protobuf:"bytes,17,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` +} +type Response_ProcessProposal struct { + ProcessProposal *ResponseProcessProposal `protobuf:"bytes,18,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` +} + +func (*Response_Exception) isResponse_Value() {} +func (*Response_Echo) isResponse_Value() {} +func (*Response_Flush) isResponse_Value() {} +func (*Response_Info) isResponse_Value() {} +func (*Response_InitChain) isResponse_Value() {} +func (*Response_Query) isResponse_Value() {} +func (*Response_BeginBlock) isResponse_Value() {} +func (*Response_CheckTx) isResponse_Value() {} +func (*Response_DeliverTx) isResponse_Value() {} +func (*Response_EndBlock) isResponse_Value() {} +func (*Response_Commit) isResponse_Value() {} +func (*Response_ListSnapshots) isResponse_Value() {} +func (*Response_OfferSnapshot) isResponse_Value() {} +func (*Response_LoadSnapshotChunk) isResponse_Value() {} +func (*Response_ApplySnapshotChunk) isResponse_Value() {} +func (*Response_PrepareProposal) isResponse_Value() {} +func (*Response_ProcessProposal) isResponse_Value() {} + +func (m *Response) GetValue() isResponse_Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *Response) GetException() *v1beta1.ResponseException { + if x, ok := m.GetValue().(*Response_Exception); ok { + return x.Exception + } + return nil +} + +func (m *Response) GetEcho() *v1beta1.ResponseEcho { + if x, ok := m.GetValue().(*Response_Echo); ok { + return x.Echo + } + return nil +} + +func (m *Response) GetFlush() *v1beta1.ResponseFlush { + if x, ok := m.GetValue().(*Response_Flush); ok { + return x.Flush + } + return nil +} + +func (m *Response) GetInfo() *v1beta1.ResponseInfo { + if x, ok := m.GetValue().(*Response_Info); ok { + return x.Info + } + return nil +} + +func (m *Response) GetInitChain() *ResponseInitChain { + if x, ok := m.GetValue().(*Response_InitChain); ok { + return x.InitChain + } + return nil +} + +func (m *Response) GetQuery() *v1beta1.ResponseQuery { + if x, ok := m.GetValue().(*Response_Query); ok { + return x.Query + } + return nil +} + +func (m *Response) GetBeginBlock() *ResponseBeginBlock { + if x, ok := m.GetValue().(*Response_BeginBlock); ok { + return x.BeginBlock + } + return nil +} + +func (m *Response) GetCheckTx() *ResponseCheckTx { + if x, ok := m.GetValue().(*Response_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Response) GetDeliverTx() *ResponseDeliverTx { + if x, ok := m.GetValue().(*Response_DeliverTx); ok { + return x.DeliverTx + } + return nil +} + +func (m *Response) GetEndBlock() *ResponseEndBlock { + if x, ok := m.GetValue().(*Response_EndBlock); ok { + return x.EndBlock + } + return nil +} + +func (m *Response) GetCommit() *v1beta1.ResponseCommit { + if x, ok := m.GetValue().(*Response_Commit); ok { + return x.Commit + } + return nil +} + +func (m *Response) GetListSnapshots() *v1beta1.ResponseListSnapshots { + if x, ok := m.GetValue().(*Response_ListSnapshots); ok { + return x.ListSnapshots + } + return nil +} + +func (m *Response) GetOfferSnapshot() *v1beta1.ResponseOfferSnapshot { + if x, ok := m.GetValue().(*Response_OfferSnapshot); ok { + return x.OfferSnapshot + } + return nil +} + +func (m *Response) GetLoadSnapshotChunk() *v1beta1.ResponseLoadSnapshotChunk { + if x, ok := m.GetValue().(*Response_LoadSnapshotChunk); ok { + return x.LoadSnapshotChunk + } + return nil +} + +func (m *Response) GetApplySnapshotChunk() *v1beta1.ResponseApplySnapshotChunk { + if x, ok := m.GetValue().(*Response_ApplySnapshotChunk); ok { + return x.ApplySnapshotChunk + } + return nil +} + +func (m *Response) GetPrepareProposal() *ResponsePrepareProposal { + if x, ok := m.GetValue().(*Response_PrepareProposal); ok { + return x.PrepareProposal + } + return nil +} + +func (m *Response) GetProcessProposal() *ResponseProcessProposal { + if x, ok := m.GetValue().(*Response_ProcessProposal); ok { + return x.ProcessProposal + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Response) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Response_Exception)(nil), + (*Response_Echo)(nil), + (*Response_Flush)(nil), + (*Response_Info)(nil), + (*Response_InitChain)(nil), + (*Response_Query)(nil), + (*Response_BeginBlock)(nil), + (*Response_CheckTx)(nil), + (*Response_DeliverTx)(nil), + (*Response_EndBlock)(nil), + (*Response_Commit)(nil), + (*Response_ListSnapshots)(nil), + (*Response_OfferSnapshot)(nil), + (*Response_LoadSnapshotChunk)(nil), + (*Response_ApplySnapshotChunk)(nil), + (*Response_PrepareProposal)(nil), + (*Response_ProcessProposal)(nil), + } +} + +// ResponseInitChain contains the ABCI application's hash and updates to the +// validator set and/or the consensus params, if any. +type ResponseInitChain struct { + ConsensusParams *v1beta2.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []v1beta1.ValidatorUpdate `protobuf:"bytes,2,rep,name=validators,proto3" json:"validators"` + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } +func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } +func (*ResponseInitChain) ProtoMessage() {} +func (*ResponseInitChain) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{7} +} +func (m *ResponseInitChain) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseInitChain.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseInitChain) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseInitChain.Merge(m, src) +} +func (m *ResponseInitChain) XXX_Size() int { + return m.Size() +} +func (m *ResponseInitChain) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseInitChain.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseInitChain proto.InternalMessageInfo + +func (m *ResponseInitChain) GetConsensusParams() *v1beta2.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return nil +} + +func (m *ResponseInitChain) GetValidators() []v1beta1.ValidatorUpdate { + if m != nil { + return m.Validators + } + return nil +} + +func (m *ResponseInitChain) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +// ResponseBeginBlock contains a list of block-level events. +type ResponseBeginBlock struct { + Events []Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` +} + +func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } +func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseBeginBlock) ProtoMessage() {} +func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{8} +} +func (m *ResponseBeginBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseBeginBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseBeginBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseBeginBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseBeginBlock.Merge(m, src) +} +func (m *ResponseBeginBlock) XXX_Size() int { + return m.Size() +} +func (m *ResponseBeginBlock) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseBeginBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseBeginBlock proto.InternalMessageInfo + +func (m *ResponseBeginBlock) GetEvents() []Event { + if m != nil { + return m.Events + } + return nil +} + +// ResponseCheckTx shows if the transaction was deemed valid by the ABCI +// application. +type ResponseCheckTx struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` + Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` + Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` + Sender string `protobuf:"bytes,9,opt,name=sender,proto3" json:"sender,omitempty"` + Priority int64 `protobuf:"varint,10,opt,name=priority,proto3" json:"priority,omitempty"` + // mempool_error is set by CometBFT. + // ABCI applications creating a ResponseCheckTX should not set mempool_error. + MempoolError string `protobuf:"bytes,11,opt,name=mempool_error,json=mempoolError,proto3" json:"mempool_error,omitempty"` +} + +func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } +func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } +func (*ResponseCheckTx) ProtoMessage() {} +func (*ResponseCheckTx) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{9} +} +func (m *ResponseCheckTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseCheckTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseCheckTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseCheckTx.Merge(m, src) +} +func (m *ResponseCheckTx) XXX_Size() int { + return m.Size() +} +func (m *ResponseCheckTx) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseCheckTx.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseCheckTx proto.InternalMessageInfo + +func (m *ResponseCheckTx) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseCheckTx) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseCheckTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseCheckTx) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + +func (m *ResponseCheckTx) GetGasWanted() int64 { + if m != nil { + return m.GasWanted + } + return 0 +} + +func (m *ResponseCheckTx) GetGasUsed() int64 { + if m != nil { + return m.GasUsed + } + return 0 +} + +func (m *ResponseCheckTx) GetEvents() []Event { + if m != nil { + return m.Events + } + return nil +} + +func (m *ResponseCheckTx) GetCodespace() string { + if m != nil { + return m.Codespace + } + return "" +} + +func (m *ResponseCheckTx) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *ResponseCheckTx) GetPriority() int64 { + if m != nil { + return m.Priority + } + return 0 +} + +func (m *ResponseCheckTx) GetMempoolError() string { + if m != nil { + return m.MempoolError + } + return "" +} + +// ResponseDeliverTx contains a result of committing the given transaction and a +// list of events. +type ResponseDeliverTx struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` + Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` + Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` +} + +func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} } +func (m *ResponseDeliverTx) String() string { return proto.CompactTextString(m) } +func (*ResponseDeliverTx) ProtoMessage() {} +func (*ResponseDeliverTx) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{10} +} +func (m *ResponseDeliverTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseDeliverTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseDeliverTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseDeliverTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseDeliverTx.Merge(m, src) +} +func (m *ResponseDeliverTx) XXX_Size() int { + return m.Size() +} +func (m *ResponseDeliverTx) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseDeliverTx.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseDeliverTx proto.InternalMessageInfo + +func (m *ResponseDeliverTx) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseDeliverTx) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseDeliverTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseDeliverTx) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + +func (m *ResponseDeliverTx) GetGasWanted() int64 { + if m != nil { + return m.GasWanted + } + return 0 +} + +func (m *ResponseDeliverTx) GetGasUsed() int64 { + if m != nil { + return m.GasUsed + } + return 0 +} + +func (m *ResponseDeliverTx) GetEvents() []Event { + if m != nil { + return m.Events + } + return nil +} + +func (m *ResponseDeliverTx) GetCodespace() string { + if m != nil { + return m.Codespace + } + return "" +} + +// ResponseEndBlock contains updates to consensus params and/or validator set changes, if any. +type ResponseEndBlock struct { + ValidatorUpdates []v1beta1.ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` + ConsensusParamUpdates *v1beta2.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` + Events []Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` +} + +func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } +func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseEndBlock) ProtoMessage() {} +func (*ResponseEndBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{11} +} +func (m *ResponseEndBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseEndBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseEndBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseEndBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseEndBlock.Merge(m, src) +} +func (m *ResponseEndBlock) XXX_Size() int { + return m.Size() +} +func (m *ResponseEndBlock) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseEndBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseEndBlock proto.InternalMessageInfo + +func (m *ResponseEndBlock) GetValidatorUpdates() []v1beta1.ValidatorUpdate { + if m != nil { + return m.ValidatorUpdates + } + return nil +} + +func (m *ResponseEndBlock) GetConsensusParamUpdates() *v1beta2.ConsensusParams { + if m != nil { + return m.ConsensusParamUpdates + } + return nil +} + +func (m *ResponseEndBlock) GetEvents() []Event { + if m != nil { + return m.Events + } + return nil +} + +// ResponsePrepareProposal contains the list of transactions that will be included in the proposal. +type ResponsePrepareProposal struct { + Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` +} + +func (m *ResponsePrepareProposal) Reset() { *m = ResponsePrepareProposal{} } +func (m *ResponsePrepareProposal) String() string { return proto.CompactTextString(m) } +func (*ResponsePrepareProposal) ProtoMessage() {} +func (*ResponsePrepareProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{12} +} +func (m *ResponsePrepareProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponsePrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponsePrepareProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponsePrepareProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponsePrepareProposal.Merge(m, src) +} +func (m *ResponsePrepareProposal) XXX_Size() int { + return m.Size() +} +func (m *ResponsePrepareProposal) XXX_DiscardUnknown() { + xxx_messageInfo_ResponsePrepareProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponsePrepareProposal proto.InternalMessageInfo + +func (m *ResponsePrepareProposal) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +// ResponseProcessProposal contains the result of processing a proposal. +type ResponseProcessProposal struct { + Status ResponseProcessProposal_ProposalStatus `protobuf:"varint,1,opt,name=status,proto3,enum=cometbft.abci.v1beta2.ResponseProcessProposal_ProposalStatus" json:"status,omitempty"` +} + +func (m *ResponseProcessProposal) Reset() { *m = ResponseProcessProposal{} } +func (m *ResponseProcessProposal) String() string { return proto.CompactTextString(m) } +func (*ResponseProcessProposal) ProtoMessage() {} +func (*ResponseProcessProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{13} +} +func (m *ResponseProcessProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseProcessProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseProcessProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseProcessProposal.Merge(m, src) +} +func (m *ResponseProcessProposal) XXX_Size() int { + return m.Size() +} +func (m *ResponseProcessProposal) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseProcessProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseProcessProposal proto.InternalMessageInfo + +func (m *ResponseProcessProposal) GetStatus() ResponseProcessProposal_ProposalStatus { + if m != nil { + return m.Status + } + return ResponseProcessProposal_UNKNOWN +} + +// CommitInfo contains votes for the particular round. +type CommitInfo struct { + Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` + Votes []v1beta1.VoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` +} + +func (m *CommitInfo) Reset() { *m = CommitInfo{} } +func (m *CommitInfo) String() string { return proto.CompactTextString(m) } +func (*CommitInfo) ProtoMessage() {} +func (*CommitInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{14} +} +func (m *CommitInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CommitInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CommitInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommitInfo.Merge(m, src) +} +func (m *CommitInfo) XXX_Size() int { + return m.Size() +} +func (m *CommitInfo) XXX_DiscardUnknown() { + xxx_messageInfo_CommitInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_CommitInfo proto.InternalMessageInfo + +func (m *CommitInfo) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *CommitInfo) GetVotes() []v1beta1.VoteInfo { + if m != nil { + return m.Votes + } + return nil +} + +// ExtendedCommitInfo is similar to CommitInfo except that it is only used in +// the PrepareProposal request such that Tendermint can provide vote extensions +// to the application. +type ExtendedCommitInfo struct { + // The round at which the block proposer decided in the previous height. + Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` + // List of validators' addresses in the last validator set with their voting + // information, including vote extensions. + Votes []ExtendedVoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` +} + +func (m *ExtendedCommitInfo) Reset() { *m = ExtendedCommitInfo{} } +func (m *ExtendedCommitInfo) String() string { return proto.CompactTextString(m) } +func (*ExtendedCommitInfo) ProtoMessage() {} +func (*ExtendedCommitInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{15} +} +func (m *ExtendedCommitInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExtendedCommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExtendedCommitInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExtendedCommitInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendedCommitInfo.Merge(m, src) +} +func (m *ExtendedCommitInfo) XXX_Size() int { + return m.Size() +} +func (m *ExtendedCommitInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendedCommitInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtendedCommitInfo proto.InternalMessageInfo + +func (m *ExtendedCommitInfo) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *ExtendedCommitInfo) GetVotes() []ExtendedVoteInfo { + if m != nil { + return m.Votes + } + return nil +} + +// Event allows application developers to attach additional information to +// ResponseFinalizeBlock (defined in .v1beta3) and ResponseCheckTx. +// Up to 0.37, this could also be used in ResponseBeginBlock, ResponseEndBlock, +// and ResponseDeliverTx. +// Later, transactions may be queried using these events. +type Event struct { + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Attributes []EventAttribute `protobuf:"bytes,2,rep,name=attributes,proto3" json:"attributes,omitempty"` +} + +func (m *Event) Reset() { *m = Event{} } +func (m *Event) String() string { return proto.CompactTextString(m) } +func (*Event) ProtoMessage() {} +func (*Event) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{16} +} +func (m *Event) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Event) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Event.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Event) XXX_Merge(src proto.Message) { + xxx_messageInfo_Event.Merge(m, src) +} +func (m *Event) XXX_Size() int { + return m.Size() +} +func (m *Event) XXX_DiscardUnknown() { + xxx_messageInfo_Event.DiscardUnknown(m) +} + +var xxx_messageInfo_Event proto.InternalMessageInfo + +func (m *Event) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *Event) GetAttributes() []EventAttribute { + if m != nil { + return m.Attributes + } + return nil +} + +// EventAttribute is a single key-value pair, associated with an event. +type EventAttribute struct { + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + Index bool `protobuf:"varint,3,opt,name=index,proto3" json:"index,omitempty"` +} + +func (m *EventAttribute) Reset() { *m = EventAttribute{} } +func (m *EventAttribute) String() string { return proto.CompactTextString(m) } +func (*EventAttribute) ProtoMessage() {} +func (*EventAttribute) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{17} +} +func (m *EventAttribute) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventAttribute) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventAttribute.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventAttribute) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventAttribute.Merge(m, src) +} +func (m *EventAttribute) XXX_Size() int { + return m.Size() +} +func (m *EventAttribute) XXX_DiscardUnknown() { + xxx_messageInfo_EventAttribute.DiscardUnknown(m) +} + +var xxx_messageInfo_EventAttribute proto.InternalMessageInfo + +func (m *EventAttribute) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *EventAttribute) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +func (m *EventAttribute) GetIndex() bool { + if m != nil { + return m.Index + } + return false +} + +// ExtendedVoteInfo extends VoteInfo with the vote extensions (non-deterministic). +type ExtendedVoteInfo struct { + // The validator that sent the vote. + Validator v1beta1.Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` + // Indicates whether the validator signed the last block, allowing for rewards based on validator availability. + SignedLastBlock bool `protobuf:"varint,2,opt,name=signed_last_block,json=signedLastBlock,proto3" json:"signed_last_block,omitempty"` + // Non-deterministic extension provided by the sending validator's application. + VoteExtension []byte `protobuf:"bytes,3,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` +} + +func (m *ExtendedVoteInfo) Reset() { *m = ExtendedVoteInfo{} } +func (m *ExtendedVoteInfo) String() string { return proto.CompactTextString(m) } +func (*ExtendedVoteInfo) ProtoMessage() {} +func (*ExtendedVoteInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{18} +} +func (m *ExtendedVoteInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExtendedVoteInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExtendedVoteInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExtendedVoteInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendedVoteInfo.Merge(m, src) +} +func (m *ExtendedVoteInfo) XXX_Size() int { + return m.Size() +} +func (m *ExtendedVoteInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendedVoteInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtendedVoteInfo proto.InternalMessageInfo + +func (m *ExtendedVoteInfo) GetValidator() v1beta1.Validator { + if m != nil { + return m.Validator + } + return v1beta1.Validator{} +} + +func (m *ExtendedVoteInfo) GetSignedLastBlock() bool { + if m != nil { + return m.SignedLastBlock + } + return false +} + +func (m *ExtendedVoteInfo) GetVoteExtension() []byte { + if m != nil { + return m.VoteExtension + } + return nil +} + +// Misbehavior is a type of misbehavior committed by a validator. +type Misbehavior struct { + Type MisbehaviorType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.abci.v1beta2.MisbehaviorType" json:"type,omitempty"` + // The offending validator + Validator v1beta1.Validator `protobuf:"bytes,2,opt,name=validator,proto3" json:"validator"` + // The height when the offense occurred + Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + // The corresponding time where the offense occurred + Time time.Time `protobuf:"bytes,4,opt,name=time,proto3,stdtime" json:"time"` + // Total voting power of the validator set in case the ABCI application does + // not store historical validators. + // https://github.com/tendermint/tendermint/issues/4581 + TotalVotingPower int64 `protobuf:"varint,5,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` +} + +func (m *Misbehavior) Reset() { *m = Misbehavior{} } +func (m *Misbehavior) String() string { return proto.CompactTextString(m) } +func (*Misbehavior) ProtoMessage() {} +func (*Misbehavior) Descriptor() ([]byte, []int) { + return fileDescriptor_84748304b8d8ccc3, []int{19} +} +func (m *Misbehavior) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Misbehavior) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Misbehavior.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Misbehavior) XXX_Merge(src proto.Message) { + xxx_messageInfo_Misbehavior.Merge(m, src) +} +func (m *Misbehavior) XXX_Size() int { + return m.Size() +} +func (m *Misbehavior) XXX_DiscardUnknown() { + xxx_messageInfo_Misbehavior.DiscardUnknown(m) +} + +var xxx_messageInfo_Misbehavior proto.InternalMessageInfo + +func (m *Misbehavior) GetType() MisbehaviorType { + if m != nil { + return m.Type + } + return MisbehaviorType_UNKNOWN +} + +func (m *Misbehavior) GetValidator() v1beta1.Validator { + if m != nil { + return m.Validator + } + return v1beta1.Validator{} +} + +func (m *Misbehavior) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Misbehavior) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *Misbehavior) GetTotalVotingPower() int64 { + if m != nil { + return m.TotalVotingPower + } + return 0 +} + +func init() { + proto.RegisterEnum("cometbft.abci.v1beta2.MisbehaviorType", MisbehaviorType_name, MisbehaviorType_value) + proto.RegisterEnum("cometbft.abci.v1beta2.ResponseProcessProposal_ProposalStatus", ResponseProcessProposal_ProposalStatus_name, ResponseProcessProposal_ProposalStatus_value) + proto.RegisterType((*Request)(nil), "cometbft.abci.v1beta2.Request") + proto.RegisterType((*RequestInfo)(nil), "cometbft.abci.v1beta2.RequestInfo") + proto.RegisterType((*RequestInitChain)(nil), "cometbft.abci.v1beta2.RequestInitChain") + proto.RegisterType((*RequestBeginBlock)(nil), "cometbft.abci.v1beta2.RequestBeginBlock") + proto.RegisterType((*RequestPrepareProposal)(nil), "cometbft.abci.v1beta2.RequestPrepareProposal") + proto.RegisterType((*RequestProcessProposal)(nil), "cometbft.abci.v1beta2.RequestProcessProposal") + proto.RegisterType((*Response)(nil), "cometbft.abci.v1beta2.Response") + proto.RegisterType((*ResponseInitChain)(nil), "cometbft.abci.v1beta2.ResponseInitChain") + proto.RegisterType((*ResponseBeginBlock)(nil), "cometbft.abci.v1beta2.ResponseBeginBlock") + proto.RegisterType((*ResponseCheckTx)(nil), "cometbft.abci.v1beta2.ResponseCheckTx") + proto.RegisterType((*ResponseDeliverTx)(nil), "cometbft.abci.v1beta2.ResponseDeliverTx") + proto.RegisterType((*ResponseEndBlock)(nil), "cometbft.abci.v1beta2.ResponseEndBlock") + proto.RegisterType((*ResponsePrepareProposal)(nil), "cometbft.abci.v1beta2.ResponsePrepareProposal") + proto.RegisterType((*ResponseProcessProposal)(nil), "cometbft.abci.v1beta2.ResponseProcessProposal") + proto.RegisterType((*CommitInfo)(nil), "cometbft.abci.v1beta2.CommitInfo") + proto.RegisterType((*ExtendedCommitInfo)(nil), "cometbft.abci.v1beta2.ExtendedCommitInfo") + proto.RegisterType((*Event)(nil), "cometbft.abci.v1beta2.Event") + proto.RegisterType((*EventAttribute)(nil), "cometbft.abci.v1beta2.EventAttribute") + proto.RegisterType((*ExtendedVoteInfo)(nil), "cometbft.abci.v1beta2.ExtendedVoteInfo") + proto.RegisterType((*Misbehavior)(nil), "cometbft.abci.v1beta2.Misbehavior") +} + +func init() { proto.RegisterFile("cometbft/abci/v1beta2/types.proto", fileDescriptor_84748304b8d8ccc3) } + +var fileDescriptor_84748304b8d8ccc3 = []byte{ + // 2262 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4f, 0x93, 0x1b, 0x47, + 0x15, 0xd7, 0xdf, 0x95, 0xf4, 0xa4, 0xd5, 0x6a, 0x3b, 0x9b, 0x58, 0x99, 0x72, 0xed, 0xda, 0x32, + 0x4e, 0x9c, 0xc4, 0x68, 0xe3, 0xa5, 0xa0, 0x08, 0x31, 0x50, 0x2b, 0x59, 0x41, 0x6b, 0x2f, 0xeb, + 0xcd, 0x58, 0x6b, 0x48, 0xb6, 0x8a, 0xa9, 0x96, 0xa6, 0x57, 0x1a, 0x2c, 0x4d, 0x4f, 0x66, 0x5a, + 0x8a, 0xc4, 0x89, 0x3b, 0x07, 0x7c, 0x80, 0x2b, 0x27, 0xaa, 0x38, 0xf0, 0x0d, 0xe0, 0x0b, 0xe4, + 0xe8, 0x63, 0x4e, 0x09, 0x65, 0xdf, 0xf8, 0x14, 0x54, 0xf7, 0xf4, 0x8c, 0x66, 0xf4, 0x77, 0x44, + 0x7c, 0xa1, 0xb8, 0x75, 0xbf, 0x79, 0xef, 0x75, 0xf7, 0xeb, 0xee, 0xdf, 0xfb, 0x3d, 0xb5, 0xe0, + 0x66, 0x87, 0x0e, 0x08, 0x6b, 0x5f, 0xb1, 0x43, 0xdc, 0xee, 0x18, 0x87, 0xa3, 0x7b, 0x6d, 0xc2, + 0xf0, 0xd1, 0x21, 0x9b, 0x58, 0xc4, 0xa9, 0x5a, 0x36, 0x65, 0x14, 0xbd, 0xe9, 0xa9, 0x54, 0xb9, + 0x4a, 0x55, 0xaa, 0x28, 0x7b, 0x5d, 0xda, 0xa5, 0x42, 0xe3, 0x90, 0xb7, 0x5c, 0x65, 0x65, 0xa1, + 0xbf, 0x7b, 0x41, 0x7f, 0x4a, 0xc5, 0x57, 0x11, 0xd2, 0x85, 0x3a, 0xb7, 0x16, 0xea, 0x1c, 0x1d, + 0x5a, 0xd8, 0xc6, 0x03, 0x4f, 0xe9, 0xa0, 0x4b, 0x69, 0xb7, 0x4f, 0x0e, 0x45, 0xaf, 0x3d, 0xbc, + 0x3a, 0x64, 0xc6, 0x80, 0x38, 0x0c, 0x0f, 0x2c, 0x57, 0xa1, 0xf2, 0x6d, 0x0e, 0x32, 0x2a, 0xf9, + 0x62, 0x48, 0x1c, 0x86, 0x7e, 0x0c, 0x29, 0xd2, 0xe9, 0xd1, 0x72, 0xfc, 0x46, 0xfc, 0x4e, 0xfe, + 0xa8, 0x52, 0x5d, 0xb4, 0xa8, 0x7b, 0x55, 0xa9, 0xdd, 0xe8, 0xf4, 0x68, 0x33, 0xa6, 0x0a, 0x0b, + 0xf4, 0x31, 0xa4, 0xaf, 0xfa, 0x43, 0xa7, 0x57, 0x4e, 0x08, 0xd3, 0x5b, 0xab, 0x4d, 0x3f, 0xe1, + 0xaa, 0xcd, 0x98, 0xea, 0xda, 0xf0, 0x61, 0x0d, 0xf3, 0x8a, 0x96, 0x93, 0x2b, 0x86, 0x3d, 0xf2, + 0x6c, 0x4f, 0xcc, 0x2b, 0x31, 0x2c, 0xb7, 0x40, 0x4d, 0x00, 0xc3, 0x34, 0x98, 0xd6, 0xe9, 0x61, + 0xc3, 0x2c, 0xa7, 0x85, 0xfd, 0xbb, 0xeb, 0xec, 0x0d, 0x56, 0xe7, 0xea, 0xcd, 0x98, 0x9a, 0x33, + 0xbc, 0x0e, 0x5f, 0xc0, 0x17, 0x43, 0x62, 0x4f, 0xca, 0x5b, 0x51, 0x16, 0xf0, 0x29, 0x57, 0xe5, + 0x0b, 0x10, 0x36, 0xe8, 0x11, 0xe4, 0xdb, 0xa4, 0x6b, 0x98, 0x5a, 0xbb, 0x4f, 0x3b, 0xcf, 0xca, + 0x19, 0xe1, 0xe2, 0xce, 0xea, 0x79, 0xd4, 0xb8, 0x41, 0x8d, 0xeb, 0x37, 0x63, 0x2a, 0xb4, 0xfd, + 0x1e, 0xaa, 0x41, 0xb6, 0xd3, 0x23, 0x9d, 0x67, 0x1a, 0x1b, 0x97, 0xb3, 0xc2, 0xd3, 0xed, 0xd5, + 0x93, 0xa9, 0x73, 0xed, 0xd6, 0xb8, 0x19, 0x53, 0x33, 0x1d, 0xb7, 0xc9, 0xe3, 0xa2, 0x93, 0xbe, + 0x31, 0x22, 0x36, 0xf7, 0x92, 0x5b, 0x11, 0x17, 0xdf, 0xcb, 0x03, 0x57, 0x5f, 0xf8, 0xc9, 0xe9, + 0x5e, 0x07, 0x35, 0x20, 0x47, 0x4c, 0x5d, 0x2e, 0x0c, 0x84, 0xa3, 0x77, 0xd6, 0x9c, 0x0b, 0x53, + 0xf7, 0x96, 0x95, 0x25, 0xb2, 0x8d, 0x7e, 0x06, 0x5b, 0x1d, 0x3a, 0x18, 0x18, 0xac, 0x9c, 0x17, + 0x3e, 0xbe, 0xb7, 0x66, 0x49, 0x42, 0xb7, 0x19, 0x53, 0xa5, 0x15, 0x6a, 0x41, 0xb1, 0x6f, 0x38, + 0x4c, 0x73, 0x4c, 0x6c, 0x39, 0x3d, 0xca, 0x9c, 0x72, 0x41, 0xf8, 0xf9, 0x60, 0xb5, 0x9f, 0x53, + 0xc3, 0x61, 0x4f, 0x3c, 0x93, 0x66, 0x4c, 0xdd, 0xee, 0x07, 0x05, 0xdc, 0x2b, 0xbd, 0xba, 0x22, + 0xb6, 0xef, 0xb6, 0xbc, 0x1d, 0xc5, 0xeb, 0x63, 0x6e, 0xe3, 0x79, 0xe1, 0x5e, 0x69, 0x50, 0x80, + 0x30, 0xbc, 0xd1, 0xa7, 0x58, 0xf7, 0x9d, 0x6a, 0x9d, 0xde, 0xd0, 0x7c, 0x56, 0x2e, 0x0a, 0xd7, + 0x87, 0x6b, 0x26, 0x4c, 0xb1, 0xee, 0x39, 0xaa, 0x73, 0xb3, 0x66, 0x4c, 0xdd, 0xed, 0xcf, 0x0a, + 0x91, 0x0e, 0x7b, 0xd8, 0xb2, 0xfa, 0x93, 0xd9, 0x31, 0x76, 0xc4, 0x18, 0x1f, 0xae, 0x1e, 0xe3, + 0x98, 0x5b, 0xce, 0x0e, 0x82, 0xf0, 0x9c, 0x14, 0x7d, 0x0e, 0x25, 0xcb, 0x26, 0x16, 0xb6, 0x89, + 0x66, 0xd9, 0xd4, 0xa2, 0x0e, 0xee, 0x97, 0x4b, 0x62, 0x84, 0xef, 0xaf, 0x3e, 0xdb, 0xe7, 0xae, + 0xd5, 0xb9, 0x34, 0x6a, 0xc6, 0xd4, 0x1d, 0x2b, 0x2c, 0x72, 0x7d, 0xd3, 0x0e, 0x71, 0x9c, 0xa9, + 0xef, 0xdd, 0x68, 0xbe, 0x85, 0x55, 0xd8, 0x77, 0x48, 0x54, 0xcb, 0x40, 0x7a, 0x84, 0xfb, 0x43, + 0xf2, 0x30, 0x95, 0x4d, 0x95, 0xd2, 0x95, 0xe7, 0x71, 0xc8, 0x07, 0xc0, 0x03, 0x95, 0x21, 0x33, + 0x22, 0xb6, 0x63, 0x50, 0x53, 0x00, 0x5d, 0x4e, 0xf5, 0xba, 0xe8, 0x16, 0x6c, 0x8b, 0x83, 0xae, + 0x79, 0xdf, 0x39, 0x9a, 0xa5, 0xd4, 0x82, 0x10, 0x3e, 0x95, 0x4a, 0x07, 0x90, 0xb7, 0x8e, 0x2c, + 0x5f, 0x25, 0x29, 0x54, 0xc0, 0x3a, 0xb2, 0x3c, 0x85, 0x9b, 0x50, 0xe0, 0x13, 0xf7, 0x35, 0x52, + 0x62, 0x90, 0x3c, 0x97, 0x49, 0x95, 0xca, 0xd7, 0x09, 0x28, 0xcd, 0xe2, 0x11, 0x87, 0x41, 0x0e, + 0xce, 0x12, 0x7d, 0x95, 0xaa, 0x8b, 0xdc, 0x55, 0x0f, 0xb9, 0xab, 0x2d, 0x0f, 0xb9, 0x6b, 0xd9, + 0xaf, 0xbe, 0x39, 0x88, 0x3d, 0xff, 0xf6, 0x20, 0xae, 0x0a, 0x0b, 0xf4, 0x36, 0x87, 0x0c, 0x6c, + 0x98, 0x9a, 0xa1, 0x8b, 0x29, 0xe7, 0x38, 0x12, 0x60, 0xc3, 0x3c, 0xd1, 0x91, 0x0a, 0xa5, 0x0e, + 0x35, 0x1d, 0x62, 0x3a, 0x43, 0x47, 0x73, 0x33, 0x83, 0xc4, 0xd9, 0x00, 0x1e, 0xb8, 0x59, 0xc5, + 0x0b, 0x74, 0xdd, 0xd3, 0x3f, 0x17, 0xea, 0xea, 0x4e, 0x27, 0x2c, 0x40, 0xa7, 0x00, 0x23, 0xdc, + 0x37, 0x74, 0xcc, 0xa8, 0xed, 0x94, 0x53, 0x37, 0x92, 0x2b, 0x40, 0xe1, 0xa9, 0xa7, 0x78, 0x61, + 0xe9, 0x98, 0x91, 0x5a, 0x8a, 0x4f, 0x5d, 0x0d, 0xd8, 0xa3, 0x77, 0x60, 0x07, 0x5b, 0x96, 0xe6, + 0x30, 0xcc, 0x88, 0xd6, 0x9e, 0x30, 0xe2, 0x08, 0x20, 0x2f, 0xa8, 0xdb, 0xd8, 0xb2, 0x9e, 0x70, + 0x69, 0x8d, 0x0b, 0xd1, 0x6d, 0x28, 0x72, 0xb8, 0x36, 0x70, 0x5f, 0xeb, 0x11, 0xa3, 0xdb, 0x63, + 0x02, 0xaa, 0x93, 0xea, 0xb6, 0x94, 0x36, 0x85, 0xb0, 0xf2, 0xe7, 0x04, 0xec, 0xce, 0x41, 0x2c, + 0x42, 0x90, 0xea, 0x61, 0xa7, 0x27, 0x62, 0x5b, 0x50, 0x45, 0x1b, 0xdd, 0x87, 0xad, 0x1e, 0xc1, + 0x3a, 0xb1, 0x65, 0xd2, 0xda, 0x5f, 0x1c, 0x90, 0x7b, 0xd5, 0xa6, 0xd0, 0x92, 0x53, 0x97, 0x36, + 0xe8, 0x53, 0x28, 0xf5, 0xb1, 0xc3, 0x34, 0x17, 0xa0, 0xb4, 0x40, 0x02, 0xbb, 0xb9, 0xe4, 0x00, + 0xbb, 0xa0, 0xc6, 0x8f, 0xa0, 0x74, 0x55, 0xe4, 0x0e, 0xa6, 0x52, 0x74, 0x09, 0x7b, 0xed, 0xc9, + 0xef, 0xb0, 0xc9, 0x0c, 0x93, 0x68, 0x73, 0x11, 0x5e, 0x96, 0x17, 0x7f, 0x69, 0x38, 0x6d, 0xd2, + 0xc3, 0x23, 0x83, 0x7a, 0x53, 0x7c, 0xc3, 0xf7, 0xe2, 0x47, 0xdf, 0xa9, 0xfc, 0x35, 0x09, 0x6f, + 0x2d, 0xbe, 0x9e, 0xe8, 0x06, 0x14, 0x06, 0x78, 0xac, 0xb1, 0xb1, 0x0c, 0x7f, 0x5c, 0xc4, 0x15, + 0x06, 0x78, 0xdc, 0x1a, 0xbb, 0xb1, 0x2f, 0x41, 0x92, 0x8d, 0x9d, 0x72, 0xe2, 0x46, 0xf2, 0x4e, + 0x41, 0xe5, 0x4d, 0x74, 0x09, 0xbb, 0x7d, 0xda, 0xc1, 0x7d, 0x2d, 0x10, 0x04, 0xb9, 0xfe, 0xf7, + 0x96, 0x4c, 0xb4, 0x31, 0x66, 0xc4, 0xd4, 0x89, 0x3e, 0x17, 0x87, 0x1d, 0xe1, 0xe9, 0xd4, 0x0f, + 0x06, 0x7a, 0x08, 0xf9, 0xc1, 0x74, 0x55, 0x1b, 0xaf, 0x3f, 0x68, 0x8c, 0xde, 0xe2, 0xbb, 0x2c, + 0x8e, 0x4b, 0x5a, 0x2c, 0x4b, 0xf6, 0xfc, 0xdb, 0xb6, 0xb5, 0xf1, 0x6d, 0xfb, 0x10, 0xf6, 0x4c, + 0x32, 0x66, 0x81, 0x1d, 0xd2, 0xc4, 0xd9, 0xca, 0x88, 0xb3, 0x85, 0xf8, 0xb7, 0x69, 0xdc, 0x9b, + 0xfc, 0xa4, 0xbd, 0x27, 0xc0, 0xce, 0xa2, 0x0e, 0xb1, 0x35, 0xac, 0xeb, 0x36, 0x71, 0x1c, 0x91, + 0xda, 0x0b, 0x02, 0xbb, 0x84, 0xfc, 0xd8, 0x15, 0x57, 0xfe, 0x14, 0xdc, 0xa6, 0x10, 0xac, 0x79, + 0x9b, 0x10, 0x9f, 0x6e, 0xc2, 0x67, 0xb0, 0x27, 0xed, 0xf5, 0xd0, 0x3e, 0x24, 0x36, 0x3b, 0x87, + 0xc8, 0x73, 0xb2, 0x7c, 0x0b, 0x92, 0xdf, 0x65, 0x0b, 0xbc, 0xcb, 0x97, 0x0a, 0x5c, 0xbe, 0xff, + 0xb1, 0x6d, 0xf9, 0x07, 0x40, 0x56, 0x25, 0x8e, 0xc5, 0x91, 0x10, 0x35, 0x21, 0x47, 0xc6, 0x1d, + 0x62, 0x31, 0x2f, 0x85, 0x2c, 0x23, 0x7b, 0x3c, 0xe5, 0xba, 0x36, 0x0d, 0x4f, 0x9f, 0xb3, 0x2b, + 0xdf, 0x18, 0x7d, 0x24, 0x09, 0xf7, 0x3a, 0xd6, 0x2c, 0x9d, 0x04, 0x19, 0xf7, 0x7d, 0x8f, 0x71, + 0x27, 0xd7, 0x10, 0x2a, 0xd7, 0x76, 0x86, 0x72, 0x7f, 0x24, 0x29, 0x77, 0x2a, 0xd2, 0xc0, 0x21, + 0xce, 0x7d, 0x12, 0xe2, 0xdc, 0x5b, 0x6b, 0xb8, 0xae, 0xe7, 0x60, 0x21, 0xe9, 0xbe, 0xef, 0x91, + 0xee, 0x4c, 0xa4, 0x35, 0xcc, 0xb0, 0xee, 0xd3, 0x30, 0xeb, 0xce, 0xae, 0x04, 0x1f, 0xcf, 0xc7, + 0x52, 0xda, 0x5d, 0x0f, 0xd0, 0xee, 0xdc, 0x0a, 0x9e, 0x3b, 0x75, 0xb5, 0x80, 0x77, 0x9f, 0x84, + 0x78, 0x37, 0x44, 0x8a, 0xcd, 0x12, 0xe2, 0xfd, 0x49, 0x90, 0x78, 0xe7, 0xd7, 0x54, 0x36, 0xf2, + 0x7c, 0x2c, 0x62, 0xde, 0x3f, 0xf7, 0x99, 0x77, 0x61, 0x4d, 0x31, 0x21, 0x57, 0x35, 0x4b, 0xbd, + 0x2f, 0xe6, 0xa8, 0xb7, 0x4b, 0x92, 0xef, 0xae, 0x71, 0xb4, 0x86, 0x7b, 0x5f, 0xcc, 0x71, 0xef, + 0x62, 0x24, 0xb7, 0x6b, 0xc8, 0x77, 0x7b, 0x31, 0xf9, 0x5e, 0x47, 0x8c, 0xe5, 0x94, 0xa3, 0xb1, + 0x6f, 0xb2, 0x84, 0x7d, 0xbb, 0xdc, 0xf8, 0xde, 0x9a, 0x41, 0x22, 0xd3, 0xef, 0xcb, 0x05, 0xf4, + 0xdb, 0xa5, 0xc8, 0xd5, 0x35, 0x07, 0x21, 0x02, 0xff, 0xbe, 0x5c, 0xc0, 0xbf, 0x51, 0x44, 0xe7, + 0x9b, 0x10, 0xf0, 0x74, 0x69, 0xab, 0xf2, 0x22, 0xce, 0x29, 0xd9, 0x0c, 0x12, 0x2c, 0x64, 0xa6, + 0xf1, 0xd7, 0xca, 0x4c, 0x13, 0xdf, 0x91, 0x99, 0xbe, 0x0d, 0x59, 0xce, 0x4c, 0x45, 0x16, 0x49, + 0x8a, 0xbc, 0x90, 0xc1, 0x96, 0xc5, 0x53, 0x47, 0x45, 0x07, 0x34, 0x8f, 0x28, 0xe8, 0x0c, 0xb6, + 0xc8, 0x88, 0x98, 0xcc, 0x4d, 0xd2, 0xf9, 0xa3, 0xeb, 0xcb, 0x98, 0x10, 0x57, 0xaa, 0x95, 0xf9, + 0x80, 0xff, 0xfe, 0xe6, 0xa0, 0xe4, 0xda, 0xdc, 0xa5, 0x03, 0x83, 0x91, 0x81, 0xc5, 0x26, 0xaa, + 0xf4, 0x52, 0x79, 0x99, 0x80, 0x9d, 0x19, 0xb4, 0xe1, 0xc9, 0xb4, 0x43, 0x75, 0xb7, 0x4a, 0xd8, + 0x56, 0x45, 0x9b, 0xcb, 0x74, 0xcc, 0xb0, 0x48, 0x23, 0x05, 0x55, 0xb4, 0x39, 0x5b, 0xe8, 0xd3, + 0xae, 0x98, 0x77, 0x4e, 0xe5, 0x4d, 0xae, 0xe5, 0x63, 0x7e, 0x4e, 0x82, 0xf9, 0x3e, 0x40, 0x17, + 0x3b, 0xda, 0x97, 0xd8, 0x64, 0x44, 0x97, 0xa9, 0x38, 0x20, 0x41, 0x0a, 0x64, 0x79, 0x6f, 0xe8, + 0x10, 0x5d, 0xd2, 0x6d, 0xbf, 0x1f, 0x58, 0x6d, 0xe6, 0x75, 0xac, 0x16, 0x5d, 0x87, 0x1c, 0x5f, + 0x8d, 0x63, 0xe1, 0x0e, 0x11, 0x68, 0x9e, 0x53, 0xa7, 0x02, 0x4e, 0x18, 0x1c, 0x4e, 0x1f, 0x6d, + 0x81, 0xce, 0x39, 0x55, 0xf6, 0xf8, 0x0c, 0x2d, 0xdb, 0xa0, 0xb6, 0xc1, 0x26, 0x02, 0x70, 0x93, + 0xaa, 0xdf, 0xe7, 0xf5, 0xdc, 0x80, 0x0c, 0x2c, 0x4a, 0xfb, 0x1a, 0xb1, 0x6d, 0x6a, 0x0b, 0x1c, + 0xcd, 0xa9, 0x05, 0x29, 0x6c, 0x70, 0x59, 0xe5, 0x0f, 0x89, 0xe9, 0xe9, 0xf4, 0xb1, 0xf8, 0xff, + 0x35, 0xcc, 0x95, 0xbf, 0x88, 0xca, 0x34, 0x9c, 0x4f, 0xd0, 0x67, 0xb0, 0xeb, 0x5f, 0x0b, 0x6d, + 0x28, 0xae, 0x8b, 0x77, 0xc4, 0x37, 0xbb, 0x5d, 0xa5, 0x51, 0x58, 0xec, 0x20, 0x0d, 0xae, 0xcd, + 0xa0, 0x80, 0x3f, 0x40, 0x62, 0x33, 0x30, 0x78, 0x33, 0x0c, 0x06, 0xde, 0x00, 0xd3, 0xf0, 0x25, + 0x5f, 0xcb, 0x9d, 0xfc, 0x00, 0xae, 0x2d, 0x81, 0xd9, 0x79, 0x82, 0x5e, 0xf9, 0x5b, 0x3c, 0xa8, + 0x1d, 0xa6, 0xf3, 0x17, 0xb0, 0xc5, 0x6b, 0xde, 0xa1, 0x8b, 0x7a, 0xc5, 0xa3, 0x9f, 0x6e, 0x86, + 0xbb, 0x55, 0xaf, 0xf1, 0x44, 0x38, 0x51, 0xa5, 0xb3, 0xca, 0x0f, 0xa1, 0x18, 0xfe, 0x82, 0xf2, + 0x90, 0xb9, 0x38, 0x7b, 0x74, 0xf6, 0xf8, 0x57, 0x67, 0xa5, 0x18, 0x02, 0xd8, 0x3a, 0xae, 0xd7, + 0x1b, 0xe7, 0xad, 0x52, 0x9c, 0xb7, 0xd5, 0xc6, 0xc3, 0x46, 0xbd, 0x55, 0x4a, 0x54, 0x34, 0x80, + 0x40, 0x25, 0xba, 0x07, 0x69, 0x9b, 0x0e, 0x4d, 0x5d, 0x4c, 0x2d, 0xad, 0xba, 0x1d, 0xf4, 0x31, + 0xa4, 0x47, 0xd4, 0xdd, 0x19, 0x1e, 0xc9, 0x83, 0x65, 0x5b, 0x4f, 0x19, 0x09, 0x54, 0x17, 0xae, + 0x4d, 0x85, 0x02, 0x9a, 0x2f, 0x00, 0x97, 0x0c, 0x54, 0x0f, 0x0f, 0xf4, 0xee, 0x9a, 0x82, 0x72, + 0xf1, 0x80, 0xbf, 0x8f, 0x43, 0x5a, 0x6c, 0x2a, 0xbf, 0x91, 0xfc, 0xe8, 0xc8, 0x5f, 0x7b, 0x44, + 0x1b, 0x75, 0x00, 0x30, 0x63, 0xb6, 0xd1, 0x1e, 0x4e, 0xc7, 0xb9, 0xbd, 0xea, 0x68, 0x1c, 0x7b, + 0xda, 0xb5, 0xeb, 0xf2, 0x8c, 0xec, 0x4d, 0x1d, 0x04, 0xce, 0x49, 0xc0, 0x6d, 0xe5, 0x0c, 0x8a, + 0x61, 0x5b, 0x7e, 0x44, 0x9e, 0x91, 0x89, 0x9c, 0x09, 0x6f, 0xf2, 0x08, 0x88, 0x5c, 0x29, 0x7f, + 0xb8, 0x71, 0x3b, 0x5c, 0x6a, 0x98, 0x3a, 0x19, 0x0b, 0x60, 0xc9, 0xaa, 0x6e, 0xa7, 0xf2, 0xf7, + 0x38, 0x94, 0x66, 0x17, 0x8d, 0x1e, 0x40, 0xce, 0xbf, 0x55, 0x32, 0x81, 0xde, 0x58, 0x77, 0x29, + 0x65, 0xa4, 0xa6, 0x86, 0xe8, 0x7d, 0xd8, 0x75, 0x8c, 0xae, 0xe9, 0x15, 0x92, 0x2e, 0xed, 0x4c, + 0x88, 0xc1, 0x77, 0xdc, 0x0f, 0xbc, 0x38, 0x74, 0xe1, 0xe0, 0x36, 0x14, 0x79, 0x88, 0x35, 0xc2, + 0xa7, 0xe2, 0xff, 0x08, 0x56, 0x50, 0xb7, 0xb9, 0xb4, 0xe1, 0x09, 0x2b, 0x7f, 0x4c, 0x40, 0x3e, + 0x50, 0x19, 0xa2, 0x9f, 0x04, 0xb6, 0xa1, 0xb8, 0x94, 0x5d, 0x07, 0x2c, 0x5a, 0x13, 0x8b, 0xc8, + 0xed, 0x0a, 0x2d, 0x32, 0xf1, 0xdf, 0x2e, 0x72, 0x5a, 0x74, 0x26, 0x17, 0x16, 0x9d, 0xa9, 0x8d, + 0x8b, 0xce, 0xbb, 0x80, 0x18, 0x65, 0xb8, 0xaf, 0x8d, 0x28, 0x33, 0xcc, 0xae, 0x66, 0xd1, 0x2f, + 0x89, 0x2d, 0x01, 0xbe, 0x24, 0xbe, 0x3c, 0x15, 0x1f, 0xce, 0xb9, 0xfc, 0xfd, 0x47, 0xb0, 0x33, + 0xb3, 0xbc, 0xf0, 0xe5, 0x44, 0x50, 0x7c, 0x70, 0x71, 0x7e, 0x7a, 0x52, 0x3f, 0x6e, 0x35, 0xb4, + 0xa7, 0x8f, 0x5b, 0x8d, 0x52, 0x1c, 0x5d, 0x83, 0x37, 0x4e, 0x4f, 0x7e, 0xd1, 0x6c, 0x69, 0xf5, + 0xd3, 0x93, 0xc6, 0x59, 0x4b, 0x3b, 0x6e, 0xb5, 0x8e, 0xeb, 0x8f, 0x4a, 0x89, 0xa3, 0x7f, 0x16, + 0x60, 0xe7, 0xb8, 0x56, 0x3f, 0xe1, 0x7c, 0xd2, 0xe8, 0x60, 0x51, 0x4f, 0x3e, 0x86, 0x14, 0x2f, + 0x12, 0x51, 0x84, 0xa7, 0x1b, 0x25, 0x4a, 0xb5, 0x89, 0x54, 0x48, 0x8b, 0xca, 0x11, 0x45, 0x79, + 0xd1, 0x51, 0x22, 0x15, 0xa1, 0x7c, 0x92, 0xe2, 0xe0, 0x46, 0x78, 0xe8, 0x51, 0xa2, 0x54, 0xa6, + 0xe8, 0x37, 0x90, 0x9b, 0x26, 0xee, 0xa8, 0xcf, 0x1c, 0x4a, 0xe4, 0xba, 0x0c, 0xfd, 0x1a, 0x32, + 0x1e, 0xfb, 0x8a, 0xf6, 0x14, 0xa3, 0x44, 0x2c, 0x1d, 0x79, 0x78, 0x45, 0x51, 0x8b, 0xa2, 0xbc, + 0x37, 0x29, 0x91, 0xea, 0x63, 0x9e, 0x57, 0xe4, 0x6f, 0x38, 0x91, 0x1e, 0x59, 0x94, 0x68, 0x05, + 0x21, 0x0f, 0xf2, 0x94, 0xbb, 0x47, 0x7d, 0x63, 0x53, 0x22, 0xff, 0x30, 0x80, 0x30, 0x40, 0x80, + 0x49, 0x47, 0x7e, 0x3c, 0x53, 0xa2, 0x17, 0xfc, 0xe8, 0x12, 0xb2, 0x3e, 0xa5, 0x89, 0xf8, 0x88, + 0xa5, 0x44, 0xad, 0xb9, 0xd1, 0x6f, 0x61, 0x3b, 0x54, 0xf1, 0xa2, 0x4d, 0x9e, 0xa6, 0x94, 0x8d, + 0x8a, 0x69, 0x3e, 0x56, 0xa8, 0x0c, 0x46, 0x9b, 0x3c, 0x58, 0x29, 0x1b, 0x55, 0xd8, 0x68, 0x04, + 0xbb, 0x73, 0x65, 0x31, 0xda, 0xf4, 0x15, 0x4b, 0xd9, 0xb8, 0xf2, 0x46, 0x13, 0x40, 0xf3, 0x95, + 0x32, 0xda, 0xf8, 0x69, 0x4b, 0xd9, 0xbc, 0x1c, 0x47, 0x16, 0xec, 0xcc, 0x52, 0xbb, 0xcd, 0x1e, + 0xbc, 0x94, 0x0d, 0x0b, 0x74, 0x77, 0xc4, 0x30, 0x3d, 0xdc, 0xec, 0x19, 0x4c, 0xd9, 0xb0, 0x6a, + 0xaf, 0x9d, 0x7f, 0xf5, 0x72, 0x3f, 0xfe, 0xe2, 0xe5, 0x7e, 0xfc, 0x5f, 0x2f, 0xf7, 0xe3, 0xcf, + 0x5f, 0xed, 0xc7, 0x5e, 0xbc, 0xda, 0x8f, 0x7d, 0xfd, 0x6a, 0x3f, 0xf6, 0xf9, 0x8f, 0xba, 0x06, + 0xeb, 0x0d, 0xdb, 0xdc, 0xdf, 0xa1, 0xff, 0x0f, 0x83, 0xe9, 0x3f, 0x16, 0x2c, 0xe3, 0x70, 0xe1, + 0xdf, 0x21, 0xda, 0x5b, 0x22, 0x5d, 0xfe, 0xe0, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc2, 0x6e, + 0x78, 0x98, 0x2e, 0x21, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// ABCIApplicationClient is the client API for ABCIApplication service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type ABCIApplicationClient interface { + // Echo returns back the same message it is sent. + Echo(ctx context.Context, in *v1beta1.RequestEcho, opts ...grpc.CallOption) (*v1beta1.ResponseEcho, error) + // Flush flushes the write buffer. + Flush(ctx context.Context, in *v1beta1.RequestFlush, opts ...grpc.CallOption) (*v1beta1.ResponseFlush, error) + // Info returns information about the application state. + Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*v1beta1.ResponseInfo, error) + // DeliverTx applies a transaction. + DeliverTx(ctx context.Context, in *v1beta1.RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) + // CheckTx validates a transaction. + CheckTx(ctx context.Context, in *v1beta1.RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) + // Query queries the application state. + Query(ctx context.Context, in *v1beta1.RequestQuery, opts ...grpc.CallOption) (*v1beta1.ResponseQuery, error) + // Commit commits a block of transactions. + Commit(ctx context.Context, in *v1beta1.RequestCommit, opts ...grpc.CallOption) (*v1beta1.ResponseCommit, error) + // InitChain initializes the blockchain. + InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) + // BeginBlock signals the beginning of a block. + BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) + // EndBlock signals the end of a block, returns changes to the validator set. + EndBlock(ctx context.Context, in *v1beta1.RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) + // ListSnapshots lists all the available snapshots. + ListSnapshots(ctx context.Context, in *v1beta1.RequestListSnapshots, opts ...grpc.CallOption) (*v1beta1.ResponseListSnapshots, error) + // OfferSnapshot sends a snapshot offer. + OfferSnapshot(ctx context.Context, in *v1beta1.RequestOfferSnapshot, opts ...grpc.CallOption) (*v1beta1.ResponseOfferSnapshot, error) + // LoadSnapshotChunk returns a chunk of snapshot. + LoadSnapshotChunk(ctx context.Context, in *v1beta1.RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*v1beta1.ResponseLoadSnapshotChunk, error) + // ApplySnapshotChunk applies a chunk of snapshot. + ApplySnapshotChunk(ctx context.Context, in *v1beta1.RequestApplySnapshotChunk, opts ...grpc.CallOption) (*v1beta1.ResponseApplySnapshotChunk, error) + // PrepareProposal returns a proposal for the next block. + PrepareProposal(ctx context.Context, in *RequestPrepareProposal, opts ...grpc.CallOption) (*ResponsePrepareProposal, error) + // ProcessProposal validates a proposal. + ProcessProposal(ctx context.Context, in *RequestProcessProposal, opts ...grpc.CallOption) (*ResponseProcessProposal, error) +} + +type aBCIApplicationClient struct { + cc grpc1.ClientConn +} + +func NewABCIApplicationClient(cc grpc1.ClientConn) ABCIApplicationClient { + return &aBCIApplicationClient{cc} +} + +func (c *aBCIApplicationClient) Echo(ctx context.Context, in *v1beta1.RequestEcho, opts ...grpc.CallOption) (*v1beta1.ResponseEcho, error) { + out := new(v1beta1.ResponseEcho) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/Echo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Flush(ctx context.Context, in *v1beta1.RequestFlush, opts ...grpc.CallOption) (*v1beta1.ResponseFlush, error) { + out := new(v1beta1.ResponseFlush) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/Flush", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*v1beta1.ResponseInfo, error) { + out := new(v1beta1.ResponseInfo) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/Info", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) DeliverTx(ctx context.Context, in *v1beta1.RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { + out := new(ResponseDeliverTx) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/DeliverTx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) CheckTx(ctx context.Context, in *v1beta1.RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { + out := new(ResponseCheckTx) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/CheckTx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Query(ctx context.Context, in *v1beta1.RequestQuery, opts ...grpc.CallOption) (*v1beta1.ResponseQuery, error) { + out := new(v1beta1.ResponseQuery) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/Query", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Commit(ctx context.Context, in *v1beta1.RequestCommit, opts ...grpc.CallOption) (*v1beta1.ResponseCommit, error) { + out := new(v1beta1.ResponseCommit) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/Commit", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { + out := new(ResponseInitChain) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/InitChain", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) { + out := new(ResponseBeginBlock) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/BeginBlock", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) EndBlock(ctx context.Context, in *v1beta1.RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) { + out := new(ResponseEndBlock) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/EndBlock", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) ListSnapshots(ctx context.Context, in *v1beta1.RequestListSnapshots, opts ...grpc.CallOption) (*v1beta1.ResponseListSnapshots, error) { + out := new(v1beta1.ResponseListSnapshots) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/ListSnapshots", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) OfferSnapshot(ctx context.Context, in *v1beta1.RequestOfferSnapshot, opts ...grpc.CallOption) (*v1beta1.ResponseOfferSnapshot, error) { + out := new(v1beta1.ResponseOfferSnapshot) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/OfferSnapshot", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) LoadSnapshotChunk(ctx context.Context, in *v1beta1.RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*v1beta1.ResponseLoadSnapshotChunk, error) { + out := new(v1beta1.ResponseLoadSnapshotChunk) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/LoadSnapshotChunk", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) ApplySnapshotChunk(ctx context.Context, in *v1beta1.RequestApplySnapshotChunk, opts ...grpc.CallOption) (*v1beta1.ResponseApplySnapshotChunk, error) { + out := new(v1beta1.ResponseApplySnapshotChunk) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/ApplySnapshotChunk", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) PrepareProposal(ctx context.Context, in *RequestPrepareProposal, opts ...grpc.CallOption) (*ResponsePrepareProposal, error) { + out := new(ResponsePrepareProposal) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/PrepareProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) ProcessProposal(ctx context.Context, in *RequestProcessProposal, opts ...grpc.CallOption) (*ResponseProcessProposal, error) { + out := new(ResponseProcessProposal) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta2.ABCIApplication/ProcessProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ABCIApplicationServer is the server API for ABCIApplication service. +type ABCIApplicationServer interface { + // Echo returns back the same message it is sent. + Echo(context.Context, *v1beta1.RequestEcho) (*v1beta1.ResponseEcho, error) + // Flush flushes the write buffer. + Flush(context.Context, *v1beta1.RequestFlush) (*v1beta1.ResponseFlush, error) + // Info returns information about the application state. + Info(context.Context, *RequestInfo) (*v1beta1.ResponseInfo, error) + // DeliverTx applies a transaction. + DeliverTx(context.Context, *v1beta1.RequestDeliverTx) (*ResponseDeliverTx, error) + // CheckTx validates a transaction. + CheckTx(context.Context, *v1beta1.RequestCheckTx) (*ResponseCheckTx, error) + // Query queries the application state. + Query(context.Context, *v1beta1.RequestQuery) (*v1beta1.ResponseQuery, error) + // Commit commits a block of transactions. + Commit(context.Context, *v1beta1.RequestCommit) (*v1beta1.ResponseCommit, error) + // InitChain initializes the blockchain. + InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) + // BeginBlock signals the beginning of a block. + BeginBlock(context.Context, *RequestBeginBlock) (*ResponseBeginBlock, error) + // EndBlock signals the end of a block, returns changes to the validator set. + EndBlock(context.Context, *v1beta1.RequestEndBlock) (*ResponseEndBlock, error) + // ListSnapshots lists all the available snapshots. + ListSnapshots(context.Context, *v1beta1.RequestListSnapshots) (*v1beta1.ResponseListSnapshots, error) + // OfferSnapshot sends a snapshot offer. + OfferSnapshot(context.Context, *v1beta1.RequestOfferSnapshot) (*v1beta1.ResponseOfferSnapshot, error) + // LoadSnapshotChunk returns a chunk of snapshot. + LoadSnapshotChunk(context.Context, *v1beta1.RequestLoadSnapshotChunk) (*v1beta1.ResponseLoadSnapshotChunk, error) + // ApplySnapshotChunk applies a chunk of snapshot. + ApplySnapshotChunk(context.Context, *v1beta1.RequestApplySnapshotChunk) (*v1beta1.ResponseApplySnapshotChunk, error) + // PrepareProposal returns a proposal for the next block. + PrepareProposal(context.Context, *RequestPrepareProposal) (*ResponsePrepareProposal, error) + // ProcessProposal validates a proposal. + ProcessProposal(context.Context, *RequestProcessProposal) (*ResponseProcessProposal, error) +} + +// UnimplementedABCIApplicationServer can be embedded to have forward compatible implementations. +type UnimplementedABCIApplicationServer struct { +} + +func (*UnimplementedABCIApplicationServer) Echo(ctx context.Context, req *v1beta1.RequestEcho) (*v1beta1.ResponseEcho, error) { + return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented") +} +func (*UnimplementedABCIApplicationServer) Flush(ctx context.Context, req *v1beta1.RequestFlush) (*v1beta1.ResponseFlush, error) { + return nil, status.Errorf(codes.Unimplemented, "method Flush not implemented") +} +func (*UnimplementedABCIApplicationServer) Info(ctx context.Context, req *RequestInfo) (*v1beta1.ResponseInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method Info not implemented") +} +func (*UnimplementedABCIApplicationServer) DeliverTx(ctx context.Context, req *v1beta1.RequestDeliverTx) (*ResponseDeliverTx, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeliverTx not implemented") +} +func (*UnimplementedABCIApplicationServer) CheckTx(ctx context.Context, req *v1beta1.RequestCheckTx) (*ResponseCheckTx, error) { + return nil, status.Errorf(codes.Unimplemented, "method CheckTx not implemented") +} +func (*UnimplementedABCIApplicationServer) Query(ctx context.Context, req *v1beta1.RequestQuery) (*v1beta1.ResponseQuery, error) { + return nil, status.Errorf(codes.Unimplemented, "method Query not implemented") +} +func (*UnimplementedABCIApplicationServer) Commit(ctx context.Context, req *v1beta1.RequestCommit) (*v1beta1.ResponseCommit, error) { + return nil, status.Errorf(codes.Unimplemented, "method Commit not implemented") +} +func (*UnimplementedABCIApplicationServer) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { + return nil, status.Errorf(codes.Unimplemented, "method InitChain not implemented") +} +func (*UnimplementedABCIApplicationServer) BeginBlock(ctx context.Context, req *RequestBeginBlock) (*ResponseBeginBlock, error) { + return nil, status.Errorf(codes.Unimplemented, "method BeginBlock not implemented") +} +func (*UnimplementedABCIApplicationServer) EndBlock(ctx context.Context, req *v1beta1.RequestEndBlock) (*ResponseEndBlock, error) { + return nil, status.Errorf(codes.Unimplemented, "method EndBlock not implemented") +} +func (*UnimplementedABCIApplicationServer) ListSnapshots(ctx context.Context, req *v1beta1.RequestListSnapshots) (*v1beta1.ResponseListSnapshots, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented") +} +func (*UnimplementedABCIApplicationServer) OfferSnapshot(ctx context.Context, req *v1beta1.RequestOfferSnapshot) (*v1beta1.ResponseOfferSnapshot, error) { + return nil, status.Errorf(codes.Unimplemented, "method OfferSnapshot not implemented") +} +func (*UnimplementedABCIApplicationServer) LoadSnapshotChunk(ctx context.Context, req *v1beta1.RequestLoadSnapshotChunk) (*v1beta1.ResponseLoadSnapshotChunk, error) { + return nil, status.Errorf(codes.Unimplemented, "method LoadSnapshotChunk not implemented") +} +func (*UnimplementedABCIApplicationServer) ApplySnapshotChunk(ctx context.Context, req *v1beta1.RequestApplySnapshotChunk) (*v1beta1.ResponseApplySnapshotChunk, error) { + return nil, status.Errorf(codes.Unimplemented, "method ApplySnapshotChunk not implemented") +} +func (*UnimplementedABCIApplicationServer) PrepareProposal(ctx context.Context, req *RequestPrepareProposal) (*ResponsePrepareProposal, error) { + return nil, status.Errorf(codes.Unimplemented, "method PrepareProposal not implemented") +} +func (*UnimplementedABCIApplicationServer) ProcessProposal(ctx context.Context, req *RequestProcessProposal) (*ResponseProcessProposal, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProcessProposal not implemented") +} + +func RegisterABCIApplicationServer(s grpc1.Server, srv ABCIApplicationServer) { + s.RegisterService(&_ABCIApplication_serviceDesc, srv) +} + +func _ABCIApplication_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestEcho) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Echo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/Echo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Echo(ctx, req.(*v1beta1.RequestEcho)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestFlush) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Flush(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/Flush", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Flush(ctx, req.(*v1beta1.RequestFlush)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Info(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/Info", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Info(ctx, req.(*RequestInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_DeliverTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestDeliverTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).DeliverTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/DeliverTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).DeliverTx(ctx, req.(*v1beta1.RequestDeliverTx)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestCheckTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).CheckTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/CheckTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).CheckTx(ctx, req.(*v1beta1.RequestCheckTx)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestQuery) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/Query", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Query(ctx, req.(*v1beta1.RequestQuery)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestCommit) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Commit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/Commit", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Commit(ctx, req.(*v1beta1.RequestCommit)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInitChain) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).InitChain(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/InitChain", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).InitChain(ctx, req.(*RequestInitChain)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_BeginBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestBeginBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).BeginBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/BeginBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).BeginBlock(ctx, req.(*RequestBeginBlock)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_EndBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestEndBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).EndBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/EndBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).EndBlock(ctx, req.(*v1beta1.RequestEndBlock)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestListSnapshots) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).ListSnapshots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/ListSnapshots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).ListSnapshots(ctx, req.(*v1beta1.RequestListSnapshots)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_OfferSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestOfferSnapshot) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).OfferSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/OfferSnapshot", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).OfferSnapshot(ctx, req.(*v1beta1.RequestOfferSnapshot)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_LoadSnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestLoadSnapshotChunk) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).LoadSnapshotChunk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/LoadSnapshotChunk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).LoadSnapshotChunk(ctx, req.(*v1beta1.RequestLoadSnapshotChunk)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_ApplySnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestApplySnapshotChunk) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).ApplySnapshotChunk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/ApplySnapshotChunk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).ApplySnapshotChunk(ctx, req.(*v1beta1.RequestApplySnapshotChunk)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_PrepareProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestPrepareProposal) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).PrepareProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/PrepareProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).PrepareProposal(ctx, req.(*RequestPrepareProposal)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_ProcessProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestProcessProposal) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).ProcessProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta2.ABCIApplication/ProcessProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).ProcessProposal(ctx, req.(*RequestProcessProposal)) + } + return interceptor(ctx, in, info, handler) +} + +var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.abci.v1beta2.ABCIApplication", + HandlerType: (*ABCIApplicationServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Echo", + Handler: _ABCIApplication_Echo_Handler, + }, + { + MethodName: "Flush", + Handler: _ABCIApplication_Flush_Handler, + }, + { + MethodName: "Info", + Handler: _ABCIApplication_Info_Handler, + }, + { + MethodName: "DeliverTx", + Handler: _ABCIApplication_DeliverTx_Handler, + }, + { + MethodName: "CheckTx", + Handler: _ABCIApplication_CheckTx_Handler, + }, + { + MethodName: "Query", + Handler: _ABCIApplication_Query_Handler, + }, + { + MethodName: "Commit", + Handler: _ABCIApplication_Commit_Handler, + }, + { + MethodName: "InitChain", + Handler: _ABCIApplication_InitChain_Handler, + }, + { + MethodName: "BeginBlock", + Handler: _ABCIApplication_BeginBlock_Handler, + }, + { + MethodName: "EndBlock", + Handler: _ABCIApplication_EndBlock_Handler, + }, + { + MethodName: "ListSnapshots", + Handler: _ABCIApplication_ListSnapshots_Handler, + }, + { + MethodName: "OfferSnapshot", + Handler: _ABCIApplication_OfferSnapshot_Handler, + }, + { + MethodName: "LoadSnapshotChunk", + Handler: _ABCIApplication_LoadSnapshotChunk_Handler, + }, + { + MethodName: "ApplySnapshotChunk", + Handler: _ABCIApplication_ApplySnapshotChunk_Handler, + }, + { + MethodName: "PrepareProposal", + Handler: _ABCIApplication_PrepareProposal_Handler, + }, + { + MethodName: "ProcessProposal", + Handler: _ABCIApplication_ProcessProposal_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/abci/v1beta2/types.proto", +} + +func (m *Request) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Request) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != nil { + { + size := m.Value.Size() + i -= size + if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Request_Echo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Echo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Echo != nil { + { + size, err := m.Echo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Request_Flush) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Flush) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Flush != nil { + { + size, err := m.Flush.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Request_Info) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Info) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Request_InitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_InitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.InitChain != nil { + { + size, err := m.InitChain.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *Request_Query) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Query != nil { + { + size, err := m.Query.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Request_BeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_BeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BeginBlock != nil { + { + size, err := m.BeginBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Request_CheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_CheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.CheckTx != nil { + { + size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *Request_DeliverTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_DeliverTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.DeliverTx != nil { + { + size, err := m.DeliverTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *Request_EndBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_EndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.EndBlock != nil { + { + size, err := m.EndBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + return len(dAtA) - i, nil +} +func (m *Request_Commit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Commit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Commit != nil { + { + size, err := m.Commit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + return len(dAtA) - i, nil +} +func (m *Request_ListSnapshots) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ListSnapshots != nil { + { + size, err := m.ListSnapshots.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } + return len(dAtA) - i, nil +} +func (m *Request_OfferSnapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_OfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.OfferSnapshot != nil { + { + size, err := m.OfferSnapshot.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + return len(dAtA) - i, nil +} +func (m *Request_LoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_LoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LoadSnapshotChunk != nil { + { + size, err := m.LoadSnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + return len(dAtA) - i, nil +} +func (m *Request_ApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ApplySnapshotChunk != nil { + { + size, err := m.ApplySnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } + return len(dAtA) - i, nil +} +func (m *Request_PrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_PrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PrepareProposal != nil { + { + size, err := m.PrepareProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } + return len(dAtA) - i, nil +} +func (m *Request_ProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ProcessProposal != nil { + { + size, err := m.ProcessProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + return len(dAtA) - i, nil +} +func (m *RequestInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AbciVersion) > 0 { + i -= len(m.AbciVersion) + copy(dAtA[i:], m.AbciVersion) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AbciVersion))) + i-- + dAtA[i] = 0x22 + } + if m.P2PVersion != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.P2PVersion)) + i-- + dAtA[i] = 0x18 + } + if m.BlockVersion != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.BlockVersion)) + i-- + dAtA[i] = 0x10 + } + if len(m.Version) > 0 { + i -= len(m.Version) + copy(dAtA[i:], m.Version) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Version))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestInitChain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestInitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.InitialHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.InitialHeight)) + i-- + dAtA[i] = 0x30 + } + if len(m.AppStateBytes) > 0 { + i -= len(m.AppStateBytes) + copy(dAtA[i:], m.AppStateBytes) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppStateBytes))) + i-- + dAtA[i] = 0x2a + } + if len(m.Validators) > 0 { + for iNdEx := len(m.Validators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Validators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if m.ConsensusParams != nil { + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0x12 + } + n18, err18 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err18 != nil { + return 0, err18 + } + i -= n18 + i = encodeVarintTypes(dAtA, i, uint64(n18)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *RequestBeginBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestBeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestBeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ByzantineValidators) > 0 { + for iNdEx := len(m.ByzantineValidators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ByzantineValidators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + { + size, err := m.LastCommitInfo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.Header.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestPrepareProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestPrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestPrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a + } + n21, err21 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err21 != nil { + return 0, err21 + } + i -= n21 + i = encodeVarintTypes(dAtA, i, uint64(n21)) + i-- + dAtA[i] = 0x32 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x28 + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + { + size, err := m.LocalLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.MaxTxBytes != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.MaxTxBytes)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *RequestProcessProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a + } + n23, err23 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err23 != nil { + return 0, err23 + } + i -= n23 + i = encodeVarintTypes(dAtA, i, uint64(n23)) + i-- + dAtA[i] = 0x32 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x28 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0x22 + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.ProposedLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Response) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Response) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != nil { + { + size := m.Value.Size() + i -= size + if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Response_Exception) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Exception) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Exception != nil { + { + size, err := m.Exception.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Response_Echo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Echo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Echo != nil { + { + size, err := m.Echo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Response_Flush) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Flush) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Flush != nil { + { + size, err := m.Flush.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Response_Info) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Info) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Response_InitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_InitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.InitChain != nil { + { + size, err := m.InitChain.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Response_Query) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Query != nil { + { + size, err := m.Query.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Response_BeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_BeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BeginBlock != nil { + { + size, err := m.BeginBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *Response_CheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_CheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.CheckTx != nil { + { + size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *Response_DeliverTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_DeliverTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.DeliverTx != nil { + { + size, err := m.DeliverTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + return len(dAtA) - i, nil +} +func (m *Response_EndBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_EndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.EndBlock != nil { + { + size, err := m.EndBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + return len(dAtA) - i, nil +} +func (m *Response_Commit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Commit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Commit != nil { + { + size, err := m.Commit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } + return len(dAtA) - i, nil +} +func (m *Response_ListSnapshots) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ListSnapshots != nil { + { + size, err := m.ListSnapshots.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + return len(dAtA) - i, nil +} +func (m *Response_OfferSnapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_OfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.OfferSnapshot != nil { + { + size, err := m.OfferSnapshot.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + return len(dAtA) - i, nil +} +func (m *Response_LoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_LoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LoadSnapshotChunk != nil { + { + size, err := m.LoadSnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } + return len(dAtA) - i, nil +} +func (m *Response_ApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ApplySnapshotChunk != nil { + { + size, err := m.ApplySnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } + return len(dAtA) - i, nil +} +func (m *Response_PrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_PrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PrepareProposal != nil { + { + size, err := m.PrepareProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + return len(dAtA) - i, nil +} +func (m *Response_ProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ProcessProposal != nil { + { + size, err := m.ProcessProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x92 + } + return len(dAtA) - i, nil +} +func (m *ResponseInitChain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseInitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x1a + } + if len(m.Validators) > 0 { + for iNdEx := len(m.Validators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Validators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.ConsensusParams != nil { + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ResponseBeginBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseBeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseBeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResponseCheckTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseCheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MempoolError) > 0 { + i -= len(m.MempoolError) + copy(dAtA[i:], m.MempoolError) + i = encodeVarintTypes(dAtA, i, uint64(len(m.MempoolError))) + i-- + dAtA[i] = 0x5a + } + if m.Priority != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Priority)) + i-- + dAtA[i] = 0x50 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0x4a + } + if len(m.Codespace) > 0 { + i -= len(m.Codespace) + copy(dAtA[i:], m.Codespace) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Codespace))) + i-- + dAtA[i] = 0x42 + } + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if m.GasUsed != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + i-- + dAtA[i] = 0x30 + } + if m.GasWanted != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + i-- + dAtA[i] = 0x28 + } + if len(m.Info) > 0 { + i -= len(m.Info) + copy(dAtA[i:], m.Info) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i-- + dAtA[i] = 0x22 + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x1a + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseDeliverTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseDeliverTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseDeliverTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Codespace) > 0 { + i -= len(m.Codespace) + copy(dAtA[i:], m.Codespace) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Codespace))) + i-- + dAtA[i] = 0x42 + } + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if m.GasUsed != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + i-- + dAtA[i] = 0x30 + } + if m.GasWanted != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + i-- + dAtA[i] = 0x28 + } + if len(m.Info) > 0 { + i -= len(m.Info) + copy(dAtA[i:], m.Info) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i-- + dAtA[i] = 0x22 + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x1a + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseEndBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseEndBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseEndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.ConsensusParamUpdates != nil { + { + size, err := m.ConsensusParamUpdates.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.ValidatorUpdates) > 0 { + for iNdEx := len(m.ValidatorUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ValidatorUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResponsePrepareProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponsePrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponsePrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResponseProcessProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Status != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *CommitInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CommitInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ExtendedCommitInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExtendedCommitInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExtendedCommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Event) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Event) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Event) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Attributes) > 0 { + for iNdEx := len(m.Attributes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Attributes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Type) > 0 { + i -= len(m.Type) + copy(dAtA[i:], m.Type) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Type))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventAttribute) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventAttribute) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventAttribute) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Index { + i-- + if m.Index { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0x12 + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ExtendedVoteInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExtendedVoteInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExtendedVoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VoteExtension) > 0 { + i -= len(m.VoteExtension) + copy(dAtA[i:], m.VoteExtension) + i = encodeVarintTypes(dAtA, i, uint64(len(m.VoteExtension))) + i-- + dAtA[i] = 0x1a + } + if m.SignedLastBlock { + i-- + if m.SignedLastBlock { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Misbehavior) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Misbehavior) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Misbehavior) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TotalVotingPower != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.TotalVotingPower)) + i-- + dAtA[i] = 0x28 + } + n45, err45 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err45 != nil { + return 0, err45 + } + i -= n45 + i = encodeVarintTypes(dAtA, i, uint64(n45)) + i-- + dAtA[i] = 0x22 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x18 + } + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.Type != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Request) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != nil { + n += m.Value.Size() + } + return n +} + +func (m *Request_Echo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Echo != nil { + l = m.Echo.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Flush) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Flush != nil { + l = m.Flush.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Info) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_InitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.InitChain != nil { + l = m.InitChain.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Query) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Query != nil { + l = m.Query.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_BeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_CheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_DeliverTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DeliverTx != nil { + l = m.DeliverTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_EndBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Commit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ListSnapshots) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ListSnapshots != nil { + l = m.ListSnapshots.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_OfferSnapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.OfferSnapshot != nil { + l = m.OfferSnapshot.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_LoadSnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LoadSnapshotChunk != nil { + l = m.LoadSnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ApplySnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ApplySnapshotChunk != nil { + l = m.ApplySnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_PrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PrepareProposal != nil { + l = m.PrepareProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProcessProposal != nil { + l = m.ProcessProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *RequestInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Version) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.BlockVersion != 0 { + n += 1 + sovTypes(uint64(m.BlockVersion)) + } + if m.P2PVersion != 0 { + n += 1 + sovTypes(uint64(m.P2PVersion)) + } + l = len(m.AbciVersion) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestInitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.ConsensusParams != nil { + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.AppStateBytes) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.InitialHeight != 0 { + n += 1 + sovTypes(uint64(m.InitialHeight)) + } + return n +} + +func (m *RequestBeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Header.Size() + n += 1 + l + sovTypes(uint64(l)) + l = m.LastCommitInfo.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.ByzantineValidators) > 0 { + for _, e := range m.ByzantineValidators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *RequestPrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxTxBytes != 0 { + n += 1 + sovTypes(uint64(m.MaxTxBytes)) + } + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.LocalLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.ProposedLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Response) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != nil { + n += m.Value.Size() + } + return n +} + +func (m *Response_Exception) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Exception != nil { + l = m.Exception.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Echo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Echo != nil { + l = m.Echo.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Flush) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Flush != nil { + l = m.Flush.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Info) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_InitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.InitChain != nil { + l = m.InitChain.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Query) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Query != nil { + l = m.Query.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_BeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_CheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_DeliverTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DeliverTx != nil { + l = m.DeliverTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_EndBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Commit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ListSnapshots) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ListSnapshots != nil { + l = m.ListSnapshots.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_OfferSnapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.OfferSnapshot != nil { + l = m.OfferSnapshot.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_LoadSnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LoadSnapshotChunk != nil { + l = m.LoadSnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ApplySnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ApplySnapshotChunk != nil { + l = m.ApplySnapshotChunk.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_PrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PrepareProposal != nil { + l = m.PrepareProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProcessProposal != nil { + l = m.ProcessProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *ResponseInitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ConsensusParams != nil { + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseBeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseCheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Codespace) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Priority != 0 { + n += 1 + sovTypes(uint64(m.Priority)) + } + l = len(m.MempoolError) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseDeliverTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Codespace) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseEndBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ValidatorUpdates) > 0 { + for _, e := range m.ValidatorUpdates { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.ConsensusParamUpdates != nil { + l = m.ConsensusParamUpdates.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponsePrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Status != 0 { + n += 1 + sovTypes(uint64(m.Status)) + } + return n +} + +func (m *CommitInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ExtendedCommitInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *Event) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Type) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Attributes) > 0 { + for _, e := range m.Attributes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *EventAttribute) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Index { + n += 2 + } + return n +} + +func (m *ExtendedVoteInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.SignedLastBlock { + n += 2 + } + l = len(m.VoteExtension) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Misbehavior) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovTypes(uint64(m.Type)) + } + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + if m.TotalVotingPower != 0 { + n += 1 + sovTypes(uint64(m.TotalVotingPower)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Request) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Request: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Request: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Echo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestEcho{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Echo{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Flush", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestFlush{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Flush{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Info{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestInitChain{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_InitChain{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestQuery{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Query{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestBeginBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_BeginBlock{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestCheckTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_CheckTx{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestDeliverTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_DeliverTx{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestEndBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_EndBlock{v} + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestCommit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Commit{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListSnapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestListSnapshots{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ListSnapshots{v} + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OfferSnapshot", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestOfferSnapshot{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_OfferSnapshot{v} + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LoadSnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestLoadSnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_LoadSnapshotChunk{v} + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplySnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestApplySnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ApplySnapshotChunk{v} + iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PrepareProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestPrepareProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_PrepareProposal{v} + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProcessProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestProcessProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ProcessProposal{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Version = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockVersion", wireType) + } + m.BlockVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field P2PVersion", wireType) + } + m.P2PVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.P2PVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AbciVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AbciVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestInitChain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestInitChain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParams == nil { + m.ConsensusParams = &v1beta2.ConsensusParams{} + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, v1beta1.ValidatorUpdate{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppStateBytes", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppStateBytes = append(m.AppStateBytes[:0], dAtA[iNdEx:postIndex]...) + if m.AppStateBytes == nil { + m.AppStateBytes = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialHeight", wireType) + } + m.InitialHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestBeginBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestBeginBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastCommitInfo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastCommitInfo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ByzantineValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ByzantineValidators = append(m.ByzantineValidators, Misbehavior{}) + if err := m.ByzantineValidators[len(m.ByzantineValidators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestPrepareProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestPrepareProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxTxBytes", wireType) + } + m.MaxTxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxTxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LocalLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestProcessProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestProcessProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposedLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ProposedLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Response) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Response: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Response: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Exception", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseException{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Exception{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Echo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseEcho{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Echo{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Flush", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseFlush{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Flush{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Info{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseInitChain{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_InitChain{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseQuery{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Query{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseBeginBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_BeginBlock{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseCheckTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_CheckTx{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseDeliverTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_DeliverTx{v} + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseEndBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_EndBlock{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseCommit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Commit{v} + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListSnapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseListSnapshots{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ListSnapshots{v} + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OfferSnapshot", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseOfferSnapshot{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_OfferSnapshot{v} + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LoadSnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseLoadSnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_LoadSnapshotChunk{v} + iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplySnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseApplySnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ApplySnapshotChunk{v} + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PrepareProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponsePrepareProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_PrepareProposal{v} + iNdEx = postIndex + case 18: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProcessProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseProcessProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ProcessProposal{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseInitChain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParams == nil { + m.ConsensusParams = &v1beta2.ConsensusParams{} + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, v1beta1.ValidatorUpdate{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseBeginBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseBeginBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseBeginBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseCheckTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseCheckTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Codespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Codespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType) + } + m.Priority = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Priority |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MempoolError", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MempoolError = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseDeliverTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseDeliverTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseDeliverTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Codespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Codespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseEndBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseEndBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorUpdates = append(m.ValidatorUpdates, v1beta1.ValidatorUpdate{}) + if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParamUpdates == nil { + m.ConsensusParamUpdates = &v1beta2.ConsensusParams{} + } + if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponsePrepareProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponsePrepareProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponsePrepareProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseProcessProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseProcessProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= ResponseProcessProposal_ProposalStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CommitInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CommitInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, v1beta1.VoteInfo{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExtendedCommitInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExtendedCommitInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExtendedCommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, ExtendedVoteInfo{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Event) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Event: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Event: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Attributes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Attributes = append(m.Attributes, EventAttribute{}) + if err := m.Attributes[len(m.Attributes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventAttribute) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventAttribute: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventAttribute: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Index = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExtendedVoteInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExtendedVoteInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExtendedVoteInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedLastBlock", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SignedLastBlock = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtension", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoteExtension = append(m.VoteExtension[:0], dAtA[iNdEx:postIndex]...) + if m.VoteExtension == nil { + m.VoteExtension = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Misbehavior) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Misbehavior: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Misbehavior: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= MisbehaviorType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalVotingPower", wireType) + } + m.TotalVotingPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalVotingPower |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/abci/v1beta3/types.go b/api/cometbft/abci/v1beta3/types.go new file mode 100644 index 00000000000..5a1266845af --- /dev/null +++ b/api/cometbft/abci/v1beta3/types.go @@ -0,0 +1,81 @@ +package v1beta3 + +import ( + "bytes" + + "github.com/cosmos/gogoproto/jsonpb" +) + +const ( + CodeTypeOK uint32 = 0 +) + +// IsOK returns true if Code is OK. +func (r ResponseCheckTx) IsOK() bool { + return r.Code == CodeTypeOK +} + +// IsErr returns true if Code is something other than OK. +func (r ResponseCheckTx) IsErr() bool { + return r.Code != CodeTypeOK +} + +// IsOK returns true if Code is OK. +func (r ExecTxResult) IsOK() bool { + return r.Code == CodeTypeOK +} + +// IsErr returns true if Code is something other than OK. +func (r ExecTxResult) IsErr() bool { + return r.Code != CodeTypeOK +} + +func (r ResponseVerifyVoteExtension) IsAccepted() bool { + return r.Status == ResponseVerifyVoteExtension_ACCEPT +} + +// IsStatusUnknown returns true if Code is Unknown +func (r ResponseVerifyVoteExtension) IsStatusUnknown() bool { + return r.Status == ResponseVerifyVoteExtension_UNKNOWN +} + +// --------------------------------------------------------------------------- +// override JSON marshaling so we emit defaults (ie. disable omitempty) + +var ( + jsonpbMarshaller = jsonpb.Marshaler{ + EnumsAsInts: true, + EmitDefaults: true, + } + jsonpbUnmarshaller = jsonpb.Unmarshaler{} +) + +func (r *ResponseCheckTx) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *ResponseCheckTx) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + +func (r *ResponseCommit) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *ResponseCommit) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} + +func (r *ExecTxResult) MarshalJSON() ([]byte, error) { + s, err := jsonpbMarshaller.MarshalToString(r) + return []byte(s), err +} + +func (r *ExecTxResult) UnmarshalJSON(b []byte) error { + reader := bytes.NewBuffer(b) + return jsonpbUnmarshaller.Unmarshal(reader, r) +} diff --git a/api/cometbft/abci/v1beta3/types.pb.go b/api/cometbft/abci/v1beta3/types.pb.go new file mode 100644 index 00000000000..92fc12e1b6d --- /dev/null +++ b/api/cometbft/abci/v1beta3/types.pb.go @@ -0,0 +1,10327 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/abci/v1beta3/types.proto + +package v1beta3 + +import ( + context "context" + fmt "fmt" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta1" + v1beta2 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta2" + v1 "github.com/cometbft/cometbft/api/cometbft/types/v1" + v1beta11 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Verification status. +type ResponseVerifyVoteExtension_VerifyStatus int32 + +const ( + // Unknown + ResponseVerifyVoteExtension_UNKNOWN ResponseVerifyVoteExtension_VerifyStatus = 0 + // Accepted + ResponseVerifyVoteExtension_ACCEPT ResponseVerifyVoteExtension_VerifyStatus = 1 + // Rejecting the vote extension will reject the entire precommit by the sender. + // Incorrectly implementing this thus has liveness implications as it may affect + // CometBFT's ability to receive 2/3+ valid votes to finalize the block. + // Honest nodes should never be rejected. + ResponseVerifyVoteExtension_REJECT ResponseVerifyVoteExtension_VerifyStatus = 2 +) + +var ResponseVerifyVoteExtension_VerifyStatus_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ACCEPT", + 2: "REJECT", +} + +var ResponseVerifyVoteExtension_VerifyStatus_value = map[string]int32{ + "UNKNOWN": 0, + "ACCEPT": 1, + "REJECT": 2, +} + +func (x ResponseVerifyVoteExtension_VerifyStatus) String() string { + return proto.EnumName(ResponseVerifyVoteExtension_VerifyStatus_name, int32(x)) +} + +func (ResponseVerifyVoteExtension_VerifyStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{12, 0} +} + +// Request represents a request to the ABCI application. +type Request struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Value: + // *Request_Echo + // *Request_Flush + // *Request_Info + // *Request_InitChain + // *Request_Query + // *Request_CheckTx + // *Request_Commit + // *Request_ListSnapshots + // *Request_OfferSnapshot + // *Request_LoadSnapshotChunk + // *Request_ApplySnapshotChunk + // *Request_PrepareProposal + // *Request_ProcessProposal + // *Request_ExtendVote + // *Request_VerifyVoteExtension + // *Request_FinalizeBlock + Value isRequest_Value `protobuf_oneof:"value"` +} + +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} +func (*Request) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{0} +} +func (m *Request) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Request.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Request) XXX_Merge(src proto.Message) { + xxx_messageInfo_Request.Merge(m, src) +} +func (m *Request) XXX_Size() int { + return m.Size() +} +func (m *Request) XXX_DiscardUnknown() { + xxx_messageInfo_Request.DiscardUnknown(m) +} + +var xxx_messageInfo_Request proto.InternalMessageInfo + +type isRequest_Value interface { + isRequest_Value() + MarshalTo([]byte) (int, error) + Size() int +} + +type Request_Echo struct { + Echo *v1beta1.RequestEcho `protobuf:"bytes,1,opt,name=echo,proto3,oneof" json:"echo,omitempty"` +} +type Request_Flush struct { + Flush *v1beta1.RequestFlush `protobuf:"bytes,2,opt,name=flush,proto3,oneof" json:"flush,omitempty"` +} +type Request_Info struct { + Info *v1beta2.RequestInfo `protobuf:"bytes,3,opt,name=info,proto3,oneof" json:"info,omitempty"` +} +type Request_InitChain struct { + InitChain *RequestInitChain `protobuf:"bytes,5,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` +} +type Request_Query struct { + Query *v1beta1.RequestQuery `protobuf:"bytes,6,opt,name=query,proto3,oneof" json:"query,omitempty"` +} +type Request_CheckTx struct { + CheckTx *v1beta1.RequestCheckTx `protobuf:"bytes,8,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` +} +type Request_Commit struct { + Commit *v1beta1.RequestCommit `protobuf:"bytes,11,opt,name=commit,proto3,oneof" json:"commit,omitempty"` +} +type Request_ListSnapshots struct { + ListSnapshots *v1beta1.RequestListSnapshots `protobuf:"bytes,12,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` +} +type Request_OfferSnapshot struct { + OfferSnapshot *v1beta1.RequestOfferSnapshot `protobuf:"bytes,13,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` +} +type Request_LoadSnapshotChunk struct { + LoadSnapshotChunk *v1beta1.RequestLoadSnapshotChunk `protobuf:"bytes,14,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` +} +type Request_ApplySnapshotChunk struct { + ApplySnapshotChunk *v1beta1.RequestApplySnapshotChunk `protobuf:"bytes,15,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` +} +type Request_PrepareProposal struct { + PrepareProposal *RequestPrepareProposal `protobuf:"bytes,16,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` +} +type Request_ProcessProposal struct { + ProcessProposal *RequestProcessProposal `protobuf:"bytes,17,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` +} +type Request_ExtendVote struct { + ExtendVote *RequestExtendVote `protobuf:"bytes,18,opt,name=extend_vote,json=extendVote,proto3,oneof" json:"extend_vote,omitempty"` +} +type Request_VerifyVoteExtension struct { + VerifyVoteExtension *RequestVerifyVoteExtension `protobuf:"bytes,19,opt,name=verify_vote_extension,json=verifyVoteExtension,proto3,oneof" json:"verify_vote_extension,omitempty"` +} +type Request_FinalizeBlock struct { + FinalizeBlock *RequestFinalizeBlock `protobuf:"bytes,20,opt,name=finalize_block,json=finalizeBlock,proto3,oneof" json:"finalize_block,omitempty"` +} + +func (*Request_Echo) isRequest_Value() {} +func (*Request_Flush) isRequest_Value() {} +func (*Request_Info) isRequest_Value() {} +func (*Request_InitChain) isRequest_Value() {} +func (*Request_Query) isRequest_Value() {} +func (*Request_CheckTx) isRequest_Value() {} +func (*Request_Commit) isRequest_Value() {} +func (*Request_ListSnapshots) isRequest_Value() {} +func (*Request_OfferSnapshot) isRequest_Value() {} +func (*Request_LoadSnapshotChunk) isRequest_Value() {} +func (*Request_ApplySnapshotChunk) isRequest_Value() {} +func (*Request_PrepareProposal) isRequest_Value() {} +func (*Request_ProcessProposal) isRequest_Value() {} +func (*Request_ExtendVote) isRequest_Value() {} +func (*Request_VerifyVoteExtension) isRequest_Value() {} +func (*Request_FinalizeBlock) isRequest_Value() {} + +func (m *Request) GetValue() isRequest_Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *Request) GetEcho() *v1beta1.RequestEcho { + if x, ok := m.GetValue().(*Request_Echo); ok { + return x.Echo + } + return nil +} + +func (m *Request) GetFlush() *v1beta1.RequestFlush { + if x, ok := m.GetValue().(*Request_Flush); ok { + return x.Flush + } + return nil +} + +func (m *Request) GetInfo() *v1beta2.RequestInfo { + if x, ok := m.GetValue().(*Request_Info); ok { + return x.Info + } + return nil +} + +func (m *Request) GetInitChain() *RequestInitChain { + if x, ok := m.GetValue().(*Request_InitChain); ok { + return x.InitChain + } + return nil +} + +func (m *Request) GetQuery() *v1beta1.RequestQuery { + if x, ok := m.GetValue().(*Request_Query); ok { + return x.Query + } + return nil +} + +func (m *Request) GetCheckTx() *v1beta1.RequestCheckTx { + if x, ok := m.GetValue().(*Request_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Request) GetCommit() *v1beta1.RequestCommit { + if x, ok := m.GetValue().(*Request_Commit); ok { + return x.Commit + } + return nil +} + +func (m *Request) GetListSnapshots() *v1beta1.RequestListSnapshots { + if x, ok := m.GetValue().(*Request_ListSnapshots); ok { + return x.ListSnapshots + } + return nil +} + +func (m *Request) GetOfferSnapshot() *v1beta1.RequestOfferSnapshot { + if x, ok := m.GetValue().(*Request_OfferSnapshot); ok { + return x.OfferSnapshot + } + return nil +} + +func (m *Request) GetLoadSnapshotChunk() *v1beta1.RequestLoadSnapshotChunk { + if x, ok := m.GetValue().(*Request_LoadSnapshotChunk); ok { + return x.LoadSnapshotChunk + } + return nil +} + +func (m *Request) GetApplySnapshotChunk() *v1beta1.RequestApplySnapshotChunk { + if x, ok := m.GetValue().(*Request_ApplySnapshotChunk); ok { + return x.ApplySnapshotChunk + } + return nil +} + +func (m *Request) GetPrepareProposal() *RequestPrepareProposal { + if x, ok := m.GetValue().(*Request_PrepareProposal); ok { + return x.PrepareProposal + } + return nil +} + +func (m *Request) GetProcessProposal() *RequestProcessProposal { + if x, ok := m.GetValue().(*Request_ProcessProposal); ok { + return x.ProcessProposal + } + return nil +} + +func (m *Request) GetExtendVote() *RequestExtendVote { + if x, ok := m.GetValue().(*Request_ExtendVote); ok { + return x.ExtendVote + } + return nil +} + +func (m *Request) GetVerifyVoteExtension() *RequestVerifyVoteExtension { + if x, ok := m.GetValue().(*Request_VerifyVoteExtension); ok { + return x.VerifyVoteExtension + } + return nil +} + +func (m *Request) GetFinalizeBlock() *RequestFinalizeBlock { + if x, ok := m.GetValue().(*Request_FinalizeBlock); ok { + return x.FinalizeBlock + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Request) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Request_Echo)(nil), + (*Request_Flush)(nil), + (*Request_Info)(nil), + (*Request_InitChain)(nil), + (*Request_Query)(nil), + (*Request_CheckTx)(nil), + (*Request_Commit)(nil), + (*Request_ListSnapshots)(nil), + (*Request_OfferSnapshot)(nil), + (*Request_LoadSnapshotChunk)(nil), + (*Request_ApplySnapshotChunk)(nil), + (*Request_PrepareProposal)(nil), + (*Request_ProcessProposal)(nil), + (*Request_ExtendVote)(nil), + (*Request_VerifyVoteExtension)(nil), + (*Request_FinalizeBlock)(nil), + } +} + +// RequestInitChain is a request to initialize the blockchain. +type RequestInitChain struct { + Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ConsensusParams *v1.ConsensusParams `protobuf:"bytes,3,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []v1beta1.ValidatorUpdate `protobuf:"bytes,4,rep,name=validators,proto3" json:"validators"` + AppStateBytes []byte `protobuf:"bytes,5,opt,name=app_state_bytes,json=appStateBytes,proto3" json:"app_state_bytes,omitempty"` + InitialHeight int64 `protobuf:"varint,6,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` +} + +func (m *RequestInitChain) Reset() { *m = RequestInitChain{} } +func (m *RequestInitChain) String() string { return proto.CompactTextString(m) } +func (*RequestInitChain) ProtoMessage() {} +func (*RequestInitChain) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{1} +} +func (m *RequestInitChain) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestInitChain.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestInitChain) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestInitChain.Merge(m, src) +} +func (m *RequestInitChain) XXX_Size() int { + return m.Size() +} +func (m *RequestInitChain) XXX_DiscardUnknown() { + xxx_messageInfo_RequestInitChain.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestInitChain proto.InternalMessageInfo + +func (m *RequestInitChain) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestInitChain) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *RequestInitChain) GetConsensusParams() *v1.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return nil +} + +func (m *RequestInitChain) GetValidators() []v1beta1.ValidatorUpdate { + if m != nil { + return m.Validators + } + return nil +} + +func (m *RequestInitChain) GetAppStateBytes() []byte { + if m != nil { + return m.AppStateBytes + } + return nil +} + +func (m *RequestInitChain) GetInitialHeight() int64 { + if m != nil { + return m.InitialHeight + } + return 0 +} + +// RequestPrepareProposal is a request for the ABCI application to prepare a new +// block proposal. +type RequestPrepareProposal struct { + // the modified transactions cannot exceed this size. + MaxTxBytes int64 `protobuf:"varint,1,opt,name=max_tx_bytes,json=maxTxBytes,proto3" json:"max_tx_bytes,omitempty"` + // txs is an array of transactions that will be included in a block, + // sent to the app for possible modifications. + Txs [][]byte `protobuf:"bytes,2,rep,name=txs,proto3" json:"txs,omitempty"` + LocalLastCommit ExtendedCommitInfo `protobuf:"bytes,3,opt,name=local_last_commit,json=localLastCommit,proto3" json:"local_last_commit"` + Misbehavior []v1beta2.Misbehavior `protobuf:"bytes,4,rep,name=misbehavior,proto3" json:"misbehavior"` + Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // address of the public key of the validator proposing the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *RequestPrepareProposal) Reset() { *m = RequestPrepareProposal{} } +func (m *RequestPrepareProposal) String() string { return proto.CompactTextString(m) } +func (*RequestPrepareProposal) ProtoMessage() {} +func (*RequestPrepareProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{2} +} +func (m *RequestPrepareProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestPrepareProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestPrepareProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestPrepareProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestPrepareProposal.Merge(m, src) +} +func (m *RequestPrepareProposal) XXX_Size() int { + return m.Size() +} +func (m *RequestPrepareProposal) XXX_DiscardUnknown() { + xxx_messageInfo_RequestPrepareProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestPrepareProposal proto.InternalMessageInfo + +func (m *RequestPrepareProposal) GetMaxTxBytes() int64 { + if m != nil { + return m.MaxTxBytes + } + return 0 +} + +func (m *RequestPrepareProposal) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *RequestPrepareProposal) GetLocalLastCommit() ExtendedCommitInfo { + if m != nil { + return m.LocalLastCommit + } + return ExtendedCommitInfo{} +} + +func (m *RequestPrepareProposal) GetMisbehavior() []v1beta2.Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *RequestPrepareProposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestPrepareProposal) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestPrepareProposal) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *RequestPrepareProposal) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +// RequestProcessProposal is a request for the ABCI application to process proposal. +type RequestProcessProposal struct { + Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` + ProposedLastCommit CommitInfo `protobuf:"bytes,2,opt,name=proposed_last_commit,json=proposedLastCommit,proto3" json:"proposed_last_commit"` + Misbehavior []v1beta2.Misbehavior `protobuf:"bytes,3,rep,name=misbehavior,proto3" json:"misbehavior"` + // hash is the merkle root hash of the fields of the proposed block. + Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` + Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // address of the public key of the original proposer of the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *RequestProcessProposal) Reset() { *m = RequestProcessProposal{} } +func (m *RequestProcessProposal) String() string { return proto.CompactTextString(m) } +func (*RequestProcessProposal) ProtoMessage() {} +func (*RequestProcessProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{3} +} +func (m *RequestProcessProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestProcessProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestProcessProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestProcessProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestProcessProposal.Merge(m, src) +} +func (m *RequestProcessProposal) XXX_Size() int { + return m.Size() +} +func (m *RequestProcessProposal) XXX_DiscardUnknown() { + xxx_messageInfo_RequestProcessProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestProcessProposal proto.InternalMessageInfo + +func (m *RequestProcessProposal) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *RequestProcessProposal) GetProposedLastCommit() CommitInfo { + if m != nil { + return m.ProposedLastCommit + } + return CommitInfo{} +} + +func (m *RequestProcessProposal) GetMisbehavior() []v1beta2.Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *RequestProcessProposal) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *RequestProcessProposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestProcessProposal) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestProcessProposal) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *RequestProcessProposal) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +// Extends a vote with application-injected data +type RequestExtendVote struct { + // the hash of the block that this vote may be referring to + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + // the height of the extended vote + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + // info of the block that this vote may be referring to + Time time.Time `protobuf:"bytes,3,opt,name=time,proto3,stdtime" json:"time"` + Txs [][]byte `protobuf:"bytes,4,rep,name=txs,proto3" json:"txs,omitempty"` + ProposedLastCommit CommitInfo `protobuf:"bytes,5,opt,name=proposed_last_commit,json=proposedLastCommit,proto3" json:"proposed_last_commit"` + Misbehavior []v1beta2.Misbehavior `protobuf:"bytes,6,rep,name=misbehavior,proto3" json:"misbehavior"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // address of the public key of the original proposer of the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *RequestExtendVote) Reset() { *m = RequestExtendVote{} } +func (m *RequestExtendVote) String() string { return proto.CompactTextString(m) } +func (*RequestExtendVote) ProtoMessage() {} +func (*RequestExtendVote) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{4} +} +func (m *RequestExtendVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestExtendVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestExtendVote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestExtendVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestExtendVote.Merge(m, src) +} +func (m *RequestExtendVote) XXX_Size() int { + return m.Size() +} +func (m *RequestExtendVote) XXX_DiscardUnknown() { + xxx_messageInfo_RequestExtendVote.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestExtendVote proto.InternalMessageInfo + +func (m *RequestExtendVote) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *RequestExtendVote) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestExtendVote) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestExtendVote) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *RequestExtendVote) GetProposedLastCommit() CommitInfo { + if m != nil { + return m.ProposedLastCommit + } + return CommitInfo{} +} + +func (m *RequestExtendVote) GetMisbehavior() []v1beta2.Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *RequestExtendVote) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *RequestExtendVote) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +// Verify the vote extension +type RequestVerifyVoteExtension struct { + // the hash of the block that this received vote corresponds to + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + // the validator that signed the vote extension + ValidatorAddress []byte `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` + Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + VoteExtension []byte `protobuf:"bytes,4,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` +} + +func (m *RequestVerifyVoteExtension) Reset() { *m = RequestVerifyVoteExtension{} } +func (m *RequestVerifyVoteExtension) String() string { return proto.CompactTextString(m) } +func (*RequestVerifyVoteExtension) ProtoMessage() {} +func (*RequestVerifyVoteExtension) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{5} +} +func (m *RequestVerifyVoteExtension) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestVerifyVoteExtension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestVerifyVoteExtension.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestVerifyVoteExtension) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestVerifyVoteExtension.Merge(m, src) +} +func (m *RequestVerifyVoteExtension) XXX_Size() int { + return m.Size() +} +func (m *RequestVerifyVoteExtension) XXX_DiscardUnknown() { + xxx_messageInfo_RequestVerifyVoteExtension.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestVerifyVoteExtension proto.InternalMessageInfo + +func (m *RequestVerifyVoteExtension) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *RequestVerifyVoteExtension) GetValidatorAddress() []byte { + if m != nil { + return m.ValidatorAddress + } + return nil +} + +func (m *RequestVerifyVoteExtension) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestVerifyVoteExtension) GetVoteExtension() []byte { + if m != nil { + return m.VoteExtension + } + return nil +} + +// RequestFinalizeBlock is a request to finalize the block. +type RequestFinalizeBlock struct { + Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` + DecidedLastCommit CommitInfo `protobuf:"bytes,2,opt,name=decided_last_commit,json=decidedLastCommit,proto3" json:"decided_last_commit"` + Misbehavior []v1beta2.Misbehavior `protobuf:"bytes,3,rep,name=misbehavior,proto3" json:"misbehavior"` + // hash is the merkle root hash of the fields of the decided block. + Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` + Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"` + NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + // proposer_address is the address of the public key of the original proposer of the block. + ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *RequestFinalizeBlock) Reset() { *m = RequestFinalizeBlock{} } +func (m *RequestFinalizeBlock) String() string { return proto.CompactTextString(m) } +func (*RequestFinalizeBlock) ProtoMessage() {} +func (*RequestFinalizeBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{6} +} +func (m *RequestFinalizeBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RequestFinalizeBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RequestFinalizeBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RequestFinalizeBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_RequestFinalizeBlock.Merge(m, src) +} +func (m *RequestFinalizeBlock) XXX_Size() int { + return m.Size() +} +func (m *RequestFinalizeBlock) XXX_DiscardUnknown() { + xxx_messageInfo_RequestFinalizeBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_RequestFinalizeBlock proto.InternalMessageInfo + +func (m *RequestFinalizeBlock) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +func (m *RequestFinalizeBlock) GetDecidedLastCommit() CommitInfo { + if m != nil { + return m.DecidedLastCommit + } + return CommitInfo{} +} + +func (m *RequestFinalizeBlock) GetMisbehavior() []v1beta2.Misbehavior { + if m != nil { + return m.Misbehavior + } + return nil +} + +func (m *RequestFinalizeBlock) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *RequestFinalizeBlock) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *RequestFinalizeBlock) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *RequestFinalizeBlock) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *RequestFinalizeBlock) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +// Response represents a response from the ABCI application. +type Response struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Value: + // *Response_Exception + // *Response_Echo + // *Response_Flush + // *Response_Info + // *Response_InitChain + // *Response_Query + // *Response_CheckTx + // *Response_Commit + // *Response_ListSnapshots + // *Response_OfferSnapshot + // *Response_LoadSnapshotChunk + // *Response_ApplySnapshotChunk + // *Response_PrepareProposal + // *Response_ProcessProposal + // *Response_ExtendVote + // *Response_VerifyVoteExtension + // *Response_FinalizeBlock + Value isResponse_Value `protobuf_oneof:"value"` +} + +func (m *Response) Reset() { *m = Response{} } +func (m *Response) String() string { return proto.CompactTextString(m) } +func (*Response) ProtoMessage() {} +func (*Response) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{7} +} +func (m *Response) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Response.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Response) XXX_Merge(src proto.Message) { + xxx_messageInfo_Response.Merge(m, src) +} +func (m *Response) XXX_Size() int { + return m.Size() +} +func (m *Response) XXX_DiscardUnknown() { + xxx_messageInfo_Response.DiscardUnknown(m) +} + +var xxx_messageInfo_Response proto.InternalMessageInfo + +type isResponse_Value interface { + isResponse_Value() + MarshalTo([]byte) (int, error) + Size() int +} + +type Response_Exception struct { + Exception *v1beta1.ResponseException `protobuf:"bytes,1,opt,name=exception,proto3,oneof" json:"exception,omitempty"` +} +type Response_Echo struct { + Echo *v1beta1.ResponseEcho `protobuf:"bytes,2,opt,name=echo,proto3,oneof" json:"echo,omitempty"` +} +type Response_Flush struct { + Flush *v1beta1.ResponseFlush `protobuf:"bytes,3,opt,name=flush,proto3,oneof" json:"flush,omitempty"` +} +type Response_Info struct { + Info *v1beta1.ResponseInfo `protobuf:"bytes,4,opt,name=info,proto3,oneof" json:"info,omitempty"` +} +type Response_InitChain struct { + InitChain *ResponseInitChain `protobuf:"bytes,6,opt,name=init_chain,json=initChain,proto3,oneof" json:"init_chain,omitempty"` +} +type Response_Query struct { + Query *v1beta1.ResponseQuery `protobuf:"bytes,7,opt,name=query,proto3,oneof" json:"query,omitempty"` +} +type Response_CheckTx struct { + CheckTx *ResponseCheckTx `protobuf:"bytes,9,opt,name=check_tx,json=checkTx,proto3,oneof" json:"check_tx,omitempty"` +} +type Response_Commit struct { + Commit *ResponseCommit `protobuf:"bytes,12,opt,name=commit,proto3,oneof" json:"commit,omitempty"` +} +type Response_ListSnapshots struct { + ListSnapshots *v1beta1.ResponseListSnapshots `protobuf:"bytes,13,opt,name=list_snapshots,json=listSnapshots,proto3,oneof" json:"list_snapshots,omitempty"` +} +type Response_OfferSnapshot struct { + OfferSnapshot *v1beta1.ResponseOfferSnapshot `protobuf:"bytes,14,opt,name=offer_snapshot,json=offerSnapshot,proto3,oneof" json:"offer_snapshot,omitempty"` +} +type Response_LoadSnapshotChunk struct { + LoadSnapshotChunk *v1beta1.ResponseLoadSnapshotChunk `protobuf:"bytes,15,opt,name=load_snapshot_chunk,json=loadSnapshotChunk,proto3,oneof" json:"load_snapshot_chunk,omitempty"` +} +type Response_ApplySnapshotChunk struct { + ApplySnapshotChunk *v1beta1.ResponseApplySnapshotChunk `protobuf:"bytes,16,opt,name=apply_snapshot_chunk,json=applySnapshotChunk,proto3,oneof" json:"apply_snapshot_chunk,omitempty"` +} +type Response_PrepareProposal struct { + PrepareProposal *v1beta2.ResponsePrepareProposal `protobuf:"bytes,17,opt,name=prepare_proposal,json=prepareProposal,proto3,oneof" json:"prepare_proposal,omitempty"` +} +type Response_ProcessProposal struct { + ProcessProposal *v1beta2.ResponseProcessProposal `protobuf:"bytes,18,opt,name=process_proposal,json=processProposal,proto3,oneof" json:"process_proposal,omitempty"` +} +type Response_ExtendVote struct { + ExtendVote *ResponseExtendVote `protobuf:"bytes,19,opt,name=extend_vote,json=extendVote,proto3,oneof" json:"extend_vote,omitempty"` +} +type Response_VerifyVoteExtension struct { + VerifyVoteExtension *ResponseVerifyVoteExtension `protobuf:"bytes,20,opt,name=verify_vote_extension,json=verifyVoteExtension,proto3,oneof" json:"verify_vote_extension,omitempty"` +} +type Response_FinalizeBlock struct { + FinalizeBlock *ResponseFinalizeBlock `protobuf:"bytes,21,opt,name=finalize_block,json=finalizeBlock,proto3,oneof" json:"finalize_block,omitempty"` +} + +func (*Response_Exception) isResponse_Value() {} +func (*Response_Echo) isResponse_Value() {} +func (*Response_Flush) isResponse_Value() {} +func (*Response_Info) isResponse_Value() {} +func (*Response_InitChain) isResponse_Value() {} +func (*Response_Query) isResponse_Value() {} +func (*Response_CheckTx) isResponse_Value() {} +func (*Response_Commit) isResponse_Value() {} +func (*Response_ListSnapshots) isResponse_Value() {} +func (*Response_OfferSnapshot) isResponse_Value() {} +func (*Response_LoadSnapshotChunk) isResponse_Value() {} +func (*Response_ApplySnapshotChunk) isResponse_Value() {} +func (*Response_PrepareProposal) isResponse_Value() {} +func (*Response_ProcessProposal) isResponse_Value() {} +func (*Response_ExtendVote) isResponse_Value() {} +func (*Response_VerifyVoteExtension) isResponse_Value() {} +func (*Response_FinalizeBlock) isResponse_Value() {} + +func (m *Response) GetValue() isResponse_Value { + if m != nil { + return m.Value + } + return nil +} + +func (m *Response) GetException() *v1beta1.ResponseException { + if x, ok := m.GetValue().(*Response_Exception); ok { + return x.Exception + } + return nil +} + +func (m *Response) GetEcho() *v1beta1.ResponseEcho { + if x, ok := m.GetValue().(*Response_Echo); ok { + return x.Echo + } + return nil +} + +func (m *Response) GetFlush() *v1beta1.ResponseFlush { + if x, ok := m.GetValue().(*Response_Flush); ok { + return x.Flush + } + return nil +} + +func (m *Response) GetInfo() *v1beta1.ResponseInfo { + if x, ok := m.GetValue().(*Response_Info); ok { + return x.Info + } + return nil +} + +func (m *Response) GetInitChain() *ResponseInitChain { + if x, ok := m.GetValue().(*Response_InitChain); ok { + return x.InitChain + } + return nil +} + +func (m *Response) GetQuery() *v1beta1.ResponseQuery { + if x, ok := m.GetValue().(*Response_Query); ok { + return x.Query + } + return nil +} + +func (m *Response) GetCheckTx() *ResponseCheckTx { + if x, ok := m.GetValue().(*Response_CheckTx); ok { + return x.CheckTx + } + return nil +} + +func (m *Response) GetCommit() *ResponseCommit { + if x, ok := m.GetValue().(*Response_Commit); ok { + return x.Commit + } + return nil +} + +func (m *Response) GetListSnapshots() *v1beta1.ResponseListSnapshots { + if x, ok := m.GetValue().(*Response_ListSnapshots); ok { + return x.ListSnapshots + } + return nil +} + +func (m *Response) GetOfferSnapshot() *v1beta1.ResponseOfferSnapshot { + if x, ok := m.GetValue().(*Response_OfferSnapshot); ok { + return x.OfferSnapshot + } + return nil +} + +func (m *Response) GetLoadSnapshotChunk() *v1beta1.ResponseLoadSnapshotChunk { + if x, ok := m.GetValue().(*Response_LoadSnapshotChunk); ok { + return x.LoadSnapshotChunk + } + return nil +} + +func (m *Response) GetApplySnapshotChunk() *v1beta1.ResponseApplySnapshotChunk { + if x, ok := m.GetValue().(*Response_ApplySnapshotChunk); ok { + return x.ApplySnapshotChunk + } + return nil +} + +func (m *Response) GetPrepareProposal() *v1beta2.ResponsePrepareProposal { + if x, ok := m.GetValue().(*Response_PrepareProposal); ok { + return x.PrepareProposal + } + return nil +} + +func (m *Response) GetProcessProposal() *v1beta2.ResponseProcessProposal { + if x, ok := m.GetValue().(*Response_ProcessProposal); ok { + return x.ProcessProposal + } + return nil +} + +func (m *Response) GetExtendVote() *ResponseExtendVote { + if x, ok := m.GetValue().(*Response_ExtendVote); ok { + return x.ExtendVote + } + return nil +} + +func (m *Response) GetVerifyVoteExtension() *ResponseVerifyVoteExtension { + if x, ok := m.GetValue().(*Response_VerifyVoteExtension); ok { + return x.VerifyVoteExtension + } + return nil +} + +func (m *Response) GetFinalizeBlock() *ResponseFinalizeBlock { + if x, ok := m.GetValue().(*Response_FinalizeBlock); ok { + return x.FinalizeBlock + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Response) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Response_Exception)(nil), + (*Response_Echo)(nil), + (*Response_Flush)(nil), + (*Response_Info)(nil), + (*Response_InitChain)(nil), + (*Response_Query)(nil), + (*Response_CheckTx)(nil), + (*Response_Commit)(nil), + (*Response_ListSnapshots)(nil), + (*Response_OfferSnapshot)(nil), + (*Response_LoadSnapshotChunk)(nil), + (*Response_ApplySnapshotChunk)(nil), + (*Response_PrepareProposal)(nil), + (*Response_ProcessProposal)(nil), + (*Response_ExtendVote)(nil), + (*Response_VerifyVoteExtension)(nil), + (*Response_FinalizeBlock)(nil), + } +} + +// ResponseInitChain contains the ABCI application's hash and updates to the +// validator set and/or the consensus params, if any. +type ResponseInitChain struct { + ConsensusParams *v1.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params,omitempty"` + Validators []v1beta1.ValidatorUpdate `protobuf:"bytes,2,rep,name=validators,proto3" json:"validators"` + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *ResponseInitChain) Reset() { *m = ResponseInitChain{} } +func (m *ResponseInitChain) String() string { return proto.CompactTextString(m) } +func (*ResponseInitChain) ProtoMessage() {} +func (*ResponseInitChain) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{8} +} +func (m *ResponseInitChain) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseInitChain) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseInitChain.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseInitChain) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseInitChain.Merge(m, src) +} +func (m *ResponseInitChain) XXX_Size() int { + return m.Size() +} +func (m *ResponseInitChain) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseInitChain.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseInitChain proto.InternalMessageInfo + +func (m *ResponseInitChain) GetConsensusParams() *v1.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return nil +} + +func (m *ResponseInitChain) GetValidators() []v1beta1.ValidatorUpdate { + if m != nil { + return m.Validators + } + return nil +} + +func (m *ResponseInitChain) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +// ResponseCheckTx shows if the transaction was deemed valid by the ABCI +// application. +type ResponseCheckTx struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` + Events []v1beta2.Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` + Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` +} + +func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } +func (m *ResponseCheckTx) String() string { return proto.CompactTextString(m) } +func (*ResponseCheckTx) ProtoMessage() {} +func (*ResponseCheckTx) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{9} +} +func (m *ResponseCheckTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseCheckTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseCheckTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseCheckTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseCheckTx.Merge(m, src) +} +func (m *ResponseCheckTx) XXX_Size() int { + return m.Size() +} +func (m *ResponseCheckTx) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseCheckTx.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseCheckTx proto.InternalMessageInfo + +func (m *ResponseCheckTx) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ResponseCheckTx) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ResponseCheckTx) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ResponseCheckTx) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + +func (m *ResponseCheckTx) GetGasWanted() int64 { + if m != nil { + return m.GasWanted + } + return 0 +} + +func (m *ResponseCheckTx) GetGasUsed() int64 { + if m != nil { + return m.GasUsed + } + return 0 +} + +func (m *ResponseCheckTx) GetEvents() []v1beta2.Event { + if m != nil { + return m.Events + } + return nil +} + +func (m *ResponseCheckTx) GetCodespace() string { + if m != nil { + return m.Codespace + } + return "" +} + +// ResponseCommit indicates how much blocks should CometBFT retain. +type ResponseCommit struct { + RetainHeight int64 `protobuf:"varint,3,opt,name=retain_height,json=retainHeight,proto3" json:"retain_height,omitempty"` +} + +func (m *ResponseCommit) Reset() { *m = ResponseCommit{} } +func (m *ResponseCommit) String() string { return proto.CompactTextString(m) } +func (*ResponseCommit) ProtoMessage() {} +func (*ResponseCommit) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{10} +} +func (m *ResponseCommit) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseCommit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseCommit.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseCommit) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseCommit.Merge(m, src) +} +func (m *ResponseCommit) XXX_Size() int { + return m.Size() +} +func (m *ResponseCommit) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseCommit.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseCommit proto.InternalMessageInfo + +func (m *ResponseCommit) GetRetainHeight() int64 { + if m != nil { + return m.RetainHeight + } + return 0 +} + +// ResponseExtendVote is the result of extending a vote with application-injected data. +type ResponseExtendVote struct { + VoteExtension []byte `protobuf:"bytes,1,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` +} + +func (m *ResponseExtendVote) Reset() { *m = ResponseExtendVote{} } +func (m *ResponseExtendVote) String() string { return proto.CompactTextString(m) } +func (*ResponseExtendVote) ProtoMessage() {} +func (*ResponseExtendVote) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{11} +} +func (m *ResponseExtendVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseExtendVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseExtendVote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseExtendVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseExtendVote.Merge(m, src) +} +func (m *ResponseExtendVote) XXX_Size() int { + return m.Size() +} +func (m *ResponseExtendVote) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseExtendVote.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseExtendVote proto.InternalMessageInfo + +func (m *ResponseExtendVote) GetVoteExtension() []byte { + if m != nil { + return m.VoteExtension + } + return nil +} + +// ResponseVerifyVoteExtension is the result of verifying a vote extension. +type ResponseVerifyVoteExtension struct { + Status ResponseVerifyVoteExtension_VerifyStatus `protobuf:"varint,1,opt,name=status,proto3,enum=cometbft.abci.v1beta3.ResponseVerifyVoteExtension_VerifyStatus" json:"status,omitempty"` +} + +func (m *ResponseVerifyVoteExtension) Reset() { *m = ResponseVerifyVoteExtension{} } +func (m *ResponseVerifyVoteExtension) String() string { return proto.CompactTextString(m) } +func (*ResponseVerifyVoteExtension) ProtoMessage() {} +func (*ResponseVerifyVoteExtension) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{12} +} +func (m *ResponseVerifyVoteExtension) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseVerifyVoteExtension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseVerifyVoteExtension.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseVerifyVoteExtension) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseVerifyVoteExtension.Merge(m, src) +} +func (m *ResponseVerifyVoteExtension) XXX_Size() int { + return m.Size() +} +func (m *ResponseVerifyVoteExtension) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseVerifyVoteExtension.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseVerifyVoteExtension proto.InternalMessageInfo + +func (m *ResponseVerifyVoteExtension) GetStatus() ResponseVerifyVoteExtension_VerifyStatus { + if m != nil { + return m.Status + } + return ResponseVerifyVoteExtension_UNKNOWN +} + +// FinalizeBlockResponse contains the result of executing the block. +type ResponseFinalizeBlock struct { + // set of block events emitted as part of executing the block + Events []v1beta2.Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` + // the result of executing each transaction including the events + // the particular transaction emitted. This should match the order + // of the transactions delivered in the block itself + TxResults []*ExecTxResult `protobuf:"bytes,2,rep,name=tx_results,json=txResults,proto3" json:"tx_results,omitempty"` + // a list of updates to the validator set. These will reflect the validator set at current height + 2. + ValidatorUpdates []v1beta1.ValidatorUpdate `protobuf:"bytes,3,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` + // updates to the consensus params, if any. + ConsensusParamUpdates *v1.ConsensusParams `protobuf:"bytes,4,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` + // app_hash is the hash of the applications' state which is used to confirm + // that execution of the transactions was deterministic. + // It is up to the application to decide which algorithm to use. + AppHash []byte `protobuf:"bytes,5,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *ResponseFinalizeBlock) Reset() { *m = ResponseFinalizeBlock{} } +func (m *ResponseFinalizeBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseFinalizeBlock) ProtoMessage() {} +func (*ResponseFinalizeBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{13} +} +func (m *ResponseFinalizeBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseFinalizeBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseFinalizeBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseFinalizeBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseFinalizeBlock.Merge(m, src) +} +func (m *ResponseFinalizeBlock) XXX_Size() int { + return m.Size() +} +func (m *ResponseFinalizeBlock) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseFinalizeBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseFinalizeBlock proto.InternalMessageInfo + +func (m *ResponseFinalizeBlock) GetEvents() []v1beta2.Event { + if m != nil { + return m.Events + } + return nil +} + +func (m *ResponseFinalizeBlock) GetTxResults() []*ExecTxResult { + if m != nil { + return m.TxResults + } + return nil +} + +func (m *ResponseFinalizeBlock) GetValidatorUpdates() []v1beta1.ValidatorUpdate { + if m != nil { + return m.ValidatorUpdates + } + return nil +} + +func (m *ResponseFinalizeBlock) GetConsensusParamUpdates() *v1.ConsensusParams { + if m != nil { + return m.ConsensusParamUpdates + } + return nil +} + +func (m *ResponseFinalizeBlock) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +// VoteInfo contains the information about the vote. +type VoteInfo struct { + Validator v1beta1.Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` + BlockIdFlag v1beta11.BlockIDFlag `protobuf:"varint,3,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=cometbft.types.v1beta1.BlockIDFlag" json:"block_id_flag,omitempty"` +} + +func (m *VoteInfo) Reset() { *m = VoteInfo{} } +func (m *VoteInfo) String() string { return proto.CompactTextString(m) } +func (*VoteInfo) ProtoMessage() {} +func (*VoteInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{14} +} +func (m *VoteInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VoteInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VoteInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *VoteInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_VoteInfo.Merge(m, src) +} +func (m *VoteInfo) XXX_Size() int { + return m.Size() +} +func (m *VoteInfo) XXX_DiscardUnknown() { + xxx_messageInfo_VoteInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_VoteInfo proto.InternalMessageInfo + +func (m *VoteInfo) GetValidator() v1beta1.Validator { + if m != nil { + return m.Validator + } + return v1beta1.Validator{} +} + +func (m *VoteInfo) GetBlockIdFlag() v1beta11.BlockIDFlag { + if m != nil { + return m.BlockIdFlag + } + return v1beta11.BlockIDFlagUnknown +} + +// ExtendedVoteInfo extends VoteInfo with the vote extensions (non-deterministic). +type ExtendedVoteInfo struct { + // The validator that sent the vote. + Validator v1beta1.Validator `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator"` + // Non-deterministic extension provided by the sending validator's application. + VoteExtension []byte `protobuf:"bytes,3,opt,name=vote_extension,json=voteExtension,proto3" json:"vote_extension,omitempty"` + // Vote extension signature created by CometBFT + ExtensionSignature []byte `protobuf:"bytes,4,opt,name=extension_signature,json=extensionSignature,proto3" json:"extension_signature,omitempty"` + // block_id_flag indicates whether the validator voted for a block, nil, or did not vote at all + BlockIdFlag v1beta11.BlockIDFlag `protobuf:"varint,5,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=cometbft.types.v1beta1.BlockIDFlag" json:"block_id_flag,omitempty"` +} + +func (m *ExtendedVoteInfo) Reset() { *m = ExtendedVoteInfo{} } +func (m *ExtendedVoteInfo) String() string { return proto.CompactTextString(m) } +func (*ExtendedVoteInfo) ProtoMessage() {} +func (*ExtendedVoteInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{15} +} +func (m *ExtendedVoteInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExtendedVoteInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExtendedVoteInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExtendedVoteInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendedVoteInfo.Merge(m, src) +} +func (m *ExtendedVoteInfo) XXX_Size() int { + return m.Size() +} +func (m *ExtendedVoteInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendedVoteInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtendedVoteInfo proto.InternalMessageInfo + +func (m *ExtendedVoteInfo) GetValidator() v1beta1.Validator { + if m != nil { + return m.Validator + } + return v1beta1.Validator{} +} + +func (m *ExtendedVoteInfo) GetVoteExtension() []byte { + if m != nil { + return m.VoteExtension + } + return nil +} + +func (m *ExtendedVoteInfo) GetExtensionSignature() []byte { + if m != nil { + return m.ExtensionSignature + } + return nil +} + +func (m *ExtendedVoteInfo) GetBlockIdFlag() v1beta11.BlockIDFlag { + if m != nil { + return m.BlockIdFlag + } + return v1beta11.BlockIDFlagUnknown +} + +// CommitInfo contains votes for the particular round. +type CommitInfo struct { + Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` + Votes []VoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` +} + +func (m *CommitInfo) Reset() { *m = CommitInfo{} } +func (m *CommitInfo) String() string { return proto.CompactTextString(m) } +func (*CommitInfo) ProtoMessage() {} +func (*CommitInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{16} +} +func (m *CommitInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CommitInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CommitInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommitInfo.Merge(m, src) +} +func (m *CommitInfo) XXX_Size() int { + return m.Size() +} +func (m *CommitInfo) XXX_DiscardUnknown() { + xxx_messageInfo_CommitInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_CommitInfo proto.InternalMessageInfo + +func (m *CommitInfo) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *CommitInfo) GetVotes() []VoteInfo { + if m != nil { + return m.Votes + } + return nil +} + +// ExtendedCommitInfo is similar to CommitInfo except that it is only used in +// the PrepareProposal request such that Tendermint can provide vote extensions +// to the application. +type ExtendedCommitInfo struct { + // The round at which the block proposer decided in the previous height. + Round int32 `protobuf:"varint,1,opt,name=round,proto3" json:"round,omitempty"` + // List of validators' addresses in the last validator set with their voting + // information, including vote extensions. + Votes []ExtendedVoteInfo `protobuf:"bytes,2,rep,name=votes,proto3" json:"votes"` +} + +func (m *ExtendedCommitInfo) Reset() { *m = ExtendedCommitInfo{} } +func (m *ExtendedCommitInfo) String() string { return proto.CompactTextString(m) } +func (*ExtendedCommitInfo) ProtoMessage() {} +func (*ExtendedCommitInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{17} +} +func (m *ExtendedCommitInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExtendedCommitInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExtendedCommitInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExtendedCommitInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExtendedCommitInfo.Merge(m, src) +} +func (m *ExtendedCommitInfo) XXX_Size() int { + return m.Size() +} +func (m *ExtendedCommitInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ExtendedCommitInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ExtendedCommitInfo proto.InternalMessageInfo + +func (m *ExtendedCommitInfo) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *ExtendedCommitInfo) GetVotes() []ExtendedVoteInfo { + if m != nil { + return m.Votes + } + return nil +} + +// ExecTxResult contains results of executing one individual transaction. +// +// * Its structure is equivalent to #ResponseDeliverTx which will be deprecated/deleted +type ExecTxResult struct { + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` + Events []v1beta2.Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` + Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` +} + +func (m *ExecTxResult) Reset() { *m = ExecTxResult{} } +func (m *ExecTxResult) String() string { return proto.CompactTextString(m) } +func (*ExecTxResult) ProtoMessage() {} +func (*ExecTxResult) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{18} +} +func (m *ExecTxResult) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExecTxResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExecTxResult.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExecTxResult) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExecTxResult.Merge(m, src) +} +func (m *ExecTxResult) XXX_Size() int { + return m.Size() +} +func (m *ExecTxResult) XXX_DiscardUnknown() { + xxx_messageInfo_ExecTxResult.DiscardUnknown(m) +} + +var xxx_messageInfo_ExecTxResult proto.InternalMessageInfo + +func (m *ExecTxResult) GetCode() uint32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *ExecTxResult) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ExecTxResult) GetLog() string { + if m != nil { + return m.Log + } + return "" +} + +func (m *ExecTxResult) GetInfo() string { + if m != nil { + return m.Info + } + return "" +} + +func (m *ExecTxResult) GetGasWanted() int64 { + if m != nil { + return m.GasWanted + } + return 0 +} + +func (m *ExecTxResult) GetGasUsed() int64 { + if m != nil { + return m.GasUsed + } + return 0 +} + +func (m *ExecTxResult) GetEvents() []v1beta2.Event { + if m != nil { + return m.Events + } + return nil +} + +func (m *ExecTxResult) GetCodespace() string { + if m != nil { + return m.Codespace + } + return "" +} + +// TxResult contains results of executing the transaction. +// +// One usage is indexing transaction results. +type TxResult struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Index uint32 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` + Tx []byte `protobuf:"bytes,3,opt,name=tx,proto3" json:"tx,omitempty"` + Result ExecTxResult `protobuf:"bytes,4,opt,name=result,proto3" json:"result"` +} + +func (m *TxResult) Reset() { *m = TxResult{} } +func (m *TxResult) String() string { return proto.CompactTextString(m) } +func (*TxResult) ProtoMessage() {} +func (*TxResult) Descriptor() ([]byte, []int) { + return fileDescriptor_1cabe0dccee1dedf, []int{19} +} +func (m *TxResult) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TxResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TxResult.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TxResult) XXX_Merge(src proto.Message) { + xxx_messageInfo_TxResult.Merge(m, src) +} +func (m *TxResult) XXX_Size() int { + return m.Size() +} +func (m *TxResult) XXX_DiscardUnknown() { + xxx_messageInfo_TxResult.DiscardUnknown(m) +} + +var xxx_messageInfo_TxResult proto.InternalMessageInfo + +func (m *TxResult) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *TxResult) GetIndex() uint32 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *TxResult) GetTx() []byte { + if m != nil { + return m.Tx + } + return nil +} + +func (m *TxResult) GetResult() ExecTxResult { + if m != nil { + return m.Result + } + return ExecTxResult{} +} + +func init() { + proto.RegisterEnum("cometbft.abci.v1beta3.ResponseVerifyVoteExtension_VerifyStatus", ResponseVerifyVoteExtension_VerifyStatus_name, ResponseVerifyVoteExtension_VerifyStatus_value) + proto.RegisterType((*Request)(nil), "cometbft.abci.v1beta3.Request") + proto.RegisterType((*RequestInitChain)(nil), "cometbft.abci.v1beta3.RequestInitChain") + proto.RegisterType((*RequestPrepareProposal)(nil), "cometbft.abci.v1beta3.RequestPrepareProposal") + proto.RegisterType((*RequestProcessProposal)(nil), "cometbft.abci.v1beta3.RequestProcessProposal") + proto.RegisterType((*RequestExtendVote)(nil), "cometbft.abci.v1beta3.RequestExtendVote") + proto.RegisterType((*RequestVerifyVoteExtension)(nil), "cometbft.abci.v1beta3.RequestVerifyVoteExtension") + proto.RegisterType((*RequestFinalizeBlock)(nil), "cometbft.abci.v1beta3.RequestFinalizeBlock") + proto.RegisterType((*Response)(nil), "cometbft.abci.v1beta3.Response") + proto.RegisterType((*ResponseInitChain)(nil), "cometbft.abci.v1beta3.ResponseInitChain") + proto.RegisterType((*ResponseCheckTx)(nil), "cometbft.abci.v1beta3.ResponseCheckTx") + proto.RegisterType((*ResponseCommit)(nil), "cometbft.abci.v1beta3.ResponseCommit") + proto.RegisterType((*ResponseExtendVote)(nil), "cometbft.abci.v1beta3.ResponseExtendVote") + proto.RegisterType((*ResponseVerifyVoteExtension)(nil), "cometbft.abci.v1beta3.ResponseVerifyVoteExtension") + proto.RegisterType((*ResponseFinalizeBlock)(nil), "cometbft.abci.v1beta3.ResponseFinalizeBlock") + proto.RegisterType((*VoteInfo)(nil), "cometbft.abci.v1beta3.VoteInfo") + proto.RegisterType((*ExtendedVoteInfo)(nil), "cometbft.abci.v1beta3.ExtendedVoteInfo") + proto.RegisterType((*CommitInfo)(nil), "cometbft.abci.v1beta3.CommitInfo") + proto.RegisterType((*ExtendedCommitInfo)(nil), "cometbft.abci.v1beta3.ExtendedCommitInfo") + proto.RegisterType((*ExecTxResult)(nil), "cometbft.abci.v1beta3.ExecTxResult") + proto.RegisterType((*TxResult)(nil), "cometbft.abci.v1beta3.TxResult") +} + +func init() { proto.RegisterFile("cometbft/abci/v1beta3/types.proto", fileDescriptor_1cabe0dccee1dedf) } + +var fileDescriptor_1cabe0dccee1dedf = []byte{ + // 2233 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x9a, 0x4f, 0x8f, 0xdb, 0xc6, + 0x15, 0xc0, 0x45, 0xfd, 0x5b, 0xe9, 0xad, 0xb4, 0xcb, 0x9d, 0x5d, 0xa7, 0x8a, 0x1a, 0xac, 0x1d, + 0xb9, 0x76, 0x1c, 0x24, 0x95, 0xb2, 0x6b, 0xa0, 0x68, 0xe0, 0xa0, 0xc1, 0xee, 0x66, 0x5d, 0xed, + 0xc6, 0xb1, 0x5d, 0x7a, 0xd7, 0x6e, 0x6d, 0xa0, 0xc4, 0x88, 0x1c, 0x49, 0xac, 0x29, 0x91, 0x21, + 0x47, 0xaa, 0xb6, 0xe8, 0xb9, 0x97, 0x1e, 0xea, 0x43, 0x8f, 0x05, 0x72, 0xe9, 0xad, 0x97, 0x7e, + 0x8c, 0x00, 0xbd, 0x04, 0xe8, 0xa5, 0x97, 0xa6, 0x85, 0x7d, 0xeb, 0x47, 0x28, 0x50, 0xb4, 0x98, + 0xe1, 0x90, 0x22, 0x25, 0x4a, 0x22, 0xbb, 0xee, 0xa1, 0x68, 0x6f, 0xe4, 0xe3, 0xfb, 0x33, 0x33, + 0x6f, 0xe6, 0xcd, 0xfc, 0x34, 0x82, 0xb7, 0x35, 0x6b, 0x40, 0x68, 0xa7, 0x4b, 0x5b, 0xb8, 0xa3, + 0x19, 0xad, 0xf1, 0x5e, 0x87, 0x50, 0x7c, 0xbb, 0x45, 0x2f, 0x6c, 0xe2, 0x36, 0x6d, 0xc7, 0xa2, + 0x16, 0xba, 0xe2, 0xab, 0x34, 0x99, 0x4a, 0x53, 0xa8, 0xd4, 0x63, 0x2d, 0xf7, 0xc2, 0x96, 0xf1, + 0x2a, 0xfb, 0x11, 0x95, 0xdd, 0x40, 0x85, 0x4b, 0x5b, 0xe3, 0xbd, 0x96, 0x8d, 0x1d, 0x3c, 0xf0, + 0xbf, 0xdf, 0x9c, 0xfb, 0xee, 0x85, 0x19, 0x63, 0xd3, 0xd0, 0x31, 0xb5, 0x1c, 0xa1, 0xb7, 0xd3, + 0xb3, 0x7a, 0x16, 0x7f, 0x6c, 0xb1, 0x27, 0x21, 0xbd, 0xda, 0xb3, 0xac, 0x9e, 0x49, 0x5a, 0xfc, + 0xad, 0x33, 0xea, 0xb6, 0xa8, 0x31, 0x20, 0x2e, 0xc5, 0x03, 0xdb, 0x53, 0x68, 0x7c, 0x01, 0xb0, + 0xa6, 0x90, 0xcf, 0x47, 0xc4, 0xa5, 0xe8, 0xbb, 0x90, 0x27, 0x5a, 0xdf, 0xaa, 0x49, 0xd7, 0xa4, + 0x5b, 0xeb, 0xfb, 0x8d, 0x66, 0x5c, 0xb7, 0xf7, 0x9a, 0x42, 0xfb, 0x58, 0xeb, 0x5b, 0xed, 0x8c, + 0xc2, 0x2d, 0xd0, 0x1d, 0x28, 0x74, 0xcd, 0x91, 0xdb, 0xaf, 0x65, 0xb9, 0xe9, 0xf5, 0xe5, 0xa6, + 0x77, 0x99, 0x6a, 0x3b, 0xa3, 0x78, 0x36, 0x2c, 0xac, 0x31, 0xec, 0x5a, 0xb5, 0xdc, 0x92, 0xb0, + 0xfb, 0xbe, 0xed, 0xc9, 0xb0, 0xcb, 0xc3, 0x32, 0x0b, 0xd4, 0x06, 0x30, 0x86, 0x06, 0x55, 0xb5, + 0x3e, 0x36, 0x86, 0xb5, 0x02, 0xb7, 0x7f, 0x27, 0xd6, 0xfe, 0xf6, 0xd4, 0xde, 0xa0, 0x47, 0x4c, + 0xbd, 0x9d, 0x51, 0xca, 0x86, 0xff, 0xc2, 0x3a, 0xf0, 0xf9, 0x88, 0x38, 0x17, 0xb5, 0x62, 0x92, + 0x0e, 0xfc, 0x80, 0xa9, 0xb2, 0x0e, 0x70, 0x1b, 0x74, 0x08, 0x25, 0xad, 0x4f, 0xb4, 0xe7, 0x2a, + 0x9d, 0xd4, 0x4a, 0xdc, 0xfe, 0xc6, 0x72, 0xfb, 0x23, 0xa6, 0x7d, 0x36, 0x69, 0x67, 0x94, 0x35, + 0xcd, 0x7b, 0x44, 0xdf, 0x83, 0xa2, 0x66, 0x0d, 0x06, 0x06, 0xad, 0xad, 0x73, 0x0f, 0xdf, 0x5a, + 0xe1, 0x81, 0xeb, 0xb6, 0x33, 0x8a, 0xb0, 0x42, 0x67, 0xb0, 0x61, 0x1a, 0x2e, 0x55, 0xdd, 0x21, + 0xb6, 0xdd, 0xbe, 0x45, 0xdd, 0x5a, 0x85, 0xfb, 0x79, 0x6f, 0xb9, 0x9f, 0x7b, 0x86, 0x4b, 0x1f, + 0xf9, 0x26, 0xed, 0x8c, 0x52, 0x35, 0xc3, 0x02, 0xe6, 0xd5, 0xea, 0x76, 0x89, 0x13, 0xb8, 0xad, + 0x55, 0x93, 0x78, 0x7d, 0xc0, 0x6c, 0x7c, 0x2f, 0xcc, 0xab, 0x15, 0x16, 0x20, 0x0c, 0xdb, 0xa6, + 0x85, 0xf5, 0xc0, 0xa9, 0xaa, 0xf5, 0x47, 0xc3, 0xe7, 0xb5, 0x0d, 0xee, 0xba, 0xb5, 0xa2, 0xc1, + 0x16, 0xd6, 0x7d, 0x47, 0x47, 0xcc, 0xac, 0x9d, 0x51, 0xb6, 0xcc, 0x59, 0x21, 0xd2, 0x61, 0x07, + 0xdb, 0xb6, 0x79, 0x31, 0x1b, 0x63, 0x93, 0xc7, 0xf8, 0x60, 0x79, 0x8c, 0x03, 0x66, 0x39, 0x1b, + 0x04, 0xe1, 0x39, 0x29, 0x7a, 0x0a, 0xb2, 0xed, 0x10, 0x1b, 0x3b, 0x44, 0xb5, 0x1d, 0xcb, 0xb6, + 0x5c, 0x6c, 0xd6, 0x64, 0x1e, 0xe1, 0xdb, 0xcb, 0x67, 0xe1, 0x43, 0xcf, 0xea, 0xa1, 0x30, 0x6a, + 0x67, 0x94, 0x4d, 0x3b, 0x2a, 0xf2, 0x7c, 0x5b, 0x1a, 0x71, 0xdd, 0xa9, 0xef, 0xad, 0x64, 0xbe, + 0xb9, 0x55, 0xd4, 0x77, 0x44, 0x84, 0x3e, 0x85, 0x75, 0x32, 0xa1, 0x64, 0xa8, 0xab, 0x63, 0x8b, + 0x92, 0x1a, 0xe2, 0x6e, 0x6f, 0x2d, 0x77, 0x7b, 0xcc, 0x0d, 0x1e, 0x5b, 0x94, 0xb4, 0x33, 0x0a, + 0x90, 0xe0, 0x0d, 0xf5, 0xe0, 0xca, 0x98, 0x38, 0x46, 0xf7, 0x82, 0x3b, 0x53, 0xf9, 0x17, 0xd7, + 0xb0, 0x86, 0xb5, 0x6d, 0xee, 0x76, 0x6f, 0xb9, 0xdb, 0xc7, 0xdc, 0x94, 0x39, 0x3a, 0xf6, 0x0d, + 0xdb, 0x19, 0x65, 0x7b, 0x3c, 0x2f, 0x66, 0x93, 0xb1, 0x6b, 0x0c, 0xb1, 0x69, 0xfc, 0x8c, 0xa8, + 0x1d, 0xd3, 0xd2, 0x9e, 0xd7, 0x76, 0x96, 0x4c, 0xc6, 0x20, 0xc2, 0x5d, 0x61, 0x73, 0xc8, 0x4c, + 0xd8, 0x64, 0xec, 0x86, 0x05, 0x87, 0x6b, 0x50, 0x18, 0x63, 0x73, 0x44, 0x4e, 0xf3, 0xa5, 0xbc, + 0x5c, 0x38, 0xcd, 0x97, 0xd6, 0xe4, 0xd2, 0x69, 0xbe, 0x54, 0x96, 0xe1, 0x34, 0x5f, 0x02, 0x79, + 0xbd, 0xf1, 0xc7, 0x2c, 0xc8, 0xb3, 0xc5, 0x83, 0xd5, 0x2c, 0x56, 0x49, 0x45, 0xa9, 0xac, 0x37, + 0xbd, 0x32, 0xdb, 0xf4, 0xcb, 0x6c, 0xf3, 0xcc, 0x2f, 0xb3, 0x87, 0xa5, 0x2f, 0xbf, 0xbe, 0x9a, + 0x79, 0xf1, 0x97, 0xab, 0x92, 0xc2, 0x2d, 0xd0, 0x9b, 0xac, 0x58, 0x60, 0x63, 0xa8, 0x1a, 0x3a, + 0xaf, 0x96, 0x65, 0x56, 0x03, 0xb0, 0x31, 0x3c, 0xd1, 0xd1, 0x67, 0x20, 0x6b, 0xd6, 0xd0, 0x25, + 0x43, 0x77, 0xe4, 0xaa, 0xde, 0x26, 0x30, 0x5f, 0x14, 0xbd, 0xbd, 0x63, 0xbc, 0xd7, 0x3c, 0xf2, + 0x55, 0x1f, 0x72, 0x4d, 0x65, 0x53, 0x8b, 0x0a, 0xd0, 0x3d, 0x80, 0x60, 0x93, 0x70, 0x6b, 0xf9, + 0x6b, 0xb9, 0x5b, 0xeb, 0xfb, 0x37, 0x17, 0xcc, 0xfc, 0xc7, 0xbe, 0xe2, 0xb9, 0xad, 0x63, 0x4a, + 0x0e, 0xf3, 0xac, 0xd5, 0x4a, 0xc8, 0x1e, 0xdd, 0x84, 0x4d, 0x6c, 0xdb, 0xaa, 0x4b, 0x31, 0x25, + 0x6a, 0xe7, 0x82, 0x12, 0x97, 0x17, 0xdc, 0x8a, 0x52, 0xc5, 0xb6, 0xfd, 0x88, 0x49, 0x0f, 0x99, + 0x10, 0xdd, 0x80, 0x0d, 0x56, 0x56, 0x0d, 0x6c, 0xaa, 0x7d, 0x62, 0xf4, 0xfa, 0x94, 0x97, 0xd4, + 0x9c, 0x52, 0x15, 0xd2, 0x36, 0x17, 0x36, 0x7e, 0x9b, 0x83, 0x37, 0xe2, 0x17, 0x03, 0xba, 0x06, + 0x95, 0x01, 0x9e, 0xa8, 0x74, 0x22, 0xc2, 0x48, 0xdc, 0x1e, 0x06, 0x78, 0x72, 0x36, 0xf1, 0x62, + 0xc8, 0x90, 0xa3, 0x13, 0xb7, 0x96, 0xbd, 0x96, 0xbb, 0x55, 0x51, 0xd8, 0x23, 0x7a, 0x06, 0x5b, + 0xa6, 0xa5, 0x61, 0x53, 0x35, 0xb1, 0x4b, 0x55, 0x51, 0x49, 0xbd, 0xb1, 0x7b, 0x77, 0xc1, 0xf4, + 0xf0, 0x26, 0x34, 0xd1, 0xbd, 0x52, 0xca, 0xf6, 0x15, 0xd1, 0xeb, 0x4d, 0xee, 0xe9, 0x1e, 0xf6, + 0xab, 0x2c, 0x3a, 0x85, 0xf5, 0x81, 0xe1, 0x76, 0x48, 0x1f, 0x8f, 0x0d, 0xcb, 0x11, 0x23, 0xb9, + 0x68, 0x9f, 0xfa, 0x6c, 0xaa, 0x29, 0xfc, 0x85, 0x8d, 0xd1, 0x1b, 0x50, 0x14, 0xc3, 0x52, 0xe0, + 0xdd, 0x12, 0x6f, 0xc1, 0x84, 0x2a, 0xa6, 0x9e, 0x50, 0x1f, 0xc0, 0xce, 0x90, 0x4c, 0xa8, 0x3a, + 0xcd, 0x95, 0xda, 0xc7, 0x6e, 0xbf, 0xb6, 0xc6, 0xb3, 0x83, 0xd8, 0xb7, 0x20, 0xbb, 0x6e, 0x1b, + 0xbb, 0x7d, 0xf4, 0x2e, 0x2f, 0x2d, 0xb6, 0xe5, 0x12, 0x47, 0xc5, 0xba, 0xee, 0x10, 0xd7, 0xe5, + 0xfb, 0x56, 0x85, 0x57, 0x0a, 0x2e, 0x3f, 0xf0, 0xc4, 0x8d, 0x5f, 0x87, 0xd3, 0x14, 0x2d, 0x22, + 0x22, 0x09, 0xd2, 0x34, 0x09, 0x3f, 0x82, 0x1d, 0x61, 0xaf, 0x47, 0xf2, 0xe0, 0x1d, 0x0a, 0xde, + 0x5e, 0x90, 0x87, 0xb9, 0xf1, 0x47, 0xbe, 0x93, 0xc5, 0x29, 0xc8, 0x5d, 0x26, 0x05, 0x08, 0xf2, + 0x7c, 0x80, 0xf2, 0xbc, 0xcb, 0xfc, 0xf9, 0xbf, 0x2d, 0x2d, 0xbf, 0xca, 0xc1, 0xd6, 0x5c, 0x5d, + 0x0e, 0x3a, 0x26, 0xc5, 0x76, 0x2c, 0x1b, 0xdb, 0xb1, 0x5c, 0xea, 0x8e, 0x89, 0xbc, 0xe7, 0x57, + 0xe7, 0xbd, 0xf0, 0xda, 0xf3, 0x5e, 0xbc, 0x4c, 0xde, 0xff, 0xa3, 0x19, 0xf9, 0x8d, 0x04, 0xf5, + 0xc5, 0x5b, 0x5a, 0x6c, 0x6a, 0xde, 0x83, 0xad, 0xa0, 0x29, 0x81, 0xfb, 0x2c, 0x57, 0x90, 0x83, + 0x0f, 0xc2, 0x7f, 0x28, 0x8f, 0xb9, 0x48, 0x1e, 0x6f, 0xc0, 0xc6, 0xcc, 0xb6, 0xeb, 0x4d, 0xeb, + 0xea, 0x38, 0x1c, 0xbf, 0xf1, 0x22, 0x07, 0x3b, 0x71, 0xfb, 0x61, 0xcc, 0x2a, 0x7e, 0x02, 0xdb, + 0x3a, 0xd1, 0x0c, 0xfd, 0x72, 0x8b, 0x78, 0x4b, 0xf8, 0xf8, 0xff, 0x1a, 0x5e, 0x34, 0x63, 0xfe, + 0x0e, 0x50, 0x52, 0x88, 0x6b, 0xb3, 0x5d, 0x1b, 0xb5, 0xa1, 0x4c, 0x26, 0x1a, 0xb1, 0x29, 0xcb, + 0xa0, 0xb4, 0xe4, 0x3c, 0xc6, 0x0e, 0xa9, 0x9e, 0xcd, 0xb1, 0xaf, 0xcf, 0x48, 0x26, 0x30, 0x46, + 0x1f, 0x0a, 0x88, 0x5b, 0x45, 0x62, 0xc2, 0x49, 0x98, 0xe2, 0x3e, 0xf2, 0x29, 0x2e, 0xb7, 0x02, + 0x41, 0x3c, 0xdb, 0x19, 0x8c, 0xfb, 0x50, 0x60, 0x5c, 0x3e, 0x51, 0xe0, 0x08, 0xc7, 0x9d, 0x44, + 0x38, 0xae, 0xb8, 0xe2, 0x38, 0xea, 0x3b, 0x88, 0x05, 0xb9, 0x8f, 0x7c, 0x90, 0x5b, 0x4b, 0xd4, + 0x87, 0x19, 0x92, 0x3b, 0x0a, 0x91, 0x5c, 0x99, 0x3b, 0xb8, 0xb9, 0xa2, 0x19, 0x31, 0x28, 0xf7, + 0x71, 0x80, 0x72, 0x95, 0x25, 0x30, 0x18, 0x72, 0x31, 0xcb, 0x72, 0xe7, 0x73, 0x2c, 0xe7, 0x51, + 0xd7, 0xfb, 0x2b, 0x3a, 0xb3, 0x02, 0xe6, 0xce, 0xe7, 0x60, 0x6e, 0x23, 0x91, 0xdb, 0x15, 0x34, + 0xd7, 0x89, 0xa7, 0xb9, 0x55, 0xa4, 0x25, 0x9a, 0x9c, 0x0c, 0xe7, 0xc8, 0x02, 0x9c, 0x93, 0x97, + 0x20, 0xc6, 0x34, 0x48, 0x62, 0x9e, 0x7b, 0x16, 0xc3, 0x73, 0x1e, 0x73, 0x35, 0x17, 0xfe, 0x2a, + 0xe1, 0x85, 0x48, 0x00, 0x74, 0xcf, 0x62, 0x80, 0x0e, 0x25, 0x74, 0xbe, 0x92, 0xe8, 0xee, 0x45, + 0x89, 0x6e, 0x7b, 0xe9, 0xc9, 0x77, 0x5a, 0x41, 0x16, 0x20, 0x5d, 0x7f, 0x11, 0xd2, 0x79, 0xc0, + 0xb5, 0xbf, 0xc2, 0x6f, 0x0a, 0xa6, 0x3b, 0x9f, 0x63, 0xba, 0x2b, 0x4b, 0xe6, 0xe4, 0x34, 0x44, + 0x72, 0xa8, 0x2b, 0xc8, 0xc5, 0xd3, 0x7c, 0xa9, 0x24, 0x97, 0x3d, 0x9c, 0x3b, 0xcd, 0x97, 0xd6, + 0xe5, 0x4a, 0xe3, 0x0f, 0x12, 0x3b, 0x40, 0xcd, 0x54, 0x92, 0x58, 0x00, 0x93, 0x5e, 0x17, 0x80, + 0x65, 0x2f, 0x09, 0x60, 0x6f, 0x42, 0x89, 0x01, 0x18, 0xdf, 0x80, 0x72, 0x7c, 0x4b, 0x59, 0xc3, + 0xb6, 0xcd, 0x76, 0x9d, 0xc6, 0xef, 0xb3, 0xb0, 0x39, 0x53, 0x90, 0xd8, 0x0e, 0xa9, 0x59, 0xba, + 0x47, 0xa8, 0x55, 0x85, 0x3f, 0x33, 0x99, 0x8e, 0x29, 0x16, 0x87, 0x0c, 0xfe, 0xcc, 0x0e, 0x00, + 0xa6, 0xd5, 0xe3, 0x1e, 0xcb, 0x0a, 0x7b, 0x64, 0x5a, 0x41, 0x21, 0x2f, 0x8b, 0x0a, 0xbd, 0x0b, + 0xd0, 0xc3, 0xae, 0xfa, 0x53, 0x3c, 0xa4, 0x44, 0x17, 0xfb, 0x6b, 0x48, 0x82, 0xea, 0x50, 0x62, + 0x6f, 0x23, 0x97, 0xe8, 0x82, 0xf7, 0x82, 0x77, 0x74, 0x1f, 0x8a, 0x64, 0x4c, 0x86, 0xd4, 0xad, + 0xad, 0xf1, 0x21, 0x78, 0x6b, 0xc1, 0x74, 0x3f, 0x66, 0x4a, 0x87, 0x35, 0xd6, 0xf1, 0xbf, 0x7d, + 0x7d, 0x55, 0xf6, 0x6c, 0xde, 0xb7, 0x06, 0x06, 0x25, 0x03, 0x9b, 0x5e, 0x28, 0xc2, 0x0b, 0x7a, + 0x0b, 0xca, 0xac, 0x37, 0xae, 0x8d, 0x35, 0xc2, 0x37, 0xd7, 0xb2, 0x32, 0x15, 0x70, 0x74, 0xaf, + 0x28, 0x45, 0x97, 0xb1, 0x9d, 0xa3, 0x94, 0x6c, 0xc7, 0xb0, 0x1c, 0x83, 0x5e, 0x28, 0xd5, 0x01, + 0x19, 0xd8, 0x96, 0x65, 0xaa, 0xc4, 0x71, 0x2c, 0xa7, 0x71, 0x00, 0x1b, 0xd1, 0xfa, 0x8b, 0xae, + 0x43, 0xd5, 0x21, 0x94, 0x91, 0x79, 0xe4, 0xa0, 0x55, 0xf1, 0x84, 0x1e, 0xb6, 0x9e, 0xe6, 0x4b, + 0x92, 0x9c, 0x3d, 0xcd, 0x97, 0xb2, 0x72, 0xae, 0x71, 0x07, 0xd0, 0xfc, 0x4a, 0x8a, 0x39, 0x90, + 0x49, 0x71, 0x07, 0xb2, 0xdf, 0x49, 0xf0, 0xcd, 0x25, 0xeb, 0x05, 0x3d, 0x81, 0x22, 0x43, 0xed, + 0x91, 0x37, 0x01, 0x37, 0xf6, 0x3f, 0x4e, 0xbf, 0xe6, 0x9a, 0x9e, 0xec, 0x11, 0x77, 0xa3, 0x08, + 0x77, 0x8d, 0xdb, 0x50, 0x09, 0xcb, 0xd1, 0x3a, 0xac, 0x9d, 0xdf, 0xff, 0xf4, 0xfe, 0x83, 0x27, + 0xf7, 0xe5, 0x0c, 0x02, 0x28, 0x1e, 0x1c, 0x1d, 0x1d, 0x3f, 0x3c, 0x93, 0x25, 0xf6, 0xac, 0x1c, + 0x9f, 0x1e, 0x1f, 0x9d, 0xc9, 0xd9, 0xc6, 0x3f, 0xb2, 0x70, 0x25, 0x76, 0xe9, 0x85, 0x92, 0x2b, + 0xbd, 0x96, 0xe4, 0x1e, 0x02, 0xd0, 0x89, 0xea, 0x10, 0x77, 0x64, 0x52, 0x7f, 0xcd, 0x5c, 0x5f, + 0x48, 0xf0, 0x44, 0x3b, 0x9b, 0x28, 0x5c, 0x57, 0x29, 0x53, 0xf1, 0xc4, 0x78, 0x24, 0x74, 0xb0, + 0x1e, 0xf1, 0xf5, 0xe4, 0x8a, 0xe3, 0x66, 0xba, 0xe5, 0x37, 0x3d, 0x86, 0x7b, 0x62, 0x17, 0x3d, + 0x85, 0x6f, 0xcc, 0x54, 0x88, 0x20, 0x40, 0x3e, 0x71, 0xa1, 0xb8, 0x12, 0x2d, 0x14, 0xbe, 0xef, + 0xf0, 0x02, 0x2f, 0x44, 0x17, 0xf8, 0x17, 0x12, 0x94, 0x58, 0x6e, 0xd9, 0xa9, 0x09, 0x7d, 0x02, + 0xe5, 0xa0, 0x5d, 0xa2, 0x3c, 0x5d, 0x5b, 0xd5, 0x2d, 0xd1, 0xa1, 0xa9, 0x21, 0xfa, 0x3e, 0x54, + 0x79, 0xc1, 0x55, 0x0d, 0x5d, 0xed, 0x9a, 0xd8, 0xab, 0x00, 0x1b, 0xe1, 0xb1, 0xf6, 0xdb, 0xef, + 0xb9, 0xe2, 0xe9, 0x3e, 0xf9, 0xe4, 0xae, 0x89, 0x7b, 0xca, 0x3a, 0xb7, 0x3c, 0xd1, 0xd9, 0x8b, + 0x58, 0x0c, 0xff, 0x94, 0x40, 0xf6, 0x7f, 0x51, 0x79, 0xcd, 0x2d, 0x9d, 0x5f, 0x51, 0xb9, 0x98, + 0x15, 0x85, 0x5a, 0xb0, 0x1d, 0x68, 0xa8, 0xae, 0xd1, 0x1b, 0x62, 0x3a, 0x72, 0x88, 0x20, 0x04, + 0x14, 0x7c, 0x7a, 0xe4, 0x7f, 0x99, 0x1f, 0x81, 0xc2, 0xa5, 0x46, 0x40, 0x05, 0x98, 0x52, 0x10, + 0xda, 0x81, 0x82, 0x63, 0x8d, 0x86, 0x3a, 0xef, 0x76, 0x41, 0xf1, 0x5e, 0xd0, 0x1d, 0x28, 0xb0, + 0x46, 0xfb, 0x13, 0xfb, 0xea, 0x82, 0x89, 0xed, 0x0f, 0xa0, 0x18, 0x0b, 0xcf, 0xa6, 0x61, 0x01, + 0x9a, 0xff, 0xcd, 0x6a, 0x41, 0xa0, 0xa3, 0x68, 0xa0, 0x77, 0x56, 0xfc, 0x06, 0x16, 0x1f, 0xf0, + 0x17, 0x59, 0xa8, 0x84, 0xd7, 0xd8, 0xff, 0xea, 0x9e, 0xd2, 0xf8, 0xa5, 0x04, 0xa5, 0x60, 0x10, + 0xa6, 0x98, 0x29, 0x45, 0x30, 0x73, 0x07, 0x0a, 0xc6, 0x50, 0x27, 0x13, 0x3e, 0x12, 0x55, 0xc5, + 0x7b, 0x41, 0x1b, 0x90, 0xa5, 0x13, 0x31, 0x61, 0xb3, 0x74, 0x82, 0x0e, 0xa0, 0xe8, 0x15, 0xb7, + 0xa5, 0x9c, 0x14, 0xad, 0x6d, 0x22, 0x2b, 0xc2, 0x70, 0xff, 0xcf, 0x15, 0xc8, 0x1f, 0x1c, 0x1e, + 0x9d, 0xa0, 0x07, 0x90, 0x67, 0xfc, 0x86, 0x12, 0xdc, 0xd4, 0xd5, 0x93, 0x80, 0x20, 0x52, 0xa0, + 0xc0, 0xa1, 0x0e, 0x25, 0xb9, 0xc0, 0xab, 0x27, 0xe2, 0x43, 0xd6, 0x48, 0x3e, 0x4f, 0x13, 0xdc, + 0xeb, 0xd5, 0x93, 0x40, 0x23, 0xfa, 0x21, 0xac, 0xf9, 0x67, 0x9c, 0x64, 0xd7, 0x6c, 0xf5, 0x84, + 0x0c, 0xc7, 0xba, 0xcf, 0x79, 0x10, 0x25, 0xb9, 0xfe, 0xab, 0x27, 0x42, 0x4b, 0x74, 0x0e, 0x45, + 0x71, 0xbe, 0x48, 0x74, 0xa3, 0x57, 0x4f, 0x06, 0x8b, 0xe8, 0xc7, 0x50, 0x9e, 0x1e, 0x5b, 0x93, + 0x5e, 0x79, 0xd6, 0x13, 0x33, 0x35, 0xfa, 0x09, 0x54, 0x23, 0x34, 0x89, 0xd2, 0xdc, 0x23, 0xd6, + 0x53, 0x81, 0x2a, 0x8b, 0x15, 0x41, 0x4c, 0x94, 0xe6, 0x76, 0xb1, 0x9e, 0x8a, 0x5e, 0xd1, 0x18, + 0xb6, 0xe6, 0x90, 0x13, 0xa5, 0xbd, 0x72, 0xac, 0xa7, 0xa6, 0x5a, 0x74, 0x01, 0x68, 0x9e, 0x42, + 0x51, 0xea, 0x7b, 0xc8, 0x7a, 0x7a, 0xd4, 0x45, 0x36, 0x6c, 0xce, 0xde, 0xb0, 0xa4, 0xbb, 0x9d, + 0xac, 0xa7, 0x84, 0x5f, 0x2f, 0x62, 0x94, 0x4f, 0xd3, 0xdd, 0x59, 0xd6, 0x53, 0x12, 0x31, 0xc2, + 0x00, 0xa1, 0x23, 0x78, 0xe2, 0x9b, 0xcc, 0x7a, 0x72, 0x42, 0x46, 0x3f, 0x87, 0xed, 0xb8, 0x73, + 0x7a, 0xfa, 0xeb, 0xcd, 0xfa, 0xbf, 0x81, 0xcf, 0x6c, 0x8d, 0x44, 0xcf, 0xdd, 0x69, 0x2e, 0x3d, + 0xeb, 0xa9, 0x68, 0xfa, 0xf0, 0xe1, 0x97, 0x2f, 0x77, 0xa5, 0xaf, 0x5e, 0xee, 0x4a, 0x7f, 0x7d, + 0xb9, 0x2b, 0xbd, 0x78, 0xb5, 0x9b, 0xf9, 0xea, 0xd5, 0x6e, 0xe6, 0x4f, 0xaf, 0x76, 0x33, 0x4f, + 0xbf, 0xd3, 0x33, 0x68, 0x7f, 0xd4, 0x61, 0xde, 0x5a, 0xc1, 0xdf, 0x52, 0xa6, 0x7f, 0x71, 0xb1, + 0x8d, 0x56, 0xec, 0x9f, 0x69, 0x3a, 0x45, 0xfe, 0x5b, 0xeb, 0xed, 0x7f, 0x05, 0x00, 0x00, 0xff, + 0xff, 0x0a, 0xda, 0xa4, 0xf8, 0x6c, 0x23, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// ABCIClient is the client API for ABCI service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type ABCIClient interface { + // Echo returns back the same message it is sent. + Echo(ctx context.Context, in *v1beta1.RequestEcho, opts ...grpc.CallOption) (*v1beta1.ResponseEcho, error) + // Flush flushes the write buffer. + Flush(ctx context.Context, in *v1beta1.RequestFlush, opts ...grpc.CallOption) (*v1beta1.ResponseFlush, error) + // Info returns information about the application state. + Info(ctx context.Context, in *v1beta2.RequestInfo, opts ...grpc.CallOption) (*v1beta1.ResponseInfo, error) + // CheckTx validates a transaction. + CheckTx(ctx context.Context, in *v1beta1.RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) + // Query queries the application state. + Query(ctx context.Context, in *v1beta1.RequestQuery, opts ...grpc.CallOption) (*v1beta1.ResponseQuery, error) + // Commit commits a block of transactions. + Commit(ctx context.Context, in *v1beta1.RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) + // InitChain initializes the blockchain. + InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) + // ListSnapshots lists all the available snapshots. + ListSnapshots(ctx context.Context, in *v1beta1.RequestListSnapshots, opts ...grpc.CallOption) (*v1beta1.ResponseListSnapshots, error) + // OfferSnapshot sends a snapshot offer. + OfferSnapshot(ctx context.Context, in *v1beta1.RequestOfferSnapshot, opts ...grpc.CallOption) (*v1beta1.ResponseOfferSnapshot, error) + // LoadSnapshotChunk returns a chunk of snapshot. + LoadSnapshotChunk(ctx context.Context, in *v1beta1.RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*v1beta1.ResponseLoadSnapshotChunk, error) + // ApplySnapshotChunk applies a chunk of snapshot. + ApplySnapshotChunk(ctx context.Context, in *v1beta1.RequestApplySnapshotChunk, opts ...grpc.CallOption) (*v1beta1.ResponseApplySnapshotChunk, error) + // PrepareProposal returns a proposal for the next block. + PrepareProposal(ctx context.Context, in *RequestPrepareProposal, opts ...grpc.CallOption) (*v1beta2.ResponsePrepareProposal, error) + // ProcessProposal validates a proposal. + ProcessProposal(ctx context.Context, in *RequestProcessProposal, opts ...grpc.CallOption) (*v1beta2.ResponseProcessProposal, error) + // ExtendVote extends a vote with application-injected data (vote extensions). + ExtendVote(ctx context.Context, in *RequestExtendVote, opts ...grpc.CallOption) (*ResponseExtendVote, error) + // VerifyVoteExtension verifies a vote extension. + VerifyVoteExtension(ctx context.Context, in *RequestVerifyVoteExtension, opts ...grpc.CallOption) (*ResponseVerifyVoteExtension, error) + // FinalizeBlock finalizes a block. + FinalizeBlock(ctx context.Context, in *RequestFinalizeBlock, opts ...grpc.CallOption) (*ResponseFinalizeBlock, error) +} + +type aBCIClient struct { + cc grpc1.ClientConn +} + +func NewABCIClient(cc grpc1.ClientConn) ABCIClient { + return &aBCIClient{cc} +} + +func (c *aBCIClient) Echo(ctx context.Context, in *v1beta1.RequestEcho, opts ...grpc.CallOption) (*v1beta1.ResponseEcho, error) { + out := new(v1beta1.ResponseEcho) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/Echo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) Flush(ctx context.Context, in *v1beta1.RequestFlush, opts ...grpc.CallOption) (*v1beta1.ResponseFlush, error) { + out := new(v1beta1.ResponseFlush) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/Flush", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) Info(ctx context.Context, in *v1beta2.RequestInfo, opts ...grpc.CallOption) (*v1beta1.ResponseInfo, error) { + out := new(v1beta1.ResponseInfo) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/Info", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) CheckTx(ctx context.Context, in *v1beta1.RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { + out := new(ResponseCheckTx) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/CheckTx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) Query(ctx context.Context, in *v1beta1.RequestQuery, opts ...grpc.CallOption) (*v1beta1.ResponseQuery, error) { + out := new(v1beta1.ResponseQuery) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/Query", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) Commit(ctx context.Context, in *v1beta1.RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { + out := new(ResponseCommit) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/Commit", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { + out := new(ResponseInitChain) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/InitChain", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) ListSnapshots(ctx context.Context, in *v1beta1.RequestListSnapshots, opts ...grpc.CallOption) (*v1beta1.ResponseListSnapshots, error) { + out := new(v1beta1.ResponseListSnapshots) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/ListSnapshots", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) OfferSnapshot(ctx context.Context, in *v1beta1.RequestOfferSnapshot, opts ...grpc.CallOption) (*v1beta1.ResponseOfferSnapshot, error) { + out := new(v1beta1.ResponseOfferSnapshot) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/OfferSnapshot", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) LoadSnapshotChunk(ctx context.Context, in *v1beta1.RequestLoadSnapshotChunk, opts ...grpc.CallOption) (*v1beta1.ResponseLoadSnapshotChunk, error) { + out := new(v1beta1.ResponseLoadSnapshotChunk) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/LoadSnapshotChunk", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) ApplySnapshotChunk(ctx context.Context, in *v1beta1.RequestApplySnapshotChunk, opts ...grpc.CallOption) (*v1beta1.ResponseApplySnapshotChunk, error) { + out := new(v1beta1.ResponseApplySnapshotChunk) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/ApplySnapshotChunk", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) PrepareProposal(ctx context.Context, in *RequestPrepareProposal, opts ...grpc.CallOption) (*v1beta2.ResponsePrepareProposal, error) { + out := new(v1beta2.ResponsePrepareProposal) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/PrepareProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) ProcessProposal(ctx context.Context, in *RequestProcessProposal, opts ...grpc.CallOption) (*v1beta2.ResponseProcessProposal, error) { + out := new(v1beta2.ResponseProcessProposal) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/ProcessProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) ExtendVote(ctx context.Context, in *RequestExtendVote, opts ...grpc.CallOption) (*ResponseExtendVote, error) { + out := new(ResponseExtendVote) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/ExtendVote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) VerifyVoteExtension(ctx context.Context, in *RequestVerifyVoteExtension, opts ...grpc.CallOption) (*ResponseVerifyVoteExtension, error) { + out := new(ResponseVerifyVoteExtension) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/VerifyVoteExtension", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIClient) FinalizeBlock(ctx context.Context, in *RequestFinalizeBlock, opts ...grpc.CallOption) (*ResponseFinalizeBlock, error) { + out := new(ResponseFinalizeBlock) + err := c.cc.Invoke(ctx, "/cometbft.abci.v1beta3.ABCI/FinalizeBlock", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ABCIServer is the server API for ABCI service. +type ABCIServer interface { + // Echo returns back the same message it is sent. + Echo(context.Context, *v1beta1.RequestEcho) (*v1beta1.ResponseEcho, error) + // Flush flushes the write buffer. + Flush(context.Context, *v1beta1.RequestFlush) (*v1beta1.ResponseFlush, error) + // Info returns information about the application state. + Info(context.Context, *v1beta2.RequestInfo) (*v1beta1.ResponseInfo, error) + // CheckTx validates a transaction. + CheckTx(context.Context, *v1beta1.RequestCheckTx) (*ResponseCheckTx, error) + // Query queries the application state. + Query(context.Context, *v1beta1.RequestQuery) (*v1beta1.ResponseQuery, error) + // Commit commits a block of transactions. + Commit(context.Context, *v1beta1.RequestCommit) (*ResponseCommit, error) + // InitChain initializes the blockchain. + InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) + // ListSnapshots lists all the available snapshots. + ListSnapshots(context.Context, *v1beta1.RequestListSnapshots) (*v1beta1.ResponseListSnapshots, error) + // OfferSnapshot sends a snapshot offer. + OfferSnapshot(context.Context, *v1beta1.RequestOfferSnapshot) (*v1beta1.ResponseOfferSnapshot, error) + // LoadSnapshotChunk returns a chunk of snapshot. + LoadSnapshotChunk(context.Context, *v1beta1.RequestLoadSnapshotChunk) (*v1beta1.ResponseLoadSnapshotChunk, error) + // ApplySnapshotChunk applies a chunk of snapshot. + ApplySnapshotChunk(context.Context, *v1beta1.RequestApplySnapshotChunk) (*v1beta1.ResponseApplySnapshotChunk, error) + // PrepareProposal returns a proposal for the next block. + PrepareProposal(context.Context, *RequestPrepareProposal) (*v1beta2.ResponsePrepareProposal, error) + // ProcessProposal validates a proposal. + ProcessProposal(context.Context, *RequestProcessProposal) (*v1beta2.ResponseProcessProposal, error) + // ExtendVote extends a vote with application-injected data (vote extensions). + ExtendVote(context.Context, *RequestExtendVote) (*ResponseExtendVote, error) + // VerifyVoteExtension verifies a vote extension. + VerifyVoteExtension(context.Context, *RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error) + // FinalizeBlock finalizes a block. + FinalizeBlock(context.Context, *RequestFinalizeBlock) (*ResponseFinalizeBlock, error) +} + +// UnimplementedABCIServer can be embedded to have forward compatible implementations. +type UnimplementedABCIServer struct { +} + +func (*UnimplementedABCIServer) Echo(ctx context.Context, req *v1beta1.RequestEcho) (*v1beta1.ResponseEcho, error) { + return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented") +} +func (*UnimplementedABCIServer) Flush(ctx context.Context, req *v1beta1.RequestFlush) (*v1beta1.ResponseFlush, error) { + return nil, status.Errorf(codes.Unimplemented, "method Flush not implemented") +} +func (*UnimplementedABCIServer) Info(ctx context.Context, req *v1beta2.RequestInfo) (*v1beta1.ResponseInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method Info not implemented") +} +func (*UnimplementedABCIServer) CheckTx(ctx context.Context, req *v1beta1.RequestCheckTx) (*ResponseCheckTx, error) { + return nil, status.Errorf(codes.Unimplemented, "method CheckTx not implemented") +} +func (*UnimplementedABCIServer) Query(ctx context.Context, req *v1beta1.RequestQuery) (*v1beta1.ResponseQuery, error) { + return nil, status.Errorf(codes.Unimplemented, "method Query not implemented") +} +func (*UnimplementedABCIServer) Commit(ctx context.Context, req *v1beta1.RequestCommit) (*ResponseCommit, error) { + return nil, status.Errorf(codes.Unimplemented, "method Commit not implemented") +} +func (*UnimplementedABCIServer) InitChain(ctx context.Context, req *RequestInitChain) (*ResponseInitChain, error) { + return nil, status.Errorf(codes.Unimplemented, "method InitChain not implemented") +} +func (*UnimplementedABCIServer) ListSnapshots(ctx context.Context, req *v1beta1.RequestListSnapshots) (*v1beta1.ResponseListSnapshots, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListSnapshots not implemented") +} +func (*UnimplementedABCIServer) OfferSnapshot(ctx context.Context, req *v1beta1.RequestOfferSnapshot) (*v1beta1.ResponseOfferSnapshot, error) { + return nil, status.Errorf(codes.Unimplemented, "method OfferSnapshot not implemented") +} +func (*UnimplementedABCIServer) LoadSnapshotChunk(ctx context.Context, req *v1beta1.RequestLoadSnapshotChunk) (*v1beta1.ResponseLoadSnapshotChunk, error) { + return nil, status.Errorf(codes.Unimplemented, "method LoadSnapshotChunk not implemented") +} +func (*UnimplementedABCIServer) ApplySnapshotChunk(ctx context.Context, req *v1beta1.RequestApplySnapshotChunk) (*v1beta1.ResponseApplySnapshotChunk, error) { + return nil, status.Errorf(codes.Unimplemented, "method ApplySnapshotChunk not implemented") +} +func (*UnimplementedABCIServer) PrepareProposal(ctx context.Context, req *RequestPrepareProposal) (*v1beta2.ResponsePrepareProposal, error) { + return nil, status.Errorf(codes.Unimplemented, "method PrepareProposal not implemented") +} +func (*UnimplementedABCIServer) ProcessProposal(ctx context.Context, req *RequestProcessProposal) (*v1beta2.ResponseProcessProposal, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProcessProposal not implemented") +} +func (*UnimplementedABCIServer) ExtendVote(ctx context.Context, req *RequestExtendVote) (*ResponseExtendVote, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExtendVote not implemented") +} +func (*UnimplementedABCIServer) VerifyVoteExtension(ctx context.Context, req *RequestVerifyVoteExtension) (*ResponseVerifyVoteExtension, error) { + return nil, status.Errorf(codes.Unimplemented, "method VerifyVoteExtension not implemented") +} +func (*UnimplementedABCIServer) FinalizeBlock(ctx context.Context, req *RequestFinalizeBlock) (*ResponseFinalizeBlock, error) { + return nil, status.Errorf(codes.Unimplemented, "method FinalizeBlock not implemented") +} + +func RegisterABCIServer(s grpc1.Server, srv ABCIServer) { + s.RegisterService(&_ABCI_serviceDesc, srv) +} + +func _ABCI_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestEcho) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).Echo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/Echo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).Echo(ctx, req.(*v1beta1.RequestEcho)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestFlush) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).Flush(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/Flush", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).Flush(ctx, req.(*v1beta1.RequestFlush)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta2.RequestInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).Info(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/Info", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).Info(ctx, req.(*v1beta2.RequestInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestCheckTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).CheckTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/CheckTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).CheckTx(ctx, req.(*v1beta1.RequestCheckTx)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestQuery) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/Query", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).Query(ctx, req.(*v1beta1.RequestQuery)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestCommit) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).Commit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/Commit", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).Commit(ctx, req.(*v1beta1.RequestCommit)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInitChain) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).InitChain(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/InitChain", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).InitChain(ctx, req.(*RequestInitChain)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_ListSnapshots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestListSnapshots) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).ListSnapshots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/ListSnapshots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).ListSnapshots(ctx, req.(*v1beta1.RequestListSnapshots)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_OfferSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestOfferSnapshot) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).OfferSnapshot(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/OfferSnapshot", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).OfferSnapshot(ctx, req.(*v1beta1.RequestOfferSnapshot)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_LoadSnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestLoadSnapshotChunk) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).LoadSnapshotChunk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/LoadSnapshotChunk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).LoadSnapshotChunk(ctx, req.(*v1beta1.RequestLoadSnapshotChunk)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_ApplySnapshotChunk_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestApplySnapshotChunk) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).ApplySnapshotChunk(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/ApplySnapshotChunk", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).ApplySnapshotChunk(ctx, req.(*v1beta1.RequestApplySnapshotChunk)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_PrepareProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestPrepareProposal) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).PrepareProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/PrepareProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).PrepareProposal(ctx, req.(*RequestPrepareProposal)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_ProcessProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestProcessProposal) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).ProcessProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/ProcessProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).ProcessProposal(ctx, req.(*RequestProcessProposal)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_ExtendVote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestExtendVote) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).ExtendVote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/ExtendVote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).ExtendVote(ctx, req.(*RequestExtendVote)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_VerifyVoteExtension_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestVerifyVoteExtension) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).VerifyVoteExtension(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/VerifyVoteExtension", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).VerifyVoteExtension(ctx, req.(*RequestVerifyVoteExtension)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCI_FinalizeBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestFinalizeBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIServer).FinalizeBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.abci.v1beta3.ABCI/FinalizeBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIServer).FinalizeBlock(ctx, req.(*RequestFinalizeBlock)) + } + return interceptor(ctx, in, info, handler) +} + +var _ABCI_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.abci.v1beta3.ABCI", + HandlerType: (*ABCIServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Echo", + Handler: _ABCI_Echo_Handler, + }, + { + MethodName: "Flush", + Handler: _ABCI_Flush_Handler, + }, + { + MethodName: "Info", + Handler: _ABCI_Info_Handler, + }, + { + MethodName: "CheckTx", + Handler: _ABCI_CheckTx_Handler, + }, + { + MethodName: "Query", + Handler: _ABCI_Query_Handler, + }, + { + MethodName: "Commit", + Handler: _ABCI_Commit_Handler, + }, + { + MethodName: "InitChain", + Handler: _ABCI_InitChain_Handler, + }, + { + MethodName: "ListSnapshots", + Handler: _ABCI_ListSnapshots_Handler, + }, + { + MethodName: "OfferSnapshot", + Handler: _ABCI_OfferSnapshot_Handler, + }, + { + MethodName: "LoadSnapshotChunk", + Handler: _ABCI_LoadSnapshotChunk_Handler, + }, + { + MethodName: "ApplySnapshotChunk", + Handler: _ABCI_ApplySnapshotChunk_Handler, + }, + { + MethodName: "PrepareProposal", + Handler: _ABCI_PrepareProposal_Handler, + }, + { + MethodName: "ProcessProposal", + Handler: _ABCI_ProcessProposal_Handler, + }, + { + MethodName: "ExtendVote", + Handler: _ABCI_ExtendVote_Handler, + }, + { + MethodName: "VerifyVoteExtension", + Handler: _ABCI_VerifyVoteExtension_Handler, + }, + { + MethodName: "FinalizeBlock", + Handler: _ABCI_FinalizeBlock_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/abci/v1beta3/types.proto", +} + +func (m *Request) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Request) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != nil { + { + size := m.Value.Size() + i -= size + if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Request_Echo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Echo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Echo != nil { + { + size, err := m.Echo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Request_Flush) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Flush) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Flush != nil { + { + size, err := m.Flush.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Request_Info) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Info) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Request_InitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_InitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.InitChain != nil { + { + size, err := m.InitChain.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *Request_Query) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Query != nil { + { + size, err := m.Query.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Request_CheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_CheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.CheckTx != nil { + { + size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *Request_Commit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_Commit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Commit != nil { + { + size, err := m.Commit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + return len(dAtA) - i, nil +} +func (m *Request_ListSnapshots) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ListSnapshots != nil { + { + size, err := m.ListSnapshots.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } + return len(dAtA) - i, nil +} +func (m *Request_OfferSnapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_OfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.OfferSnapshot != nil { + { + size, err := m.OfferSnapshot.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + return len(dAtA) - i, nil +} +func (m *Request_LoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_LoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LoadSnapshotChunk != nil { + { + size, err := m.LoadSnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + return len(dAtA) - i, nil +} +func (m *Request_ApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ApplySnapshotChunk != nil { + { + size, err := m.ApplySnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } + return len(dAtA) - i, nil +} +func (m *Request_PrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_PrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PrepareProposal != nil { + { + size, err := m.PrepareProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } + return len(dAtA) - i, nil +} +func (m *Request_ProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ProcessProposal != nil { + { + size, err := m.ProcessProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + return len(dAtA) - i, nil +} +func (m *Request_ExtendVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_ExtendVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ExtendVote != nil { + { + size, err := m.ExtendVote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x92 + } + return len(dAtA) - i, nil +} +func (m *Request_VerifyVoteExtension) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_VerifyVoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.VerifyVoteExtension != nil { + { + size, err := m.VerifyVoteExtension.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x9a + } + return len(dAtA) - i, nil +} +func (m *Request_FinalizeBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Request_FinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.FinalizeBlock != nil { + { + size, err := m.FinalizeBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa2 + } + return len(dAtA) - i, nil +} +func (m *RequestInitChain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestInitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.InitialHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.InitialHeight)) + i-- + dAtA[i] = 0x30 + } + if len(m.AppStateBytes) > 0 { + i -= len(m.AppStateBytes) + copy(dAtA[i:], m.AppStateBytes) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppStateBytes))) + i-- + dAtA[i] = 0x2a + } + if len(m.Validators) > 0 { + for iNdEx := len(m.Validators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Validators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if m.ConsensusParams != nil { + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0x12 + } + n18, err18 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err18 != nil { + return 0, err18 + } + i -= n18 + i = encodeVarintTypes(dAtA, i, uint64(n18)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *RequestPrepareProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestPrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestPrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a + } + n19, err19 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err19 != nil { + return 0, err19 + } + i -= n19 + i = encodeVarintTypes(dAtA, i, uint64(n19)) + i-- + dAtA[i] = 0x32 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x28 + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + { + size, err := m.LocalLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if m.MaxTxBytes != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.MaxTxBytes)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *RequestProcessProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a + } + n21, err21 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err21 != nil { + return 0, err21 + } + i -= n21 + i = encodeVarintTypes(dAtA, i, uint64(n21)) + i-- + dAtA[i] = 0x32 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x28 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0x22 + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.ProposedLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *RequestExtendVote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestExtendVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestExtendVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } + { + size, err := m.ProposedLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + n24, err24 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err24 != nil { + return 0, err24 + } + i -= n24 + i = encodeVarintTypes(dAtA, i, uint64(n24)) + i-- + dAtA[i] = 0x1a + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestVerifyVoteExtension) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestVerifyVoteExtension) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestVerifyVoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VoteExtension) > 0 { + i -= len(m.VoteExtension) + copy(dAtA[i:], m.VoteExtension) + i = encodeVarintTypes(dAtA, i, uint64(len(m.VoteExtension))) + i-- + dAtA[i] = 0x22 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x18 + } + if len(m.ValidatorAddress) > 0 { + i -= len(m.ValidatorAddress) + copy(dAtA[i:], m.ValidatorAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ValidatorAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *RequestFinalizeBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestFinalizeBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RequestFinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x3a + } + n25, err25 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err25 != nil { + return 0, err25 + } + i -= n25 + i = encodeVarintTypes(dAtA, i, uint64(n25)) + i-- + dAtA[i] = 0x32 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x28 + } + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0x22 + } + if len(m.Misbehavior) > 0 { + for iNdEx := len(m.Misbehavior) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Misbehavior[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.DecidedLastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Response) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Response) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Value != nil { + { + size := m.Value.Size() + i -= size + if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Response_Exception) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Exception) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Exception != nil { + { + size, err := m.Exception.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Response_Echo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Echo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Echo != nil { + { + size, err := m.Echo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Response_Flush) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Flush) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Flush != nil { + { + size, err := m.Flush.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Response_Info) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Info) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Response_InitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_InitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.InitChain != nil { + { + size, err := m.InitChain.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Response_Query) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Query) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Query != nil { + { + size, err := m.Query.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Response_CheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_CheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.CheckTx != nil { + { + size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *Response_Commit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_Commit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Commit != nil { + { + size, err := m.Commit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + } + return len(dAtA) - i, nil +} +func (m *Response_ListSnapshots) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ListSnapshots) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ListSnapshots != nil { + { + size, err := m.ListSnapshots.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + return len(dAtA) - i, nil +} +func (m *Response_OfferSnapshot) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_OfferSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.OfferSnapshot != nil { + { + size, err := m.OfferSnapshot.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + return len(dAtA) - i, nil +} +func (m *Response_LoadSnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_LoadSnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LoadSnapshotChunk != nil { + { + size, err := m.LoadSnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } + return len(dAtA) - i, nil +} +func (m *Response_ApplySnapshotChunk) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ApplySnapshotChunk) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ApplySnapshotChunk != nil { + { + size, err := m.ApplySnapshotChunk.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + } + return len(dAtA) - i, nil +} +func (m *Response_PrepareProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_PrepareProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PrepareProposal != nil { + { + size, err := m.PrepareProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + } + return len(dAtA) - i, nil +} +func (m *Response_ProcessProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ProcessProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ProcessProposal != nil { + { + size, err := m.ProcessProposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x92 + } + return len(dAtA) - i, nil +} +func (m *Response_ExtendVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_ExtendVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ExtendVote != nil { + { + size, err := m.ExtendVote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x9a + } + return len(dAtA) - i, nil +} +func (m *Response_VerifyVoteExtension) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_VerifyVoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.VerifyVoteExtension != nil { + { + size, err := m.VerifyVoteExtension.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa2 + } + return len(dAtA) - i, nil +} +func (m *Response_FinalizeBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Response_FinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.FinalizeBlock != nil { + { + size, err := m.FinalizeBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xaa + } + return len(dAtA) - i, nil +} +func (m *ResponseInitChain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseInitChain) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseInitChain) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x1a + } + if len(m.Validators) > 0 { + for iNdEx := len(m.Validators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Validators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.ConsensusParams != nil { + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ResponseCheckTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseCheckTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseCheckTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Codespace) > 0 { + i -= len(m.Codespace) + copy(dAtA[i:], m.Codespace) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Codespace))) + i-- + dAtA[i] = 0x42 + } + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if m.GasUsed != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + i-- + dAtA[i] = 0x30 + } + if m.GasWanted != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + i-- + dAtA[i] = 0x28 + } + if len(m.Info) > 0 { + i -= len(m.Info) + copy(dAtA[i:], m.Info) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i-- + dAtA[i] = 0x22 + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x1a + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseCommit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseCommit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.RetainHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.RetainHeight)) + i-- + dAtA[i] = 0x18 + } + return len(dAtA) - i, nil +} + +func (m *ResponseExtendVote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseExtendVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseExtendVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VoteExtension) > 0 { + i -= len(m.VoteExtension) + copy(dAtA[i:], m.VoteExtension) + i = encodeVarintTypes(dAtA, i, uint64(len(m.VoteExtension))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ResponseVerifyVoteExtension) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseVerifyVoteExtension) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseVerifyVoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Status != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ResponseFinalizeBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseFinalizeBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseFinalizeBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x2a + } + if m.ConsensusParamUpdates != nil { + { + size, err := m.ConsensusParamUpdates.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if len(m.ValidatorUpdates) > 0 { + for iNdEx := len(m.ValidatorUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ValidatorUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.TxResults) > 0 { + for iNdEx := len(m.TxResults) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TxResults[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *VoteInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VoteInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BlockIdFlag != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.BlockIdFlag)) + i-- + dAtA[i] = 0x18 + } + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ExtendedVoteInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExtendedVoteInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExtendedVoteInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BlockIdFlag != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.BlockIdFlag)) + i-- + dAtA[i] = 0x28 + } + if len(m.ExtensionSignature) > 0 { + i -= len(m.ExtensionSignature) + copy(dAtA[i:], m.ExtensionSignature) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ExtensionSignature))) + i-- + dAtA[i] = 0x22 + } + if len(m.VoteExtension) > 0 { + i -= len(m.VoteExtension) + copy(dAtA[i:], m.VoteExtension) + i = encodeVarintTypes(dAtA, i, uint64(len(m.VoteExtension))) + i-- + dAtA[i] = 0x1a + } + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *CommitInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CommitInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ExtendedCommitInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExtendedCommitInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExtendedCommitInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ExecTxResult) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExecTxResult) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExecTxResult) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Codespace) > 0 { + i -= len(m.Codespace) + copy(dAtA[i:], m.Codespace) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Codespace))) + i-- + dAtA[i] = 0x42 + } + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if m.GasUsed != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + i-- + dAtA[i] = 0x30 + } + if m.GasWanted != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + i-- + dAtA[i] = 0x28 + } + if len(m.Info) > 0 { + i -= len(m.Info) + copy(dAtA[i:], m.Info) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i-- + dAtA[i] = 0x22 + } + if len(m.Log) > 0 { + i -= len(m.Log) + copy(dAtA[i:], m.Log) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i-- + dAtA[i] = 0x1a + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *TxResult) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TxResult) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TxResult) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Result.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.Tx) > 0 { + i -= len(m.Tx) + copy(dAtA[i:], m.Tx) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) + i-- + dAtA[i] = 0x1a + } + if m.Index != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Request) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != nil { + n += m.Value.Size() + } + return n +} + +func (m *Request_Echo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Echo != nil { + l = m.Echo.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Flush) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Flush != nil { + l = m.Flush.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Info) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_InitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.InitChain != nil { + l = m.InitChain.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Query) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Query != nil { + l = m.Query.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_CheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Commit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ListSnapshots) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ListSnapshots != nil { + l = m.ListSnapshots.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_OfferSnapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.OfferSnapshot != nil { + l = m.OfferSnapshot.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_LoadSnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LoadSnapshotChunk != nil { + l = m.LoadSnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ApplySnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ApplySnapshotChunk != nil { + l = m.ApplySnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_PrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PrepareProposal != nil { + l = m.PrepareProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProcessProposal != nil { + l = m.ProcessProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_ExtendVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ExtendVote != nil { + l = m.ExtendVote.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_VerifyVoteExtension) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.VerifyVoteExtension != nil { + l = m.VerifyVoteExtension.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_FinalizeBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FinalizeBlock != nil { + l = m.FinalizeBlock.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *RequestInitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.ConsensusParams != nil { + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.AppStateBytes) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.InitialHeight != 0 { + n += 1 + sovTypes(uint64(m.InitialHeight)) + } + return n +} + +func (m *RequestPrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxTxBytes != 0 { + n += 1 + sovTypes(uint64(m.MaxTxBytes)) + } + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.LocalLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.ProposedLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestExtendVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.ProposedLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestVerifyVoteExtension) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = len(m.VoteExtension) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestFinalizeBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.DecidedLastCommit.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Misbehavior) > 0 { + for _, e := range m.Misbehavior { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Response) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Value != nil { + n += m.Value.Size() + } + return n +} + +func (m *Response_Exception) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Exception != nil { + l = m.Exception.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Echo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Echo != nil { + l = m.Echo.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Flush) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Flush != nil { + l = m.Flush.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Info) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_InitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.InitChain != nil { + l = m.InitChain.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Query) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Query != nil { + l = m.Query.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_CheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Commit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ListSnapshots) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ListSnapshots != nil { + l = m.ListSnapshots.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_OfferSnapshot) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.OfferSnapshot != nil { + l = m.OfferSnapshot.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_LoadSnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LoadSnapshotChunk != nil { + l = m.LoadSnapshotChunk.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ApplySnapshotChunk) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ApplySnapshotChunk != nil { + l = m.ApplySnapshotChunk.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_PrepareProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PrepareProposal != nil { + l = m.PrepareProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ProcessProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProcessProposal != nil { + l = m.ProcessProposal.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_ExtendVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ExtendVote != nil { + l = m.ExtendVote.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_VerifyVoteExtension) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.VerifyVoteExtension != nil { + l = m.VerifyVoteExtension.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_FinalizeBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FinalizeBlock != nil { + l = m.FinalizeBlock.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *ResponseInitChain) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ConsensusParams != nil { + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseCheckTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Codespace) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseCommit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.RetainHeight != 0 { + n += 1 + sovTypes(uint64(m.RetainHeight)) + } + return n +} + +func (m *ResponseExtendVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.VoteExtension) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseVerifyVoteExtension) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Status != 0 { + n += 1 + sovTypes(uint64(m.Status)) + } + return n +} + +func (m *ResponseFinalizeBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if len(m.TxResults) > 0 { + for _, e := range m.TxResults { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if len(m.ValidatorUpdates) > 0 { + for _, e := range m.ValidatorUpdates { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.ConsensusParamUpdates != nil { + l = m.ConsensusParamUpdates.Size() + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *VoteInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.BlockIdFlag != 0 { + n += 1 + sovTypes(uint64(m.BlockIdFlag)) + } + return n +} + +func (m *ExtendedVoteInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.VoteExtension) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ExtensionSignature) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.BlockIdFlag != 0 { + n += 1 + sovTypes(uint64(m.BlockIdFlag)) + } + return n +} + +func (m *CommitInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ExtendedCommitInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ExecTxResult) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.Codespace) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *TxResult) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Index != 0 { + n += 1 + sovTypes(uint64(m.Index)) + } + l = len(m.Tx) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Result.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Request) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Request: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Request: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Echo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestEcho{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Echo{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Flush", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestFlush{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Flush{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta2.RequestInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Info{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestInitChain{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_InitChain{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestQuery{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Query{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestCheckTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_CheckTx{v} + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestCommit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Commit{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListSnapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestListSnapshots{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ListSnapshots{v} + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OfferSnapshot", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestOfferSnapshot{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_OfferSnapshot{v} + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LoadSnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestLoadSnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_LoadSnapshotChunk{v} + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplySnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.RequestApplySnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ApplySnapshotChunk{v} + iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PrepareProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestPrepareProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_PrepareProposal{v} + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProcessProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestProcessProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ProcessProposal{v} + iNdEx = postIndex + case 18: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExtendVote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestExtendVote{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_ExtendVote{v} + iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VerifyVoteExtension", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestVerifyVoteExtension{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_VerifyVoteExtension{v} + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FinalizeBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestFinalizeBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_FinalizeBlock{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestInitChain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestInitChain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParams == nil { + m.ConsensusParams = &v1.ConsensusParams{} + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, v1beta1.ValidatorUpdate{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppStateBytes", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppStateBytes = append(m.AppStateBytes[:0], dAtA[iNdEx:postIndex]...) + if m.AppStateBytes == nil { + m.AppStateBytes = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialHeight", wireType) + } + m.InitialHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestPrepareProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestPrepareProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestPrepareProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxTxBytes", wireType) + } + m.MaxTxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxTxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LocalLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, v1beta2.Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestProcessProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestProcessProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestProcessProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposedLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ProposedLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, v1beta2.Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestExtendVote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestExtendVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestExtendVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposedLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ProposedLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, v1beta2.Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestVerifyVoteExtension) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestVerifyVoteExtension: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestVerifyVoteExtension: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddress = append(m.ValidatorAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ValidatorAddress == nil { + m.ValidatorAddress = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtension", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoteExtension = append(m.VoteExtension[:0], dAtA[iNdEx:postIndex]...) + if m.VoteExtension == nil { + m.VoteExtension = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestFinalizeBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestFinalizeBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestFinalizeBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DecidedLastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.DecidedLastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Misbehavior", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Misbehavior = append(m.Misbehavior, v1beta2.Misbehavior{}) + if err := m.Misbehavior[len(m.Misbehavior)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Response) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Response: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Response: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Exception", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseException{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Exception{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Echo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseEcho{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Echo{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Flush", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseFlush{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Flush{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Info{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseInitChain{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_InitChain{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseQuery{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Query{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseCheckTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_CheckTx{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseCommit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Commit{v} + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListSnapshots", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseListSnapshots{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ListSnapshots{v} + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OfferSnapshot", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseOfferSnapshot{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_OfferSnapshot{v} + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LoadSnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseLoadSnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_LoadSnapshotChunk{v} + iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplySnapshotChunk", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta1.ResponseApplySnapshotChunk{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ApplySnapshotChunk{v} + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PrepareProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta2.ResponsePrepareProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_PrepareProposal{v} + iNdEx = postIndex + case 18: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProcessProposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1beta2.ResponseProcessProposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ProcessProposal{v} + iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExtendVote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseExtendVote{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_ExtendVote{v} + iNdEx = postIndex + case 20: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VerifyVoteExtension", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseVerifyVoteExtension{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_VerifyVoteExtension{v} + iNdEx = postIndex + case 21: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FinalizeBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseFinalizeBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_FinalizeBlock{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseInitChain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParams == nil { + m.ConsensusParams = &v1.ConsensusParams{} + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, v1beta1.ValidatorUpdate{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseCheckTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseCheckTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, v1beta2.Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Codespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Codespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseCommit) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseCommit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseCommit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RetainHeight", wireType) + } + m.RetainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.RetainHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseExtendVote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseExtendVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseExtendVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtension", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoteExtension = append(m.VoteExtension[:0], dAtA[iNdEx:postIndex]...) + if m.VoteExtension == nil { + m.VoteExtension = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseVerifyVoteExtension) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseVerifyVoteExtension: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseVerifyVoteExtension: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= ResponseVerifyVoteExtension_VerifyStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseFinalizeBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseFinalizeBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseFinalizeBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, v1beta2.Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxResults", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TxResults = append(m.TxResults, &ExecTxResult{}) + if err := m.TxResults[len(m.TxResults)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorUpdates = append(m.ValidatorUpdates, v1beta1.ValidatorUpdate{}) + if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParamUpdates == nil { + m.ConsensusParamUpdates = &v1.ConsensusParams{} + } + if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VoteInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VoteInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VoteInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockIdFlag", wireType) + } + m.BlockIdFlag = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockIdFlag |= v1beta11.BlockIDFlag(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExtendedVoteInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExtendedVoteInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExtendedVoteInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtension", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VoteExtension = append(m.VoteExtension[:0], dAtA[iNdEx:postIndex]...) + if m.VoteExtension == nil { + m.VoteExtension = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExtensionSignature", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExtensionSignature = append(m.ExtensionSignature[:0], dAtA[iNdEx:postIndex]...) + if m.ExtensionSignature == nil { + m.ExtensionSignature = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockIdFlag", wireType) + } + m.BlockIdFlag = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockIdFlag |= v1beta11.BlockIDFlag(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CommitInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CommitInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, VoteInfo{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExtendedCommitInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExtendedCommitInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExtendedCommitInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, ExtendedVoteInfo{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExecTxResult) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExecTxResult: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExecTxResult: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, v1beta2.Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Codespace", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Codespace = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TxResult) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TxResult: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TxResult: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tx", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) + if m.Tx == nil { + m.Tx = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Result.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/tendermint/blocksync/message.go b/api/cometbft/blocksync/v1/message.go similarity index 85% rename from proto/tendermint/blocksync/message.go rename to api/cometbft/blocksync/v1/message.go index bce83de14ce..8b5bec3fcc9 100644 --- a/proto/tendermint/blocksync/message.go +++ b/api/cometbft/blocksync/v1/message.go @@ -1,19 +1,11 @@ -package blocksync +package v1 import ( "fmt" "github.com/cosmos/gogoproto/proto" - - "github.com/cometbft/cometbft/p2p" ) -var _ p2p.Wrapper = &StatusRequest{} -var _ p2p.Wrapper = &StatusResponse{} -var _ p2p.Wrapper = &NoBlockResponse{} -var _ p2p.Wrapper = &BlockResponse{} -var _ p2p.Wrapper = &BlockRequest{} - const ( BlockResponseMessagePrefixSize = 4 BlockResponseMessageFieldKeySize = 1 diff --git a/proto/tendermint/blocksync/types.pb.go b/api/cometbft/blocksync/v1/types.pb.go similarity index 89% rename from proto/tendermint/blocksync/types.pb.go rename to api/cometbft/blocksync/v1/types.pb.go index a9791970993..f1fde53df04 100644 --- a/proto/tendermint/blocksync/types.pb.go +++ b/api/cometbft/blocksync/v1/types.pb.go @@ -1,11 +1,11 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/blocksync/types.proto +// source: cometbft/blocksync/v1/types.proto -package blocksync +package v1 import ( fmt "fmt" - types "github.com/cometbft/cometbft/proto/tendermint/types" + v1 "github.com/cometbft/cometbft/api/cometbft/types/v1" proto "github.com/cosmos/gogoproto/proto" io "io" math "math" @@ -32,7 +32,7 @@ func (m *BlockRequest) Reset() { *m = BlockRequest{} } func (m *BlockRequest) String() string { return proto.CompactTextString(m) } func (*BlockRequest) ProtoMessage() {} func (*BlockRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_19b397c236e0fa07, []int{0} + return fileDescriptor_67182bd6cb30f2ef, []int{0} } func (m *BlockRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -77,7 +77,7 @@ func (m *NoBlockResponse) Reset() { *m = NoBlockResponse{} } func (m *NoBlockResponse) String() string { return proto.CompactTextString(m) } func (*NoBlockResponse) ProtoMessage() {} func (*NoBlockResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_19b397c236e0fa07, []int{1} + return fileDescriptor_67182bd6cb30f2ef, []int{1} } func (m *NoBlockResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -113,59 +113,6 @@ func (m *NoBlockResponse) GetHeight() int64 { return 0 } -// BlockResponse returns block to the requested -type BlockResponse struct { - Block *types.Block `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - ExtCommit *types.ExtendedCommit `protobuf:"bytes,2,opt,name=ext_commit,json=extCommit,proto3" json:"ext_commit,omitempty"` -} - -func (m *BlockResponse) Reset() { *m = BlockResponse{} } -func (m *BlockResponse) String() string { return proto.CompactTextString(m) } -func (*BlockResponse) ProtoMessage() {} -func (*BlockResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_19b397c236e0fa07, []int{2} -} -func (m *BlockResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *BlockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_BlockResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *BlockResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_BlockResponse.Merge(m, src) -} -func (m *BlockResponse) XXX_Size() int { - return m.Size() -} -func (m *BlockResponse) XXX_DiscardUnknown() { - xxx_messageInfo_BlockResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_BlockResponse proto.InternalMessageInfo - -func (m *BlockResponse) GetBlock() *types.Block { - if m != nil { - return m.Block - } - return nil -} - -func (m *BlockResponse) GetExtCommit() *types.ExtendedCommit { - if m != nil { - return m.ExtCommit - } - return nil -} - // StatusRequest requests the status of a peer. type StatusRequest struct { } @@ -174,7 +121,7 @@ func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (m *StatusRequest) String() string { return proto.CompactTextString(m) } func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_19b397c236e0fa07, []int{3} + return fileDescriptor_67182bd6cb30f2ef, []int{2} } func (m *StatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -213,7 +160,7 @@ func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_19b397c236e0fa07, []int{4} + return fileDescriptor_67182bd6cb30f2ef, []int{3} } func (m *StatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -256,7 +203,63 @@ func (m *StatusResponse) GetBase() int64 { return 0 } +// BlockResponse returns block to the requested +type BlockResponse struct { + Block *v1.Block `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + ExtCommit *v1.ExtendedCommit `protobuf:"bytes,2,opt,name=ext_commit,json=extCommit,proto3" json:"ext_commit,omitempty"` +} + +func (m *BlockResponse) Reset() { *m = BlockResponse{} } +func (m *BlockResponse) String() string { return proto.CompactTextString(m) } +func (*BlockResponse) ProtoMessage() {} +func (*BlockResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_67182bd6cb30f2ef, []int{4} +} +func (m *BlockResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockResponse.Merge(m, src) +} +func (m *BlockResponse) XXX_Size() int { + return m.Size() +} +func (m *BlockResponse) XXX_DiscardUnknown() { + xxx_messageInfo_BlockResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockResponse proto.InternalMessageInfo + +func (m *BlockResponse) GetBlock() *v1.Block { + if m != nil { + return m.Block + } + return nil +} + +func (m *BlockResponse) GetExtCommit() *v1.ExtendedCommit { + if m != nil { + return m.ExtCommit + } + return nil +} + +// Message is an abstract blocksync message. type Message struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Sum: // *Message_BlockRequest // *Message_NoBlockResponse @@ -270,7 +273,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_19b397c236e0fa07, []int{5} + return fileDescriptor_67182bd6cb30f2ef, []int{5} } func (m *Message) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -381,44 +384,44 @@ func (*Message) XXX_OneofWrappers() []interface{} { } func init() { - proto.RegisterType((*BlockRequest)(nil), "tendermint.blocksync.BlockRequest") - proto.RegisterType((*NoBlockResponse)(nil), "tendermint.blocksync.NoBlockResponse") - proto.RegisterType((*BlockResponse)(nil), "tendermint.blocksync.BlockResponse") - proto.RegisterType((*StatusRequest)(nil), "tendermint.blocksync.StatusRequest") - proto.RegisterType((*StatusResponse)(nil), "tendermint.blocksync.StatusResponse") - proto.RegisterType((*Message)(nil), "tendermint.blocksync.Message") -} - -func init() { proto.RegisterFile("tendermint/blocksync/types.proto", fileDescriptor_19b397c236e0fa07) } - -var fileDescriptor_19b397c236e0fa07 = []byte{ - // 405 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x93, 0xcd, 0x4a, 0xc3, 0x40, - 0x14, 0x85, 0x13, 0xd3, 0x56, 0xbc, 0x36, 0x0d, 0x06, 0xd1, 0x22, 0x12, 0x4a, 0xfc, 0x41, 0x17, - 0x26, 0xa0, 0x0b, 0x37, 0x82, 0x50, 0x11, 0x2a, 0xf8, 0x83, 0xe9, 0xce, 0x4d, 0xe9, 0xa4, 0x63, - 0x1b, 0x34, 0x99, 0xda, 0x99, 0x40, 0xbb, 0xf2, 0x15, 0x7c, 0x01, 0xdf, 0xc7, 0x65, 0x97, 0x2e, - 0xa5, 0x7d, 0x11, 0xe9, 0x4c, 0x9a, 0xa6, 0x31, 0x66, 0x37, 0xb9, 0x73, 0xee, 0x97, 0x73, 0xee, - 0x65, 0xa0, 0xc6, 0x70, 0xd0, 0xc1, 0x03, 0xdf, 0x0b, 0x98, 0x8d, 0x5e, 0x89, 0xfb, 0x42, 0x47, - 0x81, 0x6b, 0xb3, 0x51, 0x1f, 0x53, 0xab, 0x3f, 0x20, 0x8c, 0xe8, 0x9b, 0x0b, 0x85, 0x15, 0x2b, - 0x76, 0x76, 0x13, 0x7d, 0x5c, 0x2d, 0xba, 0x45, 0x4f, 0xc6, 0x6d, 0x82, 0x68, 0x1e, 0x42, 0xb9, - 0x3e, 0x13, 0x3b, 0xf8, 0x2d, 0xc4, 0x94, 0xe9, 0x5b, 0x50, 0xea, 0x61, 0xaf, 0xdb, 0x63, 0x55, - 0xb9, 0x26, 0x1f, 0x29, 0x4e, 0xf4, 0x65, 0x1e, 0x83, 0x76, 0x4f, 0x22, 0x25, 0xed, 0x93, 0x80, - 0xe2, 0x7f, 0xa5, 0xef, 0xa0, 0x2e, 0x0b, 0x4f, 0xa0, 0xc8, 0x0d, 0x71, 0xdd, 0xfa, 0xe9, 0xb6, - 0x95, 0x48, 0x21, 0xbc, 0x08, 0xbd, 0x50, 0xe9, 0x97, 0x00, 0x78, 0xc8, 0x5a, 0x2e, 0xf1, 0x7d, - 0x8f, 0x55, 0x57, 0x78, 0x4f, 0xed, 0x6f, 0xcf, 0xf5, 0x90, 0x97, 0x3a, 0x57, 0x5c, 0xe7, 0xac, - 0xe1, 0x21, 0x13, 0x47, 0x53, 0x03, 0xb5, 0xc9, 0xda, 0x2c, 0xa4, 0x51, 0x28, 0xf3, 0x02, 0x2a, - 0xf3, 0x42, 0xbe, 0x77, 0x5d, 0x87, 0x02, 0x6a, 0x53, 0xcc, 0xff, 0xaa, 0x38, 0xfc, 0x6c, 0x7e, - 0x2a, 0xb0, 0x7a, 0x87, 0x29, 0x6d, 0x77, 0xb1, 0x7e, 0x03, 0x2a, 0x37, 0xd9, 0x1a, 0x08, 0x74, - 0x14, 0xc9, 0xb4, 0xb2, 0x16, 0x63, 0x25, 0x27, 0xdb, 0x90, 0x9c, 0x32, 0x4a, 0x4e, 0xba, 0x09, - 0x1b, 0x01, 0x69, 0xcd, 0x69, 0xc2, 0x57, 0x94, 0xf6, 0x20, 0x1b, 0x97, 0x5a, 0x40, 0x43, 0x72, - 0xb4, 0x20, 0xb5, 0x93, 0x5b, 0xa8, 0xa4, 0x88, 0x0a, 0x27, 0xee, 0xe5, 0x1a, 0x8c, 0x79, 0x2a, - 0x4a, 0xd3, 0x28, 0x9f, 0x5b, 0x1c, 0xb7, 0x90, 0x47, 0x5b, 0x1a, 0xfa, 0x8c, 0x46, 0x93, 0x05, - 0xfd, 0x01, 0xb4, 0x98, 0x16, 0x99, 0x2b, 0x72, 0xdc, 0x7e, 0x3e, 0x2e, 0x76, 0x57, 0xa1, 0x4b, - 0x95, 0x7a, 0x11, 0x14, 0x1a, 0xfa, 0xf5, 0xc7, 0xaf, 0x89, 0x21, 0x8f, 0x27, 0x86, 0xfc, 0x33, - 0x31, 0xe4, 0x8f, 0xa9, 0x21, 0x8d, 0xa7, 0x86, 0xf4, 0x3d, 0x35, 0xa4, 0xa7, 0xf3, 0xae, 0xc7, - 0x7a, 0x21, 0xb2, 0x5c, 0xe2, 0xdb, 0x2e, 0xf1, 0x31, 0x43, 0xcf, 0x6c, 0x71, 0xe0, 0x0f, 0xc0, - 0xce, 0x7a, 0x73, 0xa8, 0xc4, 0xef, 0xce, 0x7e, 0x03, 0x00, 0x00, 0xff, 0xff, 0x56, 0x8a, 0x71, - 0xcf, 0x92, 0x03, 0x00, 0x00, + proto.RegisterType((*BlockRequest)(nil), "cometbft.blocksync.v1.BlockRequest") + proto.RegisterType((*NoBlockResponse)(nil), "cometbft.blocksync.v1.NoBlockResponse") + proto.RegisterType((*StatusRequest)(nil), "cometbft.blocksync.v1.StatusRequest") + proto.RegisterType((*StatusResponse)(nil), "cometbft.blocksync.v1.StatusResponse") + proto.RegisterType((*BlockResponse)(nil), "cometbft.blocksync.v1.BlockResponse") + proto.RegisterType((*Message)(nil), "cometbft.blocksync.v1.Message") +} + +func init() { proto.RegisterFile("cometbft/blocksync/v1/types.proto", fileDescriptor_67182bd6cb30f2ef) } + +var fileDescriptor_67182bd6cb30f2ef = []byte{ + // 416 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xcf, 0x6e, 0xda, 0x40, + 0x10, 0xc6, 0xed, 0x1a, 0xa8, 0x3a, 0x60, 0xac, 0x5a, 0x6a, 0x85, 0x2a, 0xd5, 0x2a, 0x6e, 0x8b, + 0xda, 0xcb, 0x5a, 0x50, 0xa9, 0xa7, 0x1e, 0x2a, 0xa2, 0x48, 0x28, 0x12, 0x11, 0x72, 0x72, 0xca, + 0x05, 0xd9, 0x66, 0x03, 0x56, 0x62, 0xaf, 0xc3, 0xae, 0x11, 0x1c, 0xf3, 0x06, 0x79, 0x86, 0x3c, + 0x4d, 0x8e, 0x1c, 0x73, 0x8c, 0xe0, 0x45, 0x22, 0xaf, 0xcd, 0xca, 0x58, 0x86, 0xdc, 0xc6, 0xb3, + 0xdf, 0xf7, 0xf3, 0xfc, 0xd1, 0x40, 0xdb, 0x23, 0x01, 0x66, 0xee, 0x35, 0xb3, 0xdc, 0x5b, 0xe2, + 0xdd, 0xd0, 0x55, 0xe8, 0x59, 0x8b, 0xae, 0xc5, 0x56, 0x11, 0xa6, 0x28, 0x9a, 0x13, 0x46, 0xf4, + 0x4f, 0x3b, 0x09, 0x12, 0x12, 0xb4, 0xe8, 0x7e, 0xf9, 0x2a, 0x9c, 0x5c, 0x9c, 0xb8, 0xf8, 0x7b, + 0xea, 0x2a, 0x7b, 0xce, 0x41, 0xcd, 0x0e, 0x34, 0xfa, 0x89, 0xda, 0xc6, 0x77, 0x31, 0xa6, 0x4c, + 0xff, 0x0c, 0xb5, 0x19, 0xf6, 0xa7, 0x33, 0xd6, 0x92, 0xbf, 0xc9, 0xbf, 0x14, 0x3b, 0xfb, 0x32, + 0x7f, 0x83, 0x76, 0x4e, 0x32, 0x25, 0x8d, 0x48, 0x48, 0xf1, 0x41, 0xa9, 0x06, 0xea, 0x05, 0x73, + 0x58, 0x4c, 0x33, 0xa6, 0xf9, 0x0f, 0x9a, 0xbb, 0xc4, 0x71, 0xab, 0xae, 0x43, 0xc5, 0x75, 0x28, + 0x6e, 0xbd, 0xe3, 0x59, 0x1e, 0x9b, 0xf7, 0x32, 0xa8, 0xfb, 0x3f, 0x46, 0x50, 0xe5, 0x1d, 0x72, + 0x73, 0xbd, 0xd7, 0x42, 0x62, 0x30, 0x69, 0x67, 0x8b, 0x2e, 0x4a, 0x0d, 0xa9, 0x4c, 0xff, 0x0f, + 0x80, 0x97, 0x6c, 0xec, 0x91, 0x20, 0xf0, 0x19, 0x67, 0xd7, 0x7b, 0xed, 0x12, 0xd3, 0xe9, 0x92, + 0xe1, 0x70, 0x82, 0x27, 0x27, 0x5c, 0x68, 0x7f, 0xc0, 0x4b, 0x96, 0x86, 0xe6, 0xa3, 0x02, 0xef, + 0x87, 0x98, 0x52, 0x67, 0x8a, 0xf5, 0x33, 0x50, 0x39, 0x76, 0x3c, 0x4f, 0xdb, 0xcb, 0xaa, 0xf8, + 0x8e, 0x4a, 0xd7, 0x83, 0xf2, 0xd3, 0x1d, 0x48, 0x76, 0xc3, 0xcd, 0x4f, 0xfb, 0x12, 0x3e, 0x86, + 0x64, 0xbc, 0xc3, 0xa5, 0xed, 0x65, 0x05, 0x76, 0x0e, 0xf0, 0x0a, 0x5b, 0x18, 0x48, 0xb6, 0x16, + 0x16, 0x16, 0x33, 0x84, 0x66, 0x01, 0xa9, 0x70, 0xe4, 0x8f, 0xe3, 0x25, 0x0a, 0xa0, 0xea, 0x16, + 0x71, 0x94, 0xaf, 0x4f, 0x74, 0x5c, 0x39, 0x8a, 0xdb, 0x5b, 0x7e, 0x82, 0xa3, 0xf9, 0x84, 0x3e, + 0x02, 0x4d, 0xe0, 0xb2, 0xf2, 0xaa, 0x9c, 0xf7, 0xf3, 0x0d, 0x9e, 0xa8, 0xaf, 0x49, 0xf7, 0x32, + 0xfd, 0x2a, 0x28, 0x34, 0x0e, 0xfa, 0xa3, 0xa7, 0x8d, 0x21, 0xaf, 0x37, 0x86, 0xfc, 0xb2, 0x31, + 0xe4, 0x87, 0xad, 0x21, 0xad, 0xb7, 0x86, 0xf4, 0xbc, 0x35, 0xa4, 0xab, 0xbf, 0x53, 0x9f, 0xcd, + 0x62, 0x37, 0xe1, 0x5b, 0xe2, 0x1c, 0x44, 0xe0, 0x44, 0xbe, 0x55, 0x7a, 0x7d, 0x6e, 0x8d, 0xdf, + 0xc8, 0x9f, 0xd7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0xa3, 0xca, 0xb4, 0x9d, 0x03, 0x00, 0x00, } func (m *BlockRequest) Marshal() (dAtA []byte, err error) { @@ -477,7 +480,7 @@ func (m *NoBlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *BlockResponse) Marshal() (dAtA []byte, err error) { +func (m *StatusRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -487,44 +490,20 @@ func (m *BlockResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *BlockResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *StatusRequest) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *BlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *StatusRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.ExtCommit != nil { - { - size, err := m.ExtCommit.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if m.Block != nil { - { - size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } return len(dAtA) - i, nil } -func (m *StatusRequest) Marshal() (dAtA []byte, err error) { +func (m *StatusResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -534,20 +513,30 @@ func (m *StatusRequest) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *StatusRequest) MarshalTo(dAtA []byte) (int, error) { +func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *StatusRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *StatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l + if m.Base != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Base)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } -func (m *StatusResponse) Marshal() (dAtA []byte, err error) { +func (m *BlockResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -557,25 +546,39 @@ func (m *StatusResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *BlockResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *StatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *BlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.Base != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.Base)) + if m.ExtCommit != nil { + { + size, err := m.ExtCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } i-- - dAtA[i] = 0x10 + dAtA[i] = 0x12 } - if m.Height != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + if m.Block != nil { + { + size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } i-- - dAtA[i] = 0x8 + dAtA[i] = 0xa } return len(dAtA) - i, nil } @@ -752,43 +755,43 @@ func (m *NoBlockResponse) Size() (n int) { return n } -func (m *BlockResponse) Size() (n int) { +func (m *StatusRequest) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.Block != nil { - l = m.Block.Size() - n += 1 + l + sovTypes(uint64(l)) - } - if m.ExtCommit != nil { - l = m.ExtCommit.Size() - n += 1 + l + sovTypes(uint64(l)) - } return n } -func (m *StatusRequest) Size() (n int) { +func (m *StatusResponse) Size() (n int) { if m == nil { return 0 } var l int _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Base != 0 { + n += 1 + sovTypes(uint64(m.Base)) + } return n } -func (m *StatusResponse) Size() (n int) { +func (m *BlockResponse) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.Height != 0 { - n += 1 + sovTypes(uint64(m.Height)) + if m.Block != nil { + l = m.Block.Size() + n += 1 + l + sovTypes(uint64(l)) } - if m.Base != 0 { - n += 1 + sovTypes(uint64(m.Base)) + if m.ExtCommit != nil { + l = m.ExtCommit.Size() + n += 1 + l + sovTypes(uint64(l)) } return n } @@ -1010,7 +1013,7 @@ func (m *NoBlockResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *BlockResponse) Unmarshal(dAtA []byte) error { +func (m *StatusRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1033,84 +1036,12 @@ func (m *BlockResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: BlockResponse: wiretype end group for non-group") + return fmt.Errorf("proto: StatusRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: BlockResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: StatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Block == nil { - m.Block = &types.Block{} - } - if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ExtCommit", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.ExtCommit == nil { - m.ExtCommit = &types.ExtendedCommit{} - } - if err := m.ExtCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -1132,7 +1063,7 @@ func (m *BlockResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *StatusRequest) Unmarshal(dAtA []byte) error { +func (m *StatusResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1155,12 +1086,50 @@ func (m *StatusRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: StatusRequest: wiretype end group for non-group") + return fmt.Errorf("proto: StatusResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: StatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: StatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Base", wireType) + } + m.Base = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Base |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -1182,7 +1151,7 @@ func (m *StatusRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *StatusResponse) Unmarshal(dAtA []byte) error { +func (m *BlockResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -1205,17 +1174,17 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: StatusResponse: wiretype end group for non-group") + return fmt.Errorf("proto: BlockResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: StatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: BlockResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) } - m.Height = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -1225,16 +1194,33 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Height |= int64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Block == nil { + m.Block = &v1.Block{} + } + if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Base", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExtCommit", wireType) } - m.Base = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -1244,11 +1230,28 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Base |= int64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ExtCommit == nil { + m.ExtCommit = &v1.ExtendedCommit{} + } + if err := m.ExtCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) diff --git a/api/cometbft/blocksync/v1beta1/message.go b/api/cometbft/blocksync/v1beta1/message.go new file mode 100644 index 00000000000..e43f971304e --- /dev/null +++ b/api/cometbft/blocksync/v1beta1/message.go @@ -0,0 +1,66 @@ +package v1beta1 + +import ( + "fmt" + + "github.com/cosmos/gogoproto/proto" +) + +const ( + BlockResponseMessagePrefixSize = 4 + BlockResponseMessageFieldKeySize = 1 +) + +func (m *BlockRequest) Wrap() proto.Message { + bm := &Message{} + bm.Sum = &Message_BlockRequest{BlockRequest: m} + return bm +} + +func (m *BlockResponse) Wrap() proto.Message { + bm := &Message{} + bm.Sum = &Message_BlockResponse{BlockResponse: m} + return bm +} + +func (m *NoBlockResponse) Wrap() proto.Message { + bm := &Message{} + bm.Sum = &Message_NoBlockResponse{NoBlockResponse: m} + return bm +} + +func (m *StatusRequest) Wrap() proto.Message { + bm := &Message{} + bm.Sum = &Message_StatusRequest{StatusRequest: m} + return bm +} + +func (m *StatusResponse) Wrap() proto.Message { + bm := &Message{} + bm.Sum = &Message_StatusResponse{StatusResponse: m} + return bm +} + +// Unwrap implements the p2p Wrapper interface and unwraps a wrapped blockchain +// message. +func (m *Message) Unwrap() (proto.Message, error) { + switch msg := m.Sum.(type) { + case *Message_BlockRequest: + return m.GetBlockRequest(), nil + + case *Message_BlockResponse: + return m.GetBlockResponse(), nil + + case *Message_NoBlockResponse: + return m.GetNoBlockResponse(), nil + + case *Message_StatusRequest: + return m.GetStatusRequest(), nil + + case *Message_StatusResponse: + return m.GetStatusResponse(), nil + + default: + return nil, fmt.Errorf("unknown message: %T", msg) + } +} diff --git a/api/cometbft/blocksync/v1beta1/types.pb.go b/api/cometbft/blocksync/v1beta1/types.pb.go new file mode 100644 index 00000000000..616c77efd35 --- /dev/null +++ b/api/cometbft/blocksync/v1beta1/types.pb.go @@ -0,0 +1,1524 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/blocksync/v1beta1/types.proto + +package v1beta1 + +import ( + fmt "fmt" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// BlockRequest requests a block for a specific height +type BlockRequest struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *BlockRequest) Reset() { *m = BlockRequest{} } +func (m *BlockRequest) String() string { return proto.CompactTextString(m) } +func (*BlockRequest) ProtoMessage() {} +func (*BlockRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1cc1b1b3561d256d, []int{0} +} +func (m *BlockRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockRequest.Merge(m, src) +} +func (m *BlockRequest) XXX_Size() int { + return m.Size() +} +func (m *BlockRequest) XXX_DiscardUnknown() { + xxx_messageInfo_BlockRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockRequest proto.InternalMessageInfo + +func (m *BlockRequest) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +// NoBlockResponse informs the node that the peer does not have block at the requested height +type NoBlockResponse struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *NoBlockResponse) Reset() { *m = NoBlockResponse{} } +func (m *NoBlockResponse) String() string { return proto.CompactTextString(m) } +func (*NoBlockResponse) ProtoMessage() {} +func (*NoBlockResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1cc1b1b3561d256d, []int{1} +} +func (m *NoBlockResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NoBlockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NoBlockResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NoBlockResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_NoBlockResponse.Merge(m, src) +} +func (m *NoBlockResponse) XXX_Size() int { + return m.Size() +} +func (m *NoBlockResponse) XXX_DiscardUnknown() { + xxx_messageInfo_NoBlockResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_NoBlockResponse proto.InternalMessageInfo + +func (m *NoBlockResponse) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +// BlockResponse returns block to the requested +type BlockResponse struct { + Block *v1beta1.Block `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` +} + +func (m *BlockResponse) Reset() { *m = BlockResponse{} } +func (m *BlockResponse) String() string { return proto.CompactTextString(m) } +func (*BlockResponse) ProtoMessage() {} +func (*BlockResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1cc1b1b3561d256d, []int{2} +} +func (m *BlockResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockResponse.Merge(m, src) +} +func (m *BlockResponse) XXX_Size() int { + return m.Size() +} +func (m *BlockResponse) XXX_DiscardUnknown() { + xxx_messageInfo_BlockResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockResponse proto.InternalMessageInfo + +func (m *BlockResponse) GetBlock() *v1beta1.Block { + if m != nil { + return m.Block + } + return nil +} + +// StatusRequest requests the status of a peer. +type StatusRequest struct { +} + +func (m *StatusRequest) Reset() { *m = StatusRequest{} } +func (m *StatusRequest) String() string { return proto.CompactTextString(m) } +func (*StatusRequest) ProtoMessage() {} +func (*StatusRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_1cc1b1b3561d256d, []int{3} +} +func (m *StatusRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *StatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_StatusRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *StatusRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_StatusRequest.Merge(m, src) +} +func (m *StatusRequest) XXX_Size() int { + return m.Size() +} +func (m *StatusRequest) XXX_DiscardUnknown() { + xxx_messageInfo_StatusRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_StatusRequest proto.InternalMessageInfo + +// StatusResponse is a peer response to inform their status. +type StatusResponse struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Base int64 `protobuf:"varint,2,opt,name=base,proto3" json:"base,omitempty"` +} + +func (m *StatusResponse) Reset() { *m = StatusResponse{} } +func (m *StatusResponse) String() string { return proto.CompactTextString(m) } +func (*StatusResponse) ProtoMessage() {} +func (*StatusResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_1cc1b1b3561d256d, []int{4} +} +func (m *StatusResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *StatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_StatusResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *StatusResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_StatusResponse.Merge(m, src) +} +func (m *StatusResponse) XXX_Size() int { + return m.Size() +} +func (m *StatusResponse) XXX_DiscardUnknown() { + xxx_messageInfo_StatusResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_StatusResponse proto.InternalMessageInfo + +func (m *StatusResponse) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *StatusResponse) GetBase() int64 { + if m != nil { + return m.Base + } + return 0 +} + +// Message is an abstract blocksync message. +type Message struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Sum: + // *Message_BlockRequest + // *Message_NoBlockResponse + // *Message_BlockResponse + // *Message_StatusRequest + // *Message_StatusResponse + Sum isMessage_Sum `protobuf_oneof:"sum"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_1cc1b1b3561d256d, []int{5} +} +func (m *Message) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return m.Size() +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +type isMessage_Sum interface { + isMessage_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Message_BlockRequest struct { + BlockRequest *BlockRequest `protobuf:"bytes,1,opt,name=block_request,json=blockRequest,proto3,oneof" json:"block_request,omitempty"` +} +type Message_NoBlockResponse struct { + NoBlockResponse *NoBlockResponse `protobuf:"bytes,2,opt,name=no_block_response,json=noBlockResponse,proto3,oneof" json:"no_block_response,omitempty"` +} +type Message_BlockResponse struct { + BlockResponse *BlockResponse `protobuf:"bytes,3,opt,name=block_response,json=blockResponse,proto3,oneof" json:"block_response,omitempty"` +} +type Message_StatusRequest struct { + StatusRequest *StatusRequest `protobuf:"bytes,4,opt,name=status_request,json=statusRequest,proto3,oneof" json:"status_request,omitempty"` +} +type Message_StatusResponse struct { + StatusResponse *StatusResponse `protobuf:"bytes,5,opt,name=status_response,json=statusResponse,proto3,oneof" json:"status_response,omitempty"` +} + +func (*Message_BlockRequest) isMessage_Sum() {} +func (*Message_NoBlockResponse) isMessage_Sum() {} +func (*Message_BlockResponse) isMessage_Sum() {} +func (*Message_StatusRequest) isMessage_Sum() {} +func (*Message_StatusResponse) isMessage_Sum() {} + +func (m *Message) GetSum() isMessage_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Message) GetBlockRequest() *BlockRequest { + if x, ok := m.GetSum().(*Message_BlockRequest); ok { + return x.BlockRequest + } + return nil +} + +func (m *Message) GetNoBlockResponse() *NoBlockResponse { + if x, ok := m.GetSum().(*Message_NoBlockResponse); ok { + return x.NoBlockResponse + } + return nil +} + +func (m *Message) GetBlockResponse() *BlockResponse { + if x, ok := m.GetSum().(*Message_BlockResponse); ok { + return x.BlockResponse + } + return nil +} + +func (m *Message) GetStatusRequest() *StatusRequest { + if x, ok := m.GetSum().(*Message_StatusRequest); ok { + return x.StatusRequest + } + return nil +} + +func (m *Message) GetStatusResponse() *StatusResponse { + if x, ok := m.GetSum().(*Message_StatusResponse); ok { + return x.StatusResponse + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Message) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Message_BlockRequest)(nil), + (*Message_NoBlockResponse)(nil), + (*Message_BlockResponse)(nil), + (*Message_StatusRequest)(nil), + (*Message_StatusResponse)(nil), + } +} + +func init() { + proto.RegisterType((*BlockRequest)(nil), "cometbft.blocksync.v1beta1.BlockRequest") + proto.RegisterType((*NoBlockResponse)(nil), "cometbft.blocksync.v1beta1.NoBlockResponse") + proto.RegisterType((*BlockResponse)(nil), "cometbft.blocksync.v1beta1.BlockResponse") + proto.RegisterType((*StatusRequest)(nil), "cometbft.blocksync.v1beta1.StatusRequest") + proto.RegisterType((*StatusResponse)(nil), "cometbft.blocksync.v1beta1.StatusResponse") + proto.RegisterType((*Message)(nil), "cometbft.blocksync.v1beta1.Message") +} + +func init() { + proto.RegisterFile("cometbft/blocksync/v1beta1/types.proto", fileDescriptor_1cc1b1b3561d256d) +} + +var fileDescriptor_1cc1b1b3561d256d = []byte{ + // 379 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xc1, 0x6a, 0xea, 0x40, + 0x14, 0x86, 0x93, 0x1b, 0xf5, 0xc2, 0xd1, 0x18, 0x6e, 0x16, 0x17, 0x11, 0x6e, 0xb8, 0x64, 0x21, + 0xda, 0xc2, 0x04, 0x75, 0xd9, 0xae, 0xa4, 0x0b, 0x37, 0x6d, 0x21, 0xc5, 0x45, 0xbb, 0x91, 0x8c, + 0x4c, 0x55, 0x5a, 0x33, 0xa9, 0x67, 0x52, 0xf0, 0x2d, 0xfa, 0x3e, 0x7d, 0x81, 0x2e, 0x5d, 0x76, + 0x59, 0xf4, 0x45, 0x8a, 0x93, 0x71, 0xd0, 0x80, 0xd6, 0xdd, 0xcc, 0xe1, 0x3f, 0xdf, 0xf9, 0xf3, + 0x67, 0x0e, 0x34, 0x46, 0x7c, 0xc6, 0x04, 0x7d, 0x14, 0x01, 0x7d, 0xe6, 0xa3, 0x27, 0x5c, 0xc4, + 0xa3, 0xe0, 0xb5, 0x4d, 0x99, 0x88, 0xda, 0x81, 0x58, 0x24, 0x0c, 0x49, 0x32, 0xe7, 0x82, 0xbb, + 0xf5, 0xad, 0x8e, 0x68, 0x1d, 0x51, 0xba, 0xba, 0xaf, 0x19, 0xb2, 0x43, 0xf7, 0x4b, 0x65, 0xd6, + 0xef, 0x37, 0xa0, 0xd2, 0xdb, 0x5c, 0x43, 0xf6, 0x92, 0x32, 0x14, 0xee, 0x5f, 0x28, 0x4d, 0xd8, + 0x74, 0x3c, 0x11, 0x35, 0xf3, 0xbf, 0xd9, 0xb4, 0x42, 0x75, 0xf3, 0x5b, 0xe0, 0xdc, 0x70, 0xa5, + 0xc4, 0x84, 0xc7, 0xc8, 0x0e, 0x4a, 0xaf, 0xc0, 0xde, 0x17, 0x76, 0xa1, 0x28, 0x47, 0x4a, 0x5d, + 0xb9, 0xf3, 0x8f, 0x68, 0xcf, 0xd9, 0x97, 0x28, 0x5f, 0x24, 0xeb, 0xca, 0xb4, 0xbe, 0x03, 0xf6, + 0x9d, 0x88, 0x44, 0x8a, 0xca, 0x99, 0x7f, 0x09, 0xd5, 0x6d, 0xe1, 0xb8, 0x01, 0xd7, 0x85, 0x02, + 0x8d, 0x90, 0xd5, 0x7e, 0xc9, 0xaa, 0x3c, 0xfb, 0xef, 0x16, 0xfc, 0xbe, 0x66, 0x88, 0xd1, 0x98, + 0xb9, 0xb7, 0x60, 0xcb, 0x19, 0xc3, 0x79, 0x86, 0x56, 0xbe, 0x9a, 0xe4, 0x70, 0x96, 0x64, 0x37, + 0xa4, 0xbe, 0x11, 0x56, 0xe8, 0x6e, 0x68, 0xf7, 0xf0, 0x27, 0xe6, 0xc3, 0x2d, 0x33, 0x73, 0x27, + 0xa7, 0x97, 0x3b, 0xe7, 0xc7, 0xa0, 0xb9, 0x44, 0xfb, 0x46, 0xe8, 0xc4, 0xb9, 0x90, 0x43, 0xa8, + 0xe6, 0xb8, 0x96, 0xe4, 0xb6, 0x4e, 0x30, 0xab, 0xa9, 0x36, 0xcd, 0x33, 0x51, 0x26, 0xa9, 0x03, + 0x28, 0xfc, 0xcc, 0xdc, 0xfb, 0x19, 0x1b, 0x26, 0xee, 0x16, 0xdc, 0x01, 0x38, 0x9a, 0xa9, 0x8c, + 0x16, 0x25, 0xf4, 0xec, 0x14, 0xa8, 0x76, 0x5a, 0xc5, 0xbd, 0x4a, 0xaf, 0x08, 0x16, 0xa6, 0xb3, + 0xde, 0xe0, 0x63, 0xe5, 0x99, 0xcb, 0x95, 0x67, 0x7e, 0xad, 0x3c, 0xf3, 0x6d, 0xed, 0x19, 0xcb, + 0xb5, 0x67, 0x7c, 0xae, 0x3d, 0xe3, 0xe1, 0x62, 0x3c, 0x15, 0x93, 0x94, 0x6e, 0x86, 0x04, 0xfa, + 0xb9, 0xeb, 0x43, 0x94, 0x4c, 0x83, 0xc3, 0x8b, 0x44, 0x4b, 0x72, 0x07, 0xba, 0xdf, 0x01, 0x00, + 0x00, 0xff, 0xff, 0x6b, 0xac, 0x9f, 0xc0, 0x6d, 0x03, 0x00, 0x00, +} + +func (m *BlockRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BlockRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *NoBlockResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NoBlockResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NoBlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *BlockResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Block != nil { + { + size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *StatusRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *StatusRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StatusRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *StatusResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *StatusResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Base != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Base)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Message) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Message) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Message_BlockRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_BlockRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BlockRequest != nil { + { + size, err := m.BlockRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Message_NoBlockResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_NoBlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.NoBlockResponse != nil { + { + size, err := m.NoBlockResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Message_BlockResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_BlockResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BlockResponse != nil { + { + size, err := m.BlockResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Message_StatusRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_StatusRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.StatusRequest != nil { + { + size, err := m.StatusRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Message_StatusResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_StatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.StatusResponse != nil { + { + size, err := m.StatusResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *BlockRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *NoBlockResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *BlockResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Block != nil { + l = m.Block.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *StatusRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *StatusResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Base != 0 { + n += 1 + sovTypes(uint64(m.Base)) + } + return n +} + +func (m *Message) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Message_BlockRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BlockRequest != nil { + l = m.BlockRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_NoBlockResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.NoBlockResponse != nil { + l = m.NoBlockResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_BlockResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BlockResponse != nil { + l = m.BlockResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_StatusRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.StatusRequest != nil { + l = m.StatusRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_StatusResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.StatusResponse != nil { + l = m.StatusResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *BlockRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NoBlockResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NoBlockResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NoBlockResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Block == nil { + m.Block = &v1beta1.Block{} + } + if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *StatusRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: StatusRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *StatusResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: StatusResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Base", wireType) + } + m.Base = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Base |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Message) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Message: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &BlockRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_BlockRequest{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NoBlockResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &NoBlockResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_NoBlockResponse{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &BlockResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_BlockResponse{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StatusRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &StatusRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_StatusRequest{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StatusResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &StatusResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_StatusResponse{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/tendermint/consensus/message.go b/api/cometbft/consensus/v1/message.go similarity index 84% rename from proto/tendermint/consensus/message.go rename to api/cometbft/consensus/v1/message.go index 782d30beeea..7dbbdb5b215 100644 --- a/proto/tendermint/consensus/message.go +++ b/api/cometbft/consensus/v1/message.go @@ -1,28 +1,15 @@ -package consensus +package v1 import ( "fmt" "github.com/cosmos/gogoproto/proto" - - "github.com/cometbft/cometbft/p2p" ) -var _ p2p.Wrapper = &VoteSetBits{} -var _ p2p.Wrapper = &VoteSetMaj23{} -var _ p2p.Wrapper = &Vote{} -var _ p2p.Wrapper = &ProposalPOL{} -var _ p2p.Wrapper = &Proposal{} -var _ p2p.Wrapper = &NewValidBlock{} -var _ p2p.Wrapper = &NewRoundStep{} -var _ p2p.Wrapper = &HasVote{} -var _ p2p.Wrapper = &BlockPart{} - func (m *VoteSetBits) Wrap() proto.Message { cm := &Message{} cm.Sum = &Message_VoteSetBits{VoteSetBits: m} return cm - } func (m *VoteSetMaj23) Wrap() proto.Message { @@ -73,6 +60,12 @@ func (m *NewRoundStep) Wrap() proto.Message { return cm } +func (m *HasProposalBlockPart) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_HasProposalBlockPart{HasProposalBlockPart: m} + return cm +} + // Unwrap implements the p2p Wrapper interface and unwraps a wrapped consensus // proto message. func (m *Message) Unwrap() (proto.Message, error) { @@ -98,6 +91,9 @@ func (m *Message) Unwrap() (proto.Message, error) { case *Message_HasVote: return m.GetHasVote(), nil + case *Message_HasProposalBlockPart: + return m.GetHasProposalBlockPart(), nil + case *Message_VoteSetMaj23: return m.GetVoteSetMaj23(), nil diff --git a/api/cometbft/consensus/v1/types.pb.go b/api/cometbft/consensus/v1/types.pb.go new file mode 100644 index 00000000000..3c75d7851f6 --- /dev/null +++ b/api/cometbft/consensus/v1/types.pb.go @@ -0,0 +1,3737 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/consensus/v1/types.proto + +package v1 + +import ( + fmt "fmt" + v11 "github.com/cometbft/cometbft/api/cometbft/libs/bits/v1" + v1 "github.com/cometbft/cometbft/api/cometbft/types/v1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// NewRoundStep is sent for every step taken in the ConsensusState. +// For every height/round/step transition +type NewRoundStep struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Step uint32 `protobuf:"varint,3,opt,name=step,proto3" json:"step,omitempty"` + SecondsSinceStartTime int64 `protobuf:"varint,4,opt,name=seconds_since_start_time,json=secondsSinceStartTime,proto3" json:"seconds_since_start_time,omitempty"` + LastCommitRound int32 `protobuf:"varint,5,opt,name=last_commit_round,json=lastCommitRound,proto3" json:"last_commit_round,omitempty"` +} + +func (m *NewRoundStep) Reset() { *m = NewRoundStep{} } +func (m *NewRoundStep) String() string { return proto.CompactTextString(m) } +func (*NewRoundStep) ProtoMessage() {} +func (*NewRoundStep) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{0} +} +func (m *NewRoundStep) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NewRoundStep) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NewRoundStep.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NewRoundStep) XXX_Merge(src proto.Message) { + xxx_messageInfo_NewRoundStep.Merge(m, src) +} +func (m *NewRoundStep) XXX_Size() int { + return m.Size() +} +func (m *NewRoundStep) XXX_DiscardUnknown() { + xxx_messageInfo_NewRoundStep.DiscardUnknown(m) +} + +var xxx_messageInfo_NewRoundStep proto.InternalMessageInfo + +func (m *NewRoundStep) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *NewRoundStep) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *NewRoundStep) GetStep() uint32 { + if m != nil { + return m.Step + } + return 0 +} + +func (m *NewRoundStep) GetSecondsSinceStartTime() int64 { + if m != nil { + return m.SecondsSinceStartTime + } + return 0 +} + +func (m *NewRoundStep) GetLastCommitRound() int32 { + if m != nil { + return m.LastCommitRound + } + return 0 +} + +// NewValidBlock is sent when a validator observes a valid block B in some round r, +// i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. +// In case the block is also committed, then IsCommit flag is set to true. +type NewValidBlock struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + BlockPartSetHeader v1.PartSetHeader `protobuf:"bytes,3,opt,name=block_part_set_header,json=blockPartSetHeader,proto3" json:"block_part_set_header"` + BlockParts *v11.BitArray `protobuf:"bytes,4,opt,name=block_parts,json=blockParts,proto3" json:"block_parts,omitempty"` + IsCommit bool `protobuf:"varint,5,opt,name=is_commit,json=isCommit,proto3" json:"is_commit,omitempty"` +} + +func (m *NewValidBlock) Reset() { *m = NewValidBlock{} } +func (m *NewValidBlock) String() string { return proto.CompactTextString(m) } +func (*NewValidBlock) ProtoMessage() {} +func (*NewValidBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{1} +} +func (m *NewValidBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NewValidBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NewValidBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NewValidBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_NewValidBlock.Merge(m, src) +} +func (m *NewValidBlock) XXX_Size() int { + return m.Size() +} +func (m *NewValidBlock) XXX_DiscardUnknown() { + xxx_messageInfo_NewValidBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_NewValidBlock proto.InternalMessageInfo + +func (m *NewValidBlock) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *NewValidBlock) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *NewValidBlock) GetBlockPartSetHeader() v1.PartSetHeader { + if m != nil { + return m.BlockPartSetHeader + } + return v1.PartSetHeader{} +} + +func (m *NewValidBlock) GetBlockParts() *v11.BitArray { + if m != nil { + return m.BlockParts + } + return nil +} + +func (m *NewValidBlock) GetIsCommit() bool { + if m != nil { + return m.IsCommit + } + return false +} + +// Proposal is sent when a new block is proposed. +type Proposal struct { + Proposal v1.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal"` +} + +func (m *Proposal) Reset() { *m = Proposal{} } +func (m *Proposal) String() string { return proto.CompactTextString(m) } +func (*Proposal) ProtoMessage() {} +func (*Proposal) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{2} +} +func (m *Proposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Proposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Proposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Proposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_Proposal.Merge(m, src) +} +func (m *Proposal) XXX_Size() int { + return m.Size() +} +func (m *Proposal) XXX_DiscardUnknown() { + xxx_messageInfo_Proposal.DiscardUnknown(m) +} + +var xxx_messageInfo_Proposal proto.InternalMessageInfo + +func (m *Proposal) GetProposal() v1.Proposal { + if m != nil { + return m.Proposal + } + return v1.Proposal{} +} + +// ProposalPOL is sent when a previous proposal is re-proposed. +type ProposalPOL struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + ProposalPolRound int32 `protobuf:"varint,2,opt,name=proposal_pol_round,json=proposalPolRound,proto3" json:"proposal_pol_round,omitempty"` + ProposalPol v11.BitArray `protobuf:"bytes,3,opt,name=proposal_pol,json=proposalPol,proto3" json:"proposal_pol"` +} + +func (m *ProposalPOL) Reset() { *m = ProposalPOL{} } +func (m *ProposalPOL) String() string { return proto.CompactTextString(m) } +func (*ProposalPOL) ProtoMessage() {} +func (*ProposalPOL) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{3} +} +func (m *ProposalPOL) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ProposalPOL) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ProposalPOL.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ProposalPOL) XXX_Merge(src proto.Message) { + xxx_messageInfo_ProposalPOL.Merge(m, src) +} +func (m *ProposalPOL) XXX_Size() int { + return m.Size() +} +func (m *ProposalPOL) XXX_DiscardUnknown() { + xxx_messageInfo_ProposalPOL.DiscardUnknown(m) +} + +var xxx_messageInfo_ProposalPOL proto.InternalMessageInfo + +func (m *ProposalPOL) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *ProposalPOL) GetProposalPolRound() int32 { + if m != nil { + return m.ProposalPolRound + } + return 0 +} + +func (m *ProposalPOL) GetProposalPol() v11.BitArray { + if m != nil { + return m.ProposalPol + } + return v11.BitArray{} +} + +// BlockPart is sent when gossipping a piece of the proposed block. +type BlockPart struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Part v1.Part `protobuf:"bytes,3,opt,name=part,proto3" json:"part"` +} + +func (m *BlockPart) Reset() { *m = BlockPart{} } +func (m *BlockPart) String() string { return proto.CompactTextString(m) } +func (*BlockPart) ProtoMessage() {} +func (*BlockPart) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{4} +} +func (m *BlockPart) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockPart) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockPart.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockPart) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockPart.Merge(m, src) +} +func (m *BlockPart) XXX_Size() int { + return m.Size() +} +func (m *BlockPart) XXX_DiscardUnknown() { + xxx_messageInfo_BlockPart.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockPart proto.InternalMessageInfo + +func (m *BlockPart) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *BlockPart) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *BlockPart) GetPart() v1.Part { + if m != nil { + return m.Part + } + return v1.Part{} +} + +// Vote is sent when voting for a proposal (or lack thereof). +type Vote struct { + Vote *v1.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` +} + +func (m *Vote) Reset() { *m = Vote{} } +func (m *Vote) String() string { return proto.CompactTextString(m) } +func (*Vote) ProtoMessage() {} +func (*Vote) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{5} +} +func (m *Vote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Vote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Vote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Vote) XXX_Merge(src proto.Message) { + xxx_messageInfo_Vote.Merge(m, src) +} +func (m *Vote) XXX_Size() int { + return m.Size() +} +func (m *Vote) XXX_DiscardUnknown() { + xxx_messageInfo_Vote.DiscardUnknown(m) +} + +var xxx_messageInfo_Vote proto.InternalMessageInfo + +func (m *Vote) GetVote() *v1.Vote { + if m != nil { + return m.Vote + } + return nil +} + +// HasVote is sent to indicate that a particular vote has been received. +type HasVote struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Type v1.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=cometbft.types.v1.SignedMsgType" json:"type,omitempty"` + Index int32 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` +} + +func (m *HasVote) Reset() { *m = HasVote{} } +func (m *HasVote) String() string { return proto.CompactTextString(m) } +func (*HasVote) ProtoMessage() {} +func (*HasVote) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{6} +} +func (m *HasVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *HasVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_HasVote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *HasVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_HasVote.Merge(m, src) +} +func (m *HasVote) XXX_Size() int { + return m.Size() +} +func (m *HasVote) XXX_DiscardUnknown() { + xxx_messageInfo_HasVote.DiscardUnknown(m) +} + +var xxx_messageInfo_HasVote proto.InternalMessageInfo + +func (m *HasVote) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *HasVote) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *HasVote) GetType() v1.SignedMsgType { + if m != nil { + return m.Type + } + return v1.UnknownType +} + +func (m *HasVote) GetIndex() int32 { + if m != nil { + return m.Index + } + return 0 +} + +// VoteSetMaj23 is sent to indicate that a given BlockID has seen +2/3 votes. +type VoteSetMaj23 struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Type v1.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=cometbft.types.v1.SignedMsgType" json:"type,omitempty"` + BlockID v1.BlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id"` +} + +func (m *VoteSetMaj23) Reset() { *m = VoteSetMaj23{} } +func (m *VoteSetMaj23) String() string { return proto.CompactTextString(m) } +func (*VoteSetMaj23) ProtoMessage() {} +func (*VoteSetMaj23) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{7} +} +func (m *VoteSetMaj23) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VoteSetMaj23) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VoteSetMaj23.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *VoteSetMaj23) XXX_Merge(src proto.Message) { + xxx_messageInfo_VoteSetMaj23.Merge(m, src) +} +func (m *VoteSetMaj23) XXX_Size() int { + return m.Size() +} +func (m *VoteSetMaj23) XXX_DiscardUnknown() { + xxx_messageInfo_VoteSetMaj23.DiscardUnknown(m) +} + +var xxx_messageInfo_VoteSetMaj23 proto.InternalMessageInfo + +func (m *VoteSetMaj23) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *VoteSetMaj23) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *VoteSetMaj23) GetType() v1.SignedMsgType { + if m != nil { + return m.Type + } + return v1.UnknownType +} + +func (m *VoteSetMaj23) GetBlockID() v1.BlockID { + if m != nil { + return m.BlockID + } + return v1.BlockID{} +} + +// VoteSetBits is sent to communicate the bit-array of votes seen for the BlockID. +type VoteSetBits struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Type v1.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=cometbft.types.v1.SignedMsgType" json:"type,omitempty"` + BlockID v1.BlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id"` + Votes v11.BitArray `protobuf:"bytes,5,opt,name=votes,proto3" json:"votes"` +} + +func (m *VoteSetBits) Reset() { *m = VoteSetBits{} } +func (m *VoteSetBits) String() string { return proto.CompactTextString(m) } +func (*VoteSetBits) ProtoMessage() {} +func (*VoteSetBits) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{8} +} +func (m *VoteSetBits) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VoteSetBits) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VoteSetBits.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *VoteSetBits) XXX_Merge(src proto.Message) { + xxx_messageInfo_VoteSetBits.Merge(m, src) +} +func (m *VoteSetBits) XXX_Size() int { + return m.Size() +} +func (m *VoteSetBits) XXX_DiscardUnknown() { + xxx_messageInfo_VoteSetBits.DiscardUnknown(m) +} + +var xxx_messageInfo_VoteSetBits proto.InternalMessageInfo + +func (m *VoteSetBits) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *VoteSetBits) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *VoteSetBits) GetType() v1.SignedMsgType { + if m != nil { + return m.Type + } + return v1.UnknownType +} + +func (m *VoteSetBits) GetBlockID() v1.BlockID { + if m != nil { + return m.BlockID + } + return v1.BlockID{} +} + +func (m *VoteSetBits) GetVotes() v11.BitArray { + if m != nil { + return m.Votes + } + return v11.BitArray{} +} + +// HasProposalBlockPart is sent to indicate that a particular proposal block part has been received. +type HasProposalBlockPart struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Index int32 `protobuf:"varint,3,opt,name=index,proto3" json:"index,omitempty"` +} + +func (m *HasProposalBlockPart) Reset() { *m = HasProposalBlockPart{} } +func (m *HasProposalBlockPart) String() string { return proto.CompactTextString(m) } +func (*HasProposalBlockPart) ProtoMessage() {} +func (*HasProposalBlockPart) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{9} +} +func (m *HasProposalBlockPart) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *HasProposalBlockPart) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_HasProposalBlockPart.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *HasProposalBlockPart) XXX_Merge(src proto.Message) { + xxx_messageInfo_HasProposalBlockPart.Merge(m, src) +} +func (m *HasProposalBlockPart) XXX_Size() int { + return m.Size() +} +func (m *HasProposalBlockPart) XXX_DiscardUnknown() { + xxx_messageInfo_HasProposalBlockPart.DiscardUnknown(m) +} + +var xxx_messageInfo_HasProposalBlockPart proto.InternalMessageInfo + +func (m *HasProposalBlockPart) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *HasProposalBlockPart) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *HasProposalBlockPart) GetIndex() int32 { + if m != nil { + return m.Index + } + return 0 +} + +// Message is an abstract consensus message. +type Message struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Sum: + // *Message_NewRoundStep + // *Message_NewValidBlock + // *Message_Proposal + // *Message_ProposalPol + // *Message_BlockPart + // *Message_Vote + // *Message_HasVote + // *Message_VoteSetMaj23 + // *Message_VoteSetBits + // *Message_HasProposalBlockPart + Sum isMessage_Sum `protobuf_oneof:"sum"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_4179ae4c5322abef, []int{10} +} +func (m *Message) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return m.Size() +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +type isMessage_Sum interface { + isMessage_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Message_NewRoundStep struct { + NewRoundStep *NewRoundStep `protobuf:"bytes,1,opt,name=new_round_step,json=newRoundStep,proto3,oneof" json:"new_round_step,omitempty"` +} +type Message_NewValidBlock struct { + NewValidBlock *NewValidBlock `protobuf:"bytes,2,opt,name=new_valid_block,json=newValidBlock,proto3,oneof" json:"new_valid_block,omitempty"` +} +type Message_Proposal struct { + Proposal *Proposal `protobuf:"bytes,3,opt,name=proposal,proto3,oneof" json:"proposal,omitempty"` +} +type Message_ProposalPol struct { + ProposalPol *ProposalPOL `protobuf:"bytes,4,opt,name=proposal_pol,json=proposalPol,proto3,oneof" json:"proposal_pol,omitempty"` +} +type Message_BlockPart struct { + BlockPart *BlockPart `protobuf:"bytes,5,opt,name=block_part,json=blockPart,proto3,oneof" json:"block_part,omitempty"` +} +type Message_Vote struct { + Vote *Vote `protobuf:"bytes,6,opt,name=vote,proto3,oneof" json:"vote,omitempty"` +} +type Message_HasVote struct { + HasVote *HasVote `protobuf:"bytes,7,opt,name=has_vote,json=hasVote,proto3,oneof" json:"has_vote,omitempty"` +} +type Message_VoteSetMaj23 struct { + VoteSetMaj23 *VoteSetMaj23 `protobuf:"bytes,8,opt,name=vote_set_maj23,json=voteSetMaj23,proto3,oneof" json:"vote_set_maj23,omitempty"` +} +type Message_VoteSetBits struct { + VoteSetBits *VoteSetBits `protobuf:"bytes,9,opt,name=vote_set_bits,json=voteSetBits,proto3,oneof" json:"vote_set_bits,omitempty"` +} +type Message_HasProposalBlockPart struct { + HasProposalBlockPart *HasProposalBlockPart `protobuf:"bytes,10,opt,name=has_proposal_block_part,json=hasProposalBlockPart,proto3,oneof" json:"has_proposal_block_part,omitempty"` +} + +func (*Message_NewRoundStep) isMessage_Sum() {} +func (*Message_NewValidBlock) isMessage_Sum() {} +func (*Message_Proposal) isMessage_Sum() {} +func (*Message_ProposalPol) isMessage_Sum() {} +func (*Message_BlockPart) isMessage_Sum() {} +func (*Message_Vote) isMessage_Sum() {} +func (*Message_HasVote) isMessage_Sum() {} +func (*Message_VoteSetMaj23) isMessage_Sum() {} +func (*Message_VoteSetBits) isMessage_Sum() {} +func (*Message_HasProposalBlockPart) isMessage_Sum() {} + +func (m *Message) GetSum() isMessage_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Message) GetNewRoundStep() *NewRoundStep { + if x, ok := m.GetSum().(*Message_NewRoundStep); ok { + return x.NewRoundStep + } + return nil +} + +func (m *Message) GetNewValidBlock() *NewValidBlock { + if x, ok := m.GetSum().(*Message_NewValidBlock); ok { + return x.NewValidBlock + } + return nil +} + +func (m *Message) GetProposal() *Proposal { + if x, ok := m.GetSum().(*Message_Proposal); ok { + return x.Proposal + } + return nil +} + +func (m *Message) GetProposalPol() *ProposalPOL { + if x, ok := m.GetSum().(*Message_ProposalPol); ok { + return x.ProposalPol + } + return nil +} + +func (m *Message) GetBlockPart() *BlockPart { + if x, ok := m.GetSum().(*Message_BlockPart); ok { + return x.BlockPart + } + return nil +} + +func (m *Message) GetVote() *Vote { + if x, ok := m.GetSum().(*Message_Vote); ok { + return x.Vote + } + return nil +} + +func (m *Message) GetHasVote() *HasVote { + if x, ok := m.GetSum().(*Message_HasVote); ok { + return x.HasVote + } + return nil +} + +func (m *Message) GetVoteSetMaj23() *VoteSetMaj23 { + if x, ok := m.GetSum().(*Message_VoteSetMaj23); ok { + return x.VoteSetMaj23 + } + return nil +} + +func (m *Message) GetVoteSetBits() *VoteSetBits { + if x, ok := m.GetSum().(*Message_VoteSetBits); ok { + return x.VoteSetBits + } + return nil +} + +func (m *Message) GetHasProposalBlockPart() *HasProposalBlockPart { + if x, ok := m.GetSum().(*Message_HasProposalBlockPart); ok { + return x.HasProposalBlockPart + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Message) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Message_NewRoundStep)(nil), + (*Message_NewValidBlock)(nil), + (*Message_Proposal)(nil), + (*Message_ProposalPol)(nil), + (*Message_BlockPart)(nil), + (*Message_Vote)(nil), + (*Message_HasVote)(nil), + (*Message_VoteSetMaj23)(nil), + (*Message_VoteSetBits)(nil), + (*Message_HasProposalBlockPart)(nil), + } +} + +func init() { + proto.RegisterType((*NewRoundStep)(nil), "cometbft.consensus.v1.NewRoundStep") + proto.RegisterType((*NewValidBlock)(nil), "cometbft.consensus.v1.NewValidBlock") + proto.RegisterType((*Proposal)(nil), "cometbft.consensus.v1.Proposal") + proto.RegisterType((*ProposalPOL)(nil), "cometbft.consensus.v1.ProposalPOL") + proto.RegisterType((*BlockPart)(nil), "cometbft.consensus.v1.BlockPart") + proto.RegisterType((*Vote)(nil), "cometbft.consensus.v1.Vote") + proto.RegisterType((*HasVote)(nil), "cometbft.consensus.v1.HasVote") + proto.RegisterType((*VoteSetMaj23)(nil), "cometbft.consensus.v1.VoteSetMaj23") + proto.RegisterType((*VoteSetBits)(nil), "cometbft.consensus.v1.VoteSetBits") + proto.RegisterType((*HasProposalBlockPart)(nil), "cometbft.consensus.v1.HasProposalBlockPart") + proto.RegisterType((*Message)(nil), "cometbft.consensus.v1.Message") +} + +func init() { proto.RegisterFile("cometbft/consensus/v1/types.proto", fileDescriptor_4179ae4c5322abef) } + +var fileDescriptor_4179ae4c5322abef = []byte{ + // 903 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcd, 0x6e, 0x23, 0x45, + 0x10, 0x9e, 0x21, 0x76, 0xec, 0x94, 0xf3, 0x03, 0xad, 0x84, 0xb5, 0xb2, 0xc2, 0x31, 0x03, 0x87, + 0x88, 0x45, 0xb6, 0xe2, 0x20, 0x38, 0xac, 0x90, 0xd8, 0x01, 0xc1, 0x44, 0xbb, 0xc9, 0x5a, 0xed, + 0xd5, 0x4a, 0xec, 0x65, 0x34, 0xf6, 0x34, 0x76, 0xc3, 0x78, 0x7a, 0x34, 0xdd, 0x71, 0xc8, 0x99, + 0x17, 0xe0, 0x05, 0x78, 0x0c, 0x2e, 0x3c, 0xc1, 0x1e, 0xf7, 0xc8, 0x69, 0x85, 0x12, 0xf1, 0x0a, + 0x70, 0x45, 0x5d, 0xd3, 0x1e, 0x8f, 0xbd, 0xf6, 0x86, 0x70, 0x40, 0xda, 0x5b, 0x4f, 0x57, 0xd5, + 0xd7, 0xd5, 0x5f, 0x55, 0x7d, 0x3d, 0xf0, 0xfe, 0x40, 0x8c, 0x99, 0xea, 0x7f, 0xa7, 0xda, 0x03, + 0x11, 0x4b, 0x16, 0xcb, 0x73, 0xd9, 0x9e, 0x1c, 0xb5, 0xd5, 0x65, 0xc2, 0x64, 0x2b, 0x49, 0x85, + 0x12, 0x64, 0x6f, 0xea, 0xd2, 0xca, 0x5d, 0x5a, 0x93, 0xa3, 0xfd, 0xdd, 0xa1, 0x18, 0x0a, 0xf4, + 0x68, 0xeb, 0x55, 0xe6, 0xbc, 0x3f, 0xc3, 0x8b, 0x78, 0x5f, 0xb6, 0xfb, 0x5c, 0x2d, 0xe2, 0xed, + 0xbf, 0x97, 0xbb, 0xe0, 0xee, 0x82, 0xd9, 0xf9, 0xd5, 0x86, 0xcd, 0x33, 0x76, 0x41, 0xc5, 0x79, + 0x1c, 0xf6, 0x14, 0x4b, 0xc8, 0xbb, 0xb0, 0x3e, 0x62, 0x7c, 0x38, 0x52, 0x75, 0xbb, 0x69, 0x1f, + 0xae, 0x51, 0xf3, 0x45, 0x76, 0xa1, 0x9c, 0x6a, 0xa7, 0xfa, 0x5b, 0x4d, 0xfb, 0xb0, 0x4c, 0xb3, + 0x0f, 0x42, 0xa0, 0x24, 0x15, 0x4b, 0xea, 0x6b, 0x4d, 0xfb, 0x70, 0x8b, 0xe2, 0x9a, 0x7c, 0x06, + 0x75, 0xc9, 0x06, 0x22, 0x0e, 0xa5, 0x2f, 0x79, 0x3c, 0x60, 0xbe, 0x54, 0x41, 0xaa, 0x7c, 0xc5, + 0xc7, 0xac, 0x5e, 0x42, 0xcc, 0x3d, 0x63, 0xef, 0x69, 0x73, 0x4f, 0x5b, 0x9f, 0xf0, 0x31, 0x23, + 0x1f, 0xc1, 0x3b, 0x51, 0x20, 0x95, 0x3f, 0x10, 0xe3, 0x31, 0x57, 0x7e, 0x76, 0x5c, 0x19, 0x8f, + 0xdb, 0xd1, 0x86, 0x2f, 0x71, 0x1f, 0x53, 0x75, 0xfe, 0xb6, 0x61, 0xeb, 0x8c, 0x5d, 0x3c, 0x0d, + 0x22, 0x1e, 0xba, 0x91, 0x18, 0xfc, 0x70, 0xcb, 0xc4, 0xbf, 0x85, 0xbd, 0xbe, 0x0e, 0xf3, 0x13, + 0x9d, 0x9b, 0x64, 0xca, 0x1f, 0xb1, 0x20, 0x64, 0x29, 0xde, 0xa4, 0xd6, 0x69, 0xb6, 0xf2, 0x32, + 0x64, 0x6c, 0x4d, 0x8e, 0x5a, 0xdd, 0x20, 0x55, 0x3d, 0xa6, 0x3c, 0xf4, 0x73, 0x4b, 0xcf, 0x5f, + 0x1e, 0x58, 0x94, 0x20, 0xc8, 0x9c, 0x85, 0x7c, 0x01, 0xb5, 0x19, 0xb4, 0xc4, 0x2b, 0xd7, 0x3a, + 0x07, 0x33, 0x40, 0x5d, 0xaa, 0x96, 0x2e, 0x95, 0x06, 0x75, 0xb9, 0x7a, 0x90, 0xa6, 0xc1, 0x25, + 0x85, 0x1c, 0x49, 0x92, 0xbb, 0xb0, 0xc1, 0xa5, 0xa1, 0x01, 0x09, 0xa8, 0xd2, 0x2a, 0x97, 0xd9, + 0xf5, 0x9d, 0x13, 0xa8, 0x76, 0x53, 0x91, 0x08, 0x19, 0x44, 0xe4, 0x73, 0xa8, 0x26, 0x66, 0x8d, + 0xb7, 0xae, 0x75, 0xee, 0x2e, 0x4b, 0xdc, 0xb8, 0x98, 0x9c, 0xf3, 0x10, 0xe7, 0x17, 0x1b, 0x6a, + 0x53, 0x63, 0xf7, 0xf1, 0xa3, 0x95, 0x14, 0x7e, 0x0c, 0x64, 0x1a, 0xe3, 0x27, 0x22, 0xf2, 0x8b, + 0x7c, 0xbe, 0x3d, 0xb5, 0x74, 0x45, 0x84, 0xa5, 0x21, 0x1e, 0x6c, 0x16, 0xbd, 0x0d, 0xa3, 0x37, + 0x11, 0x60, 0x92, 0xab, 0x15, 0xe0, 0x9c, 0x08, 0x36, 0xdc, 0x29, 0x2b, 0xb7, 0xac, 0xef, 0x11, + 0x94, 0x34, 0xfd, 0xe6, 0xf0, 0x3b, 0x2b, 0xca, 0x69, 0x0e, 0x45, 0x57, 0xe7, 0x18, 0x4a, 0x4f, + 0x85, 0x62, 0xe4, 0x1e, 0x94, 0x26, 0x42, 0x31, 0x43, 0xe8, 0xb2, 0x50, 0xed, 0x46, 0xd1, 0xc9, + 0xf9, 0xc9, 0x86, 0x8a, 0x17, 0x48, 0x0c, 0xbc, 0x5d, 0x86, 0x9f, 0x40, 0x49, 0x03, 0x62, 0x86, + 0xdb, 0x4b, 0x1b, 0xae, 0xc7, 0x87, 0x31, 0x0b, 0x4f, 0xe5, 0xf0, 0xc9, 0x65, 0xc2, 0x28, 0x7a, + 0x6b, 0x2c, 0x1e, 0x87, 0xec, 0x47, 0x6c, 0xab, 0x32, 0xcd, 0x3e, 0x9c, 0xdf, 0x6c, 0xd8, 0xd4, + 0x29, 0xf4, 0x98, 0x3a, 0x0d, 0xbe, 0xef, 0x1c, 0xff, 0x2f, 0xa9, 0x7c, 0x0d, 0xd5, 0xac, 0xcf, + 0x79, 0x68, 0x9a, 0x7c, 0x7f, 0x49, 0x24, 0x16, 0xf0, 0xe4, 0x2b, 0x77, 0x47, 0x33, 0x7d, 0xf5, + 0xf2, 0xa0, 0x62, 0x36, 0x68, 0x05, 0x83, 0x4f, 0x42, 0xe7, 0x2f, 0x1b, 0x6a, 0x26, 0x79, 0x97, + 0x2b, 0xf9, 0x26, 0xe5, 0x4e, 0xee, 0x43, 0x59, 0xb7, 0x81, 0xc4, 0x29, 0xfd, 0xd7, 0x4d, 0x9e, + 0xc5, 0x38, 0xcf, 0x60, 0xd7, 0x0b, 0x64, 0x3e, 0x9d, 0xff, 0xb1, 0xd3, 0xf3, 0x8e, 0x58, 0x2b, + 0x76, 0xc4, 0x9f, 0x65, 0xa8, 0x9c, 0x32, 0x29, 0x83, 0x21, 0x23, 0x0f, 0x61, 0x3b, 0x66, 0x17, + 0xd9, 0xd4, 0xfa, 0x28, 0xd7, 0x59, 0x6b, 0x7f, 0xd0, 0x5a, 0xfa, 0xd6, 0xb4, 0x8a, 0xef, 0x81, + 0x67, 0xd1, 0xcd, 0xb8, 0xf8, 0x3e, 0x9c, 0xc1, 0x8e, 0x06, 0x9b, 0x68, 0xe1, 0xf5, 0x91, 0x06, + 0x4c, 0xa7, 0xd6, 0xf9, 0x70, 0x35, 0xda, 0x4c, 0xa5, 0x3d, 0x8b, 0x6e, 0xc5, 0x73, 0xb2, 0x5d, + 0x94, 0xb0, 0x57, 0x94, 0x62, 0x0e, 0x68, 0x4a, 0x94, 0x57, 0x90, 0x30, 0xf2, 0xcd, 0x82, 0xd8, + 0x64, 0xc5, 0x74, 0x6e, 0x80, 0xe8, 0x3e, 0x7e, 0xe4, 0xcd, 0x6b, 0x0d, 0x79, 0x00, 0x30, 0x53, + 0x6d, 0x53, 0xce, 0xe6, 0x0a, 0x98, 0xbc, 0x54, 0x9e, 0x45, 0x37, 0x72, 0xdd, 0xd6, 0x9a, 0x83, + 0xc2, 0xb1, 0xbe, 0xa8, 0xc4, 0x73, 0xc1, 0xba, 0xd5, 0x3d, 0x2b, 0x93, 0x0f, 0x72, 0x1f, 0xaa, + 0xa3, 0x40, 0xfa, 0x18, 0x56, 0xc1, 0xb0, 0xc6, 0x8a, 0x30, 0x23, 0x32, 0x9e, 0x45, 0x2b, 0x23, + 0xa3, 0x37, 0x0f, 0x61, 0x5b, 0x07, 0xe2, 0xeb, 0x35, 0xd6, 0x63, 0x5f, 0xaf, 0xbe, 0xb6, 0xae, + 0x45, 0x85, 0xd0, 0x75, 0x9d, 0x14, 0x15, 0xc3, 0x83, 0xad, 0x1c, 0x4c, 0xb7, 0x6d, 0x7d, 0xe3, + 0xb5, 0x4c, 0x16, 0x06, 0x56, 0x33, 0x39, 0x29, 0xcc, 0x6f, 0x08, 0x77, 0xf4, 0x9d, 0xf2, 0xb2, + 0x14, 0x68, 0x05, 0xc4, 0xbc, 0xb7, 0xfa, 0x8a, 0xaf, 0x0c, 0x83, 0x67, 0xd1, 0xdd, 0xd1, 0x92, + 0x7d, 0xb7, 0x0c, 0x6b, 0xf2, 0x7c, 0xec, 0x76, 0x9f, 0x5f, 0x35, 0xec, 0x17, 0x57, 0x0d, 0xfb, + 0x8f, 0xab, 0x86, 0xfd, 0xf3, 0x75, 0xc3, 0x7a, 0x71, 0xdd, 0xb0, 0x7e, 0xbf, 0x6e, 0x58, 0xcf, + 0x3e, 0x1d, 0x72, 0x35, 0x3a, 0xef, 0xeb, 0xb3, 0xda, 0x85, 0xdf, 0x2e, 0xb3, 0x08, 0x12, 0xde, + 0x5e, 0xfa, 0x33, 0xd6, 0x5f, 0xc7, 0x1f, 0xa3, 0xe3, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x64, + 0x03, 0x11, 0x71, 0xac, 0x09, 0x00, 0x00, +} + +func (m *NewRoundStep) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NewRoundStep) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NewRoundStep) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LastCommitRound != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastCommitRound)) + i-- + dAtA[i] = 0x28 + } + if m.SecondsSinceStartTime != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.SecondsSinceStartTime)) + i-- + dAtA[i] = 0x20 + } + if m.Step != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Step)) + i-- + dAtA[i] = 0x18 + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *NewValidBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NewValidBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NewValidBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.IsCommit { + i-- + if m.IsCommit { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.BlockParts != nil { + { + size, err := m.BlockParts.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + { + size, err := m.BlockPartSetHeader.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Proposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Proposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Proposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ProposalPOL) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ProposalPOL) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ProposalPOL) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.ProposalPol.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.ProposalPolRound != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.ProposalPolRound)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *BlockPart) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockPart) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BlockPart) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Part.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Vote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Vote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Vote != nil { + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *HasVote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *HasVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *HasVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Index != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x20 + } + if m.Type != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x18 + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *VoteSetMaj23) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VoteSetMaj23) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VoteSetMaj23) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.Type != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x18 + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *VoteSetBits) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VoteSetBits) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VoteSetBits) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Votes.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.Type != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x18 + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *HasProposalBlockPart) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *HasProposalBlockPart) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *HasProposalBlockPart) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Index != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x18 + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Message) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Message) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Message_NewRoundStep) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_NewRoundStep) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.NewRoundStep != nil { + { + size, err := m.NewRoundStep.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Message_NewValidBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_NewValidBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.NewValidBlock != nil { + { + size, err := m.NewValidBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Message_Proposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_Proposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Proposal != nil { + { + size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Message_ProposalPol) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_ProposalPol) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.ProposalPol != nil { + { + size, err := m.ProposalPol.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Message_BlockPart) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_BlockPart) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.BlockPart != nil { + { + size, err := m.BlockPart.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *Message_Vote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Vote != nil { + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Message_HasVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_HasVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.HasVote != nil { + { + size, err := m.HasVote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Message_VoteSetMaj23) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_VoteSetMaj23) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.VoteSetMaj23 != nil { + { + size, err := m.VoteSetMaj23.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *Message_VoteSetBits) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_VoteSetBits) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.VoteSetBits != nil { + { + size, err := m.VoteSetBits.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *Message_HasProposalBlockPart) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_HasProposalBlockPart) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.HasProposalBlockPart != nil { + { + size, err := m.HasProposalBlockPart.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + return len(dAtA) - i, nil +} +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *NewRoundStep) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if m.Step != 0 { + n += 1 + sovTypes(uint64(m.Step)) + } + if m.SecondsSinceStartTime != 0 { + n += 1 + sovTypes(uint64(m.SecondsSinceStartTime)) + } + if m.LastCommitRound != 0 { + n += 1 + sovTypes(uint64(m.LastCommitRound)) + } + return n +} + +func (m *NewValidBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + l = m.BlockPartSetHeader.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.BlockParts != nil { + l = m.BlockParts.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.IsCommit { + n += 2 + } + return n +} + +func (m *Proposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Proposal.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *ProposalPOL) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.ProposalPolRound != 0 { + n += 1 + sovTypes(uint64(m.ProposalPolRound)) + } + l = m.ProposalPol.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *BlockPart) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + l = m.Part.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *Vote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Vote != nil { + l = m.Vote.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *HasVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if m.Type != 0 { + n += 1 + sovTypes(uint64(m.Type)) + } + if m.Index != 0 { + n += 1 + sovTypes(uint64(m.Index)) + } + return n +} + +func (m *VoteSetMaj23) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if m.Type != 0 { + n += 1 + sovTypes(uint64(m.Type)) + } + l = m.BlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *VoteSetBits) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if m.Type != 0 { + n += 1 + sovTypes(uint64(m.Type)) + } + l = m.BlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + l = m.Votes.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *HasProposalBlockPart) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if m.Index != 0 { + n += 1 + sovTypes(uint64(m.Index)) + } + return n +} + +func (m *Message) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Message_NewRoundStep) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.NewRoundStep != nil { + l = m.NewRoundStep.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_NewValidBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.NewValidBlock != nil { + l = m.NewValidBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_Proposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Proposal != nil { + l = m.Proposal.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_ProposalPol) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalPol != nil { + l = m.ProposalPol.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_BlockPart) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BlockPart != nil { + l = m.BlockPart.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_Vote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Vote != nil { + l = m.Vote.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_HasVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.HasVote != nil { + l = m.HasVote.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_VoteSetMaj23) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.VoteSetMaj23 != nil { + l = m.VoteSetMaj23.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_VoteSetBits) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.VoteSetBits != nil { + l = m.VoteSetBits.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_HasProposalBlockPart) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.HasProposalBlockPart != nil { + l = m.HasProposalBlockPart.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *NewRoundStep) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NewRoundStep: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NewRoundStep: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Step", wireType) + } + m.Step = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Step |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SecondsSinceStartTime", wireType) + } + m.SecondsSinceStartTime = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.SecondsSinceStartTime |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastCommitRound", wireType) + } + m.LastCommitRound = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastCommitRound |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NewValidBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NewValidBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NewValidBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockPartSetHeader", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockPartSetHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockParts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BlockParts == nil { + m.BlockParts = &v11.BitArray{} + } + if err := m.BlockParts.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsCommit", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsCommit = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Proposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Proposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Proposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Proposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ProposalPOL) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ProposalPOL: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProposalPOL: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalPolRound", wireType) + } + m.ProposalPolRound = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalPolRound |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalPol", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ProposalPol.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockPart) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockPart: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockPart: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Part", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Part.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Vote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Vote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Vote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Vote == nil { + m.Vote = &v1.Vote{} + } + if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *HasVote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: HasVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: HasVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= v1.SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VoteSetMaj23) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VoteSetMaj23: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VoteSetMaj23: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= v1.SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VoteSetBits) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VoteSetBits: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VoteSetBits: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= v1.SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Votes.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *HasProposalBlockPart) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: HasProposalBlockPart: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: HasProposalBlockPart: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Message) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Message: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewRoundStep", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &NewRoundStep{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_NewRoundStep{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewValidBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &NewValidBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_NewValidBlock{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Proposal{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_Proposal{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalPol", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ProposalPOL{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_ProposalPol{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockPart", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &BlockPart{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_BlockPart{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &Vote{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_Vote{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HasVote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &HasVote{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_HasVote{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteSetMaj23", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &VoteSetMaj23{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_VoteSetMaj23{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteSetBits", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &VoteSetBits{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_VoteSetBits{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HasProposalBlockPart", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &HasProposalBlockPart{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_HasProposalBlockPart{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/consensus/v1/wal.pb.go b/api/cometbft/consensus/v1/wal.pb.go new file mode 100644 index 00000000000..69b0c9ec34f --- /dev/null +++ b/api/cometbft/consensus/v1/wal.pb.go @@ -0,0 +1,1603 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/consensus/v1/wal.proto + +package v1 + +import ( + fmt "fmt" + v1 "github.com/cometbft/cometbft/api/cometbft/types/v1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + _ "github.com/golang/protobuf/ptypes/duration" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgInfo are msgs from the reactor which may update the state +type MsgInfo struct { + Msg Message `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg"` + PeerID string `protobuf:"bytes,2,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"` + ReceiveTime *time.Time `protobuf:"bytes,3,opt,name=receive_time,json=receiveTime,proto3,stdtime" json:"receive_time,omitempty"` +} + +func (m *MsgInfo) Reset() { *m = MsgInfo{} } +func (m *MsgInfo) String() string { return proto.CompactTextString(m) } +func (*MsgInfo) ProtoMessage() {} +func (*MsgInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_f013b385bb75d435, []int{0} +} +func (m *MsgInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgInfo.Merge(m, src) +} +func (m *MsgInfo) XXX_Size() int { + return m.Size() +} +func (m *MsgInfo) XXX_DiscardUnknown() { + xxx_messageInfo_MsgInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgInfo proto.InternalMessageInfo + +func (m *MsgInfo) GetMsg() Message { + if m != nil { + return m.Msg + } + return Message{} +} + +func (m *MsgInfo) GetPeerID() string { + if m != nil { + return m.PeerID + } + return "" +} + +func (m *MsgInfo) GetReceiveTime() *time.Time { + if m != nil { + return m.ReceiveTime + } + return nil +} + +// TimeoutInfo internally generated messages which may update the state +type TimeoutInfo struct { + Duration time.Duration `protobuf:"bytes,1,opt,name=duration,proto3,stdduration" json:"duration"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,3,opt,name=round,proto3" json:"round,omitempty"` + Step uint32 `protobuf:"varint,4,opt,name=step,proto3" json:"step,omitempty"` +} + +func (m *TimeoutInfo) Reset() { *m = TimeoutInfo{} } +func (m *TimeoutInfo) String() string { return proto.CompactTextString(m) } +func (*TimeoutInfo) ProtoMessage() {} +func (*TimeoutInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_f013b385bb75d435, []int{1} +} +func (m *TimeoutInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TimeoutInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TimeoutInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TimeoutInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_TimeoutInfo.Merge(m, src) +} +func (m *TimeoutInfo) XXX_Size() int { + return m.Size() +} +func (m *TimeoutInfo) XXX_DiscardUnknown() { + xxx_messageInfo_TimeoutInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_TimeoutInfo proto.InternalMessageInfo + +func (m *TimeoutInfo) GetDuration() time.Duration { + if m != nil { + return m.Duration + } + return 0 +} + +func (m *TimeoutInfo) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *TimeoutInfo) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *TimeoutInfo) GetStep() uint32 { + if m != nil { + return m.Step + } + return 0 +} + +// EndHeight marks the end of the given height inside WAL. +// @internal used by scripts/wal2json util. +type EndHeight struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *EndHeight) Reset() { *m = EndHeight{} } +func (m *EndHeight) String() string { return proto.CompactTextString(m) } +func (*EndHeight) ProtoMessage() {} +func (*EndHeight) Descriptor() ([]byte, []int) { + return fileDescriptor_f013b385bb75d435, []int{2} +} +func (m *EndHeight) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EndHeight) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EndHeight.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EndHeight) XXX_Merge(src proto.Message) { + xxx_messageInfo_EndHeight.Merge(m, src) +} +func (m *EndHeight) XXX_Size() int { + return m.Size() +} +func (m *EndHeight) XXX_DiscardUnknown() { + xxx_messageInfo_EndHeight.DiscardUnknown(m) +} + +var xxx_messageInfo_EndHeight proto.InternalMessageInfo + +func (m *EndHeight) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +// WALMessage describes a consensus WAL (Write Ahead Log) entry. +type WALMessage struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Sum: + // *WALMessage_EventDataRoundState + // *WALMessage_MsgInfo + // *WALMessage_TimeoutInfo + // *WALMessage_EndHeight + Sum isWALMessage_Sum `protobuf_oneof:"sum"` +} + +func (m *WALMessage) Reset() { *m = WALMessage{} } +func (m *WALMessage) String() string { return proto.CompactTextString(m) } +func (*WALMessage) ProtoMessage() {} +func (*WALMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_f013b385bb75d435, []int{3} +} +func (m *WALMessage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *WALMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_WALMessage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *WALMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_WALMessage.Merge(m, src) +} +func (m *WALMessage) XXX_Size() int { + return m.Size() +} +func (m *WALMessage) XXX_DiscardUnknown() { + xxx_messageInfo_WALMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_WALMessage proto.InternalMessageInfo + +type isWALMessage_Sum interface { + isWALMessage_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type WALMessage_EventDataRoundState struct { + EventDataRoundState *v1.EventDataRoundState `protobuf:"bytes,1,opt,name=event_data_round_state,json=eventDataRoundState,proto3,oneof" json:"event_data_round_state,omitempty"` +} +type WALMessage_MsgInfo struct { + MsgInfo *MsgInfo `protobuf:"bytes,2,opt,name=msg_info,json=msgInfo,proto3,oneof" json:"msg_info,omitempty"` +} +type WALMessage_TimeoutInfo struct { + TimeoutInfo *TimeoutInfo `protobuf:"bytes,3,opt,name=timeout_info,json=timeoutInfo,proto3,oneof" json:"timeout_info,omitempty"` +} +type WALMessage_EndHeight struct { + EndHeight *EndHeight `protobuf:"bytes,4,opt,name=end_height,json=endHeight,proto3,oneof" json:"end_height,omitempty"` +} + +func (*WALMessage_EventDataRoundState) isWALMessage_Sum() {} +func (*WALMessage_MsgInfo) isWALMessage_Sum() {} +func (*WALMessage_TimeoutInfo) isWALMessage_Sum() {} +func (*WALMessage_EndHeight) isWALMessage_Sum() {} + +func (m *WALMessage) GetSum() isWALMessage_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *WALMessage) GetEventDataRoundState() *v1.EventDataRoundState { + if x, ok := m.GetSum().(*WALMessage_EventDataRoundState); ok { + return x.EventDataRoundState + } + return nil +} + +func (m *WALMessage) GetMsgInfo() *MsgInfo { + if x, ok := m.GetSum().(*WALMessage_MsgInfo); ok { + return x.MsgInfo + } + return nil +} + +func (m *WALMessage) GetTimeoutInfo() *TimeoutInfo { + if x, ok := m.GetSum().(*WALMessage_TimeoutInfo); ok { + return x.TimeoutInfo + } + return nil +} + +func (m *WALMessage) GetEndHeight() *EndHeight { + if x, ok := m.GetSum().(*WALMessage_EndHeight); ok { + return x.EndHeight + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*WALMessage) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*WALMessage_EventDataRoundState)(nil), + (*WALMessage_MsgInfo)(nil), + (*WALMessage_TimeoutInfo)(nil), + (*WALMessage_EndHeight)(nil), + } +} + +// TimedWALMessage wraps WALMessage and adds Time for debugging purposes. +type TimedWALMessage struct { + Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"` + Msg *WALMessage `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` +} + +func (m *TimedWALMessage) Reset() { *m = TimedWALMessage{} } +func (m *TimedWALMessage) String() string { return proto.CompactTextString(m) } +func (*TimedWALMessage) ProtoMessage() {} +func (*TimedWALMessage) Descriptor() ([]byte, []int) { + return fileDescriptor_f013b385bb75d435, []int{4} +} +func (m *TimedWALMessage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TimedWALMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TimedWALMessage.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TimedWALMessage) XXX_Merge(src proto.Message) { + xxx_messageInfo_TimedWALMessage.Merge(m, src) +} +func (m *TimedWALMessage) XXX_Size() int { + return m.Size() +} +func (m *TimedWALMessage) XXX_DiscardUnknown() { + xxx_messageInfo_TimedWALMessage.DiscardUnknown(m) +} + +var xxx_messageInfo_TimedWALMessage proto.InternalMessageInfo + +func (m *TimedWALMessage) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *TimedWALMessage) GetMsg() *WALMessage { + if m != nil { + return m.Msg + } + return nil +} + +func init() { + proto.RegisterType((*MsgInfo)(nil), "cometbft.consensus.v1.MsgInfo") + proto.RegisterType((*TimeoutInfo)(nil), "cometbft.consensus.v1.TimeoutInfo") + proto.RegisterType((*EndHeight)(nil), "cometbft.consensus.v1.EndHeight") + proto.RegisterType((*WALMessage)(nil), "cometbft.consensus.v1.WALMessage") + proto.RegisterType((*TimedWALMessage)(nil), "cometbft.consensus.v1.TimedWALMessage") +} + +func init() { proto.RegisterFile("cometbft/consensus/v1/wal.proto", fileDescriptor_f013b385bb75d435) } + +var fileDescriptor_f013b385bb75d435 = []byte{ + // 574 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xc1, 0x6a, 0xdb, 0x4c, + 0x10, 0xd6, 0xc6, 0x8e, 0x63, 0xaf, 0xf3, 0xf3, 0x83, 0x9a, 0x06, 0xd7, 0x07, 0xc9, 0x51, 0xa0, + 0xf8, 0x24, 0xe1, 0x06, 0x42, 0xa1, 0x87, 0x12, 0xe3, 0x10, 0x1b, 0x1a, 0x08, 0xdb, 0x42, 0xa1, + 0x50, 0x84, 0x6c, 0x8d, 0x65, 0x41, 0xa4, 0x15, 0xda, 0x95, 0x4b, 0x6f, 0x7d, 0x04, 0x1f, 0xfb, + 0x16, 0x7d, 0x80, 0xbe, 0x80, 0x8f, 0x39, 0xf6, 0xe4, 0x16, 0xfb, 0x45, 0xca, 0xee, 0x4a, 0xb6, + 0x69, 0xec, 0xd2, 0xdb, 0x8c, 0x66, 0xbe, 0x6f, 0xbf, 0x99, 0xf9, 0x84, 0xcd, 0x11, 0x8d, 0x80, + 0x0f, 0xc7, 0xdc, 0x19, 0xd1, 0x98, 0x41, 0xcc, 0x32, 0xe6, 0x4c, 0x3b, 0xce, 0x27, 0xef, 0xde, + 0x4e, 0x52, 0xca, 0xa9, 0xfe, 0xb4, 0x68, 0xb0, 0xd7, 0x0d, 0xf6, 0xb4, 0xd3, 0x3c, 0xdb, 0x8d, + 0xe3, 0x9f, 0x13, 0x60, 0x0a, 0xd9, 0x34, 0xd6, 0x2d, 0xf2, 0xab, 0x28, 0xc3, 0x14, 0x62, 0x5e, + 0xd4, 0x4f, 0x02, 0x1a, 0x50, 0x19, 0x3a, 0x22, 0x2a, 0x50, 0x01, 0xa5, 0xc1, 0x3d, 0x38, 0x32, + 0x1b, 0x66, 0x63, 0xc7, 0xcf, 0x52, 0x8f, 0x87, 0x34, 0xce, 0xeb, 0xe6, 0x9f, 0x75, 0x1e, 0x46, + 0xc0, 0xb8, 0x17, 0x25, 0xaa, 0xc1, 0xfa, 0x86, 0xf0, 0xd1, 0x2d, 0x0b, 0x06, 0xf1, 0x98, 0xea, + 0x97, 0xb8, 0x14, 0xb1, 0xa0, 0x81, 0x5a, 0xa8, 0x5d, 0x7f, 0x61, 0xd8, 0x3b, 0x47, 0xb1, 0x6f, + 0x81, 0x31, 0x2f, 0x80, 0x6e, 0x79, 0xbe, 0x30, 0x35, 0x22, 0x00, 0xfa, 0x39, 0x3e, 0x4a, 0x00, + 0x52, 0x37, 0xf4, 0x1b, 0x07, 0x2d, 0xd4, 0xae, 0x75, 0xf1, 0x72, 0x61, 0x56, 0xee, 0x00, 0xd2, + 0x41, 0x8f, 0x54, 0x44, 0x69, 0xe0, 0xeb, 0x37, 0xf8, 0x38, 0x85, 0x11, 0x84, 0x53, 0x70, 0x85, + 0x86, 0x46, 0x49, 0xbe, 0xd2, 0xb4, 0x95, 0x40, 0xbb, 0x10, 0x68, 0xbf, 0x2b, 0x04, 0x76, 0xab, + 0xf3, 0x85, 0x89, 0x66, 0x3f, 0x4d, 0x44, 0xea, 0x39, 0x52, 0xd4, 0xac, 0x19, 0xc2, 0x75, 0x11, + 0xd0, 0x8c, 0x4b, 0xd5, 0xaf, 0x71, 0xb5, 0x18, 0x3a, 0x97, 0xfe, 0xec, 0x11, 0x69, 0x2f, 0x6f, + 0x90, 0x9c, 0xda, 0x57, 0xc1, 0xb9, 0x06, 0xe9, 0xa7, 0xb8, 0x32, 0x81, 0x30, 0x98, 0x70, 0xa9, + 0xbe, 0x44, 0xf2, 0x4c, 0x3f, 0xc1, 0x87, 0x29, 0xcd, 0x62, 0x5f, 0x4a, 0x3d, 0x24, 0x2a, 0xd1, + 0x75, 0x5c, 0x66, 0x1c, 0x92, 0x46, 0xb9, 0x85, 0xda, 0xff, 0x11, 0x19, 0x5b, 0xe7, 0xb8, 0x76, + 0x1d, 0xfb, 0x7d, 0x05, 0xdb, 0xd0, 0xa1, 0x6d, 0x3a, 0xeb, 0xfb, 0x01, 0xc6, 0xef, 0xaf, 0xde, + 0xe4, 0xfb, 0xd3, 0x3f, 0xe2, 0x53, 0x79, 0x5f, 0xd7, 0xf7, 0xb8, 0xe7, 0x4a, 0x6e, 0x97, 0x71, + 0x8f, 0x43, 0x3e, 0xc4, 0xf3, 0xcd, 0xfe, 0x95, 0x4d, 0xa6, 0x1d, 0xfb, 0x5a, 0x00, 0x7a, 0x1e, + 0xf7, 0x88, 0x68, 0x7f, 0x2b, 0xba, 0xfb, 0x1a, 0x79, 0x02, 0x8f, 0x3f, 0xeb, 0xaf, 0x70, 0x35, + 0x62, 0x81, 0x1b, 0xc6, 0x63, 0x2a, 0xc7, 0xfa, 0xcb, 0x41, 0xd5, 0xf5, 0xfb, 0x1a, 0x39, 0x8a, + 0x72, 0x23, 0xdc, 0xe0, 0x63, 0xae, 0x36, 0xac, 0x08, 0xd4, 0xad, 0xac, 0x3d, 0x04, 0x5b, 0xc7, + 0xe8, 0x6b, 0xa4, 0xce, 0xb7, 0x6e, 0x73, 0x85, 0x31, 0xc4, 0xbe, 0x9b, 0xef, 0xa3, 0x2c, 0x69, + 0x5a, 0x7b, 0x68, 0xd6, 0x1b, 0xec, 0x6b, 0xa4, 0x06, 0x45, 0xd2, 0x3d, 0xc4, 0x25, 0x96, 0x45, + 0xd6, 0x17, 0x84, 0xff, 0x17, 0x0f, 0xf9, 0x5b, 0x2b, 0x7c, 0x89, 0xcb, 0xd2, 0x4a, 0xe8, 0x9f, + 0xac, 0xa4, 0x49, 0x2b, 0x49, 0x84, 0x7e, 0xa1, 0x9c, 0xae, 0x16, 0x73, 0xb6, 0x47, 0xd0, 0xe6, + 0x25, 0x69, 0xf3, 0xee, 0xdd, 0x7c, 0x69, 0xa0, 0x87, 0xa5, 0x81, 0x7e, 0x2d, 0x0d, 0x34, 0x5b, + 0x19, 0xda, 0xc3, 0xca, 0xd0, 0x7e, 0xac, 0x0c, 0xed, 0xc3, 0x65, 0x10, 0xf2, 0x49, 0x36, 0x14, + 0x3c, 0xce, 0xd6, 0x9f, 0x9e, 0x07, 0x5e, 0x12, 0x3a, 0x3b, 0xff, 0xff, 0x61, 0x45, 0x4a, 0xbd, + 0xf8, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xb6, 0x20, 0xcb, 0xbf, 0x57, 0x04, 0x00, 0x00, +} + +func (m *MsgInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ReceiveTime != nil { + n1, err1 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(*m.ReceiveTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(*m.ReceiveTime):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintWal(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x1a + } + if len(m.PeerID) > 0 { + i -= len(m.PeerID) + copy(dAtA[i:], m.PeerID) + i = encodeVarintWal(dAtA, i, uint64(len(m.PeerID))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Msg.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintWal(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *TimeoutInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TimeoutInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TimeoutInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Step != 0 { + i = encodeVarintWal(dAtA, i, uint64(m.Step)) + i-- + dAtA[i] = 0x20 + } + if m.Round != 0 { + i = encodeVarintWal(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x18 + } + if m.Height != 0 { + i = encodeVarintWal(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + n3, err3 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.Duration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.Duration):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintWal(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *EndHeight) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EndHeight) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EndHeight) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintWal(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *WALMessage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WALMessage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WALMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *WALMessage_EventDataRoundState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WALMessage_EventDataRoundState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.EventDataRoundState != nil { + { + size, err := m.EventDataRoundState.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintWal(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *WALMessage_MsgInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WALMessage_MsgInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.MsgInfo != nil { + { + size, err := m.MsgInfo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintWal(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *WALMessage_TimeoutInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WALMessage_TimeoutInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.TimeoutInfo != nil { + { + size, err := m.TimeoutInfo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintWal(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *WALMessage_EndHeight) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WALMessage_EndHeight) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.EndHeight != nil { + { + size, err := m.EndHeight.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintWal(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *TimedWALMessage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TimedWALMessage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TimedWALMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Msg != nil { + { + size, err := m.Msg.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintWal(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + n9, err9 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err9 != nil { + return 0, err9 + } + i -= n9 + i = encodeVarintWal(dAtA, i, uint64(n9)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintWal(dAtA []byte, offset int, v uint64) int { + offset -= sovWal(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Msg.Size() + n += 1 + l + sovWal(uint64(l)) + l = len(m.PeerID) + if l > 0 { + n += 1 + l + sovWal(uint64(l)) + } + if m.ReceiveTime != nil { + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(*m.ReceiveTime) + n += 1 + l + sovWal(uint64(l)) + } + return n +} + +func (m *TimeoutInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.Duration) + n += 1 + l + sovWal(uint64(l)) + if m.Height != 0 { + n += 1 + sovWal(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovWal(uint64(m.Round)) + } + if m.Step != 0 { + n += 1 + sovWal(uint64(m.Step)) + } + return n +} + +func (m *EndHeight) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovWal(uint64(m.Height)) + } + return n +} + +func (m *WALMessage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *WALMessage_EventDataRoundState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.EventDataRoundState != nil { + l = m.EventDataRoundState.Size() + n += 1 + l + sovWal(uint64(l)) + } + return n +} +func (m *WALMessage_MsgInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MsgInfo != nil { + l = m.MsgInfo.Size() + n += 1 + l + sovWal(uint64(l)) + } + return n +} +func (m *WALMessage_TimeoutInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.TimeoutInfo != nil { + l = m.TimeoutInfo.Size() + n += 1 + l + sovWal(uint64(l)) + } + return n +} +func (m *WALMessage_EndHeight) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.EndHeight != nil { + l = m.EndHeight.Size() + n += 1 + l + sovWal(uint64(l)) + } + return n +} +func (m *TimedWALMessage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovWal(uint64(l)) + if m.Msg != nil { + l = m.Msg.Size() + n += 1 + l + sovWal(uint64(l)) + } + return n +} + +func sovWal(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozWal(x uint64) (n int) { + return sovWal(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Msg", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Msg.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PeerID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PeerID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ReceiveTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ReceiveTime == nil { + m.ReceiveTime = new(time.Time) + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(m.ReceiveTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipWal(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthWal + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TimeoutInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TimeoutInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TimeoutInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Duration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.Duration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Step", wireType) + } + m.Step = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Step |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipWal(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthWal + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EndHeight) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EndHeight: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EndHeight: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipWal(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthWal + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WALMessage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WALMessage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WALMessage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EventDataRoundState", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &v1.EventDataRoundState{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &WALMessage_EventDataRoundState{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MsgInfo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &MsgInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &WALMessage_MsgInfo{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeoutInfo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &TimeoutInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &WALMessage_TimeoutInfo{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndHeight", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &EndHeight{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &WALMessage_EndHeight{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipWal(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthWal + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TimedWALMessage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TimedWALMessage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TimedWALMessage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Msg", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowWal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthWal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthWal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Msg == nil { + m.Msg = &WALMessage{} + } + if err := m.Msg.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipWal(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthWal + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipWal(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowWal + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowWal + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowWal + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthWal + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupWal + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthWal + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthWal = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowWal = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupWal = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/consensus/v1beta1/message.go b/api/cometbft/consensus/v1beta1/message.go new file mode 100644 index 00000000000..6bfc60eea25 --- /dev/null +++ b/api/cometbft/consensus/v1beta1/message.go @@ -0,0 +1,97 @@ +package v1beta1 + +import ( + "fmt" + + "github.com/cosmos/gogoproto/proto" +) + +func (m *VoteSetBits) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_VoteSetBits{VoteSetBits: m} + return cm +} + +func (m *VoteSetMaj23) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_VoteSetMaj23{VoteSetMaj23: m} + return cm +} + +func (m *HasVote) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_HasVote{HasVote: m} + return cm +} + +func (m *Vote) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_Vote{Vote: m} + return cm +} + +func (m *BlockPart) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_BlockPart{BlockPart: m} + return cm +} + +func (m *ProposalPOL) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_ProposalPol{ProposalPol: m} + return cm +} + +func (m *Proposal) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_Proposal{Proposal: m} + return cm +} + +func (m *NewValidBlock) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_NewValidBlock{NewValidBlock: m} + return cm +} + +func (m *NewRoundStep) Wrap() proto.Message { + cm := &Message{} + cm.Sum = &Message_NewRoundStep{NewRoundStep: m} + return cm +} + +// Unwrap implements the p2p Wrapper interface and unwraps a wrapped consensus +// proto message. +func (m *Message) Unwrap() (proto.Message, error) { + switch msg := m.Sum.(type) { + case *Message_NewRoundStep: + return m.GetNewRoundStep(), nil + + case *Message_NewValidBlock: + return m.GetNewValidBlock(), nil + + case *Message_Proposal: + return m.GetProposal(), nil + + case *Message_ProposalPol: + return m.GetProposalPol(), nil + + case *Message_BlockPart: + return m.GetBlockPart(), nil + + case *Message_Vote: + return m.GetVote(), nil + + case *Message_HasVote: + return m.GetHasVote(), nil + + case *Message_VoteSetMaj23: + return m.GetVoteSetMaj23(), nil + + case *Message_VoteSetBits: + return m.GetVoteSetBits(), nil + + default: + return nil, fmt.Errorf("unknown message: %T", msg) + } +} diff --git a/proto/tendermint/consensus/types.pb.go b/api/cometbft/consensus/v1beta1/types.pb.go similarity index 86% rename from proto/tendermint/consensus/types.pb.go rename to api/cometbft/consensus/v1beta1/types.pb.go index e23f0abddee..16943db6c3b 100644 --- a/proto/tendermint/consensus/types.pb.go +++ b/api/cometbft/consensus/v1beta1/types.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/consensus/types.proto +// source: cometbft/consensus/v1beta1/types.proto -package consensus +package v1beta1 import ( fmt "fmt" - bits "github.com/cometbft/cometbft/proto/tendermint/libs/bits" - types "github.com/cometbft/cometbft/proto/tendermint/types" + v1 "github.com/cometbft/cometbft/api/cometbft/libs/bits/v1" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" @@ -39,7 +39,7 @@ func (m *NewRoundStep) Reset() { *m = NewRoundStep{} } func (m *NewRoundStep) String() string { return proto.CompactTextString(m) } func (*NewRoundStep) ProtoMessage() {} func (*NewRoundStep) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{0} + return fileDescriptor_68132c3a7139c33d, []int{0} } func (m *NewRoundStep) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -107,18 +107,18 @@ func (m *NewRoundStep) GetLastCommitRound() int32 { // i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. // In case the block is also committed, then IsCommit flag is set to true. type NewValidBlock struct { - Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` - BlockPartSetHeader types.PartSetHeader `protobuf:"bytes,3,opt,name=block_part_set_header,json=blockPartSetHeader,proto3" json:"block_part_set_header"` - BlockParts *bits.BitArray `protobuf:"bytes,4,opt,name=block_parts,json=blockParts,proto3" json:"block_parts,omitempty"` - IsCommit bool `protobuf:"varint,5,opt,name=is_commit,json=isCommit,proto3" json:"is_commit,omitempty"` + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + BlockPartSetHeader v1beta1.PartSetHeader `protobuf:"bytes,3,opt,name=block_part_set_header,json=blockPartSetHeader,proto3" json:"block_part_set_header"` + BlockParts *v1.BitArray `protobuf:"bytes,4,opt,name=block_parts,json=blockParts,proto3" json:"block_parts,omitempty"` + IsCommit bool `protobuf:"varint,5,opt,name=is_commit,json=isCommit,proto3" json:"is_commit,omitempty"` } func (m *NewValidBlock) Reset() { *m = NewValidBlock{} } func (m *NewValidBlock) String() string { return proto.CompactTextString(m) } func (*NewValidBlock) ProtoMessage() {} func (*NewValidBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{1} + return fileDescriptor_68132c3a7139c33d, []int{1} } func (m *NewValidBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -161,14 +161,14 @@ func (m *NewValidBlock) GetRound() int32 { return 0 } -func (m *NewValidBlock) GetBlockPartSetHeader() types.PartSetHeader { +func (m *NewValidBlock) GetBlockPartSetHeader() v1beta1.PartSetHeader { if m != nil { return m.BlockPartSetHeader } - return types.PartSetHeader{} + return v1beta1.PartSetHeader{} } -func (m *NewValidBlock) GetBlockParts() *bits.BitArray { +func (m *NewValidBlock) GetBlockParts() *v1.BitArray { if m != nil { return m.BlockParts } @@ -184,14 +184,14 @@ func (m *NewValidBlock) GetIsCommit() bool { // Proposal is sent when a new block is proposed. type Proposal struct { - Proposal types.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal"` + Proposal v1beta1.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal"` } func (m *Proposal) Reset() { *m = Proposal{} } func (m *Proposal) String() string { return proto.CompactTextString(m) } func (*Proposal) ProtoMessage() {} func (*Proposal) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{2} + return fileDescriptor_68132c3a7139c33d, []int{2} } func (m *Proposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -220,25 +220,25 @@ func (m *Proposal) XXX_DiscardUnknown() { var xxx_messageInfo_Proposal proto.InternalMessageInfo -func (m *Proposal) GetProposal() types.Proposal { +func (m *Proposal) GetProposal() v1beta1.Proposal { if m != nil { return m.Proposal } - return types.Proposal{} + return v1beta1.Proposal{} } // ProposalPOL is sent when a previous proposal is re-proposed. type ProposalPOL struct { - Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - ProposalPolRound int32 `protobuf:"varint,2,opt,name=proposal_pol_round,json=proposalPolRound,proto3" json:"proposal_pol_round,omitempty"` - ProposalPol bits.BitArray `protobuf:"bytes,3,opt,name=proposal_pol,json=proposalPol,proto3" json:"proposal_pol"` + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + ProposalPolRound int32 `protobuf:"varint,2,opt,name=proposal_pol_round,json=proposalPolRound,proto3" json:"proposal_pol_round,omitempty"` + ProposalPol v1.BitArray `protobuf:"bytes,3,opt,name=proposal_pol,json=proposalPol,proto3" json:"proposal_pol"` } func (m *ProposalPOL) Reset() { *m = ProposalPOL{} } func (m *ProposalPOL) String() string { return proto.CompactTextString(m) } func (*ProposalPOL) ProtoMessage() {} func (*ProposalPOL) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{3} + return fileDescriptor_68132c3a7139c33d, []int{3} } func (m *ProposalPOL) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -281,25 +281,25 @@ func (m *ProposalPOL) GetProposalPolRound() int32 { return 0 } -func (m *ProposalPOL) GetProposalPol() bits.BitArray { +func (m *ProposalPOL) GetProposalPol() v1.BitArray { if m != nil { return m.ProposalPol } - return bits.BitArray{} + return v1.BitArray{} } // BlockPart is sent when gossipping a piece of the proposed block. type BlockPart struct { - Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` - Part types.Part `protobuf:"bytes,3,opt,name=part,proto3" json:"part"` + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Part v1beta1.Part `protobuf:"bytes,3,opt,name=part,proto3" json:"part"` } func (m *BlockPart) Reset() { *m = BlockPart{} } func (m *BlockPart) String() string { return proto.CompactTextString(m) } func (*BlockPart) ProtoMessage() {} func (*BlockPart) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{4} + return fileDescriptor_68132c3a7139c33d, []int{4} } func (m *BlockPart) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -342,23 +342,23 @@ func (m *BlockPart) GetRound() int32 { return 0 } -func (m *BlockPart) GetPart() types.Part { +func (m *BlockPart) GetPart() v1beta1.Part { if m != nil { return m.Part } - return types.Part{} + return v1beta1.Part{} } // Vote is sent when voting for a proposal (or lack thereof). type Vote struct { - Vote *types.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` + Vote *v1beta1.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` } func (m *Vote) Reset() { *m = Vote{} } func (m *Vote) String() string { return proto.CompactTextString(m) } func (*Vote) ProtoMessage() {} func (*Vote) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{5} + return fileDescriptor_68132c3a7139c33d, []int{5} } func (m *Vote) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -387,7 +387,7 @@ func (m *Vote) XXX_DiscardUnknown() { var xxx_messageInfo_Vote proto.InternalMessageInfo -func (m *Vote) GetVote() *types.Vote { +func (m *Vote) GetVote() *v1beta1.Vote { if m != nil { return m.Vote } @@ -396,17 +396,17 @@ func (m *Vote) GetVote() *types.Vote { // HasVote is sent to indicate that a particular vote has been received. type HasVote struct { - Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` - Type types.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=tendermint.types.SignedMsgType" json:"type,omitempty"` - Index int32 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Type v1beta1.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=cometbft.types.v1beta1.SignedMsgType" json:"type,omitempty"` + Index int32 `protobuf:"varint,4,opt,name=index,proto3" json:"index,omitempty"` } func (m *HasVote) Reset() { *m = HasVote{} } func (m *HasVote) String() string { return proto.CompactTextString(m) } func (*HasVote) ProtoMessage() {} func (*HasVote) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{6} + return fileDescriptor_68132c3a7139c33d, []int{6} } func (m *HasVote) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -449,11 +449,11 @@ func (m *HasVote) GetRound() int32 { return 0 } -func (m *HasVote) GetType() types.SignedMsgType { +func (m *HasVote) GetType() v1beta1.SignedMsgType { if m != nil { return m.Type } - return types.UnknownType + return v1beta1.UnknownType } func (m *HasVote) GetIndex() int32 { @@ -465,17 +465,17 @@ func (m *HasVote) GetIndex() int32 { // VoteSetMaj23 is sent to indicate that a given BlockID has seen +2/3 votes. type VoteSetMaj23 struct { - Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` - Type types.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=tendermint.types.SignedMsgType" json:"type,omitempty"` - BlockID types.BlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id"` + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Type v1beta1.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=cometbft.types.v1beta1.SignedMsgType" json:"type,omitempty"` + BlockID v1beta1.BlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id"` } func (m *VoteSetMaj23) Reset() { *m = VoteSetMaj23{} } func (m *VoteSetMaj23) String() string { return proto.CompactTextString(m) } func (*VoteSetMaj23) ProtoMessage() {} func (*VoteSetMaj23) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{7} + return fileDescriptor_68132c3a7139c33d, []int{7} } func (m *VoteSetMaj23) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -518,34 +518,34 @@ func (m *VoteSetMaj23) GetRound() int32 { return 0 } -func (m *VoteSetMaj23) GetType() types.SignedMsgType { +func (m *VoteSetMaj23) GetType() v1beta1.SignedMsgType { if m != nil { return m.Type } - return types.UnknownType + return v1beta1.UnknownType } -func (m *VoteSetMaj23) GetBlockID() types.BlockID { +func (m *VoteSetMaj23) GetBlockID() v1beta1.BlockID { if m != nil { return m.BlockID } - return types.BlockID{} + return v1beta1.BlockID{} } // VoteSetBits is sent to communicate the bit-array of votes seen for the BlockID. type VoteSetBits struct { - Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` - Type types.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=tendermint.types.SignedMsgType" json:"type,omitempty"` - BlockID types.BlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id"` - Votes bits.BitArray `protobuf:"bytes,5,opt,name=votes,proto3" json:"votes"` + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Type v1beta1.SignedMsgType `protobuf:"varint,3,opt,name=type,proto3,enum=cometbft.types.v1beta1.SignedMsgType" json:"type,omitempty"` + BlockID v1beta1.BlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id"` + Votes v1.BitArray `protobuf:"bytes,5,opt,name=votes,proto3" json:"votes"` } func (m *VoteSetBits) Reset() { *m = VoteSetBits{} } func (m *VoteSetBits) String() string { return proto.CompactTextString(m) } func (*VoteSetBits) ProtoMessage() {} func (*VoteSetBits) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{8} + return fileDescriptor_68132c3a7139c33d, []int{8} } func (m *VoteSetBits) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -588,28 +588,31 @@ func (m *VoteSetBits) GetRound() int32 { return 0 } -func (m *VoteSetBits) GetType() types.SignedMsgType { +func (m *VoteSetBits) GetType() v1beta1.SignedMsgType { if m != nil { return m.Type } - return types.UnknownType + return v1beta1.UnknownType } -func (m *VoteSetBits) GetBlockID() types.BlockID { +func (m *VoteSetBits) GetBlockID() v1beta1.BlockID { if m != nil { return m.BlockID } - return types.BlockID{} + return v1beta1.BlockID{} } -func (m *VoteSetBits) GetVotes() bits.BitArray { +func (m *VoteSetBits) GetVotes() v1.BitArray { if m != nil { return m.Votes } - return bits.BitArray{} + return v1.BitArray{} } +// Message is an abstract consensus message. type Message struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Sum: // *Message_NewRoundStep // *Message_NewValidBlock @@ -627,7 +630,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_81a22d2efc008981, []int{9} + return fileDescriptor_68132c3a7139c33d, []int{9} } func (m *Message) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -786,76 +789,79 @@ func (*Message) XXX_OneofWrappers() []interface{} { } func init() { - proto.RegisterType((*NewRoundStep)(nil), "tendermint.consensus.NewRoundStep") - proto.RegisterType((*NewValidBlock)(nil), "tendermint.consensus.NewValidBlock") - proto.RegisterType((*Proposal)(nil), "tendermint.consensus.Proposal") - proto.RegisterType((*ProposalPOL)(nil), "tendermint.consensus.ProposalPOL") - proto.RegisterType((*BlockPart)(nil), "tendermint.consensus.BlockPart") - proto.RegisterType((*Vote)(nil), "tendermint.consensus.Vote") - proto.RegisterType((*HasVote)(nil), "tendermint.consensus.HasVote") - proto.RegisterType((*VoteSetMaj23)(nil), "tendermint.consensus.VoteSetMaj23") - proto.RegisterType((*VoteSetBits)(nil), "tendermint.consensus.VoteSetBits") - proto.RegisterType((*Message)(nil), "tendermint.consensus.Message") -} - -func init() { proto.RegisterFile("tendermint/consensus/types.proto", fileDescriptor_81a22d2efc008981) } - -var fileDescriptor_81a22d2efc008981 = []byte{ - // 856 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcd, 0x8e, 0xe3, 0x44, - 0x10, 0xb6, 0x19, 0x67, 0x92, 0x94, 0x93, 0x19, 0x68, 0xcd, 0xae, 0x42, 0x80, 0x24, 0x98, 0xcb, - 0x08, 0x21, 0x07, 0x65, 0x0e, 0x2b, 0xad, 0x90, 0x00, 0xf3, 0xb3, 0xde, 0xd5, 0x66, 0x37, 0x38, - 0xab, 0x15, 0xe2, 0x62, 0x39, 0x71, 0x93, 0x34, 0x1b, 0xbb, 0x2d, 0x77, 0x27, 0xc3, 0x5c, 0x79, - 0x02, 0x1e, 0x80, 0xd7, 0x40, 0xe2, 0x11, 0xe6, 0x38, 0x47, 0x4e, 0x23, 0x94, 0x79, 0x04, 0x04, - 0x67, 0xd4, 0xed, 0x4e, 0xec, 0x30, 0x9e, 0x81, 0xb9, 0x20, 0x71, 0xeb, 0x4e, 0x55, 0x7d, 0x5d, - 0xf5, 0x55, 0xd5, 0x17, 0x43, 0x8f, 0xe3, 0x38, 0xc4, 0x69, 0x44, 0x62, 0xde, 0x9f, 0xd2, 0x98, - 0xe1, 0x98, 0x2d, 0x59, 0x9f, 0x9f, 0x25, 0x98, 0xd9, 0x49, 0x4a, 0x39, 0x45, 0x47, 0xb9, 0x87, - 0xbd, 0xf5, 0x68, 0x1f, 0xcd, 0xe8, 0x8c, 0x4a, 0x87, 0xbe, 0x38, 0x65, 0xbe, 0xed, 0xb7, 0x0b, - 0x68, 0x12, 0xa3, 0x88, 0xd4, 0x2e, 0xbe, 0xb5, 0x20, 0x13, 0xd6, 0x9f, 0x10, 0xbe, 0xe3, 0x61, - 0xfd, 0xac, 0x43, 0xe3, 0x19, 0x3e, 0xf5, 0xe8, 0x32, 0x0e, 0xc7, 0x1c, 0x27, 0xe8, 0x3e, 0xec, - 0xcf, 0x31, 0x99, 0xcd, 0x79, 0x4b, 0xef, 0xe9, 0xc7, 0x7b, 0x9e, 0xba, 0xa1, 0x23, 0xa8, 0xa4, - 0xc2, 0xa9, 0xf5, 0x5a, 0x4f, 0x3f, 0xae, 0x78, 0xd9, 0x05, 0x21, 0x30, 0x18, 0xc7, 0x49, 0x6b, - 0xaf, 0xa7, 0x1f, 0x37, 0x3d, 0x79, 0x46, 0x0f, 0xa0, 0xc5, 0xf0, 0x94, 0xc6, 0x21, 0xf3, 0x19, - 0x89, 0xa7, 0xd8, 0x67, 0x3c, 0x48, 0xb9, 0xcf, 0x49, 0x84, 0x5b, 0x86, 0xc4, 0xbc, 0xa7, 0xec, - 0x63, 0x61, 0x1e, 0x0b, 0xeb, 0x0b, 0x12, 0x61, 0xf4, 0x3e, 0xbc, 0xb1, 0x08, 0x18, 0xf7, 0xa7, - 0x34, 0x8a, 0x08, 0xf7, 0xb3, 0xe7, 0x2a, 0xf2, 0xb9, 0x43, 0x61, 0xf8, 0x4c, 0xfe, 0x2e, 0x53, - 0xb5, 0xfe, 0xd0, 0xa1, 0xf9, 0x0c, 0x9f, 0xbe, 0x0c, 0x16, 0x24, 0x74, 0x16, 0x74, 0xfa, 0xea, - 0x8e, 0x89, 0x7f, 0x0d, 0xf7, 0x26, 0x22, 0xcc, 0x4f, 0x44, 0x6e, 0x0c, 0x73, 0x7f, 0x8e, 0x83, - 0x10, 0xa7, 0xb2, 0x12, 0x73, 0xd0, 0xb5, 0x0b, 0x3d, 0xc8, 0xf8, 0x1a, 0x05, 0x29, 0x1f, 0x63, - 0xee, 0x4a, 0x37, 0xc7, 0x38, 0xbf, 0xec, 0x6a, 0x1e, 0x92, 0x18, 0x3b, 0x16, 0xf4, 0x31, 0x98, - 0x39, 0x32, 0x93, 0x15, 0x9b, 0x83, 0x4e, 0x11, 0x4f, 0x74, 0xc2, 0x16, 0x9d, 0xb0, 0x1d, 0xc2, - 0x3f, 0x4d, 0xd3, 0xe0, 0xcc, 0x83, 0x2d, 0x10, 0x43, 0x6f, 0x41, 0x9d, 0x30, 0x45, 0x82, 0x2c, - 0xbf, 0xe6, 0xd5, 0x08, 0xcb, 0x8a, 0xb7, 0x5c, 0xa8, 0x8d, 0x52, 0x9a, 0x50, 0x16, 0x2c, 0xd0, - 0x47, 0x50, 0x4b, 0xd4, 0x59, 0xd6, 0x6c, 0x0e, 0xda, 0x25, 0x69, 0x2b, 0x0f, 0x95, 0xf1, 0x36, - 0xc2, 0xfa, 0x49, 0x07, 0x73, 0x63, 0x1c, 0x3d, 0x7f, 0x7a, 0x23, 0x7f, 0x1f, 0x00, 0xda, 0xc4, - 0xf8, 0x09, 0x5d, 0xf8, 0x45, 0x32, 0x5f, 0xdf, 0x58, 0x46, 0x74, 0x21, 0xfb, 0x82, 0x1e, 0x41, - 0xa3, 0xe8, 0xad, 0xe8, 0xfc, 0x87, 0xf2, 0x55, 0x6e, 0x66, 0x01, 0xcd, 0x7a, 0x05, 0x75, 0x67, - 0xc3, 0xc9, 0x1d, 0x7b, 0xfb, 0x21, 0x18, 0x82, 0x7b, 0xf5, 0xf6, 0xfd, 0xf2, 0x56, 0xaa, 0x37, - 0xa5, 0xa7, 0x35, 0x00, 0xe3, 0x25, 0xe5, 0x62, 0x02, 0x8d, 0x15, 0xe5, 0x58, 0xb1, 0x59, 0x12, - 0x29, 0xbc, 0x3c, 0xe9, 0x63, 0xfd, 0xa0, 0x43, 0xd5, 0x0d, 0x98, 0x8c, 0xbb, 0x5b, 0x7e, 0x27, - 0x60, 0x08, 0x34, 0x99, 0xdf, 0x41, 0xd9, 0xa8, 0x8d, 0xc9, 0x2c, 0xc6, 0xe1, 0x90, 0xcd, 0x5e, - 0x9c, 0x25, 0xd8, 0x93, 0xce, 0x02, 0x8a, 0xc4, 0x21, 0xfe, 0x5e, 0x0e, 0x54, 0xc5, 0xcb, 0x2e, - 0xd6, 0x2f, 0x3a, 0x34, 0x44, 0x06, 0x63, 0xcc, 0x87, 0xc1, 0x77, 0x83, 0x93, 0xff, 0x22, 0x93, - 0x2f, 0xa0, 0x96, 0x0d, 0x38, 0x09, 0xd5, 0x74, 0xbf, 0x79, 0x3d, 0x50, 0xf6, 0xee, 0xf1, 0xe7, - 0xce, 0xa1, 0x60, 0x79, 0x7d, 0xd9, 0xad, 0xaa, 0x1f, 0xbc, 0xaa, 0x8c, 0x7d, 0x1c, 0x5a, 0xbf, - 0xeb, 0x60, 0xaa, 0xd4, 0x1d, 0xc2, 0xd9, 0xff, 0x27, 0x73, 0xf4, 0x10, 0x2a, 0x62, 0x02, 0x98, - 0x5c, 0xce, 0x7f, 0x3b, 0xdc, 0x59, 0x88, 0xf5, 0xa7, 0x01, 0xd5, 0x21, 0x66, 0x2c, 0x98, 0x61, - 0xf4, 0x04, 0x0e, 0x62, 0x7c, 0x9a, 0x2d, 0x94, 0x2f, 0x65, 0x34, 0x9b, 0x3b, 0xcb, 0x2e, 0xfb, - 0x03, 0xb0, 0x8b, 0x32, 0xed, 0x6a, 0x5e, 0x23, 0x2e, 0xca, 0xf6, 0x10, 0x0e, 0x05, 0xd6, 0x4a, - 0xe8, 0xa1, 0x2f, 0x13, 0x95, 0x7c, 0x99, 0x83, 0xf7, 0x6e, 0x04, 0xcb, 0xb5, 0xd3, 0xd5, 0xbc, - 0x66, 0xbc, 0x23, 0xa6, 0x45, 0x69, 0x29, 0x59, 0xe1, 0x1c, 0x67, 0xa3, 0x20, 0x6e, 0x41, 0x5a, - 0xd0, 0x97, 0x7f, 0x13, 0x81, 0x8c, 0xeb, 0x77, 0x6f, 0x47, 0x18, 0x3d, 0x7f, 0xea, 0xee, 0x6a, - 0x00, 0xfa, 0x04, 0x20, 0x97, 0x52, 0xc5, 0x76, 0xb7, 0x1c, 0x65, 0xab, 0x15, 0xae, 0xe6, 0xd5, - 0xb7, 0x62, 0x2a, 0xa4, 0x40, 0x2e, 0xf4, 0xfe, 0x75, 0x79, 0xcc, 0x63, 0xc5, 0x14, 0xba, 0x5a, - 0xb6, 0xd6, 0xe8, 0x21, 0xd4, 0xe6, 0x01, 0xf3, 0x65, 0x54, 0x55, 0x46, 0xbd, 0x53, 0x1e, 0xa5, - 0x76, 0xdf, 0xd5, 0xbc, 0xea, 0x5c, 0xc9, 0xc0, 0x13, 0x38, 0x10, 0x71, 0xf2, 0xef, 0x24, 0x12, - 0xeb, 0xd8, 0xaa, 0xdd, 0xd6, 0xd0, 0xe2, 0xe2, 0x8a, 0x86, 0xae, 0x8a, 0x8b, 0xfc, 0x08, 0x9a, - 0x5b, 0x2c, 0x31, 0x4f, 0xad, 0xfa, 0x6d, 0x24, 0x16, 0x16, 0x49, 0x90, 0xb8, 0xca, 0xaf, 0x4e, - 0x05, 0xf6, 0xd8, 0x32, 0x72, 0xbe, 0x3a, 0x5f, 0x77, 0xf4, 0x8b, 0x75, 0x47, 0xff, 0x6d, 0xdd, - 0xd1, 0x7f, 0xbc, 0xea, 0x68, 0x17, 0x57, 0x1d, 0xed, 0xd7, 0xab, 0x8e, 0xf6, 0xcd, 0x83, 0x19, - 0xe1, 0xf3, 0xe5, 0xc4, 0x9e, 0xd2, 0xa8, 0x3f, 0xa5, 0x11, 0xe6, 0x93, 0x6f, 0x79, 0x7e, 0xc8, - 0xbe, 0x38, 0xca, 0xbe, 0x59, 0x26, 0xfb, 0xd2, 0x76, 0xf2, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xfe, 0x06, 0x66, 0x65, 0xd2, 0x08, 0x00, 0x00, + proto.RegisterType((*NewRoundStep)(nil), "cometbft.consensus.v1beta1.NewRoundStep") + proto.RegisterType((*NewValidBlock)(nil), "cometbft.consensus.v1beta1.NewValidBlock") + proto.RegisterType((*Proposal)(nil), "cometbft.consensus.v1beta1.Proposal") + proto.RegisterType((*ProposalPOL)(nil), "cometbft.consensus.v1beta1.ProposalPOL") + proto.RegisterType((*BlockPart)(nil), "cometbft.consensus.v1beta1.BlockPart") + proto.RegisterType((*Vote)(nil), "cometbft.consensus.v1beta1.Vote") + proto.RegisterType((*HasVote)(nil), "cometbft.consensus.v1beta1.HasVote") + proto.RegisterType((*VoteSetMaj23)(nil), "cometbft.consensus.v1beta1.VoteSetMaj23") + proto.RegisterType((*VoteSetBits)(nil), "cometbft.consensus.v1beta1.VoteSetBits") + proto.RegisterType((*Message)(nil), "cometbft.consensus.v1beta1.Message") +} + +func init() { + proto.RegisterFile("cometbft/consensus/v1beta1/types.proto", fileDescriptor_68132c3a7139c33d) +} + +var fileDescriptor_68132c3a7139c33d = []byte{ + // 872 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0x4f, 0x6f, 0xe3, 0x44, + 0x14, 0xb7, 0xb7, 0x49, 0x93, 0x3c, 0x27, 0x2d, 0x8c, 0x76, 0x51, 0x14, 0x50, 0x1a, 0x0c, 0x0b, + 0x01, 0x21, 0x87, 0x66, 0x25, 0xfe, 0x68, 0x2f, 0x8b, 0x41, 0xc8, 0x2b, 0x9a, 0x6e, 0xe4, 0x94, + 0x1e, 0x38, 0x60, 0x39, 0xf1, 0x90, 0x0c, 0x24, 0x1e, 0xe3, 0x99, 0xa4, 0xf4, 0xc6, 0x91, 0x23, + 0x5f, 0x80, 0x6f, 0xc0, 0x95, 0x6f, 0xc0, 0xa1, 0xc7, 0x1e, 0x39, 0x55, 0x28, 0xfd, 0x1a, 0x1c, + 0xd0, 0x8c, 0x27, 0x8e, 0xd3, 0x92, 0xa4, 0xbd, 0x20, 0xed, 0x6d, 0x26, 0xf3, 0x7b, 0xbf, 0x79, + 0xf3, 0x7b, 0xef, 0xfd, 0x62, 0x78, 0x67, 0x40, 0x27, 0x98, 0xf7, 0xbf, 0xe3, 0xad, 0x01, 0x0d, + 0x19, 0x0e, 0xd9, 0x94, 0xb5, 0x66, 0x87, 0x7d, 0xcc, 0xfd, 0xc3, 0x16, 0x3f, 0x8f, 0x30, 0xb3, + 0xa2, 0x98, 0x72, 0x8a, 0x6a, 0x0b, 0x9c, 0x95, 0xe2, 0x2c, 0x85, 0xab, 0x3d, 0x1c, 0xd2, 0x21, + 0x95, 0xb0, 0x96, 0x58, 0x25, 0x11, 0x35, 0x33, 0x65, 0x96, 0x3c, 0xff, 0xc5, 0x5a, 0x7b, 0x33, + 0xc5, 0x8c, 0x49, 0x9f, 0xb5, 0xfa, 0x84, 0x0b, 0x5c, 0x16, 0x62, 0xfe, 0xa1, 0x43, 0xf9, 0x18, + 0x9f, 0xb9, 0x74, 0x1a, 0x06, 0x3d, 0x8e, 0x23, 0xf4, 0x1a, 0xec, 0x8e, 0x30, 0x19, 0x8e, 0x78, + 0x55, 0x6f, 0xe8, 0xcd, 0x1d, 0x57, 0xed, 0xd0, 0x43, 0xc8, 0xc7, 0x02, 0x54, 0x7d, 0xd0, 0xd0, + 0x9b, 0x79, 0x37, 0xd9, 0x20, 0x04, 0x39, 0xc6, 0x71, 0x54, 0xdd, 0x69, 0xe8, 0xcd, 0x8a, 0x2b, + 0xd7, 0xe8, 0x63, 0xa8, 0x32, 0x3c, 0xa0, 0x61, 0xc0, 0x3c, 0x46, 0xc2, 0x01, 0xf6, 0x18, 0xf7, + 0x63, 0xee, 0x71, 0x32, 0xc1, 0xd5, 0x9c, 0xe4, 0x7c, 0xa4, 0xce, 0x7b, 0xe2, 0xb8, 0x27, 0x4e, + 0x4f, 0xc8, 0x04, 0xa3, 0xf7, 0xe1, 0xd5, 0xb1, 0xcf, 0xb8, 0x37, 0xa0, 0x93, 0x09, 0xe1, 0x5e, + 0x72, 0x5d, 0x5e, 0x5e, 0xb7, 0x2f, 0x0e, 0x3e, 0x97, 0xbf, 0xcb, 0x54, 0xcd, 0x7f, 0x74, 0xa8, + 0x1c, 0xe3, 0xb3, 0x53, 0x7f, 0x4c, 0x02, 0x7b, 0x4c, 0x07, 0x3f, 0xdc, 0x33, 0xf1, 0x6f, 0xe1, + 0x51, 0x5f, 0x84, 0x79, 0x91, 0xc8, 0x8d, 0x61, 0xee, 0x8d, 0xb0, 0x1f, 0xe0, 0x58, 0xbe, 0xc4, + 0x68, 0x3f, 0xb6, 0xd2, 0x82, 0x24, 0x6a, 0x29, 0x79, 0xad, 0xae, 0x1f, 0xf3, 0x1e, 0xe6, 0x8e, + 0x04, 0xdb, 0xb9, 0x8b, 0xab, 0x03, 0xcd, 0x45, 0x92, 0x69, 0xe5, 0x04, 0x3d, 0x03, 0x63, 0xc9, + 0xcf, 0xe4, 0xbb, 0x8d, 0xf6, 0xc1, 0x92, 0x55, 0x14, 0xc4, 0x12, 0x05, 0xb1, 0x66, 0x87, 0x96, + 0x4d, 0xf8, 0x67, 0x71, 0xec, 0x9f, 0xbb, 0x90, 0x32, 0x31, 0xf4, 0x3a, 0x94, 0x08, 0x53, 0x5a, + 0x48, 0x15, 0x8a, 0x6e, 0x91, 0xb0, 0x44, 0x03, 0xf3, 0x18, 0x8a, 0xdd, 0x98, 0x46, 0x94, 0xf9, + 0x63, 0x64, 0x43, 0x31, 0x52, 0x6b, 0xf9, 0x74, 0xa3, 0xdd, 0x58, 0x9b, 0xbd, 0xc2, 0xa9, 0xc4, + 0xd3, 0x38, 0xf3, 0x37, 0x1d, 0x8c, 0xc5, 0x61, 0xf7, 0xc5, 0xd1, 0x5a, 0x31, 0x3f, 0x00, 0xb4, + 0x88, 0xf1, 0x22, 0x3a, 0xf6, 0xb2, 0xca, 0xbe, 0xb2, 0x38, 0xe9, 0xd2, 0xb1, 0x2c, 0x12, 0x72, + 0xa0, 0x9c, 0x45, 0x2b, 0x6d, 0xb7, 0xa9, 0xa0, 0x92, 0x33, 0x32, 0x74, 0xe6, 0x8f, 0x50, 0xb2, + 0x17, 0xd2, 0xdc, 0xb3, 0xd2, 0x1f, 0x41, 0x4e, 0xd4, 0x40, 0x5d, 0xfe, 0xc6, 0xa6, 0xc2, 0xaa, + 0x9b, 0x25, 0xde, 0xfc, 0x04, 0x72, 0xa7, 0x94, 0x63, 0xf4, 0x21, 0xe4, 0x66, 0x94, 0x63, 0x25, + 0xed, 0xda, 0x78, 0x81, 0x75, 0x25, 0xd2, 0xfc, 0x45, 0x87, 0x82, 0xe3, 0x33, 0x19, 0x7d, 0xbf, + 0x5c, 0x3f, 0x85, 0x9c, 0x60, 0x95, 0xb9, 0xee, 0xad, 0x6f, 0xc2, 0x1e, 0x19, 0x86, 0x38, 0xe8, + 0xb0, 0xe1, 0xc9, 0x79, 0x84, 0x5d, 0x19, 0x22, 0x08, 0x49, 0x18, 0xe0, 0x9f, 0x64, 0xab, 0xe5, + 0xdd, 0x64, 0x63, 0xfe, 0xa9, 0x43, 0x59, 0xe4, 0xd1, 0xc3, 0xbc, 0xe3, 0x7f, 0xdf, 0x7e, 0xf2, + 0xff, 0xe5, 0xf3, 0x15, 0x14, 0x93, 0x01, 0x20, 0xc1, 0xed, 0xee, 0x5f, 0x0d, 0x97, 0x95, 0x7d, + 0xfe, 0x85, 0xbd, 0x2f, 0xd4, 0x9f, 0x5f, 0x1d, 0x14, 0xd4, 0x0f, 0x6e, 0x41, 0x32, 0x3c, 0x0f, + 0xcc, 0x9f, 0x1f, 0x80, 0xa1, 0x9e, 0x61, 0x13, 0xce, 0x5e, 0xce, 0x57, 0xa0, 0xa7, 0x90, 0x17, + 0xfd, 0xc1, 0xe4, 0x34, 0xdf, 0x79, 0x0e, 0x92, 0x18, 0xf3, 0xf7, 0x3c, 0x14, 0x3a, 0x98, 0x31, + 0x7f, 0x88, 0x51, 0x17, 0xf6, 0x42, 0x7c, 0x96, 0x0c, 0x9f, 0x27, 0xfd, 0x37, 0x69, 0xce, 0xa6, + 0xb5, 0xfe, 0x6f, 0xc4, 0xca, 0xba, 0xbc, 0xa3, 0xb9, 0xe5, 0x30, 0xeb, 0xfa, 0x3d, 0xd8, 0x17, + 0x8c, 0x33, 0x61, 0xa7, 0x9e, 0xcc, 0x57, 0x4a, 0x68, 0xb4, 0xdf, 0xdb, 0x42, 0xb9, 0x34, 0x60, + 0x47, 0x73, 0x2b, 0xe1, 0x8a, 0x23, 0x67, 0x8d, 0x29, 0x99, 0xbe, 0xb7, 0x37, 0xb1, 0x2d, 0xfc, + 0xc7, 0xc9, 0x18, 0x13, 0x3a, 0xba, 0x61, 0x21, 0x49, 0x11, 0xde, 0xbd, 0x0b, 0x4f, 0xf7, 0xc5, + 0x91, 0xb3, 0x6a, 0x23, 0xe8, 0x4b, 0x80, 0xa5, 0x2b, 0xab, 0x32, 0x3c, 0xde, 0xc4, 0x95, 0x9a, + 0x8e, 0xa3, 0xb9, 0xa5, 0xd4, 0x9c, 0x85, 0xa7, 0x48, 0x4f, 0xd8, 0xbd, 0x69, 0xb7, 0xb7, 0x19, + 0x44, 0xdb, 0x3a, 0x5a, 0xe2, 0x0c, 0xe8, 0x19, 0x14, 0x47, 0x3e, 0xf3, 0x64, 0x6c, 0x41, 0xc6, + 0xbe, 0xb5, 0x29, 0x56, 0x99, 0x88, 0xa3, 0xb9, 0x85, 0x91, 0xf2, 0x93, 0x2e, 0xec, 0x89, 0x68, + 0xf9, 0x8f, 0x35, 0x11, 0x13, 0x5d, 0x2d, 0x6e, 0x2f, 0x7d, 0xd6, 0x01, 0x44, 0xe9, 0x67, 0x59, + 0x47, 0xe8, 0x40, 0x25, 0x65, 0x14, 0x2d, 0x58, 0x2d, 0x6d, 0x97, 0x38, 0x33, 0x8b, 0x42, 0xe2, + 0xd9, 0x72, 0x6b, 0xe7, 0x61, 0x87, 0x4d, 0x27, 0xf6, 0xd7, 0x17, 0xf3, 0xba, 0x7e, 0x39, 0xaf, + 0xeb, 0x7f, 0xcf, 0xeb, 0xfa, 0xaf, 0xd7, 0x75, 0xed, 0xf2, 0xba, 0xae, 0xfd, 0x75, 0x5d, 0xd7, + 0xbe, 0x79, 0x3a, 0x24, 0x7c, 0x34, 0xed, 0x0b, 0xfa, 0x56, 0xe6, 0xeb, 0x48, 0x2d, 0xfc, 0x88, + 0xb4, 0xd6, 0x7f, 0x33, 0xf5, 0x77, 0xe5, 0x57, 0xcb, 0x93, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xea, 0x7b, 0x56, 0x58, 0x09, 0x00, 0x00, } func (m *NewRoundStep) Marshal() (dAtA []byte, err error) { @@ -2077,7 +2083,7 @@ func (m *NewValidBlock) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.BlockParts == nil { - m.BlockParts = &bits.BitArray{} + m.BlockParts = &v1.BitArray{} } if err := m.BlockParts.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -2508,7 +2514,7 @@ func (m *Vote) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Vote == nil { - m.Vote = &types.Vote{} + m.Vote = &v1beta1.Vote{} } if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -2616,7 +2622,7 @@ func (m *HasVote) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Type |= types.SignedMsgType(b&0x7F) << shift + m.Type |= v1beta1.SignedMsgType(b&0x7F) << shift if b < 0x80 { break } @@ -2742,7 +2748,7 @@ func (m *VoteSetMaj23) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Type |= types.SignedMsgType(b&0x7F) << shift + m.Type |= v1beta1.SignedMsgType(b&0x7F) << shift if b < 0x80 { break } @@ -2882,7 +2888,7 @@ func (m *VoteSetBits) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Type |= types.SignedMsgType(b&0x7F) << shift + m.Type |= v1beta1.SignedMsgType(b&0x7F) << shift if b < 0x80 { break } diff --git a/proto/tendermint/consensus/wal.pb.go b/api/cometbft/consensus/v1beta1/wal.pb.go similarity index 87% rename from proto/tendermint/consensus/wal.pb.go rename to api/cometbft/consensus/v1beta1/wal.pb.go index f870835ef8b..e0c3fb0d8f1 100644 --- a/proto/tendermint/consensus/wal.pb.go +++ b/api/cometbft/consensus/v1beta1/wal.pb.go @@ -1,11 +1,11 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/consensus/wal.proto +// source: cometbft/consensus/v1beta1/wal.proto -package consensus +package v1beta1 import ( fmt "fmt" - types "github.com/cometbft/cometbft/proto/tendermint/types" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" _ "github.com/cosmos/gogoproto/types" @@ -39,7 +39,7 @@ func (m *MsgInfo) Reset() { *m = MsgInfo{} } func (m *MsgInfo) String() string { return proto.CompactTextString(m) } func (*MsgInfo) ProtoMessage() {} func (*MsgInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_ed0b60c2d348ab09, []int{0} + return fileDescriptor_2778d8be83f1e994, []int{0} } func (m *MsgInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -94,7 +94,7 @@ func (m *TimeoutInfo) Reset() { *m = TimeoutInfo{} } func (m *TimeoutInfo) String() string { return proto.CompactTextString(m) } func (*TimeoutInfo) ProtoMessage() {} func (*TimeoutInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_ed0b60c2d348ab09, []int{1} + return fileDescriptor_2778d8be83f1e994, []int{1} } func (m *TimeoutInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -161,7 +161,7 @@ func (m *EndHeight) Reset() { *m = EndHeight{} } func (m *EndHeight) String() string { return proto.CompactTextString(m) } func (*EndHeight) ProtoMessage() {} func (*EndHeight) Descriptor() ([]byte, []int) { - return fileDescriptor_ed0b60c2d348ab09, []int{2} + return fileDescriptor_2778d8be83f1e994, []int{2} } func (m *EndHeight) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -197,7 +197,10 @@ func (m *EndHeight) GetHeight() int64 { return 0 } +// WALMessage describes a consensus WAL (Write Ahead Log) entry. type WALMessage struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Sum: // *WALMessage_EventDataRoundState // *WALMessage_MsgInfo @@ -210,7 +213,7 @@ func (m *WALMessage) Reset() { *m = WALMessage{} } func (m *WALMessage) String() string { return proto.CompactTextString(m) } func (*WALMessage) ProtoMessage() {} func (*WALMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_ed0b60c2d348ab09, []int{3} + return fileDescriptor_2778d8be83f1e994, []int{3} } func (m *WALMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -246,7 +249,7 @@ type isWALMessage_Sum interface { } type WALMessage_EventDataRoundState struct { - EventDataRoundState *types.EventDataRoundState `protobuf:"bytes,1,opt,name=event_data_round_state,json=eventDataRoundState,proto3,oneof" json:"event_data_round_state,omitempty"` + EventDataRoundState *v1beta1.EventDataRoundState `protobuf:"bytes,1,opt,name=event_data_round_state,json=eventDataRoundState,proto3,oneof" json:"event_data_round_state,omitempty"` } type WALMessage_MsgInfo struct { MsgInfo *MsgInfo `protobuf:"bytes,2,opt,name=msg_info,json=msgInfo,proto3,oneof" json:"msg_info,omitempty"` @@ -270,7 +273,7 @@ func (m *WALMessage) GetSum() isWALMessage_Sum { return nil } -func (m *WALMessage) GetEventDataRoundState() *types.EventDataRoundState { +func (m *WALMessage) GetEventDataRoundState() *v1beta1.EventDataRoundState { if x, ok := m.GetSum().(*WALMessage_EventDataRoundState); ok { return x.EventDataRoundState } @@ -318,7 +321,7 @@ func (m *TimedWALMessage) Reset() { *m = TimedWALMessage{} } func (m *TimedWALMessage) String() string { return proto.CompactTextString(m) } func (*TimedWALMessage) ProtoMessage() {} func (*TimedWALMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_ed0b60c2d348ab09, []int{4} + return fileDescriptor_2778d8be83f1e994, []int{4} } func (m *TimedWALMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -362,51 +365,54 @@ func (m *TimedWALMessage) GetMsg() *WALMessage { } func init() { - proto.RegisterType((*MsgInfo)(nil), "tendermint.consensus.MsgInfo") - proto.RegisterType((*TimeoutInfo)(nil), "tendermint.consensus.TimeoutInfo") - proto.RegisterType((*EndHeight)(nil), "tendermint.consensus.EndHeight") - proto.RegisterType((*WALMessage)(nil), "tendermint.consensus.WALMessage") - proto.RegisterType((*TimedWALMessage)(nil), "tendermint.consensus.TimedWALMessage") -} - -func init() { proto.RegisterFile("tendermint/consensus/wal.proto", fileDescriptor_ed0b60c2d348ab09) } - -var fileDescriptor_ed0b60c2d348ab09 = []byte{ - // 543 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x53, 0xdf, 0x8a, 0xd3, 0x4e, - 0x14, 0xce, 0x6c, 0xff, 0x9f, 0xfe, 0x7e, 0x08, 0xb1, 0x2c, 0xb5, 0xb0, 0x69, 0xec, 0x22, 0xf4, - 0x2a, 0x81, 0x15, 0x51, 0xbc, 0x51, 0x4b, 0x57, 0x5a, 0x70, 0x41, 0xc7, 0x05, 0x41, 0x84, 0x90, - 0x36, 0xa7, 0x69, 0x60, 0x33, 0x53, 0x32, 0x13, 0xc5, 0x2b, 0x5f, 0xa1, 0x97, 0xbe, 0x89, 0xaf, - 0xb0, 0x97, 0x7b, 0xe9, 0xd5, 0x2a, 0xed, 0x8b, 0x48, 0x66, 0xd2, 0x36, 0xb8, 0xf1, 0x6e, 0xce, - 0x9c, 0xef, 0x9c, 0xef, 0x9c, 0xef, 0x9b, 0x01, 0x4b, 0x22, 0x0b, 0x30, 0x89, 0x23, 0x26, 0xdd, - 0x39, 0x67, 0x02, 0x99, 0x48, 0x85, 0xfb, 0xc5, 0xbf, 0x72, 0x56, 0x09, 0x97, 0xdc, 0xec, 0x1c, - 0xf2, 0xce, 0x3e, 0xdf, 0xeb, 0x84, 0x3c, 0xe4, 0x0a, 0xe0, 0x66, 0x27, 0x8d, 0xed, 0xd9, 0xa5, - 0xbd, 0xe4, 0xd7, 0x15, 0x8a, 0x1c, 0x71, 0x52, 0x40, 0xa8, 0x7b, 0x17, 0x3f, 0x23, 0x93, 0xbb, - 0xb4, 0x15, 0x72, 0x1e, 0x5e, 0xa1, 0xab, 0xa2, 0x59, 0xba, 0x70, 0x83, 0x34, 0xf1, 0x65, 0xc4, - 0x59, 0x9e, 0xef, 0xff, 0x9d, 0x97, 0x51, 0x8c, 0x42, 0xfa, 0xf1, 0x4a, 0x03, 0x06, 0x08, 0x8d, - 0x0b, 0x11, 0x4e, 0xd9, 0x82, 0x9b, 0x4f, 0xa0, 0x12, 0x8b, 0xb0, 0x4b, 0x6c, 0x32, 0x6c, 0x9f, - 0x9d, 0x38, 0x65, 0x6b, 0x38, 0x17, 0x28, 0x84, 0x1f, 0xe2, 0xa8, 0x7a, 0x7d, 0xdb, 0x37, 0x68, - 0x86, 0x37, 0x4f, 0xa1, 0xb1, 0x42, 0x4c, 0xbc, 0x28, 0xe8, 0x1e, 0xd9, 0x64, 0xd8, 0x1a, 0xc1, - 0xe6, 0xb6, 0x5f, 0x7f, 0x8b, 0x98, 0x4c, 0xc7, 0xb4, 0x9e, 0xa5, 0xa6, 0xc1, 0x60, 0x4d, 0xa0, - 0x7d, 0x19, 0xc5, 0xc8, 0x53, 0xa9, 0xb8, 0x5e, 0x40, 0x73, 0x37, 0x69, 0x4e, 0xf8, 0xc0, 0xd1, - 0xa3, 0x3a, 0xbb, 0x51, 0x9d, 0x71, 0x0e, 0x18, 0x35, 0x33, 0xb2, 0xef, 0xbf, 0xfa, 0x84, 0xee, - 0x8b, 0xcc, 0x63, 0xa8, 0x2f, 0x31, 0x0a, 0x97, 0x52, 0x91, 0x56, 0x68, 0x1e, 0x99, 0x1d, 0xa8, - 0x25, 0x3c, 0x65, 0x41, 0xb7, 0x62, 0x93, 0x61, 0x8d, 0xea, 0xc0, 0x34, 0xa1, 0x2a, 0x24, 0xae, - 0xba, 0x55, 0x9b, 0x0c, 0xff, 0xa7, 0xea, 0x3c, 0x38, 0x85, 0xd6, 0x39, 0x0b, 0x26, 0xba, 0xec, - 0xd0, 0x8e, 0x14, 0xdb, 0x0d, 0x7e, 0x1c, 0x01, 0x7c, 0x78, 0xf5, 0x26, 0x5f, 0xdb, 0xfc, 0x04, - 0xc7, 0x4a, 0x7e, 0x2f, 0xf0, 0xa5, 0xef, 0xa9, 0xde, 0x9e, 0x90, 0xbe, 0xc4, 0x7c, 0x89, 0x47, - 0x45, 0xd5, 0xb4, 0x8d, 0xe7, 0x19, 0x7e, 0xec, 0x4b, 0x9f, 0x66, 0xe8, 0xf7, 0x19, 0x78, 0x62, - 0xd0, 0xfb, 0x78, 0xf7, 0xda, 0x7c, 0x0e, 0xcd, 0x58, 0x84, 0x5e, 0xc4, 0x16, 0x5c, 0x6d, 0xf5, - 0x6f, 0x17, 0xb4, 0x63, 0x13, 0x83, 0x36, 0xe2, 0xdc, 0xbc, 0xd7, 0xf0, 0x9f, 0xd4, 0xfa, 0xea, - 0xfa, 0x8a, 0xaa, 0x7f, 0x58, 0x5e, 0x5f, 0x70, 0x62, 0x62, 0xd0, 0xb6, 0x2c, 0x18, 0xf3, 0x12, - 0x00, 0x59, 0xe0, 0xe5, 0x62, 0x54, 0x55, 0x97, 0x7e, 0x79, 0x97, 0xbd, 0x7a, 0x13, 0x83, 0xb6, - 0x70, 0x17, 0x8c, 0x6a, 0x50, 0x11, 0x69, 0x3c, 0xf8, 0x06, 0xf7, 0x32, 0x9a, 0xa0, 0xa0, 0xde, - 0x33, 0xa8, 0x66, 0x54, 0xb9, 0x56, 0xbd, 0x3b, 0x86, 0x5f, 0xee, 0xde, 0xa6, 0x76, 0x7c, 0x9d, - 0x39, 0xae, 0x2a, 0xcc, 0x33, 0xfd, 0x34, 0xb5, 0x28, 0x76, 0xf9, 0x38, 0x07, 0x22, 0xf5, 0x2e, - 0x47, 0xef, 0xae, 0x37, 0x16, 0xb9, 0xd9, 0x58, 0xe4, 0xf7, 0xc6, 0x22, 0xeb, 0xad, 0x65, 0xdc, - 0x6c, 0x2d, 0xe3, 0xe7, 0xd6, 0x32, 0x3e, 0x3e, 0x0d, 0x23, 0xb9, 0x4c, 0x67, 0xce, 0x9c, 0xc7, - 0xee, 0x9c, 0xc7, 0x28, 0x67, 0x0b, 0x79, 0x38, 0xe8, 0x4f, 0x5a, 0xf6, 0x31, 0x67, 0x75, 0x95, - 0x7b, 0xfc, 0x27, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x81, 0x69, 0x90, 0x03, 0x04, 0x00, 0x00, + proto.RegisterType((*MsgInfo)(nil), "cometbft.consensus.v1beta1.MsgInfo") + proto.RegisterType((*TimeoutInfo)(nil), "cometbft.consensus.v1beta1.TimeoutInfo") + proto.RegisterType((*EndHeight)(nil), "cometbft.consensus.v1beta1.EndHeight") + proto.RegisterType((*WALMessage)(nil), "cometbft.consensus.v1beta1.WALMessage") + proto.RegisterType((*TimedWALMessage)(nil), "cometbft.consensus.v1beta1.TimedWALMessage") +} + +func init() { + proto.RegisterFile("cometbft/consensus/v1beta1/wal.proto", fileDescriptor_2778d8be83f1e994) +} + +var fileDescriptor_2778d8be83f1e994 = []byte{ + // 554 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x53, 0xcf, 0x6b, 0x13, 0x41, + 0x14, 0xde, 0x69, 0xd2, 0xfc, 0x98, 0x28, 0xc2, 0x5a, 0x4a, 0xcc, 0x61, 0x13, 0x12, 0xad, 0x01, + 0x61, 0x97, 0xea, 0xa5, 0xd0, 0x83, 0x1a, 0x52, 0x49, 0xa0, 0x05, 0x19, 0x2b, 0x82, 0x97, 0x65, + 0xb6, 0xfb, 0xb2, 0x59, 0xec, 0xee, 0x2c, 0x99, 0xd9, 0x8a, 0x7f, 0x80, 0xf7, 0x1c, 0xfd, 0x93, + 0x7a, 0xb3, 0x47, 0x4f, 0x55, 0x92, 0x7f, 0x44, 0xe6, 0xc7, 0x26, 0xc1, 0xd2, 0x78, 0x9b, 0x37, + 0xf3, 0x7d, 0xdf, 0x7b, 0xef, 0x7b, 0x6f, 0xf0, 0xd3, 0x0b, 0x96, 0x80, 0x08, 0x26, 0xc2, 0xbb, + 0x60, 0x29, 0x87, 0x94, 0xe7, 0xdc, 0xbb, 0x3a, 0x0c, 0x40, 0xd0, 0x43, 0xef, 0x2b, 0xbd, 0x74, + 0xb3, 0x19, 0x13, 0xcc, 0x6e, 0x15, 0x28, 0x77, 0x85, 0x72, 0x0d, 0xaa, 0xb5, 0x17, 0xb1, 0x88, + 0x29, 0x98, 0x27, 0x4f, 0x9a, 0xd1, 0x3a, 0xd8, 0xa2, 0x2b, 0xbe, 0x65, 0xc0, 0x0d, 0xae, 0xb7, + 0xc2, 0xa9, 0xdb, 0x15, 0x06, 0xae, 0x20, 0x15, 0x05, 0xc8, 0x89, 0x18, 0x8b, 0x2e, 0xc1, 0x53, + 0x51, 0x90, 0x4f, 0xbc, 0x30, 0x9f, 0x51, 0x11, 0xb3, 0xd4, 0xbc, 0xb7, 0xff, 0x7d, 0x17, 0x71, + 0x02, 0x5c, 0xd0, 0x24, 0xd3, 0x80, 0xee, 0x17, 0x5c, 0x3d, 0xe3, 0xd1, 0x38, 0x9d, 0x30, 0xfb, + 0x18, 0x97, 0x12, 0x1e, 0x35, 0x51, 0x07, 0xf5, 0x1b, 0x2f, 0x7b, 0xee, 0xfd, 0x8d, 0xb9, 0x67, + 0xc0, 0x39, 0x8d, 0x60, 0x50, 0xbe, 0xbe, 0x6d, 0x5b, 0x44, 0xb2, 0xec, 0x1e, 0xae, 0x66, 0x00, + 0x33, 0x3f, 0x0e, 0x9b, 0x3b, 0x1d, 0xd4, 0xaf, 0x0f, 0xf0, 0xe2, 0xb6, 0x5d, 0x79, 0x0f, 0x30, + 0x1b, 0x0f, 0x49, 0x45, 0x3e, 0x8d, 0xc3, 0xee, 0x1c, 0xe1, 0xc6, 0x79, 0x9c, 0x00, 0xcb, 0x85, + 0xca, 0xf8, 0x1a, 0xd7, 0x8a, 0x7a, 0x4d, 0xda, 0x27, 0xae, 0x2e, 0xd8, 0x2d, 0x0a, 0x76, 0x87, + 0x06, 0x30, 0xa8, 0xc9, 0x64, 0x3f, 0x7e, 0xb7, 0x11, 0x59, 0x91, 0xec, 0x7d, 0x5c, 0x99, 0x42, + 0x1c, 0x4d, 0x85, 0x4a, 0x5a, 0x22, 0x26, 0xb2, 0xf7, 0xf0, 0xee, 0x8c, 0xe5, 0x69, 0xd8, 0x2c, + 0x75, 0x50, 0x7f, 0x97, 0xe8, 0xc0, 0xb6, 0x71, 0x99, 0x0b, 0xc8, 0x9a, 0xe5, 0x0e, 0xea, 0x3f, + 0x24, 0xea, 0xdc, 0xed, 0xe1, 0xfa, 0x49, 0x1a, 0x8e, 0x34, 0x6d, 0x2d, 0x87, 0x36, 0xe5, 0xba, + 0x3f, 0x77, 0x30, 0xfe, 0xf4, 0xf6, 0xd4, 0xb4, 0x6d, 0x07, 0x78, 0x5f, 0x0d, 0xc1, 0x0f, 0xa9, + 0xa0, 0xbe, 0xd2, 0xf6, 0xb9, 0xa0, 0x02, 0x4c, 0x13, 0x2f, 0xd6, 0xde, 0xe9, 0x81, 0x16, 0xbe, + 0x9d, 0x48, 0xd6, 0x90, 0x0a, 0x4a, 0x24, 0xe7, 0x83, 0xa4, 0x8c, 0x2c, 0xf2, 0x18, 0xee, 0x5e, + 0xdb, 0x6f, 0x70, 0x2d, 0xe1, 0x91, 0x1f, 0xa7, 0x13, 0xa6, 0x7a, 0xfb, 0xdf, 0x44, 0xf4, 0x0c, + 0x47, 0x16, 0xa9, 0x26, 0x66, 0x9c, 0xa7, 0xf8, 0x81, 0xd0, 0x5e, 0x6b, 0x95, 0x92, 0x52, 0x79, + 0xbe, 0x4d, 0x65, 0x63, 0x36, 0x23, 0x8b, 0x34, 0xc4, 0xc6, 0xa8, 0xde, 0x61, 0x0c, 0x69, 0xe8, + 0x1b, 0x7b, 0xca, 0x4a, 0xeb, 0xd9, 0x36, 0xad, 0x95, 0xab, 0x23, 0x8b, 0xd4, 0xa1, 0x08, 0x06, + 0xbb, 0xb8, 0xc4, 0xf3, 0xa4, 0xfb, 0x1d, 0xe1, 0x47, 0x32, 0x5b, 0xb8, 0x61, 0xeb, 0x11, 0x2e, + 0xcb, 0x8c, 0xc6, 0xc4, 0xd6, 0x9d, 0x4d, 0x38, 0x2f, 0x56, 0x57, 0xaf, 0xc2, 0x5c, 0xae, 0x82, + 0x62, 0xd8, 0x47, 0x7a, 0x73, 0xb5, 0x4f, 0x07, 0xdb, 0xaa, 0x5a, 0xa7, 0x53, 0x6b, 0x3b, 0xf8, + 0x78, 0xbd, 0x70, 0xd0, 0xcd, 0xc2, 0x41, 0x7f, 0x16, 0x0e, 0x9a, 0x2f, 0x1d, 0xeb, 0x66, 0xe9, + 0x58, 0xbf, 0x96, 0x8e, 0xf5, 0xf9, 0x38, 0x8a, 0xc5, 0x34, 0x0f, 0xa4, 0x98, 0xb7, 0xf1, 0x63, + 0xcd, 0x81, 0x66, 0xb1, 0x77, 0xff, 0x3f, 0x0e, 0x2a, 0xaa, 0xe8, 0x57, 0x7f, 0x03, 0x00, 0x00, + 0xff, 0xff, 0xe5, 0x41, 0xcc, 0x52, 0x44, 0x04, 0x00, 0x00, } func (m *MsgInfo) Marshal() (dAtA []byte, err error) { @@ -1203,7 +1209,7 @@ func (m *WALMessage) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - v := &types.EventDataRoundState{} + v := &v1beta1.EventDataRoundState{} if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } diff --git a/proto/tendermint/crypto/keys.pb.go b/api/cometbft/crypto/v1/keys.pb.go similarity index 74% rename from proto/tendermint/crypto/keys.pb.go rename to api/cometbft/crypto/v1/keys.pb.go index 0edb2269f53..2564ca993ef 100644 --- a/proto/tendermint/crypto/keys.pb.go +++ b/api/cometbft/crypto/v1/keys.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/crypto/keys.proto +// source: cometbft/crypto/v1/keys.proto -package crypto +package v1 import ( bytes "bytes" @@ -24,12 +24,15 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// PublicKey defines the keys available for use with Validators +// PublicKey is a ED25519 or a secp256k1 public key. type PublicKey struct { + // The type of key. + // // Types that are valid to be assigned to Sum: // // *PublicKey_Ed25519 // *PublicKey_Secp256K1 + // *PublicKey_Bls12381 Sum isPublicKey_Sum `protobuf_oneof:"sum"` } @@ -37,7 +40,7 @@ func (m *PublicKey) Reset() { *m = PublicKey{} } func (m *PublicKey) String() string { return proto.CompactTextString(m) } func (*PublicKey) ProtoMessage() {} func (*PublicKey) Descriptor() ([]byte, []int) { - return fileDescriptor_cb048658b234868c, []int{0} + return fileDescriptor_25c5fd298152e170, []int{0} } func (m *PublicKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -80,9 +83,13 @@ type PublicKey_Ed25519 struct { type PublicKey_Secp256K1 struct { Secp256K1 []byte `protobuf:"bytes,2,opt,name=secp256k1,proto3,oneof" json:"secp256k1,omitempty"` } +type PublicKey_Bls12381 struct { + Bls12381 []byte `protobuf:"bytes,3,opt,name=bls12381,proto3,oneof" json:"bls12381,omitempty"` +} func (*PublicKey_Ed25519) isPublicKey_Sum() {} func (*PublicKey_Secp256K1) isPublicKey_Sum() {} +func (*PublicKey_Bls12381) isPublicKey_Sum() {} func (m *PublicKey) GetSum() isPublicKey_Sum { if m != nil { @@ -105,35 +112,44 @@ func (m *PublicKey) GetSecp256K1() []byte { return nil } +func (m *PublicKey) GetBls12381() []byte { + if x, ok := m.GetSum().(*PublicKey_Bls12381); ok { + return x.Bls12381 + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*PublicKey) XXX_OneofWrappers() []interface{} { return []interface{}{ (*PublicKey_Ed25519)(nil), (*PublicKey_Secp256K1)(nil), + (*PublicKey_Bls12381)(nil), } } func init() { - proto.RegisterType((*PublicKey)(nil), "tendermint.crypto.PublicKey") + proto.RegisterType((*PublicKey)(nil), "cometbft.crypto.v1.PublicKey") } -func init() { proto.RegisterFile("tendermint/crypto/keys.proto", fileDescriptor_cb048658b234868c) } +func init() { proto.RegisterFile("cometbft/crypto/v1/keys.proto", fileDescriptor_25c5fd298152e170) } -var fileDescriptor_cb048658b234868c = []byte{ - // 204 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x49, 0xcd, 0x4b, - 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x4e, - 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x44, 0xc8, 0xea, 0x41, 0x64, 0xa5, - 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xb2, 0xfa, 0x20, 0x16, 0x44, 0xa1, 0x52, 0x04, 0x17, 0x67, - 0x40, 0x69, 0x52, 0x4e, 0x66, 0xb2, 0x77, 0x6a, 0xa5, 0x90, 0x14, 0x17, 0x7b, 0x6a, 0x8a, 0x91, - 0xa9, 0xa9, 0xa1, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x07, 0x43, 0x10, 0x4c, 0x40, 0x48, - 0x8e, 0x8b, 0xb3, 0x38, 0x35, 0xb9, 0xc0, 0xc8, 0xd4, 0x2c, 0xdb, 0x50, 0x82, 0x09, 0x2a, 0x8b, - 0x10, 0xb2, 0xe2, 0x78, 0xb1, 0x40, 0x9e, 0xf1, 0xc5, 0x42, 0x79, 0x46, 0x27, 0x56, 0x2e, 0xe6, - 0xe2, 0xd2, 0x5c, 0x27, 0xbf, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, - 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, - 0x49, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x4d, 0x2d, - 0x49, 0x4a, 0x2b, 0x41, 0x30, 0x20, 0x4e, 0xc4, 0xf0, 0x5d, 0x12, 0x1b, 0x58, 0xc2, 0x18, 0x10, - 0x00, 0x00, 0xff, 0xff, 0xa3, 0xfb, 0xf7, 0x98, 0xf9, 0x00, 0x00, 0x00, +var fileDescriptor_25c5fd298152e170 = []byte{ + // 222 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4d, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x33, 0xd4, 0xcf, + 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x82, 0x49, 0xeb, 0x41, 0xa4, + 0xf5, 0xca, 0x0c, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xd2, 0xfa, 0x20, 0x16, 0x44, 0xa5, + 0x52, 0x19, 0x17, 0x67, 0x40, 0x69, 0x52, 0x4e, 0x66, 0xb2, 0x77, 0x6a, 0xa5, 0x90, 0x14, 0x17, + 0x7b, 0x6a, 0x8a, 0x91, 0xa9, 0xa9, 0xa1, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x07, 0x43, + 0x10, 0x4c, 0x40, 0x48, 0x8e, 0x8b, 0xb3, 0x38, 0x35, 0xb9, 0xc0, 0xc8, 0xd4, 0x2c, 0xdb, 0x50, + 0x82, 0x09, 0x2a, 0x8b, 0x10, 0x12, 0x92, 0xe1, 0xe2, 0x48, 0xca, 0x29, 0x36, 0x34, 0x32, 0xb6, + 0x30, 0x94, 0x60, 0x86, 0x4a, 0xc3, 0x45, 0xac, 0x38, 0x5e, 0x2c, 0x90, 0x67, 0x7c, 0xb1, 0x50, + 0x9e, 0xd1, 0x89, 0x95, 0x8b, 0xb9, 0xb8, 0x34, 0xd7, 0xc9, 0xf7, 0xc4, 0x23, 0x39, 0xc6, 0x0b, + 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, + 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0x8c, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, + 0xf5, 0x11, 0xbe, 0x84, 0x31, 0x12, 0x0b, 0x32, 0xf5, 0x31, 0xfd, 0x9e, 0xc4, 0x06, 0xf6, 0x8d, + 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x82, 0x23, 0x0d, 0x18, 0x01, 0x00, 0x00, } func (this *PublicKey) Compare(that interface{}) int { @@ -174,6 +190,8 @@ func (this *PublicKey) Compare(that interface{}) int { thisType = 0 case *PublicKey_Secp256K1: thisType = 1 + case *PublicKey_Bls12381: + thisType = 2 default: panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.Sum)) } @@ -183,6 +201,8 @@ func (this *PublicKey) Compare(that interface{}) int { that1Type = 0 case *PublicKey_Secp256K1: that1Type = 1 + case *PublicKey_Bls12381: + that1Type = 2 default: panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.Sum)) } @@ -258,6 +278,36 @@ func (this *PublicKey_Secp256K1) Compare(that interface{}) int { } return 0 } +func (this *PublicKey_Bls12381) Compare(that interface{}) int { + if that == nil { + if this == nil { + return 0 + } + return 1 + } + + that1, ok := that.(*PublicKey_Bls12381) + if !ok { + that2, ok := that.(PublicKey_Bls12381) + if ok { + that1 = &that2 + } else { + return 1 + } + } + if that1 == nil { + if this == nil { + return 0 + } + return 1 + } else if this == nil { + return -1 + } + if c := bytes.Compare(this.Bls12381, that1.Bls12381); c != 0 { + return c + } + return 0 +} func (this *PublicKey) Equal(that interface{}) bool { if that == nil { return this == nil @@ -336,6 +386,30 @@ func (this *PublicKey_Secp256K1) Equal(that interface{}) bool { } return true } +func (this *PublicKey_Bls12381) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PublicKey_Bls12381) + if !ok { + that2, ok := that.(PublicKey_Bls12381) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Bls12381, that1.Bls12381) { + return false + } + return true +} func (m *PublicKey) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -400,6 +474,22 @@ func (m *PublicKey_Secp256K1) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } +func (m *PublicKey_Bls12381) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PublicKey_Bls12381) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Bls12381 != nil { + i -= len(m.Bls12381) + copy(dAtA[i:], m.Bls12381) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Bls12381))) + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} func encodeVarintKeys(dAtA []byte, offset int, v uint64) int { offset -= sovKeys(v) base := offset @@ -447,6 +537,18 @@ func (m *PublicKey_Secp256K1) Size() (n int) { } return n } +func (m *PublicKey_Bls12381) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Bls12381 != nil { + l = len(m.Bls12381) + n += 1 + l + sovKeys(uint64(l)) + } + return n +} func sovKeys(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 @@ -549,6 +651,39 @@ func (m *PublicKey) Unmarshal(dAtA []byte) error { copy(v, dAtA[iNdEx:postIndex]) m.Sum = &PublicKey_Secp256K1{v} iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Bls12381", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowKeys + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthKeys + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthKeys + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := make([]byte, postIndex-iNdEx) + copy(v, dAtA[iNdEx:postIndex]) + m.Sum = &PublicKey_Bls12381{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipKeys(dAtA[iNdEx:]) diff --git a/proto/tendermint/crypto/proof.pb.go b/api/cometbft/crypto/v1/proof.pb.go similarity index 90% rename from proto/tendermint/crypto/proof.pb.go rename to api/cometbft/crypto/v1/proof.pb.go index 1c2273a7491..9437efcbbae 100644 --- a/proto/tendermint/crypto/proof.pb.go +++ b/api/cometbft/crypto/v1/proof.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/crypto/proof.proto +// source: cometbft/crypto/v1/proof.proto -package crypto +package v1 import ( fmt "fmt" @@ -23,6 +23,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// Proof is a Merkle proof. type Proof struct { Total int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` Index int64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` @@ -34,7 +35,7 @@ func (m *Proof) Reset() { *m = Proof{} } func (m *Proof) String() string { return proto.CompactTextString(m) } func (*Proof) ProtoMessage() {} func (*Proof) Descriptor() ([]byte, []int) { - return fileDescriptor_6b60b6ba2ab5b856, []int{0} + return fileDescriptor_d6fc6c2b7bed957e, []int{0} } func (m *Proof) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -91,6 +92,7 @@ func (m *Proof) GetAunts() [][]byte { return nil } +// ValueOp is a Merkle proof for a single key. type ValueOp struct { // Encoded in ProofOp.Key. Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` @@ -102,7 +104,7 @@ func (m *ValueOp) Reset() { *m = ValueOp{} } func (m *ValueOp) String() string { return proto.CompactTextString(m) } func (*ValueOp) ProtoMessage() {} func (*ValueOp) Descriptor() ([]byte, []int) { - return fileDescriptor_6b60b6ba2ab5b856, []int{1} + return fileDescriptor_d6fc6c2b7bed957e, []int{1} } func (m *ValueOp) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -145,6 +147,7 @@ func (m *ValueOp) GetProof() *Proof { return nil } +// DominoOp always returns the given output. type DominoOp struct { Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Input string `protobuf:"bytes,2,opt,name=input,proto3" json:"input,omitempty"` @@ -155,7 +158,7 @@ func (m *DominoOp) Reset() { *m = DominoOp{} } func (m *DominoOp) String() string { return proto.CompactTextString(m) } func (*DominoOp) ProtoMessage() {} func (*DominoOp) Descriptor() ([]byte, []int) { - return fileDescriptor_6b60b6ba2ab5b856, []int{2} + return fileDescriptor_d6fc6c2b7bed957e, []int{2} } func (m *DominoOp) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -206,7 +209,7 @@ func (m *DominoOp) GetOutput() string { } // ProofOp defines an operation used for calculating Merkle root -// The data could be arbitrary format, providing nessecary data +// The data could be arbitrary format, providing necessary data // for example neighbouring node hash type ProofOp struct { Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` @@ -218,7 +221,7 @@ func (m *ProofOp) Reset() { *m = ProofOp{} } func (m *ProofOp) String() string { return proto.CompactTextString(m) } func (*ProofOp) ProtoMessage() {} func (*ProofOp) Descriptor() ([]byte, []int) { - return fileDescriptor_6b60b6ba2ab5b856, []int{3} + return fileDescriptor_d6fc6c2b7bed957e, []int{3} } func (m *ProofOp) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -277,7 +280,7 @@ func (m *ProofOps) Reset() { *m = ProofOps{} } func (m *ProofOps) String() string { return proto.CompactTextString(m) } func (*ProofOps) ProtoMessage() {} func (*ProofOps) Descriptor() ([]byte, []int) { - return fileDescriptor_6b60b6ba2ab5b856, []int{4} + return fileDescriptor_d6fc6c2b7bed957e, []int{4} } func (m *ProofOps) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -314,40 +317,40 @@ func (m *ProofOps) GetOps() []ProofOp { } func init() { - proto.RegisterType((*Proof)(nil), "tendermint.crypto.Proof") - proto.RegisterType((*ValueOp)(nil), "tendermint.crypto.ValueOp") - proto.RegisterType((*DominoOp)(nil), "tendermint.crypto.DominoOp") - proto.RegisterType((*ProofOp)(nil), "tendermint.crypto.ProofOp") - proto.RegisterType((*ProofOps)(nil), "tendermint.crypto.ProofOps") + proto.RegisterType((*Proof)(nil), "cometbft.crypto.v1.Proof") + proto.RegisterType((*ValueOp)(nil), "cometbft.crypto.v1.ValueOp") + proto.RegisterType((*DominoOp)(nil), "cometbft.crypto.v1.DominoOp") + proto.RegisterType((*ProofOp)(nil), "cometbft.crypto.v1.ProofOp") + proto.RegisterType((*ProofOps)(nil), "cometbft.crypto.v1.ProofOps") } -func init() { proto.RegisterFile("tendermint/crypto/proof.proto", fileDescriptor_6b60b6ba2ab5b856) } +func init() { proto.RegisterFile("cometbft/crypto/v1/proof.proto", fileDescriptor_d6fc6c2b7bed957e) } -var fileDescriptor_6b60b6ba2ab5b856 = []byte{ - // 357 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xbd, 0x6a, 0xe3, 0x40, - 0x10, 0x96, 0x2c, 0xf9, 0x6f, 0xed, 0xe2, 0x6e, 0x31, 0x87, 0xf0, 0x71, 0x3a, 0xa1, 0x4a, 0x95, - 0x04, 0x4e, 0xea, 0x14, 0x4e, 0x8a, 0x90, 0x40, 0x1c, 0x54, 0xa4, 0x48, 0x13, 0xd6, 0xf6, 0xca, - 0x12, 0xb1, 0x34, 0x8b, 0x34, 0x82, 0xf8, 0x2d, 0xf2, 0x58, 0x2e, 0x5d, 0xa6, 0x0a, 0xc1, 0x7e, - 0x91, 0xb0, 0xbb, 0x0a, 0x26, 0x98, 0x74, 0xdf, 0xcf, 0xec, 0x37, 0xdf, 0x20, 0x91, 0x7f, 0xc8, - 0x8b, 0x25, 0x2f, 0xf3, 0xac, 0xc0, 0x68, 0x51, 0x6e, 0x04, 0x42, 0x24, 0x4a, 0x80, 0x24, 0x14, - 0x25, 0x20, 0xd0, 0xdf, 0x47, 0x3b, 0xd4, 0xf6, 0x78, 0xb4, 0x82, 0x15, 0x28, 0x37, 0x92, 0x48, - 0x0f, 0xfa, 0x09, 0x69, 0xdf, 0xcb, 0x77, 0x74, 0x44, 0xda, 0x08, 0xc8, 0xd6, 0x8e, 0xe9, 0x99, - 0x81, 0x15, 0x6b, 0x22, 0xd5, 0xac, 0x58, 0xf2, 0x17, 0xa7, 0xa5, 0x55, 0x45, 0xe8, 0x5f, 0xd2, - 0x5f, 0x73, 0x96, 0x3c, 0xa5, 0xac, 0x4a, 0x1d, 0xcb, 0x33, 0x83, 0x61, 0xdc, 0x93, 0xc2, 0x35, - 0xab, 0x52, 0xf9, 0x84, 0xd5, 0x05, 0x56, 0x8e, 0xed, 0x59, 0xc1, 0x30, 0xd6, 0xc4, 0xbf, 0x25, - 0xdd, 0x07, 0xb6, 0xae, 0xf9, 0x4c, 0xd0, 0x5f, 0xc4, 0x7a, 0xe6, 0x1b, 0xb5, 0x67, 0x18, 0x4b, - 0x48, 0x43, 0xd2, 0x56, 0xe5, 0xd5, 0x96, 0xc1, 0xc4, 0x09, 0x4f, 0xda, 0x87, 0xaa, 0x64, 0xac, - 0xc7, 0xfc, 0x1b, 0xd2, 0xbb, 0x82, 0x3c, 0x2b, 0xe0, 0x7b, 0x5a, 0x5f, 0xa7, 0xa9, 0xce, 0xa2, - 0x46, 0x95, 0xd6, 0x8f, 0x35, 0xa1, 0x7f, 0x48, 0x07, 0x6a, 0x94, 0xb2, 0xa5, 0xe4, 0x86, 0xf9, - 0x97, 0xa4, 0xab, 0xb2, 0x67, 0x82, 0x52, 0x62, 0xe3, 0x46, 0xf0, 0x26, 0x4b, 0xe1, 0xaf, 0xf8, - 0xd6, 0xb1, 0x2c, 0x25, 0xf6, 0x92, 0x21, 0x6b, 0xee, 0x56, 0xd8, 0xbf, 0x20, 0xbd, 0x26, 0xa4, - 0xa2, 0x13, 0x62, 0x81, 0xa8, 0x1c, 0xd3, 0xb3, 0x82, 0xc1, 0x64, 0xfc, 0xd3, 0x29, 0x33, 0x31, - 0xb5, 0xb7, 0xef, 0xff, 0x8d, 0x58, 0x0e, 0x4f, 0xef, 0xb6, 0x7b, 0xd7, 0xdc, 0xed, 0x5d, 0xf3, - 0x63, 0xef, 0x9a, 0xaf, 0x07, 0xd7, 0xd8, 0x1d, 0x5c, 0xe3, 0xed, 0xe0, 0x1a, 0x8f, 0xe7, 0xab, - 0x0c, 0xd3, 0x7a, 0x1e, 0x2e, 0x20, 0x8f, 0x16, 0x90, 0x73, 0x9c, 0x27, 0x78, 0x04, 0xfa, 0x73, - 0x9e, 0xfc, 0x0a, 0xf3, 0x8e, 0x32, 0xce, 0x3e, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa6, 0x5a, 0xb3, - 0xb6, 0x26, 0x02, 0x00, 0x00, +var fileDescriptor_d6fc6c2b7bed957e = []byte{ + // 356 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xcd, 0x6a, 0xf2, 0x40, + 0x14, 0x4d, 0x4c, 0xfc, 0xbb, 0xba, 0xf8, 0x18, 0xe4, 0x23, 0xad, 0x30, 0x0d, 0x59, 0x65, 0x95, + 0x41, 0x7d, 0x80, 0x82, 0xed, 0xa2, 0x94, 0x16, 0xcb, 0x2c, 0xba, 0xe8, 0xa6, 0x8c, 0x9a, 0x98, + 0x50, 0x75, 0x06, 0x33, 0x91, 0xfa, 0x16, 0x7d, 0x2c, 0x97, 0x2e, 0xbb, 0x2a, 0x45, 0x5f, 0xa4, + 0xcc, 0x4c, 0x44, 0x8a, 0x74, 0x77, 0xce, 0xb9, 0x77, 0xce, 0x3d, 0x97, 0x3b, 0x80, 0x27, 0x7c, + 0x11, 0xcb, 0x71, 0x22, 0xc9, 0x64, 0xb5, 0x11, 0x92, 0x93, 0x75, 0x8f, 0x88, 0x15, 0xe7, 0x49, + 0x24, 0x56, 0x5c, 0x72, 0x84, 0x8e, 0xf5, 0xc8, 0xd4, 0xa3, 0x75, 0xef, 0xb2, 0x33, 0xe3, 0x33, + 0xae, 0xcb, 0x44, 0x21, 0xd3, 0x19, 0x24, 0x50, 0x7d, 0x52, 0x0f, 0x51, 0x07, 0xaa, 0x92, 0x4b, + 0x36, 0xf7, 0x6c, 0xdf, 0x0e, 0x1d, 0x6a, 0x88, 0x52, 0xb3, 0xe5, 0x34, 0x7e, 0xf7, 0x2a, 0x46, + 0xd5, 0x04, 0x75, 0xa1, 0x39, 0x8f, 0x59, 0xf2, 0x9a, 0xb2, 0x3c, 0xf5, 0x1c, 0xdf, 0x0e, 0xdb, + 0xb4, 0xa1, 0x84, 0x3b, 0x96, 0xa7, 0xea, 0x09, 0x2b, 0x96, 0x32, 0xf7, 0x5c, 0xdf, 0x09, 0xdb, + 0xd4, 0x90, 0xe0, 0x01, 0xea, 0xcf, 0x6c, 0x5e, 0xc4, 0x23, 0x81, 0xfe, 0x81, 0xf3, 0x16, 0x6f, + 0xf4, 0x9c, 0x36, 0x55, 0x10, 0x11, 0xa8, 0xea, 0xf4, 0x7a, 0x4a, 0xab, 0x7f, 0x11, 0x9d, 0xc7, + 0x8f, 0x74, 0x4a, 0x6a, 0xfa, 0x82, 0x7b, 0x68, 0xdc, 0xf2, 0x45, 0xb6, 0xe4, 0xbf, 0xed, 0x9a, + 0xc6, 0x4e, 0x87, 0x16, 0x85, 0xd4, 0x76, 0x4d, 0x6a, 0x08, 0xfa, 0x0f, 0x35, 0x5e, 0x48, 0x25, + 0x3b, 0x5a, 0x2e, 0x59, 0x70, 0x03, 0x75, 0xed, 0x3d, 0x12, 0x08, 0x81, 0x2b, 0x37, 0x22, 0x2e, + 0xbd, 0x34, 0x3e, 0xda, 0x57, 0x4e, 0x69, 0x11, 0xb8, 0x53, 0x26, 0x59, 0xb9, 0xb8, 0xc6, 0xc1, + 0x35, 0x34, 0x4a, 0x93, 0x1c, 0x0d, 0xc0, 0xe1, 0x22, 0xf7, 0x6c, 0xdf, 0x09, 0x5b, 0xfd, 0xee, + 0x9f, 0xbb, 0x8c, 0xc4, 0xd0, 0xdd, 0x7e, 0x5d, 0x59, 0x54, 0x75, 0x0f, 0x1f, 0xb7, 0x7b, 0x6c, + 0xef, 0xf6, 0xd8, 0xfe, 0xde, 0x63, 0xfb, 0xe3, 0x80, 0xad, 0xdd, 0x01, 0x5b, 0x9f, 0x07, 0x6c, + 0xbd, 0x0c, 0x66, 0x99, 0x4c, 0x8b, 0xb1, 0xf2, 0x21, 0xa7, 0xb3, 0x1f, 0x01, 0x13, 0x19, 0x39, + 0xff, 0x0c, 0xe3, 0x9a, 0xbe, 0xee, 0xe0, 0x27, 0x00, 0x00, 0xff, 0xff, 0x69, 0xea, 0x58, 0xaf, + 0x29, 0x02, 0x00, 0x00, } func (m *Proof) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/libs/bits/types.pb.go b/api/cometbft/libs/bits/v1/types.pb.go similarity index 86% rename from proto/tendermint/libs/bits/types.pb.go rename to api/cometbft/libs/bits/v1/types.pb.go index 9dc37733632..2817d0afb26 100644 --- a/proto/tendermint/libs/bits/types.pb.go +++ b/api/cometbft/libs/bits/v1/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/libs/bits/types.proto +// source: cometbft/libs/bits/v1/types.proto -package bits +package v1 import ( fmt "fmt" @@ -22,6 +22,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// BitArray is an array of bits. type BitArray struct { Bits int64 `protobuf:"varint,1,opt,name=bits,proto3" json:"bits,omitempty"` Elems []uint64 `protobuf:"varint,2,rep,packed,name=elems,proto3" json:"elems,omitempty"` @@ -31,7 +32,7 @@ func (m *BitArray) Reset() { *m = BitArray{} } func (m *BitArray) String() string { return proto.CompactTextString(m) } func (*BitArray) ProtoMessage() {} func (*BitArray) Descriptor() ([]byte, []int) { - return fileDescriptor_e91ab2672920d7d4, []int{0} + return fileDescriptor_14f91284a011ac96, []int{0} } func (m *BitArray) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -75,24 +76,24 @@ func (m *BitArray) GetElems() []uint64 { } func init() { - proto.RegisterType((*BitArray)(nil), "tendermint.libs.bits.BitArray") + proto.RegisterType((*BitArray)(nil), "cometbft.libs.bits.v1.BitArray") } -func init() { proto.RegisterFile("tendermint/libs/bits/types.proto", fileDescriptor_e91ab2672920d7d4) } +func init() { proto.RegisterFile("cometbft/libs/bits/v1/types.proto", fileDescriptor_14f91284a011ac96) } -var fileDescriptor_e91ab2672920d7d4 = []byte{ +var fileDescriptor_14f91284a011ac96 = []byte{ // 173 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x28, 0x49, 0xcd, 0x4b, - 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0xcf, 0xc9, 0x4c, 0x2a, 0xd6, 0x4f, 0xca, 0x2c, 0x29, - 0xd6, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x41, 0xa8, - 0xd0, 0x03, 0xa9, 0xd0, 0x03, 0xa9, 0x50, 0x32, 0xe1, 0xe2, 0x70, 0xca, 0x2c, 0x71, 0x2c, 0x2a, - 0x4a, 0xac, 0x14, 0x12, 0xe2, 0x62, 0x01, 0x89, 0x49, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0x81, - 0xd9, 0x42, 0x22, 0x5c, 0xac, 0xa9, 0x39, 0xa9, 0xb9, 0xc5, 0x12, 0x4c, 0x0a, 0xcc, 0x1a, 0x2c, - 0x41, 0x10, 0x8e, 0x53, 0xe0, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, - 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x99, - 0xa7, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x27, 0xe7, 0xe7, 0xa6, 0x96, - 0x24, 0xa5, 0x95, 0x20, 0x18, 0x60, 0x97, 0xe8, 0x63, 0x73, 0x6a, 0x12, 0x1b, 0x58, 0xce, 0x18, - 0x10, 0x00, 0x00, 0xff, 0xff, 0x09, 0xfd, 0x78, 0xed, 0xc9, 0x00, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4c, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0xcf, 0xc9, 0x4c, 0x2a, 0xd6, 0x4f, 0xca, 0x2c, 0x29, 0xd6, 0x2f, + 0x33, 0xd4, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x85, + 0x29, 0xd1, 0x03, 0x29, 0xd1, 0x03, 0x29, 0xd1, 0x2b, 0x33, 0x54, 0x32, 0xe1, 0xe2, 0x70, 0xca, + 0x2c, 0x71, 0x2c, 0x2a, 0x4a, 0xac, 0x14, 0x12, 0xe2, 0x62, 0x01, 0x09, 0x4b, 0x30, 0x2a, 0x30, + 0x6a, 0x30, 0x07, 0x81, 0xd9, 0x42, 0x22, 0x5c, 0xac, 0xa9, 0x39, 0xa9, 0xb9, 0xc5, 0x12, 0x4c, + 0x0a, 0xcc, 0x1a, 0x2c, 0x41, 0x10, 0x8e, 0x53, 0xc0, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, + 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, + 0xcb, 0x31, 0x44, 0x99, 0xa5, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xc3, + 0x1d, 0x05, 0x67, 0x24, 0x16, 0x64, 0xea, 0x63, 0x75, 0x6a, 0x12, 0x1b, 0xd8, 0x95, 0xc6, 0x80, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xd0, 0xd4, 0xb6, 0x64, 0xca, 0x00, 0x00, 0x00, } func (m *BitArray) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/mempool/message.go b/api/cometbft/mempool/v1/message.go similarity index 81% rename from proto/tendermint/mempool/message.go rename to api/cometbft/mempool/v1/message.go index 270a744faec..a2093ee8682 100644 --- a/proto/tendermint/mempool/message.go +++ b/api/cometbft/mempool/v1/message.go @@ -1,16 +1,11 @@ -package mempool +package v1 import ( "fmt" "github.com/cosmos/gogoproto/proto" - - "github.com/cometbft/cometbft/p2p" ) -var _ p2p.Wrapper = &Txs{} -var _ p2p.Unwrapper = &Message{} - // Wrap implements the p2p Wrapper interface and wraps a mempool message. func (m *Txs) Wrap() proto.Message { mm := &Message{} diff --git a/proto/tendermint/mempool/types.pb.go b/api/cometbft/mempool/v1/types.pb.go similarity index 87% rename from proto/tendermint/mempool/types.pb.go rename to api/cometbft/mempool/v1/types.pb.go index 4a6a40ef341..dac12ec1685 100644 --- a/proto/tendermint/mempool/types.pb.go +++ b/api/cometbft/mempool/v1/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/mempool/types.proto +// source: cometbft/mempool/v1/types.proto -package mempool +package v1 import ( fmt "fmt" @@ -22,6 +22,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// Txs contains a list of transaction from the mempool. type Txs struct { Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` } @@ -30,7 +31,7 @@ func (m *Txs) Reset() { *m = Txs{} } func (m *Txs) String() string { return proto.CompactTextString(m) } func (*Txs) ProtoMessage() {} func (*Txs) Descriptor() ([]byte, []int) { - return fileDescriptor_2af51926fdbcbc05, []int{0} + return fileDescriptor_d8bb39f484575b79, []int{0} } func (m *Txs) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -66,7 +67,10 @@ func (m *Txs) GetTxs() [][]byte { return nil } +// Message is an abstract mempool message. type Message struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Sum: // // *Message_Txs @@ -77,7 +81,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_2af51926fdbcbc05, []int{1} + return fileDescriptor_d8bb39f484575b79, []int{1} } func (m *Message) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -140,26 +144,26 @@ func (*Message) XXX_OneofWrappers() []interface{} { } func init() { - proto.RegisterType((*Txs)(nil), "tendermint.mempool.Txs") - proto.RegisterType((*Message)(nil), "tendermint.mempool.Message") -} - -func init() { proto.RegisterFile("tendermint/mempool/types.proto", fileDescriptor_2af51926fdbcbc05) } - -var fileDescriptor_2af51926fdbcbc05 = []byte{ - // 184 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x49, 0xcd, 0x4b, - 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0xcf, 0x4d, 0xcd, 0x2d, 0xc8, 0xcf, 0xcf, 0xd1, 0x2f, - 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x42, 0xc8, 0xeb, 0x41, - 0xe5, 0x95, 0xc4, 0xb9, 0x98, 0x43, 0x2a, 0x8a, 0x85, 0x04, 0xb8, 0x98, 0x4b, 0x2a, 0x8a, 0x25, - 0x18, 0x15, 0x98, 0x35, 0x78, 0x82, 0x40, 0x4c, 0x25, 0x5b, 0x2e, 0x76, 0xdf, 0xd4, 0xe2, 0xe2, - 0xc4, 0xf4, 0x54, 0x21, 0x6d, 0x98, 0x24, 0xa3, 0x06, 0xb7, 0x91, 0xb8, 0x1e, 0xa6, 0x29, 0x7a, - 0x21, 0x15, 0xc5, 0x1e, 0x0c, 0x60, 0x7d, 0x4e, 0xac, 0x5c, 0xcc, 0xc5, 0xa5, 0xb9, 0x4e, 0xfe, - 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, - 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0x65, 0x9a, 0x9e, 0x59, 0x92, 0x51, - 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x9f, 0x9c, 0x9f, 0x9b, 0x5a, 0x92, 0x94, 0x56, 0x82, 0x60, - 0x80, 0x5d, 0xaa, 0x8f, 0xe9, 0x91, 0x24, 0x36, 0xb0, 0x8c, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, - 0x53, 0xc3, 0xc4, 0x0a, 0xe5, 0x00, 0x00, 0x00, + proto.RegisterType((*Txs)(nil), "cometbft.mempool.v1.Txs") + proto.RegisterType((*Message)(nil), "cometbft.mempool.v1.Message") +} + +func init() { proto.RegisterFile("cometbft/mempool/v1/types.proto", fileDescriptor_d8bb39f484575b79) } + +var fileDescriptor_d8bb39f484575b79 = []byte{ + // 182 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0xcf, 0x4d, 0xcd, 0x2d, 0xc8, 0xcf, 0xcf, 0xd1, 0x2f, 0x33, 0xd4, + 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x86, 0x29, 0xd0, + 0x83, 0x2a, 0xd0, 0x2b, 0x33, 0x54, 0x12, 0xe7, 0x62, 0x0e, 0xa9, 0x28, 0x16, 0x12, 0xe0, 0x62, + 0x2e, 0xa9, 0x28, 0x96, 0x60, 0x54, 0x60, 0xd6, 0xe0, 0x09, 0x02, 0x31, 0x95, 0xec, 0xb8, 0xd8, + 0x7d, 0x53, 0x8b, 0x8b, 0x13, 0xd3, 0x53, 0x85, 0x74, 0x60, 0x92, 0x8c, 0x1a, 0xdc, 0x46, 0x12, + 0x7a, 0x58, 0x8c, 0xd1, 0x0b, 0xa9, 0x28, 0xf6, 0x60, 0x00, 0x6b, 0x74, 0x62, 0xe5, 0x62, 0x2e, + 0x2e, 0xcd, 0x75, 0xf2, 0x3b, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, + 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x93, + 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0x90, 0x39, 0xfa, 0x70, 0x37, 0xc3, 0x19, 0x89, 0x05, 0x99, + 0xfa, 0x58, 0x7c, 0x92, 0xc4, 0x06, 0xf6, 0x84, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x09, + 0x89, 0xce, 0xe7, 0x00, 0x00, 0x00, } func (m *Txs) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/p2p/conn.pb.go b/api/cometbft/p2p/v1/conn.pb.go similarity index 86% rename from proto/tendermint/p2p/conn.pb.go rename to api/cometbft/p2p/v1/conn.pb.go index 4a0f8256428..fb2a0b5bae9 100644 --- a/proto/tendermint/p2p/conn.pb.go +++ b/api/cometbft/p2p/v1/conn.pb.go @@ -1,11 +1,11 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/p2p/conn.proto +// source: cometbft/p2p/v1/conn.proto -package p2p +package v1 import ( fmt "fmt" - crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" @@ -24,6 +24,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// PacketPing is a request to confirm that the connection is alive. type PacketPing struct { } @@ -31,7 +32,7 @@ func (m *PacketPing) Reset() { *m = PacketPing{} } func (m *PacketPing) String() string { return proto.CompactTextString(m) } func (*PacketPing) ProtoMessage() {} func (*PacketPing) Descriptor() ([]byte, []int) { - return fileDescriptor_22474b5527c8fa9f, []int{0} + return fileDescriptor_3ad66b5863681764, []int{0} } func (m *PacketPing) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -60,6 +61,7 @@ func (m *PacketPing) XXX_DiscardUnknown() { var xxx_messageInfo_PacketPing proto.InternalMessageInfo +// PacketPong is a response to confirm that the connection is alive. type PacketPong struct { } @@ -67,7 +69,7 @@ func (m *PacketPong) Reset() { *m = PacketPong{} } func (m *PacketPong) String() string { return proto.CompactTextString(m) } func (*PacketPong) ProtoMessage() {} func (*PacketPong) Descriptor() ([]byte, []int) { - return fileDescriptor_22474b5527c8fa9f, []int{1} + return fileDescriptor_3ad66b5863681764, []int{1} } func (m *PacketPong) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -96,6 +98,8 @@ func (m *PacketPong) XXX_DiscardUnknown() { var xxx_messageInfo_PacketPong proto.InternalMessageInfo +// PacketMsg contains data for the specified channel ID. EOF means the message +// is fully received. type PacketMsg struct { ChannelID int32 `protobuf:"varint,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` EOF bool `protobuf:"varint,2,opt,name=eof,proto3" json:"eof,omitempty"` @@ -106,7 +110,7 @@ func (m *PacketMsg) Reset() { *m = PacketMsg{} } func (m *PacketMsg) String() string { return proto.CompactTextString(m) } func (*PacketMsg) ProtoMessage() {} func (*PacketMsg) Descriptor() ([]byte, []int) { - return fileDescriptor_22474b5527c8fa9f, []int{2} + return fileDescriptor_3ad66b5863681764, []int{2} } func (m *PacketMsg) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -156,7 +160,10 @@ func (m *PacketMsg) GetData() []byte { return nil } +// Packet is an abstract p2p message. type Packet struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Sum: // // *Packet_PacketPing @@ -169,7 +176,7 @@ func (m *Packet) Reset() { *m = Packet{} } func (m *Packet) String() string { return proto.CompactTextString(m) } func (*Packet) ProtoMessage() {} func (*Packet) Descriptor() ([]byte, []int) { - return fileDescriptor_22474b5527c8fa9f, []int{3} + return fileDescriptor_3ad66b5863681764, []int{3} } func (m *Packet) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -255,16 +262,18 @@ func (*Packet) XXX_OneofWrappers() []interface{} { } } +// AuthSigMessage is sent during the authentication and contains our/remote's +// signature along with the public key. type AuthSigMessage struct { - PubKey crypto.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` - Sig []byte `protobuf:"bytes,2,opt,name=sig,proto3" json:"sig,omitempty"` + PubKey v1.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + Sig []byte `protobuf:"bytes,2,opt,name=sig,proto3" json:"sig,omitempty"` } func (m *AuthSigMessage) Reset() { *m = AuthSigMessage{} } func (m *AuthSigMessage) String() string { return proto.CompactTextString(m) } func (*AuthSigMessage) ProtoMessage() {} func (*AuthSigMessage) Descriptor() ([]byte, []int) { - return fileDescriptor_22474b5527c8fa9f, []int{4} + return fileDescriptor_3ad66b5863681764, []int{4} } func (m *AuthSigMessage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -293,11 +302,11 @@ func (m *AuthSigMessage) XXX_DiscardUnknown() { var xxx_messageInfo_AuthSigMessage proto.InternalMessageInfo -func (m *AuthSigMessage) GetPubKey() crypto.PublicKey { +func (m *AuthSigMessage) GetPubKey() v1.PublicKey { if m != nil { return m.PubKey } - return crypto.PublicKey{} + return v1.PublicKey{} } func (m *AuthSigMessage) GetSig() []byte { @@ -308,42 +317,43 @@ func (m *AuthSigMessage) GetSig() []byte { } func init() { - proto.RegisterType((*PacketPing)(nil), "tendermint.p2p.PacketPing") - proto.RegisterType((*PacketPong)(nil), "tendermint.p2p.PacketPong") - proto.RegisterType((*PacketMsg)(nil), "tendermint.p2p.PacketMsg") - proto.RegisterType((*Packet)(nil), "tendermint.p2p.Packet") - proto.RegisterType((*AuthSigMessage)(nil), "tendermint.p2p.AuthSigMessage") -} - -func init() { proto.RegisterFile("tendermint/p2p/conn.proto", fileDescriptor_22474b5527c8fa9f) } - -var fileDescriptor_22474b5527c8fa9f = []byte{ - // 397 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0x4d, 0x8f, 0xd3, 0x30, - 0x10, 0x8d, 0xc9, 0x6e, 0x97, 0x4e, 0xcb, 0x0a, 0x59, 0x1c, 0xda, 0x6a, 0x95, 0x56, 0x3d, 0xf5, - 0x80, 0x12, 0x11, 0x6e, 0x20, 0x0e, 0x84, 0x0f, 0xb1, 0xaa, 0x2a, 0xaa, 0x70, 0xe3, 0x12, 0xe5, - 0xc3, 0xeb, 0x58, 0xdd, 0xd8, 0x56, 0xed, 0x1c, 0xf2, 0x2f, 0xf8, 0x59, 0xcb, 0xad, 0x47, 0x4e, - 0x15, 0x4a, 0xff, 0x08, 0x4a, 0x5c, 0x68, 0x2a, 0xb1, 0xb7, 0xf7, 0x66, 0xfc, 0x66, 0xde, 0x93, - 0x07, 0xc6, 0x9a, 0xf0, 0x8c, 0x6c, 0x0b, 0xc6, 0xb5, 0x27, 0x7d, 0xe9, 0xa5, 0x82, 0x73, 0x57, - 0x6e, 0x85, 0x16, 0xf8, 0xfa, 0xd4, 0x72, 0xa5, 0x2f, 0x27, 0x2f, 0xa8, 0xa0, 0xa2, 0x6d, 0x79, - 0x0d, 0x32, 0xaf, 0x26, 0x37, 0x9d, 0x01, 0xe9, 0xb6, 0x92, 0x5a, 0x78, 0x1b, 0x52, 0x29, 0xd3, - 0x9d, 0x0f, 0x01, 0xd6, 0x71, 0xba, 0x21, 0x7a, 0xcd, 0x38, 0xed, 0x30, 0xc1, 0xe9, 0x3c, 0x87, - 0xbe, 0x61, 0x2b, 0x45, 0xf1, 0x4b, 0x80, 0x34, 0x8f, 0x39, 0x27, 0xf7, 0x11, 0xcb, 0x46, 0x68, - 0x86, 0x16, 0x97, 0xc1, 0xb3, 0x7a, 0x3f, 0xed, 0x7f, 0x30, 0xd5, 0xdb, 0x8f, 0x61, 0xff, 0xf8, - 0xe0, 0x36, 0xc3, 0x63, 0xb0, 0x89, 0xb8, 0x1b, 0x3d, 0x99, 0xa1, 0xc5, 0xd3, 0xe0, 0xaa, 0xde, - 0x4f, 0xed, 0x4f, 0x5f, 0x3f, 0x87, 0x4d, 0x0d, 0x63, 0xb8, 0xc8, 0x62, 0x1d, 0x8f, 0xec, 0x19, - 0x5a, 0x0c, 0xc3, 0x16, 0xcf, 0x7f, 0x22, 0xe8, 0x99, 0x55, 0xf8, 0x1d, 0x0c, 0x64, 0x8b, 0x22, - 0xc9, 0x38, 0x6d, 0x17, 0x0d, 0xfc, 0x89, 0x7b, 0x1e, 0xd5, 0x3d, 0x79, 0xfe, 0x62, 0x85, 0x20, - 0xff, 0xb1, 0xae, 0x5c, 0x70, 0xda, 0x1a, 0x78, 0x5c, 0x2e, 0xce, 0xe4, 0x82, 0x53, 0xfc, 0x06, - 0x8e, 0x2c, 0x2a, 0x14, 0x6d, 0x2d, 0x0e, 0xfc, 0xf1, 0xff, 0xd5, 0x2b, 0xd5, 0x88, 0xfb, 0xf2, - 0x2f, 0x09, 0x2e, 0xc1, 0x56, 0x65, 0x31, 0x8f, 0xe0, 0xfa, 0x7d, 0xa9, 0xf3, 0x6f, 0x8c, 0xae, - 0x88, 0x52, 0x31, 0x25, 0xf8, 0x2d, 0x5c, 0xc9, 0x32, 0x89, 0x36, 0xa4, 0x3a, 0xc6, 0xb9, 0xe9, - 0x4e, 0x34, 0x7f, 0xe2, 0xae, 0xcb, 0xe4, 0x9e, 0xa5, 0x4b, 0x52, 0x05, 0x17, 0x0f, 0xfb, 0xa9, - 0x15, 0xf6, 0x64, 0x99, 0x2c, 0x49, 0x85, 0x9f, 0x83, 0xad, 0x98, 0x09, 0x32, 0x0c, 0x1b, 0x18, - 0x2c, 0x1f, 0x6a, 0x07, 0xed, 0x6a, 0x07, 0xfd, 0xae, 0x1d, 0xf4, 0xe3, 0xe0, 0x58, 0xbb, 0x83, - 0x63, 0xfd, 0x3a, 0x38, 0xd6, 0xf7, 0x57, 0x94, 0xe9, 0xbc, 0x4c, 0xdc, 0x54, 0x14, 0x5e, 0x2a, - 0x0a, 0xa2, 0x93, 0x3b, 0x7d, 0x02, 0xe6, 0x32, 0xce, 0xcf, 0x29, 0xe9, 0xb5, 0xd5, 0xd7, 0x7f, - 0x02, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xf9, 0x75, 0xae, 0x67, 0x02, 0x00, 0x00, + proto.RegisterType((*PacketPing)(nil), "cometbft.p2p.v1.PacketPing") + proto.RegisterType((*PacketPong)(nil), "cometbft.p2p.v1.PacketPong") + proto.RegisterType((*PacketMsg)(nil), "cometbft.p2p.v1.PacketMsg") + proto.RegisterType((*Packet)(nil), "cometbft.p2p.v1.Packet") + proto.RegisterType((*AuthSigMessage)(nil), "cometbft.p2p.v1.AuthSigMessage") +} + +func init() { proto.RegisterFile("cometbft/p2p/v1/conn.proto", fileDescriptor_3ad66b5863681764) } + +var fileDescriptor_3ad66b5863681764 = []byte{ + // 402 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0xf5, 0xe2, 0x36, 0xc5, 0x93, 0xf0, 0xa1, 0x15, 0x87, 0x60, 0x54, 0x27, 0xf2, 0x29, 0x07, + 0x64, 0x53, 0x73, 0x04, 0x21, 0x61, 0x3e, 0x44, 0xa9, 0x22, 0x2a, 0x73, 0xe3, 0x62, 0x6c, 0x67, + 0xbb, 0x5e, 0xa5, 0xd9, 0x5d, 0x75, 0xd7, 0x95, 0xfc, 0x2f, 0xf8, 0x59, 0x3d, 0x70, 0xe8, 0x91, + 0x53, 0x84, 0x9c, 0x3f, 0x82, 0xbc, 0x4e, 0x9a, 0x10, 0x09, 0x6e, 0xef, 0xcd, 0xcc, 0x7b, 0x33, + 0xa3, 0x19, 0x70, 0x0b, 0xb1, 0x20, 0x3a, 0xbf, 0xd0, 0xa1, 0x8c, 0x64, 0x78, 0x7d, 0x12, 0x16, + 0x82, 0xf3, 0x40, 0x5e, 0x09, 0x2d, 0xf0, 0xa3, 0x4d, 0x2e, 0x90, 0x91, 0x0c, 0xae, 0x4f, 0xdc, + 0x27, 0x54, 0x50, 0x61, 0x72, 0x61, 0x8b, 0xba, 0x32, 0xf7, 0xf8, 0xce, 0xa2, 0xb8, 0xaa, 0xa5, + 0x16, 0xad, 0xcb, 0x9c, 0xd4, 0xaa, 0x4b, 0xfb, 0x03, 0x80, 0xf3, 0xac, 0x98, 0x13, 0x7d, 0xce, + 0x38, 0xdd, 0x61, 0x82, 0x53, 0xbf, 0x04, 0xa7, 0x63, 0x53, 0x45, 0xf1, 0x73, 0x80, 0xa2, 0xcc, + 0x38, 0x27, 0x97, 0x29, 0x9b, 0x0d, 0xd1, 0x18, 0x4d, 0x0e, 0xe3, 0x07, 0xcd, 0x72, 0xe4, 0xbc, + 0xeb, 0xa2, 0xa7, 0xef, 0x13, 0x67, 0x5d, 0x70, 0x3a, 0xc3, 0x4f, 0xc1, 0x26, 0xe2, 0x62, 0x78, + 0x6f, 0x8c, 0x26, 0xf7, 0xe3, 0xa3, 0x66, 0x39, 0xb2, 0x3f, 0x7c, 0xf9, 0x98, 0xb4, 0x31, 0x8c, + 0xe1, 0x60, 0x96, 0xe9, 0x6c, 0x68, 0x8f, 0xd1, 0x64, 0x90, 0x18, 0xec, 0xff, 0x44, 0xd0, 0xeb, + 0x5a, 0xe1, 0x37, 0xd0, 0x97, 0x06, 0xa5, 0x92, 0x71, 0x6a, 0x1a, 0xf5, 0xa3, 0x67, 0xc1, 0xde, + 0xb2, 0xc1, 0x76, 0xe8, 0x4f, 0x56, 0x02, 0xf2, 0x8e, 0xed, 0xea, 0x05, 0xa7, 0x66, 0x82, 0xff, + 0xe8, 0xc5, 0x5f, 0x7a, 0xc1, 0x29, 0x7e, 0x05, 0x6b, 0x96, 0x2e, 0x14, 0x35, 0x43, 0xf6, 0x23, + 0xf7, 0x1f, 0xf2, 0xa9, 0x6a, 0xd5, 0x8e, 0xdc, 0x90, 0xf8, 0x10, 0x6c, 0x55, 0x2d, 0xfc, 0xef, + 0xf0, 0xf0, 0x6d, 0xa5, 0xcb, 0xaf, 0x8c, 0x4e, 0x89, 0x52, 0x19, 0x25, 0xf8, 0x35, 0x1c, 0xc9, + 0x2a, 0x4f, 0xe7, 0xa4, 0x5e, 0x6f, 0x74, 0xbc, 0xb5, 0xec, 0xee, 0x62, 0x5c, 0xab, 0xfc, 0x92, + 0x15, 0x67, 0xa4, 0x8e, 0x0f, 0x6e, 0x96, 0x23, 0x2b, 0xe9, 0xc9, 0x2a, 0x3f, 0x23, 0x35, 0x7e, + 0x0c, 0xb6, 0x62, 0xdd, 0x2e, 0x83, 0xa4, 0x85, 0xf1, 0xe7, 0x9b, 0xc6, 0x43, 0xb7, 0x8d, 0x87, + 0x7e, 0x37, 0x1e, 0xfa, 0xb1, 0xf2, 0xac, 0xdb, 0x95, 0x67, 0xfd, 0x5a, 0x79, 0xd6, 0xb7, 0x17, + 0x94, 0xe9, 0xb2, 0xca, 0x5b, 0xfb, 0x70, 0x7b, 0xfa, 0x0d, 0xc8, 0x24, 0x0b, 0xf7, 0x7e, 0x2a, + 0xef, 0x99, 0x4f, 0x78, 0xf9, 0x27, 0x00, 0x00, 0xff, 0xff, 0xa9, 0x7c, 0x1d, 0x4e, 0x6d, 0x02, + 0x00, 0x00, } func (m *PacketPing) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/p2p/pex.go b/api/cometbft/p2p/v1/pex.go similarity index 98% rename from proto/tendermint/p2p/pex.go rename to api/cometbft/p2p/v1/pex.go index 6d369d4da72..be80aaa0312 100644 --- a/proto/tendermint/p2p/pex.go +++ b/api/cometbft/p2p/v1/pex.go @@ -1,4 +1,4 @@ -package p2p +package v1 import ( "fmt" diff --git a/proto/tendermint/p2p/pex.pb.go b/api/cometbft/p2p/v1/pex.pb.go similarity index 87% rename from proto/tendermint/p2p/pex.pb.go rename to api/cometbft/p2p/v1/pex.pb.go index d8dcb94add8..61ab210825c 100644 --- a/proto/tendermint/p2p/pex.pb.go +++ b/api/cometbft/p2p/v1/pex.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/p2p/pex.proto +// source: cometbft/p2p/v1/pex.proto -package p2p +package v1 import ( fmt "fmt" @@ -23,6 +23,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// PexRequest is a request for peer addresses. type PexRequest struct { } @@ -30,7 +31,7 @@ func (m *PexRequest) Reset() { *m = PexRequest{} } func (m *PexRequest) String() string { return proto.CompactTextString(m) } func (*PexRequest) ProtoMessage() {} func (*PexRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_81c2f011fd13be57, []int{0} + return fileDescriptor_3aad92aea372f558, []int{0} } func (m *PexRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -59,6 +60,7 @@ func (m *PexRequest) XXX_DiscardUnknown() { var xxx_messageInfo_PexRequest proto.InternalMessageInfo +// PexAddrs is a response with peer addresses. type PexAddrs struct { Addrs []NetAddress `protobuf:"bytes,1,rep,name=addrs,proto3" json:"addrs"` } @@ -67,7 +69,7 @@ func (m *PexAddrs) Reset() { *m = PexAddrs{} } func (m *PexAddrs) String() string { return proto.CompactTextString(m) } func (*PexAddrs) ProtoMessage() {} func (*PexAddrs) Descriptor() ([]byte, []int) { - return fileDescriptor_81c2f011fd13be57, []int{1} + return fileDescriptor_3aad92aea372f558, []int{1} } func (m *PexAddrs) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -103,7 +105,10 @@ func (m *PexAddrs) GetAddrs() []NetAddress { return nil } +// Message is an abstract PEX message. type Message struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Sum: // *Message_PexRequest // *Message_PexAddrs @@ -114,7 +119,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_81c2f011fd13be57, []int{2} + return fileDescriptor_3aad92aea372f558, []int{2} } func (m *Message) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -189,33 +194,32 @@ func (*Message) XXX_OneofWrappers() []interface{} { } func init() { - proto.RegisterType((*PexRequest)(nil), "tendermint.p2p.PexRequest") - proto.RegisterType((*PexAddrs)(nil), "tendermint.p2p.PexAddrs") - proto.RegisterType((*Message)(nil), "tendermint.p2p.Message") -} - -func init() { proto.RegisterFile("tendermint/p2p/pex.proto", fileDescriptor_81c2f011fd13be57) } - -var fileDescriptor_81c2f011fd13be57 = []byte{ - // 273 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x28, 0x49, 0xcd, 0x4b, - 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x2f, 0x30, 0x2a, 0xd0, 0x2f, 0x48, 0xad, 0xd0, 0x2b, - 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x43, 0xc8, 0xe8, 0x15, 0x18, 0x15, 0x48, 0x49, 0xa1, 0xa9, - 0x2c, 0xa9, 0x2c, 0x48, 0x2d, 0x86, 0xa8, 0x95, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x33, 0xf5, - 0x41, 0x2c, 0x88, 0xa8, 0x12, 0x0f, 0x17, 0x57, 0x40, 0x6a, 0x45, 0x50, 0x6a, 0x61, 0x69, 0x6a, - 0x71, 0x89, 0x92, 0x13, 0x17, 0x47, 0x40, 0x6a, 0x85, 0x63, 0x4a, 0x4a, 0x51, 0xb1, 0x90, 0x19, - 0x17, 0x6b, 0x22, 0x88, 0x21, 0xc1, 0xa8, 0xc0, 0xac, 0xc1, 0x6d, 0x24, 0xa5, 0x87, 0x6a, 0x97, - 0x9e, 0x5f, 0x6a, 0x09, 0x48, 0x61, 0x6a, 0x71, 0xb1, 0x13, 0xcb, 0x89, 0x7b, 0xf2, 0x0c, 0x41, - 0x10, 0xe5, 0x4a, 0x1d, 0x8c, 0x5c, 0xec, 0xbe, 0xa9, 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x42, 0xb6, - 0x5c, 0xdc, 0x05, 0xa9, 0x15, 0xf1, 0x45, 0x10, 0xe3, 0x25, 0x18, 0x15, 0x18, 0xb1, 0x99, 0x84, - 0x70, 0x80, 0x07, 0x43, 0x10, 0x57, 0x01, 0x9c, 0x27, 0x64, 0xce, 0xc5, 0x09, 0xd2, 0x0e, 0x71, - 0x06, 0x13, 0x58, 0xb3, 0x04, 0x16, 0xcd, 0x60, 0xf7, 0x7a, 0x30, 0x04, 0x71, 0x14, 0x40, 0xd9, - 0x4e, 0xac, 0x5c, 0xcc, 0xc5, 0xa5, 0xb9, 0x4e, 0xde, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, - 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, - 0x2c, 0xc7, 0x10, 0x65, 0x98, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x9f, - 0x9c, 0x9f, 0x9b, 0x5a, 0x92, 0x94, 0x56, 0x82, 0x60, 0x40, 0x42, 0x09, 0x35, 0x2c, 0x93, 0xd8, - 0xc0, 0xa2, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0xad, 0x52, 0xe1, 0x8e, 0x01, 0x00, - 0x00, + proto.RegisterType((*PexRequest)(nil), "cometbft.p2p.v1.PexRequest") + proto.RegisterType((*PexAddrs)(nil), "cometbft.p2p.v1.PexAddrs") + proto.RegisterType((*Message)(nil), "cometbft.p2p.v1.Message") +} + +func init() { proto.RegisterFile("cometbft/p2p/v1/pex.proto", fileDescriptor_3aad92aea372f558) } + +var fileDescriptor_3aad92aea372f558 = []byte{ + // 271 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x30, 0x2a, 0xd0, 0x2f, 0x33, 0xd4, 0x2f, 0x48, 0xad, 0xd0, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x87, 0x49, 0xe9, 0x15, 0x18, 0x15, 0xe8, 0x95, 0x19, + 0x4a, 0x49, 0xa3, 0xab, 0x2d, 0xa9, 0x2c, 0x48, 0x2d, 0x86, 0xa8, 0x96, 0x12, 0x49, 0xcf, 0x4f, + 0xcf, 0x07, 0x33, 0xf5, 0x41, 0x2c, 0x88, 0xa8, 0x12, 0x0f, 0x17, 0x57, 0x40, 0x6a, 0x45, 0x50, + 0x6a, 0x61, 0x69, 0x6a, 0x71, 0x89, 0x92, 0x33, 0x17, 0x47, 0x40, 0x6a, 0x85, 0x63, 0x4a, 0x4a, + 0x51, 0xb1, 0x90, 0x39, 0x17, 0x6b, 0x22, 0x88, 0x21, 0xc1, 0xa8, 0xc0, 0xac, 0xc1, 0x6d, 0x24, + 0xad, 0x87, 0x66, 0x9b, 0x9e, 0x5f, 0x6a, 0x09, 0x48, 0x65, 0x6a, 0x71, 0xb1, 0x13, 0xcb, 0x89, + 0x7b, 0xf2, 0x0c, 0x41, 0x10, 0xf5, 0x4a, 0x5d, 0x8c, 0x5c, 0xec, 0xbe, 0xa9, 0xc5, 0xc5, 0x89, + 0xe9, 0xa9, 0x42, 0x76, 0x5c, 0xdc, 0x05, 0xa9, 0x15, 0xf1, 0x45, 0x10, 0xf3, 0x25, 0x18, 0x15, + 0x18, 0xb1, 0x1a, 0x85, 0x70, 0x82, 0x07, 0x43, 0x10, 0x57, 0x01, 0x9c, 0x27, 0x64, 0xc1, 0xc5, + 0x09, 0xd2, 0x0f, 0x71, 0x08, 0x13, 0x58, 0xb7, 0x24, 0x36, 0xdd, 0x60, 0x27, 0x7b, 0x30, 0x04, + 0x71, 0x14, 0x40, 0xd9, 0x4e, 0xac, 0x5c, 0xcc, 0xc5, 0xa5, 0xb9, 0x4e, 0x5e, 0x27, 0x1e, 0xc9, + 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, + 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0x65, 0x90, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0x04, 0x32, + 0x4d, 0x1f, 0x1e, 0x6e, 0x70, 0x46, 0x62, 0x41, 0xa6, 0x3e, 0x5a, 0x68, 0x26, 0xb1, 0x81, 0x83, + 0xcc, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x22, 0x9c, 0xde, 0x93, 0x01, 0x00, 0x00, } func (m *PexRequest) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/p2p/types.pb.go b/api/cometbft/p2p/v1/types.pb.go similarity index 88% rename from proto/tendermint/p2p/types.pb.go rename to api/cometbft/p2p/v1/types.pb.go index 9de144b3490..8e2cdd50658 100644 --- a/proto/tendermint/p2p/types.pb.go +++ b/api/cometbft/p2p/v1/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/p2p/types.proto +// source: cometbft/p2p/v1/types.proto -package p2p +package v1 import ( fmt "fmt" @@ -23,6 +23,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// NetAddress represents a peer's network address. type NetAddress struct { ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` IP string `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip,omitempty"` @@ -33,7 +34,7 @@ func (m *NetAddress) Reset() { *m = NetAddress{} } func (m *NetAddress) String() string { return proto.CompactTextString(m) } func (*NetAddress) ProtoMessage() {} func (*NetAddress) Descriptor() ([]byte, []int) { - return fileDescriptor_c8a29e659aeca578, []int{0} + return fileDescriptor_b87302e2cbe06eca, []int{0} } func (m *NetAddress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -83,6 +84,7 @@ func (m *NetAddress) GetPort() uint32 { return 0 } +// ProtocolVersion represents the current p2p protocol version. type ProtocolVersion struct { P2P uint64 `protobuf:"varint,1,opt,name=p2p,proto3" json:"p2p,omitempty"` Block uint64 `protobuf:"varint,2,opt,name=block,proto3" json:"block,omitempty"` @@ -93,7 +95,7 @@ func (m *ProtocolVersion) Reset() { *m = ProtocolVersion{} } func (m *ProtocolVersion) String() string { return proto.CompactTextString(m) } func (*ProtocolVersion) ProtoMessage() {} func (*ProtocolVersion) Descriptor() ([]byte, []int) { - return fileDescriptor_c8a29e659aeca578, []int{1} + return fileDescriptor_b87302e2cbe06eca, []int{1} } func (m *ProtocolVersion) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -143,6 +145,8 @@ func (m *ProtocolVersion) GetApp() uint64 { return 0 } +// DefaultNodeInfo is a basic node's information sent to other peers during the +// p2p handshake. type DefaultNodeInfo struct { ProtocolVersion ProtocolVersion `protobuf:"bytes,1,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version"` DefaultNodeID string `protobuf:"bytes,2,opt,name=default_node_id,json=defaultNodeId,proto3" json:"default_node_id,omitempty"` @@ -158,7 +162,7 @@ func (m *DefaultNodeInfo) Reset() { *m = DefaultNodeInfo{} } func (m *DefaultNodeInfo) String() string { return proto.CompactTextString(m) } func (*DefaultNodeInfo) ProtoMessage() {} func (*DefaultNodeInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_c8a29e659aeca578, []int{2} + return fileDescriptor_b87302e2cbe06eca, []int{2} } func (m *DefaultNodeInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -243,6 +247,7 @@ func (m *DefaultNodeInfo) GetOther() DefaultNodeInfoOther { return DefaultNodeInfoOther{} } +// DefaultNodeInfoOther is the misc. application specific data. type DefaultNodeInfoOther struct { TxIndex string `protobuf:"bytes,1,opt,name=tx_index,json=txIndex,proto3" json:"tx_index,omitempty"` RPCAddress string `protobuf:"bytes,2,opt,name=rpc_address,json=rpcAddress,proto3" json:"rpc_address,omitempty"` @@ -252,7 +257,7 @@ func (m *DefaultNodeInfoOther) Reset() { *m = DefaultNodeInfoOther{} } func (m *DefaultNodeInfoOther) String() string { return proto.CompactTextString(m) } func (*DefaultNodeInfoOther) ProtoMessage() {} func (*DefaultNodeInfoOther) Descriptor() ([]byte, []int) { - return fileDescriptor_c8a29e659aeca578, []int{3} + return fileDescriptor_b87302e2cbe06eca, []int{3} } func (m *DefaultNodeInfoOther) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -296,47 +301,47 @@ func (m *DefaultNodeInfoOther) GetRPCAddress() string { } func init() { - proto.RegisterType((*NetAddress)(nil), "tendermint.p2p.NetAddress") - proto.RegisterType((*ProtocolVersion)(nil), "tendermint.p2p.ProtocolVersion") - proto.RegisterType((*DefaultNodeInfo)(nil), "tendermint.p2p.DefaultNodeInfo") - proto.RegisterType((*DefaultNodeInfoOther)(nil), "tendermint.p2p.DefaultNodeInfoOther") + proto.RegisterType((*NetAddress)(nil), "cometbft.p2p.v1.NetAddress") + proto.RegisterType((*ProtocolVersion)(nil), "cometbft.p2p.v1.ProtocolVersion") + proto.RegisterType((*DefaultNodeInfo)(nil), "cometbft.p2p.v1.DefaultNodeInfo") + proto.RegisterType((*DefaultNodeInfoOther)(nil), "cometbft.p2p.v1.DefaultNodeInfoOther") } -func init() { proto.RegisterFile("tendermint/p2p/types.proto", fileDescriptor_c8a29e659aeca578) } +func init() { proto.RegisterFile("cometbft/p2p/v1/types.proto", fileDescriptor_b87302e2cbe06eca) } -var fileDescriptor_c8a29e659aeca578 = []byte{ - // 483 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0x3d, 0x8f, 0xda, 0x40, - 0x10, 0xc5, 0xc6, 0x7c, 0xdc, 0x10, 0x8e, 0xcb, 0x0a, 0x45, 0x3e, 0x0a, 0x1b, 0xa1, 0x14, 0x54, - 0xa0, 0x90, 0x2a, 0x5d, 0x42, 0x68, 0x50, 0xa4, 0x8b, 0xb5, 0x8a, 0x52, 0xa4, 0x41, 0xe0, 0x5d, - 0x60, 0x85, 0xd9, 0x5d, 0xad, 0xf7, 0x12, 0xf2, 0x2f, 0xf2, 0xb3, 0xae, 0xbc, 0x32, 0x95, 0x15, - 0x99, 0x32, 0x7f, 0x22, 0xf2, 0xae, 0x2f, 0xc7, 0xa1, 0xeb, 0xe6, 0xcd, 0x9b, 0x99, 0x37, 0xf3, - 0x34, 0xd0, 0xd3, 0x94, 0x13, 0xaa, 0xf6, 0x8c, 0xeb, 0xb1, 0x9c, 0xc8, 0xb1, 0xfe, 0x29, 0x69, - 0x3a, 0x92, 0x4a, 0x68, 0x81, 0x2e, 0x1f, 0xb9, 0x91, 0x9c, 0xc8, 0x5e, 0x77, 0x23, 0x36, 0xc2, - 0x50, 0xe3, 0x22, 0xb2, 0x55, 0x83, 0x08, 0xe0, 0x86, 0xea, 0x0f, 0x84, 0x28, 0x9a, 0xa6, 0xe8, - 0x15, 0xb8, 0x8c, 0xf8, 0x4e, 0xdf, 0x19, 0x5e, 0x4c, 0xeb, 0x79, 0x16, 0xba, 0xf3, 0x19, 0x76, - 0x19, 0x31, 0x79, 0xe9, 0xbb, 0x27, 0xf9, 0x08, 0xbb, 0x4c, 0x22, 0x04, 0x9e, 0x14, 0x4a, 0xfb, - 0xd5, 0xbe, 0x33, 0x6c, 0x63, 0x13, 0x0f, 0xbe, 0x40, 0x27, 0x2a, 0x46, 0xc7, 0x22, 0xf9, 0x4a, - 0x55, 0xca, 0x04, 0x47, 0xd7, 0x50, 0x95, 0x13, 0x69, 0xe6, 0x7a, 0xd3, 0x46, 0x9e, 0x85, 0xd5, - 0x68, 0x12, 0xe1, 0x22, 0x87, 0xba, 0x50, 0x5b, 0x25, 0x22, 0xde, 0x99, 0xe1, 0x1e, 0xb6, 0x00, - 0x5d, 0x41, 0x75, 0x29, 0xa5, 0x19, 0xeb, 0xe1, 0x22, 0x1c, 0xfc, 0x75, 0xa1, 0x33, 0xa3, 0xeb, - 0xe5, 0x6d, 0xa2, 0x6f, 0x04, 0xa1, 0x73, 0xbe, 0x16, 0x28, 0x82, 0x2b, 0x59, 0x2a, 0x2d, 0xbe, - 0x5b, 0x29, 0xa3, 0xd1, 0x9a, 0x84, 0xa3, 0xa7, 0xc7, 0x8f, 0xce, 0x36, 0x9a, 0x7a, 0x77, 0x59, - 0x58, 0xc1, 0x1d, 0x79, 0xb6, 0xe8, 0x3b, 0xe8, 0x10, 0x2b, 0xb2, 0xe0, 0x82, 0xd0, 0x05, 0x23, - 0xe5, 0xd1, 0x2f, 0xf3, 0x2c, 0x6c, 0x9f, 0xea, 0xcf, 0x70, 0x9b, 0x9c, 0x40, 0x82, 0x42, 0x68, - 0x25, 0x2c, 0xd5, 0x94, 0x2f, 0x96, 0x84, 0x28, 0xb3, 0xfa, 0x05, 0x06, 0x9b, 0x2a, 0xec, 0x45, - 0x3e, 0x34, 0x38, 0xd5, 0x3f, 0x84, 0xda, 0xf9, 0x9e, 0x21, 0x1f, 0x60, 0xc1, 0x3c, 0xac, 0x5f, - 0xb3, 0x4c, 0x09, 0x51, 0x0f, 0x9a, 0xf1, 0x76, 0xc9, 0x39, 0x4d, 0x52, 0xbf, 0xde, 0x77, 0x86, - 0x2f, 0xf0, 0x7f, 0x5c, 0x74, 0xed, 0x05, 0x67, 0x3b, 0xaa, 0xfc, 0x86, 0xed, 0x2a, 0x21, 0x7a, - 0x0f, 0x35, 0xa1, 0xb7, 0x54, 0xf9, 0x4d, 0x63, 0xc6, 0xeb, 0x73, 0x33, 0xce, 0x7c, 0xfc, 0x5c, - 0xd4, 0x96, 0x8e, 0xd8, 0xc6, 0xc1, 0x0a, 0xba, 0xcf, 0x15, 0xa1, 0x6b, 0x68, 0xea, 0xc3, 0x82, - 0x71, 0x42, 0x0f, 0xf6, 0x4b, 0x70, 0x43, 0x1f, 0xe6, 0x05, 0x44, 0x63, 0x68, 0x29, 0x19, 0x9b, - 0xe3, 0x69, 0x9a, 0x96, 0xb6, 0x5d, 0xe6, 0x59, 0x08, 0x38, 0xfa, 0x58, 0xfe, 0x17, 0x06, 0x25, - 0xe3, 0x32, 0x9e, 0x7e, 0xba, 0xcb, 0x03, 0xe7, 0x3e, 0x0f, 0x9c, 0x3f, 0x79, 0xe0, 0xfc, 0x3a, - 0x06, 0x95, 0xfb, 0x63, 0x50, 0xf9, 0x7d, 0x0c, 0x2a, 0xdf, 0xde, 0x6c, 0x98, 0xde, 0xde, 0xae, - 0x46, 0xb1, 0xd8, 0x8f, 0x63, 0xb1, 0xa7, 0x7a, 0xb5, 0xd6, 0x8f, 0x81, 0x7d, 0xe1, 0xa7, 0x8f, - 0xbf, 0xaa, 0x9b, 0xec, 0xdb, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xae, 0xdb, 0x56, 0x6d, 0x11, - 0x03, 0x00, 0x00, +var fileDescriptor_b87302e2cbe06eca = []byte{ + // 485 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0x4d, 0x8f, 0xda, 0x30, + 0x10, 0x25, 0x21, 0x7c, 0xec, 0x50, 0xca, 0xd6, 0x42, 0x55, 0x76, 0x2b, 0x25, 0x08, 0xa9, 0x12, + 0x27, 0xd2, 0xa5, 0xa7, 0x1e, 0x97, 0x72, 0xa1, 0x87, 0x6d, 0x6a, 0x55, 0x3d, 0xf4, 0x82, 0x20, + 0x36, 0x60, 0xc1, 0xc6, 0x96, 0xe3, 0xa5, 0xf4, 0x5f, 0xf4, 0x67, 0xed, 0x71, 0x8f, 0x3d, 0x45, + 0x55, 0x38, 0xf7, 0x3f, 0x54, 0x76, 0x02, 0x42, 0xe9, 0xde, 0xe6, 0xcd, 0xf3, 0xcc, 0xbc, 0x79, + 0x1e, 0x78, 0x13, 0xf1, 0x7b, 0xaa, 0x16, 0x4b, 0x15, 0x88, 0x91, 0x08, 0x76, 0x37, 0x81, 0xfa, + 0x29, 0x68, 0x32, 0x14, 0x92, 0x2b, 0x8e, 0x3a, 0x47, 0x72, 0x28, 0x46, 0x62, 0xb8, 0xbb, 0xb9, + 0xee, 0xae, 0xf8, 0x8a, 0x1b, 0x2e, 0xd0, 0x51, 0xfe, 0xac, 0x1f, 0x02, 0xdc, 0x51, 0x75, 0x4b, + 0x88, 0xa4, 0x49, 0x82, 0x5e, 0x83, 0xcd, 0x88, 0x6b, 0xf5, 0xac, 0xc1, 0xc5, 0xb8, 0x9e, 0xa5, + 0xbe, 0x3d, 0x9d, 0x60, 0x9b, 0x11, 0x93, 0x17, 0xae, 0x7d, 0x96, 0x0f, 0xb1, 0xcd, 0x04, 0x42, + 0xe0, 0x08, 0x2e, 0x95, 0x5b, 0xed, 0x59, 0x83, 0x36, 0x36, 0x71, 0xff, 0x2b, 0x74, 0x42, 0xdd, + 0x3a, 0xe2, 0xdb, 0x6f, 0x54, 0x26, 0x8c, 0xc7, 0xe8, 0x0a, 0xaa, 0x62, 0x24, 0x4c, 0x5f, 0x67, + 0xdc, 0xc8, 0x52, 0xbf, 0x1a, 0x8e, 0x42, 0xac, 0x73, 0xa8, 0x0b, 0xb5, 0xc5, 0x96, 0x47, 0x1b, + 0xd3, 0xdc, 0xc1, 0x39, 0x40, 0x97, 0x50, 0x9d, 0x0b, 0x61, 0xda, 0x3a, 0x58, 0x87, 0xfd, 0xbf, + 0x36, 0x74, 0x26, 0x74, 0x39, 0x7f, 0xd8, 0xaa, 0x3b, 0x4e, 0xe8, 0x34, 0x5e, 0x72, 0xf4, 0x05, + 0x2e, 0x45, 0x31, 0x69, 0xb6, 0xcb, 0x47, 0x99, 0x19, 0xad, 0x51, 0x6f, 0x58, 0xda, 0x7e, 0x58, + 0x92, 0x34, 0x76, 0x1e, 0x53, 0xbf, 0x82, 0x3b, 0xa2, 0xa4, 0xf4, 0x03, 0x74, 0x48, 0x3e, 0x65, + 0x16, 0x73, 0x42, 0x67, 0x8c, 0x14, 0x5b, 0xbf, 0xca, 0x52, 0xbf, 0x7d, 0x2e, 0x60, 0x82, 0xdb, + 0xe4, 0x0c, 0x12, 0xe4, 0x43, 0x6b, 0xcb, 0x12, 0x45, 0xe3, 0xd9, 0x9c, 0x10, 0x69, 0xb4, 0x5f, + 0x60, 0xc8, 0x53, 0xda, 0x5f, 0xe4, 0x42, 0x23, 0xa6, 0xea, 0x07, 0x97, 0x1b, 0xd7, 0x31, 0xe4, + 0x11, 0x6a, 0xe6, 0xa8, 0xbf, 0x96, 0x33, 0x05, 0x44, 0xd7, 0xd0, 0x8c, 0xd6, 0xf3, 0x38, 0xa6, + 0xdb, 0xc4, 0xad, 0xf7, 0xac, 0xc1, 0x0b, 0x7c, 0xc2, 0xba, 0xea, 0x9e, 0xc7, 0x6c, 0x43, 0xa5, + 0xdb, 0xc8, 0xab, 0x0a, 0x88, 0x6e, 0xa1, 0xc6, 0xd5, 0x9a, 0x4a, 0xb7, 0x69, 0xdc, 0x78, 0xfb, + 0x9f, 0x1b, 0x25, 0x27, 0x3f, 0xeb, 0xc7, 0x85, 0x25, 0x79, 0x65, 0x7f, 0x01, 0xdd, 0xe7, 0x1e, + 0xa1, 0x2b, 0x68, 0xaa, 0xfd, 0x8c, 0xc5, 0x84, 0xee, 0xf3, 0x3b, 0xc1, 0x0d, 0xb5, 0x9f, 0x6a, + 0x88, 0x02, 0x68, 0x49, 0x11, 0x99, 0xed, 0x69, 0x92, 0x14, 0xbe, 0xbd, 0xcc, 0x52, 0x1f, 0x70, + 0xf8, 0xb1, 0xb8, 0x30, 0x0c, 0x52, 0x44, 0x45, 0x3c, 0xfe, 0xf4, 0x98, 0x79, 0xd6, 0x53, 0xe6, + 0x59, 0x7f, 0x32, 0xcf, 0xfa, 0x75, 0xf0, 0x2a, 0x4f, 0x07, 0xaf, 0xf2, 0xfb, 0xe0, 0x55, 0xbe, + 0xbf, 0x5b, 0x31, 0xb5, 0x7e, 0x58, 0x68, 0xdd, 0xc1, 0xe9, 0xc8, 0x4f, 0xc1, 0x5c, 0xb0, 0xa0, + 0x74, 0xfa, 0x8b, 0xba, 0xf9, 0xc9, 0xf7, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x50, 0x06, 0xfb, + 0xcd, 0x14, 0x03, 0x00, 0x00, } func (m *NetAddress) Marshal() (dAtA []byte, err error) { diff --git a/api/cometbft/privval/v1/types.pb.go b/api/cometbft/privval/v1/types.pb.go new file mode 100644 index 00000000000..30d21af4bce --- /dev/null +++ b/api/cometbft/privval/v1/types.pb.go @@ -0,0 +1,3379 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/privval/v1/types.proto + +package v1 + +import ( + fmt "fmt" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + v11 "github.com/cometbft/cometbft/api/cometbft/types/v1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// remotesignererror is returned when the remote signer fails. +type RemoteSignerError struct { + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` +} + +func (m *RemoteSignerError) Reset() { *m = RemoteSignerError{} } +func (m *RemoteSignerError) String() string { return proto.CompactTextString(m) } +func (*RemoteSignerError) ProtoMessage() {} +func (*RemoteSignerError) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{0} +} +func (m *RemoteSignerError) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RemoteSignerError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RemoteSignerError.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RemoteSignerError) XXX_Merge(src proto.Message) { + xxx_messageInfo_RemoteSignerError.Merge(m, src) +} +func (m *RemoteSignerError) XXX_Size() int { + return m.Size() +} +func (m *RemoteSignerError) XXX_DiscardUnknown() { + xxx_messageInfo_RemoteSignerError.DiscardUnknown(m) +} + +var xxx_messageInfo_RemoteSignerError proto.InternalMessageInfo + +func (m *RemoteSignerError) GetCode() int32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *RemoteSignerError) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +// PubKeyRequest requests the consensus public key from the remote signer. +type PubKeyRequest struct { + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *PubKeyRequest) Reset() { *m = PubKeyRequest{} } +func (m *PubKeyRequest) String() string { return proto.CompactTextString(m) } +func (*PubKeyRequest) ProtoMessage() {} +func (*PubKeyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{1} +} +func (m *PubKeyRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PubKeyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PubKeyRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PubKeyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PubKeyRequest.Merge(m, src) +} +func (m *PubKeyRequest) XXX_Size() int { + return m.Size() +} +func (m *PubKeyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PubKeyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PubKeyRequest proto.InternalMessageInfo + +func (m *PubKeyRequest) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +// PubKeyResponse is a response message containing the public key. +type PubKeyResponse struct { + PubKey v1.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *PubKeyResponse) Reset() { *m = PubKeyResponse{} } +func (m *PubKeyResponse) String() string { return proto.CompactTextString(m) } +func (*PubKeyResponse) ProtoMessage() {} +func (*PubKeyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{2} +} +func (m *PubKeyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PubKeyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PubKeyResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PubKeyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PubKeyResponse.Merge(m, src) +} +func (m *PubKeyResponse) XXX_Size() int { + return m.Size() +} +func (m *PubKeyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PubKeyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PubKeyResponse proto.InternalMessageInfo + +func (m *PubKeyResponse) GetPubKey() v1.PublicKey { + if m != nil { + return m.PubKey + } + return v1.PublicKey{} +} + +func (m *PubKeyResponse) GetError() *RemoteSignerError { + if m != nil { + return m.Error + } + return nil +} + +// SignVoteRequest is a request to sign a vote +type SignVoteRequest struct { + Vote *v11.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + SkipExtensionSigning bool `protobuf:"varint,3,opt,name=skip_extension_signing,json=skipExtensionSigning,proto3" json:"skip_extension_signing,omitempty"` +} + +func (m *SignVoteRequest) Reset() { *m = SignVoteRequest{} } +func (m *SignVoteRequest) String() string { return proto.CompactTextString(m) } +func (*SignVoteRequest) ProtoMessage() {} +func (*SignVoteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{3} +} +func (m *SignVoteRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignVoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignVoteRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignVoteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignVoteRequest.Merge(m, src) +} +func (m *SignVoteRequest) XXX_Size() int { + return m.Size() +} +func (m *SignVoteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SignVoteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SignVoteRequest proto.InternalMessageInfo + +func (m *SignVoteRequest) GetVote() *v11.Vote { + if m != nil { + return m.Vote + } + return nil +} + +func (m *SignVoteRequest) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *SignVoteRequest) GetSkipExtensionSigning() bool { + if m != nil { + return m.SkipExtensionSigning + } + return false +} + +// SignedVoteResponse is a response containing a signed vote or an error +type SignedVoteResponse struct { + Vote v11.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote"` + Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *SignedVoteResponse) Reset() { *m = SignedVoteResponse{} } +func (m *SignedVoteResponse) String() string { return proto.CompactTextString(m) } +func (*SignedVoteResponse) ProtoMessage() {} +func (*SignedVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{4} +} +func (m *SignedVoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignedVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignedVoteResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignedVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignedVoteResponse.Merge(m, src) +} +func (m *SignedVoteResponse) XXX_Size() int { + return m.Size() +} +func (m *SignedVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SignedVoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SignedVoteResponse proto.InternalMessageInfo + +func (m *SignedVoteResponse) GetVote() v11.Vote { + if m != nil { + return m.Vote + } + return v11.Vote{} +} + +func (m *SignedVoteResponse) GetError() *RemoteSignerError { + if m != nil { + return m.Error + } + return nil +} + +// SignProposalRequest is a request to sign a proposal +type SignProposalRequest struct { + Proposal *v11.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *SignProposalRequest) Reset() { *m = SignProposalRequest{} } +func (m *SignProposalRequest) String() string { return proto.CompactTextString(m) } +func (*SignProposalRequest) ProtoMessage() {} +func (*SignProposalRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{5} +} +func (m *SignProposalRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignProposalRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignProposalRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignProposalRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignProposalRequest.Merge(m, src) +} +func (m *SignProposalRequest) XXX_Size() int { + return m.Size() +} +func (m *SignProposalRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SignProposalRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SignProposalRequest proto.InternalMessageInfo + +func (m *SignProposalRequest) GetProposal() *v11.Proposal { + if m != nil { + return m.Proposal + } + return nil +} + +func (m *SignProposalRequest) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +// SignedProposalResponse is response containing a signed proposal or an error +type SignedProposalResponse struct { + Proposal v11.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal"` + Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *SignedProposalResponse) Reset() { *m = SignedProposalResponse{} } +func (m *SignedProposalResponse) String() string { return proto.CompactTextString(m) } +func (*SignedProposalResponse) ProtoMessage() {} +func (*SignedProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{6} +} +func (m *SignedProposalResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignedProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignedProposalResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignedProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignedProposalResponse.Merge(m, src) +} +func (m *SignedProposalResponse) XXX_Size() int { + return m.Size() +} +func (m *SignedProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SignedProposalResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SignedProposalResponse proto.InternalMessageInfo + +func (m *SignedProposalResponse) GetProposal() v11.Proposal { + if m != nil { + return m.Proposal + } + return v11.Proposal{} +} + +func (m *SignedProposalResponse) GetError() *RemoteSignerError { + if m != nil { + return m.Error + } + return nil +} + +// SignBytesRequest is a request to sign arbitrary bytes +type SignBytesRequest struct { + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *SignBytesRequest) Reset() { *m = SignBytesRequest{} } +func (m *SignBytesRequest) String() string { return proto.CompactTextString(m) } +func (*SignBytesRequest) ProtoMessage() {} +func (*SignBytesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{7} +} +func (m *SignBytesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignBytesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignBytesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignBytesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignBytesRequest.Merge(m, src) +} +func (m *SignBytesRequest) XXX_Size() int { + return m.Size() +} +func (m *SignBytesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SignBytesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SignBytesRequest proto.InternalMessageInfo + +func (m *SignBytesRequest) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +// SignBytesResponse is a response containing a signature or an error +type SignBytesResponse struct { + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *SignBytesResponse) Reset() { *m = SignBytesResponse{} } +func (m *SignBytesResponse) String() string { return proto.CompactTextString(m) } +func (*SignBytesResponse) ProtoMessage() {} +func (*SignBytesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{8} +} +func (m *SignBytesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignBytesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignBytesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignBytesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignBytesResponse.Merge(m, src) +} +func (m *SignBytesResponse) XXX_Size() int { + return m.Size() +} +func (m *SignBytesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SignBytesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SignBytesResponse proto.InternalMessageInfo + +func (m *SignBytesResponse) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *SignBytesResponse) GetError() *RemoteSignerError { + if m != nil { + return m.Error + } + return nil +} + +// PingRequest is a request to confirm that the connection is alive. +type PingRequest struct { +} + +func (m *PingRequest) Reset() { *m = PingRequest{} } +func (m *PingRequest) String() string { return proto.CompactTextString(m) } +func (*PingRequest) ProtoMessage() {} +func (*PingRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{9} +} +func (m *PingRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PingRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PingRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PingRequest.Merge(m, src) +} +func (m *PingRequest) XXX_Size() int { + return m.Size() +} +func (m *PingRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PingRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PingRequest proto.InternalMessageInfo + +// PingResponse is a response to confirm that the connection is alive. +type PingResponse struct { +} + +func (m *PingResponse) Reset() { *m = PingResponse{} } +func (m *PingResponse) String() string { return proto.CompactTextString(m) } +func (*PingResponse) ProtoMessage() {} +func (*PingResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{10} +} +func (m *PingResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PingResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PingResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PingResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PingResponse.Merge(m, src) +} +func (m *PingResponse) XXX_Size() int { + return m.Size() +} +func (m *PingResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PingResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PingResponse proto.InternalMessageInfo + +// Message is an abstract message to/from the remote signer. +type Message struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Sum: + // *Message_PubKeyRequest + // *Message_PubKeyResponse + // *Message_SignVoteRequest + // *Message_SignedVoteResponse + // *Message_SignProposalRequest + // *Message_SignedProposalResponse + // *Message_PingRequest + // *Message_PingResponse + // *Message_SignBytesRequest + // *Message_SignBytesResponse + Sum isMessage_Sum `protobuf_oneof:"sum"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_00b969dcac92905e, []int{11} +} +func (m *Message) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return m.Size() +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +type isMessage_Sum interface { + isMessage_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Message_PubKeyRequest struct { + PubKeyRequest *PubKeyRequest `protobuf:"bytes,1,opt,name=pub_key_request,json=pubKeyRequest,proto3,oneof" json:"pub_key_request,omitempty"` +} +type Message_PubKeyResponse struct { + PubKeyResponse *PubKeyResponse `protobuf:"bytes,2,opt,name=pub_key_response,json=pubKeyResponse,proto3,oneof" json:"pub_key_response,omitempty"` +} +type Message_SignVoteRequest struct { + SignVoteRequest *SignVoteRequest `protobuf:"bytes,3,opt,name=sign_vote_request,json=signVoteRequest,proto3,oneof" json:"sign_vote_request,omitempty"` +} +type Message_SignedVoteResponse struct { + SignedVoteResponse *SignedVoteResponse `protobuf:"bytes,4,opt,name=signed_vote_response,json=signedVoteResponse,proto3,oneof" json:"signed_vote_response,omitempty"` +} +type Message_SignProposalRequest struct { + SignProposalRequest *SignProposalRequest `protobuf:"bytes,5,opt,name=sign_proposal_request,json=signProposalRequest,proto3,oneof" json:"sign_proposal_request,omitempty"` +} +type Message_SignedProposalResponse struct { + SignedProposalResponse *SignedProposalResponse `protobuf:"bytes,6,opt,name=signed_proposal_response,json=signedProposalResponse,proto3,oneof" json:"signed_proposal_response,omitempty"` +} +type Message_PingRequest struct { + PingRequest *PingRequest `protobuf:"bytes,7,opt,name=ping_request,json=pingRequest,proto3,oneof" json:"ping_request,omitempty"` +} +type Message_PingResponse struct { + PingResponse *PingResponse `protobuf:"bytes,8,opt,name=ping_response,json=pingResponse,proto3,oneof" json:"ping_response,omitempty"` +} +type Message_SignBytesRequest struct { + SignBytesRequest *SignBytesRequest `protobuf:"bytes,9,opt,name=sign_bytes_request,json=signBytesRequest,proto3,oneof" json:"sign_bytes_request,omitempty"` +} +type Message_SignBytesResponse struct { + SignBytesResponse *SignBytesResponse `protobuf:"bytes,10,opt,name=sign_bytes_response,json=signBytesResponse,proto3,oneof" json:"sign_bytes_response,omitempty"` +} + +func (*Message_PubKeyRequest) isMessage_Sum() {} +func (*Message_PubKeyResponse) isMessage_Sum() {} +func (*Message_SignVoteRequest) isMessage_Sum() {} +func (*Message_SignedVoteResponse) isMessage_Sum() {} +func (*Message_SignProposalRequest) isMessage_Sum() {} +func (*Message_SignedProposalResponse) isMessage_Sum() {} +func (*Message_PingRequest) isMessage_Sum() {} +func (*Message_PingResponse) isMessage_Sum() {} +func (*Message_SignBytesRequest) isMessage_Sum() {} +func (*Message_SignBytesResponse) isMessage_Sum() {} + +func (m *Message) GetSum() isMessage_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Message) GetPubKeyRequest() *PubKeyRequest { + if x, ok := m.GetSum().(*Message_PubKeyRequest); ok { + return x.PubKeyRequest + } + return nil +} + +func (m *Message) GetPubKeyResponse() *PubKeyResponse { + if x, ok := m.GetSum().(*Message_PubKeyResponse); ok { + return x.PubKeyResponse + } + return nil +} + +func (m *Message) GetSignVoteRequest() *SignVoteRequest { + if x, ok := m.GetSum().(*Message_SignVoteRequest); ok { + return x.SignVoteRequest + } + return nil +} + +func (m *Message) GetSignedVoteResponse() *SignedVoteResponse { + if x, ok := m.GetSum().(*Message_SignedVoteResponse); ok { + return x.SignedVoteResponse + } + return nil +} + +func (m *Message) GetSignProposalRequest() *SignProposalRequest { + if x, ok := m.GetSum().(*Message_SignProposalRequest); ok { + return x.SignProposalRequest + } + return nil +} + +func (m *Message) GetSignedProposalResponse() *SignedProposalResponse { + if x, ok := m.GetSum().(*Message_SignedProposalResponse); ok { + return x.SignedProposalResponse + } + return nil +} + +func (m *Message) GetPingRequest() *PingRequest { + if x, ok := m.GetSum().(*Message_PingRequest); ok { + return x.PingRequest + } + return nil +} + +func (m *Message) GetPingResponse() *PingResponse { + if x, ok := m.GetSum().(*Message_PingResponse); ok { + return x.PingResponse + } + return nil +} + +func (m *Message) GetSignBytesRequest() *SignBytesRequest { + if x, ok := m.GetSum().(*Message_SignBytesRequest); ok { + return x.SignBytesRequest + } + return nil +} + +func (m *Message) GetSignBytesResponse() *SignBytesResponse { + if x, ok := m.GetSum().(*Message_SignBytesResponse); ok { + return x.SignBytesResponse + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Message) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Message_PubKeyRequest)(nil), + (*Message_PubKeyResponse)(nil), + (*Message_SignVoteRequest)(nil), + (*Message_SignedVoteResponse)(nil), + (*Message_SignProposalRequest)(nil), + (*Message_SignedProposalResponse)(nil), + (*Message_PingRequest)(nil), + (*Message_PingResponse)(nil), + (*Message_SignBytesRequest)(nil), + (*Message_SignBytesResponse)(nil), + } +} + +func init() { + proto.RegisterType((*RemoteSignerError)(nil), "cometbft.privval.v1.RemoteSignerError") + proto.RegisterType((*PubKeyRequest)(nil), "cometbft.privval.v1.PubKeyRequest") + proto.RegisterType((*PubKeyResponse)(nil), "cometbft.privval.v1.PubKeyResponse") + proto.RegisterType((*SignVoteRequest)(nil), "cometbft.privval.v1.SignVoteRequest") + proto.RegisterType((*SignedVoteResponse)(nil), "cometbft.privval.v1.SignedVoteResponse") + proto.RegisterType((*SignProposalRequest)(nil), "cometbft.privval.v1.SignProposalRequest") + proto.RegisterType((*SignedProposalResponse)(nil), "cometbft.privval.v1.SignedProposalResponse") + proto.RegisterType((*SignBytesRequest)(nil), "cometbft.privval.v1.SignBytesRequest") + proto.RegisterType((*SignBytesResponse)(nil), "cometbft.privval.v1.SignBytesResponse") + proto.RegisterType((*PingRequest)(nil), "cometbft.privval.v1.PingRequest") + proto.RegisterType((*PingResponse)(nil), "cometbft.privval.v1.PingResponse") + proto.RegisterType((*Message)(nil), "cometbft.privval.v1.Message") +} + +func init() { proto.RegisterFile("cometbft/privval/v1/types.proto", fileDescriptor_00b969dcac92905e) } + +var fileDescriptor_00b969dcac92905e = []byte{ + // 784 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xcb, 0x6e, 0xdb, 0x46, + 0x14, 0x25, 0x6d, 0x3d, 0xaf, 0x24, 0xdb, 0xa2, 0x54, 0x57, 0x75, 0x6b, 0x59, 0x65, 0x5f, 0x42, + 0x0d, 0x50, 0x90, 0x6b, 0xa0, 0x1b, 0x77, 0x23, 0xc0, 0x00, 0x0d, 0xf7, 0x21, 0x8c, 0xd1, 0x20, + 0x48, 0x80, 0x08, 0x7a, 0x4c, 0xe8, 0x81, 0x65, 0xce, 0x84, 0x43, 0x12, 0xd1, 0x07, 0x64, 0x17, + 0x20, 0xd9, 0xe4, 0x9f, 0xbc, 0xf4, 0x32, 0xab, 0x20, 0xb0, 0x97, 0xf9, 0x89, 0x80, 0xc3, 0x21, + 0x29, 0xc9, 0xb4, 0x90, 0xc0, 0xbb, 0x99, 0x3b, 0x77, 0xce, 0x3d, 0xe7, 0x70, 0x0e, 0x24, 0xd8, + 0x1b, 0xd3, 0x4b, 0xec, 0x8e, 0x9e, 0xbb, 0x1d, 0xe6, 0x10, 0xdf, 0x1f, 0x4e, 0x3b, 0x7e, 0xb7, + 0xe3, 0xce, 0x18, 0xe6, 0x06, 0x73, 0xa8, 0x4b, 0xb5, 0x5a, 0xd4, 0x60, 0xc8, 0x06, 0xc3, 0xef, + 0xee, 0xec, 0xc6, 0xb7, 0xc6, 0xce, 0x8c, 0xb9, 0x34, 0xb8, 0x74, 0x81, 0x67, 0xf2, 0xce, 0xdc, + 0xb1, 0x40, 0x5a, 0x82, 0xdc, 0xa9, 0x5b, 0xd4, 0xa2, 0x62, 0xd9, 0x09, 0x56, 0x61, 0x55, 0x3f, + 0x81, 0x2a, 0xc2, 0x97, 0xd4, 0xc5, 0x67, 0xc4, 0xb2, 0xb1, 0x73, 0xec, 0x38, 0xd4, 0xd1, 0x34, + 0xc8, 0x8c, 0xe9, 0x04, 0x37, 0xd4, 0x96, 0xda, 0xce, 0x22, 0xb1, 0xd6, 0x5a, 0x50, 0x9a, 0x60, + 0x3e, 0x76, 0x08, 0x73, 0x09, 0xb5, 0x1b, 0x6b, 0x2d, 0xb5, 0x5d, 0x44, 0xf3, 0x25, 0xfd, 0x77, + 0xa8, 0xf4, 0xbd, 0xd1, 0x29, 0x9e, 0x21, 0xfc, 0xc2, 0xc3, 0xdc, 0xd5, 0xbe, 0x83, 0xc2, 0xf8, + 0x7c, 0x48, 0xec, 0x01, 0x99, 0x08, 0xa8, 0x22, 0xca, 0x8b, 0xfd, 0xc9, 0x44, 0x7f, 0xad, 0xc2, + 0x46, 0xd4, 0xcc, 0x19, 0xb5, 0x39, 0xd6, 0x8e, 0x20, 0xcf, 0xbc, 0xd1, 0xe0, 0x02, 0xcf, 0x44, + 0x73, 0xe9, 0x60, 0xd7, 0x88, 0x4d, 0x08, 0xf5, 0x1a, 0x7e, 0xd7, 0xe8, 0x7b, 0xa3, 0x29, 0x19, + 0x9f, 0xe2, 0x59, 0x2f, 0x73, 0xf5, 0x61, 0x4f, 0x41, 0x39, 0x26, 0x50, 0xb4, 0x23, 0xc8, 0xe2, + 0x80, 0xbb, 0x20, 0x56, 0x3a, 0xf8, 0xd5, 0x48, 0x31, 0xd0, 0xb8, 0xa3, 0x14, 0x85, 0x97, 0xf4, + 0x37, 0x2a, 0x6c, 0x06, 0xe5, 0x47, 0xd4, 0xc5, 0x11, 0xfb, 0x7d, 0xc8, 0xf8, 0xd4, 0xc5, 0x92, + 0xcc, 0xb7, 0x09, 0x60, 0x68, 0xaa, 0xdf, 0x35, 0x44, 0xb7, 0x68, 0x5a, 0x90, 0xba, 0xb6, 0x20, + 0x55, 0x3b, 0x84, 0x6d, 0x7e, 0x41, 0xd8, 0x00, 0xbf, 0x74, 0xb1, 0xcd, 0x09, 0xb5, 0x07, 0x9c, + 0x58, 0x36, 0xb1, 0xad, 0xc6, 0x7a, 0x4b, 0x6d, 0x17, 0x50, 0x3d, 0x38, 0x3d, 0x8e, 0x0e, 0xcf, + 0xc2, 0x33, 0xfd, 0x95, 0x0a, 0x9a, 0x20, 0x3a, 0x09, 0x39, 0x49, 0x93, 0xba, 0x5f, 0x44, 0x4a, + 0x7a, 0x13, 0x52, 0x7b, 0x98, 0x33, 0x04, 0x6a, 0x41, 0xb5, 0xef, 0x50, 0x46, 0xf9, 0x70, 0x1a, + 0x99, 0xf3, 0x27, 0x14, 0x98, 0x2c, 0x49, 0x2e, 0xdf, 0xa7, 0x70, 0x89, 0x6f, 0xc5, 0xcd, 0x2b, + 0x8c, 0xd2, 0xdf, 0xa9, 0xb0, 0x1d, 0x4a, 0x4e, 0xa6, 0x49, 0xd9, 0x7f, 0x7d, 0xd5, 0x38, 0x29, + 0x3f, 0x19, 0xfa, 0x30, 0x0b, 0xda, 0xb0, 0x15, 0x54, 0x7b, 0x33, 0x17, 0xf3, 0x48, 0x7f, 0x1d, + 0xb2, 0xfe, 0x70, 0xea, 0x85, 0x1f, 0xa2, 0x8c, 0xc2, 0x8d, 0x4e, 0xa1, 0x3a, 0xd7, 0x29, 0xb9, + 0xff, 0x00, 0xc5, 0xe0, 0x83, 0x0f, 0x5d, 0xcf, 0x89, 0xda, 0x93, 0xc2, 0x03, 0xa9, 0x55, 0xa0, + 0xd4, 0x27, 0xb6, 0x25, 0x59, 0xe9, 0x1b, 0x50, 0x0e, 0xb7, 0xe1, 0x68, 0xfd, 0x53, 0x0e, 0xf2, + 0xff, 0x60, 0xce, 0x87, 0x16, 0xd6, 0xfe, 0x86, 0x4d, 0x19, 0xaf, 0x81, 0x13, 0xb6, 0x4b, 0x27, + 0xf5, 0xd4, 0x91, 0x0b, 0x49, 0x36, 0x15, 0x54, 0x61, 0x0b, 0xd1, 0xfe, 0x0f, 0xb6, 0x12, 0xb4, + 0x70, 0x9a, 0x54, 0xf0, 0xd3, 0x4a, 0xb8, 0xb0, 0xd5, 0x54, 0xd0, 0x06, 0x5b, 0x4c, 0x3f, 0x82, + 0x6a, 0x60, 0xca, 0x20, 0x78, 0xb2, 0x31, 0xc1, 0x75, 0x81, 0xf8, 0x73, 0x2a, 0xe2, 0x52, 0x5c, + 0x4d, 0x05, 0x6d, 0xf2, 0xa5, 0x04, 0x3f, 0x85, 0x3a, 0x17, 0xef, 0x29, 0x42, 0x95, 0x44, 0x33, + 0x02, 0xf6, 0xb7, 0x7b, 0x61, 0x17, 0x33, 0x67, 0x2a, 0x48, 0xe3, 0x77, 0x93, 0xf8, 0x0c, 0xbe, + 0x11, 0x84, 0xa3, 0x47, 0x16, 0x93, 0xce, 0x0a, 0xf4, 0xf6, 0xbd, 0xe8, 0x4b, 0x51, 0x32, 0x15, + 0x54, 0xe3, 0x29, 0x09, 0xb3, 0xa0, 0x21, 0xc9, 0xcf, 0x4d, 0x90, 0x02, 0x72, 0x62, 0xc4, 0xfe, + 0x0a, 0x01, 0xcb, 0x09, 0x32, 0x15, 0xb4, 0xcd, 0xd3, 0xb3, 0x75, 0x0c, 0x65, 0x46, 0x6c, 0x2b, + 0xe6, 0x9f, 0x17, 0xe0, 0xad, 0xf4, 0xcf, 0x98, 0x3c, 0x36, 0x53, 0x41, 0x25, 0x96, 0x6c, 0x35, + 0x13, 0x2a, 0x12, 0x46, 0x92, 0x2c, 0x08, 0x9c, 0x1f, 0x57, 0xe0, 0xc4, 0xd4, 0xca, 0x6c, 0x6e, + 0xaf, 0xfd, 0x0f, 0xc2, 0xef, 0xc1, 0x28, 0x88, 0x51, 0x4c, 0xab, 0x28, 0xe0, 0x7e, 0xb9, 0x57, + 0xf3, 0x7c, 0x3c, 0x4d, 0x05, 0x6d, 0xf1, 0xe5, 0xc8, 0x3e, 0x86, 0xda, 0x02, 0xac, 0xa4, 0x09, + 0x2b, 0x72, 0x77, 0x27, 0xcc, 0xa6, 0x82, 0xaa, 0x7c, 0xb9, 0xd8, 0xcb, 0xc2, 0x3a, 0xf7, 0x2e, + 0x7b, 0xff, 0x5e, 0xdd, 0x34, 0xd5, 0xeb, 0x9b, 0xa6, 0xfa, 0xf1, 0xa6, 0xa9, 0xbe, 0xbd, 0x6d, + 0x2a, 0xd7, 0xb7, 0x4d, 0xe5, 0xfd, 0x6d, 0x53, 0x79, 0x72, 0x68, 0x11, 0xf7, 0xdc, 0x1b, 0x05, + 0x33, 0x3a, 0xc9, 0x6f, 0x78, 0xb4, 0x18, 0x32, 0xd2, 0x49, 0xf9, 0x3f, 0x30, 0xca, 0x89, 0x5f, + 0xe8, 0x3f, 0x3e, 0x07, 0x00, 0x00, 0xff, 0xff, 0x33, 0x9d, 0x7f, 0x6d, 0x2d, 0x08, 0x00, 0x00, +} + +func (m *RemoteSignerError) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RemoteSignerError) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RemoteSignerError) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *PubKeyRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PubKeyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PubKeyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PubKeyResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PubKeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PubKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Error != nil { + { + size, err := m.Error.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *SignVoteRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignVoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SkipExtensionSigning { + i-- + if m.SkipExtensionSigning { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0x12 + } + if m.Vote != nil { + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SignedVoteResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignedVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignedVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Error != nil { + { + size, err := m.Error.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *SignProposalRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignProposalRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0x12 + } + if m.Proposal != nil { + { + size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SignedProposalResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignedProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignedProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Error != nil { + { + size, err := m.Error.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *SignBytesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignBytesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignBytesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SignBytesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignBytesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignBytesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Error != nil { + { + size, err := m.Error.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Signature) > 0 { + i -= len(m.Signature) + copy(dAtA[i:], m.Signature) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Signature))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PingRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PingRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PingRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *PingResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PingResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *Message) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Message) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Message_PubKeyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PubKeyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PubKeyRequest != nil { + { + size, err := m.PubKeyRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Message_PubKeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PubKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PubKeyResponse != nil { + { + size, err := m.PubKeyResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Message_SignVoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignVoteRequest != nil { + { + size, err := m.SignVoteRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Message_SignedVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignedVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignedVoteResponse != nil { + { + size, err := m.SignedVoteResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Message_SignProposalRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignProposalRequest != nil { + { + size, err := m.SignProposalRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *Message_SignedProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignedProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignedProposalResponse != nil { + { + size, err := m.SignedProposalResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Message_PingRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PingRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PingRequest != nil { + { + size, err := m.PingRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Message_PingResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PingResponse != nil { + { + size, err := m.PingResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func (m *Message_SignBytesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignBytesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignBytesRequest != nil { + { + size, err := m.SignBytesRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + return len(dAtA) - i, nil +} +func (m *Message_SignBytesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignBytesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignBytesResponse != nil { + { + size, err := m.SignBytesResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + return len(dAtA) - i, nil +} +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *RemoteSignerError) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *PubKeyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *PubKeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.PubKey.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Error != nil { + l = m.Error.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignVoteRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Vote != nil { + l = m.Vote.Size() + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.SkipExtensionSigning { + n += 2 + } + return n +} + +func (m *SignedVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Vote.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Error != nil { + l = m.Error.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignProposalRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Proposal != nil { + l = m.Proposal.Size() + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignedProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Proposal.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Error != nil { + l = m.Error.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignBytesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Value) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignBytesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Signature) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Error != nil { + l = m.Error.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *PingRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *PingResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *Message) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Message_PubKeyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubKeyRequest != nil { + l = m.PubKeyRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_PubKeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubKeyResponse != nil { + l = m.PubKeyResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignVoteRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignVoteRequest != nil { + l = m.SignVoteRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignedVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignedVoteResponse != nil { + l = m.SignedVoteResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignProposalRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignProposalRequest != nil { + l = m.SignProposalRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignedProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignedProposalResponse != nil { + l = m.SignedProposalResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_PingRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PingRequest != nil { + l = m.PingRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_PingResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PingResponse != nil { + l = m.PingResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignBytesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignBytesRequest != nil { + l = m.SignBytesRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignBytesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignBytesResponse != nil { + l = m.SignBytesResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *RemoteSignerError) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RemoteSignerError: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RemoteSignerError: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PubKeyRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PubKeyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PubKeyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PubKeyResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PubKeyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PubKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Error == nil { + m.Error = &RemoteSignerError{} + } + if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignVoteRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignVoteRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignVoteRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Vote == nil { + m.Vote = &v11.Vote{} + } + if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SkipExtensionSigning", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SkipExtensionSigning = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignedVoteResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignedVoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignedVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Error == nil { + m.Error = &RemoteSignerError{} + } + if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignProposalRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignProposalRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignProposalRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proposal == nil { + m.Proposal = &v11.Proposal{} + } + if err := m.Proposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignedProposalResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignedProposalResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignedProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Proposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Error == nil { + m.Error = &RemoteSignerError{} + } + if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignBytesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignBytesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignBytesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...) + if m.Value == nil { + m.Value = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignBytesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignBytesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignBytesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...) + if m.Signature == nil { + m.Signature = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Error == nil { + m.Error = &RemoteSignerError{} + } + if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PingRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PingRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PingRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PingResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PingResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PingResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Message) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Message: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKeyRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PubKeyRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PubKeyRequest{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKeyResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PubKeyResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PubKeyResponse{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignVoteRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignVoteRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignVoteRequest{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedVoteResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignedVoteResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignedVoteResponse{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignProposalRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignProposalRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignProposalRequest{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedProposalResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignedProposalResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignedProposalResponse{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PingRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PingRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PingRequest{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PingResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PingResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PingResponse{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignBytesRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignBytesRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignBytesRequest{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignBytesResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignBytesResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignBytesResponse{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/privval/v1beta1/types.pb.go b/api/cometbft/privval/v1beta1/types.pb.go new file mode 100644 index 00000000000..69adae65550 --- /dev/null +++ b/api/cometbft/privval/v1beta1/types.pb.go @@ -0,0 +1,2817 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/privval/v1beta1/types.proto + +package v1beta1 + +import ( + fmt "fmt" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Errors is a list of error codes that can be returned by the remote signer. +type Errors int32 + +const ( + // Unknown error + Errors_ERRORS_UNKNOWN Errors = 0 + // Unexpected response + Errors_ERRORS_UNEXPECTED_RESPONSE Errors = 1 + // Connection lost + Errors_ERRORS_NO_CONNECTION Errors = 2 + // Connection timeout + Errors_ERRORS_CONNECTION_TIMEOUT Errors = 3 + // Read timeout + Errors_ERRORS_READ_TIMEOUT Errors = 4 + // Write timeout + Errors_ERRORS_WRITE_TIMEOUT Errors = 5 +) + +var Errors_name = map[int32]string{ + 0: "ERRORS_UNKNOWN", + 1: "ERRORS_UNEXPECTED_RESPONSE", + 2: "ERRORS_NO_CONNECTION", + 3: "ERRORS_CONNECTION_TIMEOUT", + 4: "ERRORS_READ_TIMEOUT", + 5: "ERRORS_WRITE_TIMEOUT", +} + +var Errors_value = map[string]int32{ + "ERRORS_UNKNOWN": 0, + "ERRORS_UNEXPECTED_RESPONSE": 1, + "ERRORS_NO_CONNECTION": 2, + "ERRORS_CONNECTION_TIMEOUT": 3, + "ERRORS_READ_TIMEOUT": 4, + "ERRORS_WRITE_TIMEOUT": 5, +} + +func (x Errors) String() string { + return proto.EnumName(Errors_name, int32(x)) +} + +func (Errors) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{0} +} + +// A service for broadcasting transactions. +type RemoteSignerError struct { + Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` +} + +func (m *RemoteSignerError) Reset() { *m = RemoteSignerError{} } +func (m *RemoteSignerError) String() string { return proto.CompactTextString(m) } +func (*RemoteSignerError) ProtoMessage() {} +func (*RemoteSignerError) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{0} +} +func (m *RemoteSignerError) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RemoteSignerError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RemoteSignerError.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RemoteSignerError) XXX_Merge(src proto.Message) { + xxx_messageInfo_RemoteSignerError.Merge(m, src) +} +func (m *RemoteSignerError) XXX_Size() int { + return m.Size() +} +func (m *RemoteSignerError) XXX_DiscardUnknown() { + xxx_messageInfo_RemoteSignerError.DiscardUnknown(m) +} + +var xxx_messageInfo_RemoteSignerError proto.InternalMessageInfo + +func (m *RemoteSignerError) GetCode() int32 { + if m != nil { + return m.Code + } + return 0 +} + +func (m *RemoteSignerError) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +// PubKeyRequest requests the consensus public key from the remote signer. +type PubKeyRequest struct { + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *PubKeyRequest) Reset() { *m = PubKeyRequest{} } +func (m *PubKeyRequest) String() string { return proto.CompactTextString(m) } +func (*PubKeyRequest) ProtoMessage() {} +func (*PubKeyRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{1} +} +func (m *PubKeyRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PubKeyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PubKeyRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PubKeyRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PubKeyRequest.Merge(m, src) +} +func (m *PubKeyRequest) XXX_Size() int { + return m.Size() +} +func (m *PubKeyRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PubKeyRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PubKeyRequest proto.InternalMessageInfo + +func (m *PubKeyRequest) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +// PubKeyResponse is a response message containing the public key. +type PubKeyResponse struct { + PubKey v1.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *PubKeyResponse) Reset() { *m = PubKeyResponse{} } +func (m *PubKeyResponse) String() string { return proto.CompactTextString(m) } +func (*PubKeyResponse) ProtoMessage() {} +func (*PubKeyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{2} +} +func (m *PubKeyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PubKeyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PubKeyResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PubKeyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PubKeyResponse.Merge(m, src) +} +func (m *PubKeyResponse) XXX_Size() int { + return m.Size() +} +func (m *PubKeyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PubKeyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PubKeyResponse proto.InternalMessageInfo + +func (m *PubKeyResponse) GetPubKey() v1.PublicKey { + if m != nil { + return m.PubKey + } + return v1.PublicKey{} +} + +func (m *PubKeyResponse) GetError() *RemoteSignerError { + if m != nil { + return m.Error + } + return nil +} + +// SignVoteRequest is a request to sign a vote +type SignVoteRequest struct { + Vote *v1beta1.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *SignVoteRequest) Reset() { *m = SignVoteRequest{} } +func (m *SignVoteRequest) String() string { return proto.CompactTextString(m) } +func (*SignVoteRequest) ProtoMessage() {} +func (*SignVoteRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{3} +} +func (m *SignVoteRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignVoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignVoteRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignVoteRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignVoteRequest.Merge(m, src) +} +func (m *SignVoteRequest) XXX_Size() int { + return m.Size() +} +func (m *SignVoteRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SignVoteRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SignVoteRequest proto.InternalMessageInfo + +func (m *SignVoteRequest) GetVote() *v1beta1.Vote { + if m != nil { + return m.Vote + } + return nil +} + +func (m *SignVoteRequest) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +// SignedVoteResponse is a response containing a signed vote or an error +type SignedVoteResponse struct { + Vote v1beta1.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote"` + Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *SignedVoteResponse) Reset() { *m = SignedVoteResponse{} } +func (m *SignedVoteResponse) String() string { return proto.CompactTextString(m) } +func (*SignedVoteResponse) ProtoMessage() {} +func (*SignedVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{4} +} +func (m *SignedVoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignedVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignedVoteResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignedVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignedVoteResponse.Merge(m, src) +} +func (m *SignedVoteResponse) XXX_Size() int { + return m.Size() +} +func (m *SignedVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SignedVoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SignedVoteResponse proto.InternalMessageInfo + +func (m *SignedVoteResponse) GetVote() v1beta1.Vote { + if m != nil { + return m.Vote + } + return v1beta1.Vote{} +} + +func (m *SignedVoteResponse) GetError() *RemoteSignerError { + if m != nil { + return m.Error + } + return nil +} + +// SignProposalRequest is a request to sign a proposal +type SignProposalRequest struct { + Proposal *v1beta1.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *SignProposalRequest) Reset() { *m = SignProposalRequest{} } +func (m *SignProposalRequest) String() string { return proto.CompactTextString(m) } +func (*SignProposalRequest) ProtoMessage() {} +func (*SignProposalRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{5} +} +func (m *SignProposalRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignProposalRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignProposalRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignProposalRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignProposalRequest.Merge(m, src) +} +func (m *SignProposalRequest) XXX_Size() int { + return m.Size() +} +func (m *SignProposalRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SignProposalRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SignProposalRequest proto.InternalMessageInfo + +func (m *SignProposalRequest) GetProposal() *v1beta1.Proposal { + if m != nil { + return m.Proposal + } + return nil +} + +func (m *SignProposalRequest) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +// SignedProposalResponse is response containing a signed proposal or an error +type SignedProposalResponse struct { + Proposal v1beta1.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal"` + Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` +} + +func (m *SignedProposalResponse) Reset() { *m = SignedProposalResponse{} } +func (m *SignedProposalResponse) String() string { return proto.CompactTextString(m) } +func (*SignedProposalResponse) ProtoMessage() {} +func (*SignedProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{6} +} +func (m *SignedProposalResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignedProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignedProposalResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignedProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignedProposalResponse.Merge(m, src) +} +func (m *SignedProposalResponse) XXX_Size() int { + return m.Size() +} +func (m *SignedProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SignedProposalResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SignedProposalResponse proto.InternalMessageInfo + +func (m *SignedProposalResponse) GetProposal() v1beta1.Proposal { + if m != nil { + return m.Proposal + } + return v1beta1.Proposal{} +} + +func (m *SignedProposalResponse) GetError() *RemoteSignerError { + if m != nil { + return m.Error + } + return nil +} + +// PingRequest is a request to confirm that the connection is alive. +type PingRequest struct { +} + +func (m *PingRequest) Reset() { *m = PingRequest{} } +func (m *PingRequest) String() string { return proto.CompactTextString(m) } +func (*PingRequest) ProtoMessage() {} +func (*PingRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{7} +} +func (m *PingRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PingRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PingRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_PingRequest.Merge(m, src) +} +func (m *PingRequest) XXX_Size() int { + return m.Size() +} +func (m *PingRequest) XXX_DiscardUnknown() { + xxx_messageInfo_PingRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_PingRequest proto.InternalMessageInfo + +// PingResponse is a response to confirm that the connection is alive. +type PingResponse struct { +} + +func (m *PingResponse) Reset() { *m = PingResponse{} } +func (m *PingResponse) String() string { return proto.CompactTextString(m) } +func (*PingResponse) ProtoMessage() {} +func (*PingResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{8} +} +func (m *PingResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PingResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PingResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PingResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_PingResponse.Merge(m, src) +} +func (m *PingResponse) XXX_Size() int { + return m.Size() +} +func (m *PingResponse) XXX_DiscardUnknown() { + xxx_messageInfo_PingResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_PingResponse proto.InternalMessageInfo + +// Message is an abstract message to/from the remote signer. +type Message struct { + // Sum of all possible messages. + // + // Types that are valid to be assigned to Sum: + // *Message_PubKeyRequest + // *Message_PubKeyResponse + // *Message_SignVoteRequest + // *Message_SignedVoteResponse + // *Message_SignProposalRequest + // *Message_SignedProposalResponse + // *Message_PingRequest + // *Message_PingResponse + Sum isMessage_Sum `protobuf_oneof:"sum"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { + return fileDescriptor_2e82066b29171f6d, []int{9} +} +func (m *Message) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Message.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Message) XXX_Merge(src proto.Message) { + xxx_messageInfo_Message.Merge(m, src) +} +func (m *Message) XXX_Size() int { + return m.Size() +} +func (m *Message) XXX_DiscardUnknown() { + xxx_messageInfo_Message.DiscardUnknown(m) +} + +var xxx_messageInfo_Message proto.InternalMessageInfo + +type isMessage_Sum interface { + isMessage_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Message_PubKeyRequest struct { + PubKeyRequest *PubKeyRequest `protobuf:"bytes,1,opt,name=pub_key_request,json=pubKeyRequest,proto3,oneof" json:"pub_key_request,omitempty"` +} +type Message_PubKeyResponse struct { + PubKeyResponse *PubKeyResponse `protobuf:"bytes,2,opt,name=pub_key_response,json=pubKeyResponse,proto3,oneof" json:"pub_key_response,omitempty"` +} +type Message_SignVoteRequest struct { + SignVoteRequest *SignVoteRequest `protobuf:"bytes,3,opt,name=sign_vote_request,json=signVoteRequest,proto3,oneof" json:"sign_vote_request,omitempty"` +} +type Message_SignedVoteResponse struct { + SignedVoteResponse *SignedVoteResponse `protobuf:"bytes,4,opt,name=signed_vote_response,json=signedVoteResponse,proto3,oneof" json:"signed_vote_response,omitempty"` +} +type Message_SignProposalRequest struct { + SignProposalRequest *SignProposalRequest `protobuf:"bytes,5,opt,name=sign_proposal_request,json=signProposalRequest,proto3,oneof" json:"sign_proposal_request,omitempty"` +} +type Message_SignedProposalResponse struct { + SignedProposalResponse *SignedProposalResponse `protobuf:"bytes,6,opt,name=signed_proposal_response,json=signedProposalResponse,proto3,oneof" json:"signed_proposal_response,omitempty"` +} +type Message_PingRequest struct { + PingRequest *PingRequest `protobuf:"bytes,7,opt,name=ping_request,json=pingRequest,proto3,oneof" json:"ping_request,omitempty"` +} +type Message_PingResponse struct { + PingResponse *PingResponse `protobuf:"bytes,8,opt,name=ping_response,json=pingResponse,proto3,oneof" json:"ping_response,omitempty"` +} + +func (*Message_PubKeyRequest) isMessage_Sum() {} +func (*Message_PubKeyResponse) isMessage_Sum() {} +func (*Message_SignVoteRequest) isMessage_Sum() {} +func (*Message_SignedVoteResponse) isMessage_Sum() {} +func (*Message_SignProposalRequest) isMessage_Sum() {} +func (*Message_SignedProposalResponse) isMessage_Sum() {} +func (*Message_PingRequest) isMessage_Sum() {} +func (*Message_PingResponse) isMessage_Sum() {} + +func (m *Message) GetSum() isMessage_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Message) GetPubKeyRequest() *PubKeyRequest { + if x, ok := m.GetSum().(*Message_PubKeyRequest); ok { + return x.PubKeyRequest + } + return nil +} + +func (m *Message) GetPubKeyResponse() *PubKeyResponse { + if x, ok := m.GetSum().(*Message_PubKeyResponse); ok { + return x.PubKeyResponse + } + return nil +} + +func (m *Message) GetSignVoteRequest() *SignVoteRequest { + if x, ok := m.GetSum().(*Message_SignVoteRequest); ok { + return x.SignVoteRequest + } + return nil +} + +func (m *Message) GetSignedVoteResponse() *SignedVoteResponse { + if x, ok := m.GetSum().(*Message_SignedVoteResponse); ok { + return x.SignedVoteResponse + } + return nil +} + +func (m *Message) GetSignProposalRequest() *SignProposalRequest { + if x, ok := m.GetSum().(*Message_SignProposalRequest); ok { + return x.SignProposalRequest + } + return nil +} + +func (m *Message) GetSignedProposalResponse() *SignedProposalResponse { + if x, ok := m.GetSum().(*Message_SignedProposalResponse); ok { + return x.SignedProposalResponse + } + return nil +} + +func (m *Message) GetPingRequest() *PingRequest { + if x, ok := m.GetSum().(*Message_PingRequest); ok { + return x.PingRequest + } + return nil +} + +func (m *Message) GetPingResponse() *PingResponse { + if x, ok := m.GetSum().(*Message_PingResponse); ok { + return x.PingResponse + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Message) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Message_PubKeyRequest)(nil), + (*Message_PubKeyResponse)(nil), + (*Message_SignVoteRequest)(nil), + (*Message_SignedVoteResponse)(nil), + (*Message_SignProposalRequest)(nil), + (*Message_SignedProposalResponse)(nil), + (*Message_PingRequest)(nil), + (*Message_PingResponse)(nil), + } +} + +func init() { + proto.RegisterEnum("cometbft.privval.v1beta1.Errors", Errors_name, Errors_value) + proto.RegisterType((*RemoteSignerError)(nil), "cometbft.privval.v1beta1.RemoteSignerError") + proto.RegisterType((*PubKeyRequest)(nil), "cometbft.privval.v1beta1.PubKeyRequest") + proto.RegisterType((*PubKeyResponse)(nil), "cometbft.privval.v1beta1.PubKeyResponse") + proto.RegisterType((*SignVoteRequest)(nil), "cometbft.privval.v1beta1.SignVoteRequest") + proto.RegisterType((*SignedVoteResponse)(nil), "cometbft.privval.v1beta1.SignedVoteResponse") + proto.RegisterType((*SignProposalRequest)(nil), "cometbft.privval.v1beta1.SignProposalRequest") + proto.RegisterType((*SignedProposalResponse)(nil), "cometbft.privval.v1beta1.SignedProposalResponse") + proto.RegisterType((*PingRequest)(nil), "cometbft.privval.v1beta1.PingRequest") + proto.RegisterType((*PingResponse)(nil), "cometbft.privval.v1beta1.PingResponse") + proto.RegisterType((*Message)(nil), "cometbft.privval.v1beta1.Message") +} + +func init() { + proto.RegisterFile("cometbft/privval/v1beta1/types.proto", fileDescriptor_2e82066b29171f6d) +} + +var fileDescriptor_2e82066b29171f6d = []byte{ + // 773 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x4e, 0xeb, 0x46, + 0x14, 0xb6, 0x21, 0x3f, 0x70, 0x42, 0x42, 0x18, 0x28, 0x0d, 0x51, 0x49, 0xa3, 0xa8, 0x3f, 0x94, + 0xb6, 0x36, 0xa1, 0x52, 0xa5, 0x4a, 0x6c, 0x08, 0x58, 0x4a, 0x8a, 0x70, 0xd2, 0x49, 0x28, 0x55, + 0x17, 0x75, 0xf3, 0x33, 0x35, 0x16, 0xc1, 0x9e, 0x7a, 0x9c, 0x48, 0x79, 0x8a, 0xb6, 0x4f, 0xd0, + 0x6d, 0x1f, 0x85, 0x25, 0xcb, 0xae, 0xae, 0xae, 0xc2, 0x8b, 0x5c, 0x65, 0x3c, 0xb6, 0x93, 0x40, + 0xc2, 0xbd, 0x12, 0xbb, 0x99, 0x33, 0xe7, 0x7c, 0x3f, 0xc7, 0xe7, 0xc8, 0xf0, 0x59, 0xd7, 0xb9, + 0x23, 0x5e, 0xe7, 0x0f, 0x4f, 0xa5, 0xae, 0x35, 0x1c, 0xb6, 0xfb, 0xea, 0xb0, 0xdc, 0x21, 0x5e, + 0xbb, 0xac, 0x7a, 0x23, 0x4a, 0x98, 0x42, 0x5d, 0xc7, 0x73, 0x50, 0x2e, 0xc8, 0x52, 0x44, 0x96, + 0x22, 0xb2, 0xf2, 0xfb, 0x61, 0x7d, 0xd7, 0x1d, 0x51, 0xcf, 0x51, 0x87, 0x65, 0xf5, 0x96, 0x8c, + 0x44, 0x61, 0xbe, 0x14, 0x3e, 0x73, 0xb8, 0xe7, 0xc0, 0xf3, 0x3b, 0xa6, 0x63, 0x3a, 0xfc, 0xa8, + 0x4e, 0x4e, 0x7e, 0xb4, 0x54, 0x83, 0x2d, 0x4c, 0xee, 0x1c, 0x8f, 0x34, 0x2d, 0xd3, 0x26, 0xae, + 0xe6, 0xba, 0x8e, 0x8b, 0x10, 0xc4, 0xba, 0x4e, 0x8f, 0xe4, 0xe4, 0xa2, 0x7c, 0x10, 0xc7, 0xfc, + 0x8c, 0x8a, 0x90, 0xea, 0x11, 0xd6, 0x75, 0x2d, 0xea, 0x59, 0x8e, 0x9d, 0x5b, 0x29, 0xca, 0x07, + 0xeb, 0x78, 0x3a, 0x54, 0x3a, 0x84, 0x74, 0x63, 0xd0, 0xb9, 0x20, 0x23, 0x4c, 0xfe, 0x1c, 0x10, + 0xe6, 0xa1, 0x3d, 0x58, 0xeb, 0xde, 0xb4, 0x2d, 0xdb, 0xb0, 0x7a, 0x1c, 0x6a, 0x1d, 0x27, 0xf9, + 0xbd, 0xd6, 0x2b, 0xfd, 0x23, 0x43, 0x26, 0x48, 0x66, 0xd4, 0xb1, 0x19, 0x41, 0x27, 0x90, 0xa4, + 0x83, 0x8e, 0x71, 0x4b, 0x46, 0x3c, 0x39, 0x75, 0xbc, 0xaf, 0x84, 0xed, 0xf0, 0x4d, 0x2b, 0xc3, + 0xb2, 0xd2, 0x18, 0x74, 0xfa, 0x56, 0xf7, 0x82, 0x8c, 0x2a, 0xb1, 0xfb, 0x37, 0x9f, 0x4a, 0x38, + 0x41, 0x39, 0x0a, 0x3a, 0x85, 0x38, 0x99, 0x68, 0xe7, 0xc2, 0x52, 0xc7, 0x5f, 0x2b, 0x8b, 0x5a, + 0xa9, 0x3c, 0xb1, 0x8b, 0xfd, 0xca, 0xd2, 0x6f, 0xb0, 0x39, 0x89, 0xfe, 0xec, 0x78, 0x24, 0x70, + 0x70, 0x04, 0xb1, 0xa1, 0xe3, 0x11, 0x21, 0xe8, 0x93, 0x08, 0xd4, 0x6f, 0x6c, 0x00, 0xc9, 0x4b, + 0x78, 0xe6, 0x8c, 0xe7, 0x95, 0x59, 0xcf, 0x7f, 0xc9, 0x80, 0x38, 0x6d, 0xcf, 0xa7, 0x10, 0xbe, + 0xbf, 0x7f, 0x7f, 0x0e, 0xe1, 0xd9, 0x67, 0x7a, 0x05, 0xc7, 0x36, 0x6c, 0x4f, 0xa2, 0x0d, 0xd7, + 0xa1, 0x0e, 0x6b, 0xf7, 0x03, 0xd7, 0x27, 0xb0, 0x46, 0x45, 0x48, 0xa8, 0x2a, 0x2e, 0x52, 0x15, + 0x96, 0x86, 0x15, 0xcb, 0x3a, 0xf0, 0xaf, 0x0c, 0xbb, 0x7e, 0x07, 0x22, 0x4a, 0xd1, 0x85, 0xca, + 0x87, 0x73, 0x8a, 0x6e, 0x44, 0xcc, 0xaf, 0xd0, 0x91, 0x34, 0xa4, 0x1a, 0x96, 0x6d, 0x8a, 0x4e, + 0x94, 0x32, 0xb0, 0xe1, 0x5f, 0x7d, 0x95, 0xa5, 0x71, 0x1c, 0x92, 0x97, 0x84, 0xb1, 0xb6, 0x49, + 0xd0, 0x4f, 0xb0, 0x29, 0xe6, 0xd5, 0x70, 0xfd, 0x74, 0x21, 0xfc, 0xcb, 0xc5, 0xbc, 0x33, 0xfb, + 0x51, 0x95, 0x70, 0x9a, 0xce, 0x2c, 0x4c, 0x0b, 0xb2, 0x11, 0xa4, 0x4f, 0x29, 0xbc, 0x1c, 0xbc, + 0x8c, 0xe9, 0xe7, 0x57, 0x25, 0x9c, 0xa1, 0xb3, 0x8b, 0x75, 0x0d, 0x5b, 0xcc, 0x32, 0x6d, 0x63, + 0x32, 0x35, 0xa1, 0xd4, 0x55, 0x0e, 0xfb, 0xd5, 0x62, 0xd8, 0xb9, 0x55, 0xa8, 0x4a, 0x78, 0x93, + 0xcd, 0x6d, 0xc7, 0xef, 0xb0, 0xc3, 0xf8, 0xd7, 0x0c, 0xa0, 0x85, 0xe4, 0x18, 0xc7, 0xfe, 0x66, + 0x39, 0xf6, 0xec, 0x16, 0x54, 0x25, 0x8c, 0xd8, 0xd3, 0xdd, 0xe8, 0xc2, 0x47, 0x5c, 0x7a, 0xf0, + 0x89, 0x43, 0xf9, 0x71, 0x4e, 0xf1, 0xed, 0x72, 0x8a, 0xb9, 0xb9, 0xae, 0x4a, 0x78, 0x9b, 0x3d, + 0x33, 0xee, 0x7d, 0xc8, 0x09, 0x1b, 0x53, 0x34, 0xc2, 0x4a, 0x82, 0xf3, 0x1c, 0xbd, 0x64, 0x65, + 0x7e, 0x9c, 0xab, 0x12, 0xde, 0x65, 0xcf, 0x0f, 0xfa, 0x8f, 0xb0, 0x41, 0x2d, 0xdb, 0x0c, 0x9d, + 0x24, 0x39, 0xc3, 0xe7, 0x4b, 0xbe, 0x6f, 0x34, 0x8f, 0x55, 0x09, 0xa7, 0x68, 0x74, 0x45, 0x97, + 0x90, 0x16, 0x58, 0x42, 0xee, 0x1a, 0x07, 0xfb, 0xe2, 0x25, 0xb0, 0x50, 0xe4, 0x06, 0x9d, 0xba, + 0x57, 0xe2, 0xb0, 0xca, 0x06, 0x77, 0x87, 0xff, 0xc9, 0x90, 0xe0, 0x4b, 0xc1, 0x10, 0x82, 0x8c, + 0x86, 0x71, 0x1d, 0x37, 0x8d, 0x2b, 0xfd, 0x42, 0xaf, 0x5f, 0xeb, 0x59, 0x09, 0x15, 0x20, 0x1f, + 0xc6, 0xb4, 0x5f, 0x1a, 0xda, 0x59, 0x4b, 0x3b, 0x37, 0xb0, 0xd6, 0x6c, 0xd4, 0xf5, 0xa6, 0x96, + 0x95, 0x51, 0x0e, 0x76, 0xc4, 0xbb, 0x5e, 0x37, 0xce, 0xea, 0xba, 0xae, 0x9d, 0xb5, 0x6a, 0x75, + 0x3d, 0xbb, 0x82, 0xf6, 0x61, 0x4f, 0xbc, 0x44, 0x61, 0xa3, 0x55, 0xbb, 0xd4, 0xea, 0x57, 0xad, + 0xec, 0x2a, 0xfa, 0x18, 0xb6, 0xc5, 0x33, 0xd6, 0x4e, 0xcf, 0xc3, 0x87, 0xd8, 0x14, 0xe2, 0x35, + 0xae, 0xb5, 0xb4, 0xf0, 0x25, 0x5e, 0x69, 0xde, 0x8f, 0x0b, 0xf2, 0xc3, 0xb8, 0x20, 0xbf, 0x1d, + 0x17, 0xe4, 0xbf, 0x1f, 0x0b, 0xd2, 0xc3, 0x63, 0x41, 0xfa, 0xff, 0xb1, 0x20, 0xfd, 0xfa, 0x83, + 0x69, 0x79, 0x37, 0x83, 0xce, 0xa4, 0x13, 0x6a, 0xf4, 0xef, 0x0c, 0x0e, 0x6d, 0x6a, 0xa9, 0x8b, + 0xfe, 0xc8, 0x9d, 0x04, 0xff, 0x33, 0x7e, 0xf7, 0x2e, 0x00, 0x00, 0xff, 0xff, 0xe7, 0x94, 0x16, + 0x90, 0xb4, 0x07, 0x00, 0x00, +} + +func (m *RemoteSignerError) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RemoteSignerError) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RemoteSignerError) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if m.Code != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *PubKeyRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PubKeyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PubKeyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *PubKeyResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PubKeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PubKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Error != nil { + { + size, err := m.Error.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *SignVoteRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignVoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0x12 + } + if m.Vote != nil { + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SignedVoteResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignedVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignedVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Error != nil { + { + size, err := m.Error.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *SignProposalRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignProposalRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0x12 + } + if m.Proposal != nil { + { + size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SignedProposalResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignedProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignedProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Error != nil { + { + size, err := m.Error.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *PingRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PingRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PingRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *PingResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PingResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *Message) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Message) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Message_PubKeyRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PubKeyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PubKeyRequest != nil { + { + size, err := m.PubKeyRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Message_PubKeyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PubKeyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PubKeyResponse != nil { + { + size, err := m.PubKeyResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *Message_SignVoteRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignVoteRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignVoteRequest != nil { + { + size, err := m.SignVoteRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *Message_SignedVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignedVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignedVoteResponse != nil { + { + size, err := m.SignedVoteResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + return len(dAtA) - i, nil +} +func (m *Message_SignProposalRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignProposalRequest != nil { + { + size, err := m.SignProposalRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} +func (m *Message_SignedProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_SignedProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SignedProposalResponse != nil { + { + size, err := m.SignedProposalResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + return len(dAtA) - i, nil +} +func (m *Message_PingRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PingRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PingRequest != nil { + { + size, err := m.PingRequest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + return len(dAtA) - i, nil +} +func (m *Message_PingResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Message_PingResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.PingResponse != nil { + { + size, err := m.PingResponse.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *RemoteSignerError) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *PubKeyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *PubKeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.PubKey.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Error != nil { + l = m.Error.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignVoteRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Vote != nil { + l = m.Vote.Size() + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignedVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Vote.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Error != nil { + l = m.Error.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignProposalRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Proposal != nil { + l = m.Proposal.Size() + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignedProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Proposal.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Error != nil { + l = m.Error.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *PingRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *PingResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *Message) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Message_PubKeyRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubKeyRequest != nil { + l = m.PubKeyRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_PubKeyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubKeyResponse != nil { + l = m.PubKeyResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignVoteRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignVoteRequest != nil { + l = m.SignVoteRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignedVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignedVoteResponse != nil { + l = m.SignedVoteResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignProposalRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignProposalRequest != nil { + l = m.SignProposalRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_SignedProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignedProposalResponse != nil { + l = m.SignedProposalResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_PingRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PingRequest != nil { + l = m.PingRequest.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Message_PingResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PingResponse != nil { + l = m.PingResponse.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *RemoteSignerError) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RemoteSignerError: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RemoteSignerError: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PubKeyRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PubKeyRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PubKeyRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PubKeyResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PubKeyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PubKeyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Error == nil { + m.Error = &RemoteSignerError{} + } + if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignVoteRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignVoteRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignVoteRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Vote == nil { + m.Vote = &v1beta1.Vote{} + } + if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignedVoteResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignedVoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignedVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Error == nil { + m.Error = &RemoteSignerError{} + } + if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignProposalRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignProposalRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignProposalRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proposal == nil { + m.Proposal = &v1beta1.Proposal{} + } + if err := m.Proposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignedProposalResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignedProposalResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignedProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Proposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Error == nil { + m.Error = &RemoteSignerError{} + } + if err := m.Error.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PingRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PingRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PingRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PingResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PingResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PingResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Message) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Message: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Message: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKeyRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PubKeyRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PubKeyRequest{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKeyResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PubKeyResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PubKeyResponse{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignVoteRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignVoteRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignVoteRequest{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedVoteResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignedVoteResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignedVoteResponse{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignProposalRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignProposalRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignProposalRequest{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedProposalResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SignedProposalResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_SignedProposalResponse{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PingRequest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PingRequest{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PingRequest{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PingResponse", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &PingResponse{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Message_PingResponse{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/tendermint/privval/types.pb.go b/api/cometbft/privval/v1beta2/types.pb.go similarity index 88% rename from proto/tendermint/privval/types.pb.go rename to api/cometbft/privval/v1beta2/types.pb.go index cafa0e9278c..342a4d54bf4 100644 --- a/proto/tendermint/privval/types.pb.go +++ b/api/cometbft/privval/v1beta2/types.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/privval/types.proto +// source: cometbft/privval/v1beta2/types.proto -package privval +package v1beta2 import ( fmt "fmt" - crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" - types "github.com/cometbft/cometbft/proto/tendermint/types" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + v11 "github.com/cometbft/cometbft/api/cometbft/types/v1" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" @@ -25,15 +25,22 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// Errors is a list of error codes that can be returned by the remote signer. type Errors int32 const ( - Errors_ERRORS_UNKNOWN Errors = 0 + // Unknown error + Errors_ERRORS_UNKNOWN Errors = 0 + // Unexpected response Errors_ERRORS_UNEXPECTED_RESPONSE Errors = 1 - Errors_ERRORS_NO_CONNECTION Errors = 2 - Errors_ERRORS_CONNECTION_TIMEOUT Errors = 3 - Errors_ERRORS_READ_TIMEOUT Errors = 4 - Errors_ERRORS_WRITE_TIMEOUT Errors = 5 + // Connection lost + Errors_ERRORS_NO_CONNECTION Errors = 2 + // Connection timeout + Errors_ERRORS_CONNECTION_TIMEOUT Errors = 3 + // Read timeout + Errors_ERRORS_READ_TIMEOUT Errors = 4 + // Write timeout + Errors_ERRORS_WRITE_TIMEOUT Errors = 5 ) var Errors_name = map[int32]string{ @@ -59,9 +66,10 @@ func (x Errors) String() string { } func (Errors) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{0} + return fileDescriptor_7eb66e8513d3d538, []int{0} } +// remotesignererror is returned when the remote signer fails. type RemoteSignerError struct { Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` @@ -71,7 +79,7 @@ func (m *RemoteSignerError) Reset() { *m = RemoteSignerError{} } func (m *RemoteSignerError) String() string { return proto.CompactTextString(m) } func (*RemoteSignerError) ProtoMessage() {} func (*RemoteSignerError) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{0} + return fileDescriptor_7eb66e8513d3d538, []int{0} } func (m *RemoteSignerError) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -123,7 +131,7 @@ func (m *PubKeyRequest) Reset() { *m = PubKeyRequest{} } func (m *PubKeyRequest) String() string { return proto.CompactTextString(m) } func (*PubKeyRequest) ProtoMessage() {} func (*PubKeyRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{1} + return fileDescriptor_7eb66e8513d3d538, []int{1} } func (m *PubKeyRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -161,7 +169,7 @@ func (m *PubKeyRequest) GetChainId() string { // PubKeyResponse is a response message containing the public key. type PubKeyResponse struct { - PubKey crypto.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + PubKey v1.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` } @@ -169,7 +177,7 @@ func (m *PubKeyResponse) Reset() { *m = PubKeyResponse{} } func (m *PubKeyResponse) String() string { return proto.CompactTextString(m) } func (*PubKeyResponse) ProtoMessage() {} func (*PubKeyResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{2} + return fileDescriptor_7eb66e8513d3d538, []int{2} } func (m *PubKeyResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -198,11 +206,11 @@ func (m *PubKeyResponse) XXX_DiscardUnknown() { var xxx_messageInfo_PubKeyResponse proto.InternalMessageInfo -func (m *PubKeyResponse) GetPubKey() crypto.PublicKey { +func (m *PubKeyResponse) GetPubKey() v1.PublicKey { if m != nil { return m.PubKey } - return crypto.PublicKey{} + return v1.PublicKey{} } func (m *PubKeyResponse) GetError() *RemoteSignerError { @@ -214,15 +222,15 @@ func (m *PubKeyResponse) GetError() *RemoteSignerError { // SignVoteRequest is a request to sign a vote type SignVoteRequest struct { - Vote *types.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Vote *v11.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` } func (m *SignVoteRequest) Reset() { *m = SignVoteRequest{} } func (m *SignVoteRequest) String() string { return proto.CompactTextString(m) } func (*SignVoteRequest) ProtoMessage() {} func (*SignVoteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{3} + return fileDescriptor_7eb66e8513d3d538, []int{3} } func (m *SignVoteRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -251,7 +259,7 @@ func (m *SignVoteRequest) XXX_DiscardUnknown() { var xxx_messageInfo_SignVoteRequest proto.InternalMessageInfo -func (m *SignVoteRequest) GetVote() *types.Vote { +func (m *SignVoteRequest) GetVote() *v11.Vote { if m != nil { return m.Vote } @@ -267,7 +275,7 @@ func (m *SignVoteRequest) GetChainId() string { // SignedVoteResponse is a response containing a signed vote or an error type SignedVoteResponse struct { - Vote types.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote"` + Vote v11.Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote"` Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` } @@ -275,7 +283,7 @@ func (m *SignedVoteResponse) Reset() { *m = SignedVoteResponse{} } func (m *SignedVoteResponse) String() string { return proto.CompactTextString(m) } func (*SignedVoteResponse) ProtoMessage() {} func (*SignedVoteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{4} + return fileDescriptor_7eb66e8513d3d538, []int{4} } func (m *SignedVoteResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -304,11 +312,11 @@ func (m *SignedVoteResponse) XXX_DiscardUnknown() { var xxx_messageInfo_SignedVoteResponse proto.InternalMessageInfo -func (m *SignedVoteResponse) GetVote() types.Vote { +func (m *SignedVoteResponse) GetVote() v11.Vote { if m != nil { return m.Vote } - return types.Vote{} + return v11.Vote{} } func (m *SignedVoteResponse) GetError() *RemoteSignerError { @@ -320,15 +328,15 @@ func (m *SignedVoteResponse) GetError() *RemoteSignerError { // SignProposalRequest is a request to sign a proposal type SignProposalRequest struct { - Proposal *types.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Proposal *v11.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` } func (m *SignProposalRequest) Reset() { *m = SignProposalRequest{} } func (m *SignProposalRequest) String() string { return proto.CompactTextString(m) } func (*SignProposalRequest) ProtoMessage() {} func (*SignProposalRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{5} + return fileDescriptor_7eb66e8513d3d538, []int{5} } func (m *SignProposalRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -357,7 +365,7 @@ func (m *SignProposalRequest) XXX_DiscardUnknown() { var xxx_messageInfo_SignProposalRequest proto.InternalMessageInfo -func (m *SignProposalRequest) GetProposal() *types.Proposal { +func (m *SignProposalRequest) GetProposal() *v11.Proposal { if m != nil { return m.Proposal } @@ -373,7 +381,7 @@ func (m *SignProposalRequest) GetChainId() string { // SignedProposalResponse is response containing a signed proposal or an error type SignedProposalResponse struct { - Proposal types.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal"` + Proposal v11.Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal"` Error *RemoteSignerError `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` } @@ -381,7 +389,7 @@ func (m *SignedProposalResponse) Reset() { *m = SignedProposalResponse{} func (m *SignedProposalResponse) String() string { return proto.CompactTextString(m) } func (*SignedProposalResponse) ProtoMessage() {} func (*SignedProposalResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{6} + return fileDescriptor_7eb66e8513d3d538, []int{6} } func (m *SignedProposalResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -410,11 +418,11 @@ func (m *SignedProposalResponse) XXX_DiscardUnknown() { var xxx_messageInfo_SignedProposalResponse proto.InternalMessageInfo -func (m *SignedProposalResponse) GetProposal() types.Proposal { +func (m *SignedProposalResponse) GetProposal() v11.Proposal { if m != nil { return m.Proposal } - return types.Proposal{} + return v11.Proposal{} } func (m *SignedProposalResponse) GetError() *RemoteSignerError { @@ -432,7 +440,7 @@ func (m *PingRequest) Reset() { *m = PingRequest{} } func (m *PingRequest) String() string { return proto.CompactTextString(m) } func (*PingRequest) ProtoMessage() {} func (*PingRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{7} + return fileDescriptor_7eb66e8513d3d538, []int{7} } func (m *PingRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -469,7 +477,7 @@ func (m *PingResponse) Reset() { *m = PingResponse{} } func (m *PingResponse) String() string { return proto.CompactTextString(m) } func (*PingResponse) ProtoMessage() {} func (*PingResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{8} + return fileDescriptor_7eb66e8513d3d538, []int{8} } func (m *PingResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -498,7 +506,10 @@ func (m *PingResponse) XXX_DiscardUnknown() { var xxx_messageInfo_PingResponse proto.InternalMessageInfo +// Message is an abstract message to/from the remote signer. type Message struct { + // Sum of all possible messages. + // // Types that are valid to be assigned to Sum: // *Message_PubKeyRequest // *Message_PubKeyResponse @@ -515,7 +526,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_cb4e437a5328cf9c, []int{9} + return fileDescriptor_7eb66e8513d3d538, []int{9} } func (m *Message) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -662,71 +673,74 @@ func (*Message) XXX_OneofWrappers() []interface{} { } func init() { - proto.RegisterEnum("tendermint.privval.Errors", Errors_name, Errors_value) - proto.RegisterType((*RemoteSignerError)(nil), "tendermint.privval.RemoteSignerError") - proto.RegisterType((*PubKeyRequest)(nil), "tendermint.privval.PubKeyRequest") - proto.RegisterType((*PubKeyResponse)(nil), "tendermint.privval.PubKeyResponse") - proto.RegisterType((*SignVoteRequest)(nil), "tendermint.privval.SignVoteRequest") - proto.RegisterType((*SignedVoteResponse)(nil), "tendermint.privval.SignedVoteResponse") - proto.RegisterType((*SignProposalRequest)(nil), "tendermint.privval.SignProposalRequest") - proto.RegisterType((*SignedProposalResponse)(nil), "tendermint.privval.SignedProposalResponse") - proto.RegisterType((*PingRequest)(nil), "tendermint.privval.PingRequest") - proto.RegisterType((*PingResponse)(nil), "tendermint.privval.PingResponse") - proto.RegisterType((*Message)(nil), "tendermint.privval.Message") -} - -func init() { proto.RegisterFile("tendermint/privval/types.proto", fileDescriptor_cb4e437a5328cf9c) } - -var fileDescriptor_cb4e437a5328cf9c = []byte{ - // 756 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x4d, 0x4f, 0xe3, 0x46, - 0x18, 0xb6, 0x21, 0x1f, 0xf0, 0x86, 0x84, 0x30, 0x50, 0x1a, 0x22, 0x6a, 0xd2, 0x54, 0x6d, 0x51, - 0x0e, 0x49, 0x45, 0xd5, 0x5e, 0xe8, 0xa5, 0x80, 0xd5, 0x44, 0x11, 0x76, 0x3a, 0x09, 0x05, 0x21, - 0x55, 0x56, 0x3e, 0x06, 0x63, 0x41, 0x3c, 0x5e, 0x8f, 0x83, 0x94, 0xf3, 0xde, 0xf6, 0xb4, 0xd2, - 0xfe, 0x89, 0x3d, 0xef, 0xaf, 0xe0, 0xc8, 0x71, 0x4f, 0xab, 0x15, 0xfc, 0x91, 0x55, 0xc6, 0x13, - 0xdb, 0xf9, 0x42, 0xbb, 0xe2, 0x36, 0xf3, 0xbe, 0xef, 0x3c, 0x1f, 0x33, 0x8f, 0x65, 0x50, 0x3c, - 0x62, 0xf7, 0x88, 0xdb, 0xb7, 0x6c, 0xaf, 0xe2, 0xb8, 0xd6, 0xdd, 0x5d, 0xfb, 0xb6, 0xe2, 0x0d, - 0x1d, 0xc2, 0xca, 0x8e, 0x4b, 0x3d, 0x8a, 0x50, 0xd8, 0x2f, 0x8b, 0x7e, 0x7e, 0x37, 0x72, 0xa6, - 0xeb, 0x0e, 0x1d, 0x8f, 0x56, 0x6e, 0xc8, 0x50, 0x9c, 0x98, 0xe8, 0x72, 0xa4, 0x28, 0x5e, 0x7e, - 0xcb, 0xa4, 0x26, 0xe5, 0xcb, 0xca, 0x68, 0xe5, 0x57, 0x8b, 0x35, 0xd8, 0xc0, 0xa4, 0x4f, 0x3d, - 0xd2, 0xb4, 0x4c, 0x9b, 0xb8, 0xaa, 0xeb, 0x52, 0x17, 0x21, 0x88, 0x75, 0x69, 0x8f, 0xe4, 0xe4, - 0x82, 0xbc, 0x1f, 0xc7, 0x7c, 0x8d, 0x0a, 0x90, 0xea, 0x11, 0xd6, 0x75, 0x2d, 0xc7, 0xb3, 0xa8, - 0x9d, 0x5b, 0x2a, 0xc8, 0xfb, 0xab, 0x38, 0x5a, 0x2a, 0x96, 0x20, 0xdd, 0x18, 0x74, 0xea, 0x64, - 0x88, 0xc9, 0xab, 0x01, 0x61, 0x1e, 0xda, 0x81, 0x95, 0xee, 0x75, 0xdb, 0xb2, 0x0d, 0xab, 0xc7, - 0xa1, 0x56, 0x71, 0x92, 0xef, 0x6b, 0xbd, 0xe2, 0x1b, 0x19, 0x32, 0xe3, 0x61, 0xe6, 0x50, 0x9b, - 0x11, 0x74, 0x08, 0x49, 0x67, 0xd0, 0x31, 0x6e, 0xc8, 0x90, 0x0f, 0xa7, 0x0e, 0x76, 0xcb, 0x91, - 0x1b, 0xf0, 0xdd, 0x96, 0x1b, 0x83, 0xce, 0xad, 0xd5, 0xad, 0x93, 0xe1, 0x51, 0xec, 0xfe, 0xd3, - 0x9e, 0x84, 0x13, 0x0e, 0x07, 0x41, 0x87, 0x10, 0x27, 0x23, 0xe9, 0x5c, 0x57, 0xea, 0xe0, 0xe7, - 0xf2, 0xec, 0xe5, 0x95, 0x67, 0x7c, 0x62, 0xff, 0x4c, 0xf1, 0x02, 0xd6, 0x47, 0xd5, 0xff, 0xa8, - 0x47, 0xc6, 0xd2, 0x4b, 0x10, 0xbb, 0xa3, 0x1e, 0x11, 0x4a, 0xb6, 0xa3, 0x70, 0xfe, 0x9d, 0xf2, - 0x61, 0x3e, 0x33, 0x61, 0x73, 0x69, 0xd2, 0xe6, 0x6b, 0x19, 0x10, 0x27, 0xec, 0xf9, 0xe0, 0xc2, - 0xea, 0x6f, 0x5f, 0x83, 0x2e, 0x1c, 0xfa, 0x1c, 0x2f, 0xf2, 0x77, 0x0d, 0x9b, 0xa3, 0x6a, 0xc3, - 0xa5, 0x0e, 0x65, 0xed, 0xdb, 0xb1, 0xc7, 0x3f, 0x61, 0xc5, 0x11, 0x25, 0xa1, 0x24, 0x3f, 0xab, - 0x24, 0x38, 0x14, 0xcc, 0x3e, 0xe7, 0xf7, 0x9d, 0x0c, 0xdb, 0xbe, 0xdf, 0x90, 0x4c, 0x78, 0xfe, - 0xeb, 0x5b, 0xd8, 0x84, 0xf7, 0x90, 0xf3, 0x45, 0xfe, 0xd3, 0x90, 0x6a, 0x58, 0xb6, 0x29, 0x7c, - 0x17, 0x33, 0xb0, 0xe6, 0x6f, 0x7d, 0x65, 0xc5, 0x0f, 0x71, 0x48, 0x9e, 0x12, 0xc6, 0xda, 0x26, - 0x41, 0x75, 0x58, 0x17, 0x21, 0x34, 0x5c, 0x7f, 0x5c, 0x88, 0xfd, 0x71, 0x1e, 0xe3, 0x44, 0xdc, - 0xab, 0x12, 0x4e, 0x3b, 0x13, 0xf9, 0xd7, 0x20, 0x1b, 0x82, 0xf9, 0x64, 0x42, 0x7f, 0xf1, 0x39, - 0x34, 0x7f, 0xb2, 0x2a, 0xe1, 0x8c, 0x33, 0xf9, 0x85, 0xfc, 0x0b, 0x1b, 0xcc, 0x32, 0x6d, 0x63, - 0x94, 0x88, 0x40, 0xde, 0x32, 0x07, 0xfc, 0x69, 0x1e, 0xe0, 0x54, 0xa8, 0xab, 0x12, 0x5e, 0x67, - 0x53, 0x39, 0xbf, 0x84, 0x2d, 0xc6, 0xdf, 0x6b, 0x0c, 0x2a, 0x64, 0xc6, 0x38, 0xea, 0x2f, 0x8b, - 0x50, 0x27, 0xf3, 0x5c, 0x95, 0x30, 0x62, 0xb3, 0x29, 0xff, 0x1f, 0xbe, 0xe3, 0x72, 0xc7, 0x8f, - 0x18, 0x48, 0x8e, 0x73, 0xf0, 0x5f, 0x17, 0x81, 0x4f, 0xe5, 0xb4, 0x2a, 0xe1, 0x4d, 0x36, 0x27, - 0xbe, 0x57, 0x90, 0x13, 0xd2, 0x23, 0x04, 0x42, 0x7e, 0x82, 0x33, 0x94, 0x16, 0xcb, 0x9f, 0x8e, - 0x67, 0x55, 0xc2, 0xdb, 0x6c, 0x7e, 0x70, 0x4f, 0x60, 0xcd, 0xb1, 0x6c, 0x33, 0x50, 0x9f, 0xe4, - 0xd8, 0x7b, 0x73, 0x5f, 0x30, 0x4c, 0x59, 0x55, 0xc2, 0x29, 0x27, 0xdc, 0xa2, 0x7f, 0x20, 0x2d, - 0x50, 0x84, 0xc4, 0x15, 0x0e, 0x53, 0x58, 0x0c, 0x13, 0x08, 0x5b, 0x73, 0x22, 0xfb, 0xa3, 0x38, - 0x2c, 0xb3, 0x41, 0xbf, 0xf4, 0x5e, 0x86, 0x04, 0x0f, 0x39, 0x43, 0x08, 0x32, 0x2a, 0xc6, 0x3a, - 0x6e, 0x1a, 0x67, 0x5a, 0x5d, 0xd3, 0xcf, 0xb5, 0xac, 0x84, 0x14, 0xc8, 0x07, 0x35, 0xf5, 0xa2, - 0xa1, 0x1e, 0xb7, 0xd4, 0x13, 0x03, 0xab, 0xcd, 0x86, 0xae, 0x35, 0xd5, 0xac, 0x8c, 0x72, 0xb0, - 0x25, 0xfa, 0x9a, 0x6e, 0x1c, 0xeb, 0x9a, 0xa6, 0x1e, 0xb7, 0x6a, 0xba, 0x96, 0x5d, 0x42, 0x3f, - 0xc0, 0x8e, 0xe8, 0x84, 0x65, 0xa3, 0x55, 0x3b, 0x55, 0xf5, 0xb3, 0x56, 0x76, 0x19, 0x7d, 0x0f, - 0x9b, 0xa2, 0x8d, 0xd5, 0xbf, 0x4f, 0x82, 0x46, 0x2c, 0x82, 0x78, 0x8e, 0x6b, 0x2d, 0x35, 0xe8, - 0xc4, 0x8f, 0xf4, 0xfb, 0x47, 0x45, 0x7e, 0x78, 0x54, 0xe4, 0xcf, 0x8f, 0x8a, 0xfc, 0xf6, 0x49, - 0x91, 0x1e, 0x9e, 0x14, 0xe9, 0xe3, 0x93, 0x22, 0x5d, 0xfe, 0x61, 0x5a, 0xde, 0xf5, 0xa0, 0x53, - 0xee, 0xd2, 0x7e, 0xa5, 0x4b, 0xfb, 0xc4, 0xeb, 0x5c, 0x79, 0xe1, 0xc2, 0xff, 0x57, 0xcd, 0xfe, - 0x25, 0x3b, 0x09, 0xde, 0xf9, 0xfd, 0x4b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xda, 0x9f, 0x99, 0x3e, - 0x42, 0x07, 0x00, 0x00, + proto.RegisterEnum("cometbft.privval.v1beta2.Errors", Errors_name, Errors_value) + proto.RegisterType((*RemoteSignerError)(nil), "cometbft.privval.v1beta2.RemoteSignerError") + proto.RegisterType((*PubKeyRequest)(nil), "cometbft.privval.v1beta2.PubKeyRequest") + proto.RegisterType((*PubKeyResponse)(nil), "cometbft.privval.v1beta2.PubKeyResponse") + proto.RegisterType((*SignVoteRequest)(nil), "cometbft.privval.v1beta2.SignVoteRequest") + proto.RegisterType((*SignedVoteResponse)(nil), "cometbft.privval.v1beta2.SignedVoteResponse") + proto.RegisterType((*SignProposalRequest)(nil), "cometbft.privval.v1beta2.SignProposalRequest") + proto.RegisterType((*SignedProposalResponse)(nil), "cometbft.privval.v1beta2.SignedProposalResponse") + proto.RegisterType((*PingRequest)(nil), "cometbft.privval.v1beta2.PingRequest") + proto.RegisterType((*PingResponse)(nil), "cometbft.privval.v1beta2.PingResponse") + proto.RegisterType((*Message)(nil), "cometbft.privval.v1beta2.Message") +} + +func init() { + proto.RegisterFile("cometbft/privval/v1beta2/types.proto", fileDescriptor_7eb66e8513d3d538) +} + +var fileDescriptor_7eb66e8513d3d538 = []byte{ + // 773 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcb, 0x4e, 0xdb, 0x4c, + 0x14, 0xb6, 0x21, 0x17, 0x38, 0x21, 0x21, 0x0c, 0xfc, 0x10, 0xf8, 0x45, 0x7e, 0x14, 0xfd, 0x6d, + 0x29, 0xb4, 0x76, 0x43, 0x17, 0x55, 0xa5, 0x76, 0xc1, 0xc5, 0x52, 0x52, 0x84, 0x93, 0x4e, 0x42, + 0x69, 0xbb, 0x71, 0x73, 0x99, 0x1a, 0x8b, 0x10, 0x4f, 0x3d, 0x4e, 0xa4, 0xbc, 0x42, 0x57, 0xed, + 0xb6, 0x4f, 0xd0, 0x47, 0x61, 0xc9, 0xb2, 0xab, 0xaa, 0x0a, 0x2f, 0x52, 0x65, 0x3c, 0xb1, 0x93, + 0x40, 0x42, 0x2b, 0xb1, 0x9b, 0x39, 0xe7, 0xcc, 0x77, 0x39, 0x3e, 0x47, 0x86, 0xff, 0x6b, 0xf6, + 0x39, 0x71, 0xab, 0x1f, 0x5d, 0x95, 0x3a, 0x56, 0xbb, 0x5d, 0x69, 0xa8, 0xed, 0x6c, 0x95, 0xb8, + 0x95, 0x1d, 0xd5, 0xed, 0x50, 0xc2, 0x14, 0xea, 0xd8, 0xae, 0x8d, 0x52, 0xfd, 0x2a, 0x45, 0x54, + 0x29, 0xa2, 0x6a, 0x6d, 0xdd, 0x7f, 0x5f, 0x73, 0x3a, 0xd4, 0xb5, 0xd5, 0x76, 0x56, 0x3d, 0x23, + 0x1d, 0xf1, 0x70, 0x20, 0xcd, 0xe1, 0x7a, 0xd9, 0x01, 0xdc, 0xb5, 0x25, 0xd3, 0x36, 0x6d, 0x7e, + 0x54, 0x7b, 0x27, 0x2f, 0x9a, 0xc9, 0xc3, 0x02, 0x26, 0xe7, 0xb6, 0x4b, 0x4a, 0x96, 0xd9, 0x24, + 0x8e, 0xe6, 0x38, 0xb6, 0x83, 0x10, 0x84, 0x6a, 0x76, 0x9d, 0xa4, 0xe4, 0x0d, 0x79, 0x33, 0x8c, + 0xf9, 0x19, 0x6d, 0x40, 0xac, 0x4e, 0x58, 0xcd, 0xb1, 0xa8, 0x6b, 0xd9, 0xcd, 0xd4, 0xd4, 0x86, + 0xbc, 0x39, 0x8b, 0x07, 0x43, 0x99, 0x2d, 0x88, 0x17, 0x5b, 0xd5, 0x43, 0xd2, 0xc1, 0xe4, 0x53, + 0x8b, 0x30, 0x17, 0xad, 0xc2, 0x4c, 0xed, 0xb4, 0x62, 0x35, 0x0d, 0xab, 0xce, 0xa1, 0x66, 0x71, + 0x94, 0xdf, 0xf3, 0xf5, 0xcc, 0x57, 0x19, 0x12, 0xfd, 0x62, 0x46, 0xed, 0x26, 0x23, 0xe8, 0x05, + 0x44, 0x69, 0xab, 0x6a, 0x9c, 0x91, 0x0e, 0x2f, 0x8e, 0xed, 0xac, 0x2b, 0x7e, 0x27, 0x3c, 0xbf, + 0x4a, 0x3b, 0xab, 0x14, 0x5b, 0xd5, 0x86, 0x55, 0x3b, 0x24, 0x9d, 0xbd, 0xd0, 0xc5, 0xcf, 0xff, + 0x24, 0x1c, 0xa1, 0x1c, 0x05, 0xed, 0x42, 0x98, 0xf4, 0xb4, 0x73, 0x61, 0xb1, 0x9d, 0x6d, 0x65, + 0x5c, 0x17, 0x95, 0x6b, 0x76, 0xb1, 0xf7, 0x32, 0xf3, 0x0e, 0xe6, 0x7b, 0xd1, 0x37, 0xb6, 0x4b, + 0xfa, 0x0e, 0xb6, 0x21, 0xd4, 0xb6, 0x5d, 0x22, 0x04, 0xad, 0x04, 0xa0, 0x5e, 0x63, 0xdb, 0x59, + 0x85, 0x57, 0xf3, 0xa2, 0x21, 0xbb, 0x53, 0xc3, 0x76, 0x3f, 0xcb, 0x80, 0x38, 0x63, 0xdd, 0x43, + 0x17, 0x96, 0xb3, 0x7f, 0x04, 0x2f, 0x9c, 0x7a, 0x24, 0x77, 0xe0, 0xd3, 0x82, 0xc5, 0x5e, 0xb4, + 0xe8, 0xd8, 0xd4, 0x66, 0x95, 0x46, 0xdf, 0xeb, 0x33, 0x98, 0xa1, 0x22, 0x24, 0x04, 0xfd, 0x7b, + 0x83, 0x20, 0xff, 0x95, 0x5f, 0x3c, 0xc9, 0xf7, 0x37, 0x19, 0x96, 0x3d, 0xdf, 0x01, 0x9b, 0xf0, + 0xfe, 0xf2, 0xaf, 0xe8, 0x44, 0x0f, 0x02, 0xd2, 0x3b, 0xe8, 0x43, 0x1c, 0x62, 0x45, 0xab, 0x69, + 0x0a, 0xff, 0x99, 0x04, 0xcc, 0x79, 0x57, 0x4f, 0x60, 0xa6, 0x1b, 0x86, 0xe8, 0x11, 0x61, 0xac, + 0x62, 0x12, 0xf4, 0x1a, 0xe6, 0xc5, 0x6c, 0x1a, 0x8e, 0x57, 0x2e, 0x34, 0x3f, 0x18, 0xcf, 0x3b, + 0xb4, 0x0b, 0x39, 0x09, 0xc7, 0xe9, 0xd0, 0x72, 0x94, 0x21, 0x19, 0x40, 0x7a, 0x94, 0xc2, 0xcb, + 0xe6, 0xed, 0x98, 0x5e, 0x7d, 0x4e, 0xc2, 0x09, 0x3a, 0xbc, 0x44, 0x27, 0xb0, 0xc0, 0x2c, 0xb3, + 0x69, 0xf4, 0x66, 0xc5, 0x97, 0x3a, 0xcd, 0x61, 0x1f, 0x8e, 0x87, 0x1d, 0x19, 0xfb, 0x9c, 0x84, + 0xe7, 0xd9, 0xc8, 0x26, 0x7c, 0x80, 0x25, 0xc6, 0x3f, 0x64, 0x1f, 0x5a, 0x48, 0x0e, 0x71, 0xec, + 0x47, 0x93, 0xb1, 0x87, 0xc7, 0x3e, 0x27, 0x61, 0xc4, 0xae, 0x2f, 0x43, 0x0d, 0xfe, 0xe1, 0xd2, + 0xfb, 0x9f, 0xd8, 0x97, 0x1f, 0xe6, 0x14, 0x8f, 0x27, 0x53, 0x8c, 0x4c, 0x73, 0x4e, 0xc2, 0x8b, + 0xec, 0x86, 0x21, 0x6f, 0x40, 0x4a, 0xd8, 0x18, 0xa0, 0x11, 0x56, 0x22, 0x9c, 0xe7, 0xc9, 0x6d, + 0x56, 0x46, 0x27, 0x39, 0x27, 0xe1, 0x65, 0x76, 0xf3, 0x8c, 0xbf, 0x82, 0x39, 0x6a, 0x35, 0x4d, + 0xdf, 0x49, 0x94, 0x33, 0xdc, 0x9b, 0xf0, 0x7d, 0x83, 0x79, 0xcc, 0x49, 0x38, 0x46, 0x83, 0x2b, + 0x3a, 0x82, 0xb8, 0xc0, 0x12, 0x72, 0x67, 0x38, 0xd8, 0xfd, 0xdb, 0xc0, 0x7c, 0x91, 0x73, 0x74, + 0xe0, 0xbe, 0x17, 0x86, 0x69, 0xd6, 0x3a, 0xdf, 0xfa, 0x2e, 0x43, 0x84, 0x2f, 0x05, 0x43, 0x08, + 0x12, 0x1a, 0xc6, 0x05, 0x5c, 0x32, 0x8e, 0xf5, 0x43, 0xbd, 0x70, 0xa2, 0x27, 0x25, 0x94, 0x86, + 0x35, 0x3f, 0xa6, 0xbd, 0x2d, 0x6a, 0xfb, 0x65, 0xed, 0xc0, 0xc0, 0x5a, 0xa9, 0x58, 0xd0, 0x4b, + 0x5a, 0x52, 0x46, 0x29, 0x58, 0x12, 0x79, 0xbd, 0x60, 0xec, 0x17, 0x74, 0x5d, 0xdb, 0x2f, 0xe7, + 0x0b, 0x7a, 0x72, 0x0a, 0xad, 0xc3, 0xaa, 0xc8, 0x04, 0x61, 0xa3, 0x9c, 0x3f, 0xd2, 0x0a, 0xc7, + 0xe5, 0xe4, 0x34, 0x5a, 0x81, 0x45, 0x91, 0xc6, 0xda, 0xee, 0x81, 0x9f, 0x08, 0x0d, 0x20, 0x9e, + 0xe0, 0x7c, 0x59, 0xf3, 0x33, 0xe1, 0xbd, 0xd2, 0x45, 0x37, 0x2d, 0x5f, 0x76, 0xd3, 0xf2, 0xaf, + 0x6e, 0x5a, 0xfe, 0x72, 0x95, 0x96, 0x2e, 0xaf, 0xd2, 0xd2, 0x8f, 0xab, 0xb4, 0xf4, 0xfe, 0xb9, + 0x69, 0xb9, 0xa7, 0xad, 0x6a, 0xaf, 0x13, 0x6a, 0xf0, 0x8b, 0xec, 0x1f, 0x2a, 0xd4, 0x52, 0xc7, + 0xfd, 0x78, 0xab, 0x11, 0xfe, 0x17, 0x7c, 0xfa, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x4c, 0x2e, 0x08, + 0x1c, 0x9b, 0x07, 0x00, 0x00, } func (m *RemoteSignerError) Marshal() (dAtA []byte, err error) { @@ -1872,7 +1886,7 @@ func (m *SignVoteRequest) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Vote == nil { - m.Vote = &types.Vote{} + m.Vote = &v11.Vote{} } if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -2109,7 +2123,7 @@ func (m *SignProposalRequest) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Proposal == nil { - m.Proposal = &types.Proposal{} + m.Proposal = &v11.Proposal{} } if err := m.Proposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err diff --git a/proto/tendermint/rpc/grpc/types.pb.go b/api/cometbft/rpc/grpc/v1beta1/types.pb.go similarity index 81% rename from proto/tendermint/rpc/grpc/types.pb.go rename to api/cometbft/rpc/grpc/v1beta1/types.pb.go index 393c7394764..b93f941f80d 100644 --- a/proto/tendermint/rpc/grpc/types.pb.go +++ b/api/cometbft/rpc/grpc/v1beta1/types.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/rpc/grpc/types.proto +// source: cometbft/rpc/grpc/v1beta1/types.proto -package coregrpc +package v1beta1 import ( context "context" fmt "fmt" - types "github.com/cometbft/cometbft/abci/types" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta1" grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" grpc "google.golang.org/grpc" @@ -28,6 +28,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// PingRequest is a request to confirm that the connection is alive. type RequestPing struct { } @@ -35,7 +36,7 @@ func (m *RequestPing) Reset() { *m = RequestPing{} } func (m *RequestPing) String() string { return proto.CompactTextString(m) } func (*RequestPing) ProtoMessage() {} func (*RequestPing) Descriptor() ([]byte, []int) { - return fileDescriptor_0ffff5682c662b95, []int{0} + return fileDescriptor_2bd787770c28cdca, []int{0} } func (m *RequestPing) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -64,6 +65,7 @@ func (m *RequestPing) XXX_DiscardUnknown() { var xxx_messageInfo_RequestPing proto.InternalMessageInfo +// RequestBroadcastTx is a request to broadcast the transaction. type RequestBroadcastTx struct { Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` } @@ -72,7 +74,7 @@ func (m *RequestBroadcastTx) Reset() { *m = RequestBroadcastTx{} } func (m *RequestBroadcastTx) String() string { return proto.CompactTextString(m) } func (*RequestBroadcastTx) ProtoMessage() {} func (*RequestBroadcastTx) Descriptor() ([]byte, []int) { - return fileDescriptor_0ffff5682c662b95, []int{1} + return fileDescriptor_2bd787770c28cdca, []int{1} } func (m *RequestBroadcastTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -108,6 +110,7 @@ func (m *RequestBroadcastTx) GetTx() []byte { return nil } +// PingResponse is a response to confirm that the connection is alive. type ResponsePing struct { } @@ -115,7 +118,7 @@ func (m *ResponsePing) Reset() { *m = ResponsePing{} } func (m *ResponsePing) String() string { return proto.CompactTextString(m) } func (*ResponsePing) ProtoMessage() {} func (*ResponsePing) Descriptor() ([]byte, []int) { - return fileDescriptor_0ffff5682c662b95, []int{2} + return fileDescriptor_2bd787770c28cdca, []int{2} } func (m *ResponsePing) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -144,16 +147,17 @@ func (m *ResponsePing) XXX_DiscardUnknown() { var xxx_messageInfo_ResponsePing proto.InternalMessageInfo +// ResponseBroadcastTx is a response of broadcasting the transaction. type ResponseBroadcastTx struct { - CheckTx *types.ResponseCheckTx `protobuf:"bytes,1,opt,name=check_tx,json=checkTx,proto3" json:"check_tx,omitempty"` - TxResult *types.ExecTxResult `protobuf:"bytes,2,opt,name=tx_result,json=txResult,proto3" json:"tx_result,omitempty"` + CheckTx *v1beta1.ResponseCheckTx `protobuf:"bytes,1,opt,name=check_tx,json=checkTx,proto3" json:"check_tx,omitempty"` + DeliverTx *v1beta1.ResponseDeliverTx `protobuf:"bytes,2,opt,name=deliver_tx,json=deliverTx,proto3" json:"deliver_tx,omitempty"` } func (m *ResponseBroadcastTx) Reset() { *m = ResponseBroadcastTx{} } func (m *ResponseBroadcastTx) String() string { return proto.CompactTextString(m) } func (*ResponseBroadcastTx) ProtoMessage() {} func (*ResponseBroadcastTx) Descriptor() ([]byte, []int) { - return fileDescriptor_0ffff5682c662b95, []int{3} + return fileDescriptor_2bd787770c28cdca, []int{3} } func (m *ResponseBroadcastTx) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -182,52 +186,54 @@ func (m *ResponseBroadcastTx) XXX_DiscardUnknown() { var xxx_messageInfo_ResponseBroadcastTx proto.InternalMessageInfo -func (m *ResponseBroadcastTx) GetCheckTx() *types.ResponseCheckTx { +func (m *ResponseBroadcastTx) GetCheckTx() *v1beta1.ResponseCheckTx { if m != nil { return m.CheckTx } return nil } -func (m *ResponseBroadcastTx) GetTxResult() *types.ExecTxResult { +func (m *ResponseBroadcastTx) GetDeliverTx() *v1beta1.ResponseDeliverTx { if m != nil { - return m.TxResult + return m.DeliverTx } return nil } func init() { - proto.RegisterType((*RequestPing)(nil), "tendermint.rpc.grpc.RequestPing") - proto.RegisterType((*RequestBroadcastTx)(nil), "tendermint.rpc.grpc.RequestBroadcastTx") - proto.RegisterType((*ResponsePing)(nil), "tendermint.rpc.grpc.ResponsePing") - proto.RegisterType((*ResponseBroadcastTx)(nil), "tendermint.rpc.grpc.ResponseBroadcastTx") -} - -func init() { proto.RegisterFile("tendermint/rpc/grpc/types.proto", fileDescriptor_0ffff5682c662b95) } - -var fileDescriptor_0ffff5682c662b95 = []byte{ - // 324 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x31, 0x4f, 0x02, 0x31, - 0x14, 0xc7, 0x29, 0x31, 0x8a, 0x05, 0x19, 0xca, 0x42, 0x30, 0x9e, 0x48, 0x4c, 0x64, 0x2a, 0x09, - 0x6e, 0x32, 0x89, 0x31, 0xd1, 0xb8, 0x90, 0x86, 0xc9, 0x05, 0xb9, 0xf2, 0x84, 0x8b, 0x72, 0x3d, - 0xdb, 0x47, 0x52, 0xbf, 0x84, 0xf1, 0x0b, 0xb9, 0x3b, 0x32, 0x3a, 0x1a, 0xf8, 0x22, 0xa6, 0x27, - 0x27, 0x35, 0x46, 0x96, 0xe6, 0xdf, 0xe6, 0xff, 0x7b, 0xfd, 0xbf, 0xd7, 0xd2, 0x43, 0x84, 0x78, - 0x04, 0x7a, 0x1a, 0xc5, 0xd8, 0xd2, 0x89, 0x6c, 0x8d, 0xdd, 0x82, 0xcf, 0x09, 0x18, 0x9e, 0x68, - 0x85, 0x8a, 0x55, 0xd6, 0x06, 0xae, 0x13, 0xc9, 0x9d, 0xa1, 0xb6, 0xef, 0x51, 0xc3, 0x50, 0x46, - 0x3e, 0xd1, 0xd8, 0xa3, 0x45, 0x01, 0x4f, 0x33, 0x30, 0xd8, 0x8b, 0xe2, 0x71, 0xe3, 0x98, 0xb2, - 0xd5, 0xb6, 0xab, 0xd5, 0x70, 0x24, 0x87, 0x06, 0xfb, 0x96, 0x95, 0x69, 0x1e, 0x6d, 0x95, 0xd4, - 0x49, 0xb3, 0x24, 0xf2, 0x68, 0x1b, 0x65, 0x5a, 0x12, 0x60, 0x12, 0x15, 0x1b, 0x48, 0xa9, 0x17, - 0x42, 0x2b, 0xd9, 0x81, 0xcf, 0x75, 0x68, 0x41, 0x4e, 0x40, 0x3e, 0x0c, 0x56, 0x74, 0xb1, 0x5d, - 0xe7, 0x5e, 0x42, 0x17, 0x86, 0x67, 0xdc, 0x85, 0x33, 0xf6, 0xad, 0xd8, 0x91, 0xdf, 0x82, 0x9d, - 0xd1, 0x5d, 0xb4, 0x03, 0x0d, 0x66, 0xf6, 0x88, 0xd5, 0x7c, 0x4a, 0x1f, 0xfc, 0xa1, 0x2f, 0x2d, - 0xc8, 0xbe, 0x15, 0xa9, 0x49, 0x14, 0x70, 0xa5, 0xda, 0x6f, 0x84, 0x96, 0x7e, 0x82, 0x9c, 0xf7, - 0xae, 0xd9, 0x0d, 0xdd, 0x72, 0x49, 0xd9, 0xaf, 0xfb, 0xb3, 0x09, 0x71, 0x6f, 0x02, 0xb5, 0xa3, - 0x7f, 0x1c, 0xeb, 0x76, 0xd9, 0x1d, 0x2d, 0xfa, 0x5d, 0x9e, 0x6c, 0xaa, 0xe9, 0x19, 0x6b, 0xcd, - 0x8d, 0xa5, 0x3d, 0x67, 0xf7, 0xea, 0x7d, 0x11, 0x90, 0xf9, 0x22, 0x20, 0x9f, 0x8b, 0x80, 0xbc, - 0x2e, 0x83, 0xdc, 0x7c, 0x19, 0xe4, 0x3e, 0x96, 0x41, 0xee, 0x96, 0x8f, 0x23, 0x9c, 0xcc, 0x42, - 0x2e, 0xd5, 0xb4, 0x25, 0xd5, 0x14, 0x30, 0xbc, 0xc7, 0xb5, 0xc8, 0x3e, 0x45, 0x47, 0x2a, 0x0d, - 0x4e, 0x84, 0xdb, 0xe9, 0x33, 0x9f, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x0c, 0xca, 0xdb, 0xe7, - 0x3b, 0x02, 0x00, 0x00, + proto.RegisterType((*RequestPing)(nil), "cometbft.rpc.grpc.v1beta1.RequestPing") + proto.RegisterType((*RequestBroadcastTx)(nil), "cometbft.rpc.grpc.v1beta1.RequestBroadcastTx") + proto.RegisterType((*ResponsePing)(nil), "cometbft.rpc.grpc.v1beta1.ResponsePing") + proto.RegisterType((*ResponseBroadcastTx)(nil), "cometbft.rpc.grpc.v1beta1.ResponseBroadcastTx") +} + +func init() { + proto.RegisterFile("cometbft/rpc/grpc/v1beta1/types.proto", fileDescriptor_2bd787770c28cdca) +} + +var fileDescriptor_2bd787770c28cdca = []byte{ + // 325 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x2a, 0x48, 0xd6, 0x4f, 0x07, 0x11, 0x65, 0x86, 0x49, 0xa9, + 0x25, 0x89, 0x86, 0xfa, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, + 0x92, 0x30, 0x65, 0x7a, 0x45, 0x05, 0xc9, 0x7a, 0x20, 0x65, 0x7a, 0x50, 0x65, 0x52, 0x8a, 0x70, + 0x13, 0x12, 0x93, 0x92, 0x33, 0xb1, 0xe9, 0x56, 0xe2, 0xe5, 0xe2, 0x0e, 0x4a, 0x2d, 0x2c, 0x4d, + 0x2d, 0x2e, 0x09, 0xc8, 0xcc, 0x4b, 0x57, 0x52, 0xe1, 0x12, 0x82, 0x72, 0x9d, 0x8a, 0xf2, 0x13, + 0x53, 0x92, 0x13, 0x8b, 0x4b, 0x42, 0x2a, 0x84, 0xf8, 0xb8, 0x98, 0x4a, 0x2a, 0x24, 0x18, 0x15, + 0x18, 0x35, 0x78, 0x82, 0x98, 0x4a, 0x2a, 0x94, 0xf8, 0xb8, 0x78, 0x82, 0x52, 0x8b, 0x0b, 0xf2, + 0xf3, 0x8a, 0x53, 0xc1, 0xba, 0x16, 0x32, 0x72, 0x09, 0xc3, 0x04, 0x90, 0xf5, 0x39, 0x72, 0x71, + 0x24, 0x67, 0xa4, 0x26, 0x67, 0xc7, 0x43, 0x75, 0x73, 0x1b, 0xa9, 0xe9, 0xc1, 0x5d, 0x0b, 0x72, + 0x12, 0xcc, 0xa5, 0x7a, 0x30, 0xdd, 0xce, 0x20, 0xe5, 0x21, 0x15, 0x41, 0xec, 0xc9, 0x10, 0x86, + 0x90, 0x3b, 0x17, 0x57, 0x4a, 0x6a, 0x4e, 0x66, 0x59, 0x6a, 0x11, 0xc8, 0x10, 0x26, 0xb0, 0x21, + 0x1a, 0x04, 0x0c, 0x71, 0x81, 0x68, 0x08, 0xa9, 0x08, 0xe2, 0x4c, 0x81, 0x31, 0x8d, 0xae, 0x32, + 0x72, 0xf1, 0xc0, 0xdd, 0xe6, 0x18, 0xe0, 0x29, 0x14, 0xce, 0xc5, 0x02, 0x72, 0xbc, 0x10, 0x92, + 0x93, 0xd0, 0x03, 0x50, 0x0f, 0x29, 0x68, 0xa4, 0xd4, 0xf1, 0xaa, 0x43, 0x84, 0x86, 0x50, 0x0e, + 0x17, 0x37, 0x72, 0x20, 0xe8, 0x12, 0x36, 0x1f, 0x49, 0xb9, 0x94, 0x1e, 0x11, 0xd6, 0x20, 0xa9, + 0x77, 0x0a, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, + 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xab, 0xf4, 0xcc, + 0x92, 0x8c, 0xd2, 0x24, 0x90, 0x79, 0xfa, 0xf0, 0x84, 0x80, 0x48, 0x11, 0x05, 0x99, 0xfa, 0x38, + 0x13, 0x58, 0x12, 0x1b, 0x38, 0x75, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xc7, 0x56, 0x2e, + 0x4a, 0x84, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -242,7 +248,9 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type BroadcastAPIClient interface { + // Ping the connection. Ping(ctx context.Context, in *RequestPing, opts ...grpc.CallOption) (*ResponsePing, error) + // BroadcastTx broadcasts the transaction. BroadcastTx(ctx context.Context, in *RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) } @@ -256,7 +264,7 @@ func NewBroadcastAPIClient(cc grpc1.ClientConn) BroadcastAPIClient { func (c *broadcastAPIClient) Ping(ctx context.Context, in *RequestPing, opts ...grpc.CallOption) (*ResponsePing, error) { out := new(ResponsePing) - err := c.cc.Invoke(ctx, "/tendermint.rpc.grpc.BroadcastAPI/Ping", in, out, opts...) + err := c.cc.Invoke(ctx, "/cometbft.rpc.grpc.v1beta1.BroadcastAPI/Ping", in, out, opts...) if err != nil { return nil, err } @@ -265,7 +273,7 @@ func (c *broadcastAPIClient) Ping(ctx context.Context, in *RequestPing, opts ... func (c *broadcastAPIClient) BroadcastTx(ctx context.Context, in *RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) { out := new(ResponseBroadcastTx) - err := c.cc.Invoke(ctx, "/tendermint.rpc.grpc.BroadcastAPI/BroadcastTx", in, out, opts...) + err := c.cc.Invoke(ctx, "/cometbft.rpc.grpc.v1beta1.BroadcastAPI/BroadcastTx", in, out, opts...) if err != nil { return nil, err } @@ -274,7 +282,9 @@ func (c *broadcastAPIClient) BroadcastTx(ctx context.Context, in *RequestBroadca // BroadcastAPIServer is the server API for BroadcastAPI service. type BroadcastAPIServer interface { + // Ping the connection. Ping(context.Context, *RequestPing) (*ResponsePing, error) + // BroadcastTx broadcasts the transaction. BroadcastTx(context.Context, *RequestBroadcastTx) (*ResponseBroadcastTx, error) } @@ -303,7 +313,7 @@ func _BroadcastAPI_Ping_Handler(srv interface{}, ctx context.Context, dec func(i } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tendermint.rpc.grpc.BroadcastAPI/Ping", + FullMethod: "/cometbft.rpc.grpc.v1beta1.BroadcastAPI/Ping", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BroadcastAPIServer).Ping(ctx, req.(*RequestPing)) @@ -321,7 +331,7 @@ func _BroadcastAPI_BroadcastTx_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tendermint.rpc.grpc.BroadcastAPI/BroadcastTx", + FullMethod: "/cometbft.rpc.grpc.v1beta1.BroadcastAPI/BroadcastTx", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(BroadcastAPIServer).BroadcastTx(ctx, req.(*RequestBroadcastTx)) @@ -330,7 +340,7 @@ func _BroadcastAPI_BroadcastTx_Handler(srv interface{}, ctx context.Context, dec } var _BroadcastAPI_serviceDesc = grpc.ServiceDesc{ - ServiceName: "tendermint.rpc.grpc.BroadcastAPI", + ServiceName: "cometbft.rpc.grpc.v1beta1.BroadcastAPI", HandlerType: (*BroadcastAPIServer)(nil), Methods: []grpc.MethodDesc{ { @@ -343,7 +353,7 @@ var _BroadcastAPI_serviceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "tendermint/rpc/grpc/types.proto", + Metadata: "cometbft/rpc/grpc/v1beta1/types.proto", } func (m *RequestPing) Marshal() (dAtA []byte, err error) { @@ -442,9 +452,9 @@ func (m *ResponseBroadcastTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.TxResult != nil { + if m.DeliverTx != nil { { - size, err := m.TxResult.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.DeliverTx.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -521,8 +531,8 @@ func (m *ResponseBroadcastTx) Size() (n int) { l = m.CheckTx.Size() n += 1 + l + sovTypes(uint64(l)) } - if m.TxResult != nil { - l = m.TxResult.Size() + if m.DeliverTx != nil { + l = m.DeliverTx.Size() n += 1 + l + sovTypes(uint64(l)) } return n @@ -777,7 +787,7 @@ func (m *ResponseBroadcastTx) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.CheckTx == nil { - m.CheckTx = &types.ResponseCheckTx{} + m.CheckTx = &v1beta1.ResponseCheckTx{} } if err := m.CheckTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -785,7 +795,7 @@ func (m *ResponseBroadcastTx) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TxResult", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -812,10 +822,10 @@ func (m *ResponseBroadcastTx) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.TxResult == nil { - m.TxResult = &types.ExecTxResult{} + if m.DeliverTx == nil { + m.DeliverTx = &v1beta1.ResponseDeliverTx{} } - if err := m.TxResult.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.DeliverTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/api/cometbft/rpc/grpc/v1beta2/types.pb.go b/api/cometbft/rpc/grpc/v1beta2/types.pb.go new file mode 100644 index 00000000000..2e1f9331b58 --- /dev/null +++ b/api/cometbft/rpc/grpc/v1beta2/types.pb.go @@ -0,0 +1,522 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/rpc/grpc/v1beta2/types.proto + +package v1beta2 + +import ( + context "context" + fmt "fmt" + v1beta2 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta2" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/rpc/grpc/v1beta1" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ResponseBroadcastTx is a response of broadcasting the transaction. +type ResponseBroadcastTx struct { + CheckTx *v1beta2.ResponseCheckTx `protobuf:"bytes,1,opt,name=check_tx,json=checkTx,proto3" json:"check_tx,omitempty"` + DeliverTx *v1beta2.ResponseDeliverTx `protobuf:"bytes,2,opt,name=deliver_tx,json=deliverTx,proto3" json:"deliver_tx,omitempty"` +} + +func (m *ResponseBroadcastTx) Reset() { *m = ResponseBroadcastTx{} } +func (m *ResponseBroadcastTx) String() string { return proto.CompactTextString(m) } +func (*ResponseBroadcastTx) ProtoMessage() {} +func (*ResponseBroadcastTx) Descriptor() ([]byte, []int) { + return fileDescriptor_cc9b252f8c29b3ef, []int{0} +} +func (m *ResponseBroadcastTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseBroadcastTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseBroadcastTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseBroadcastTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseBroadcastTx.Merge(m, src) +} +func (m *ResponseBroadcastTx) XXX_Size() int { + return m.Size() +} +func (m *ResponseBroadcastTx) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseBroadcastTx.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseBroadcastTx proto.InternalMessageInfo + +func (m *ResponseBroadcastTx) GetCheckTx() *v1beta2.ResponseCheckTx { + if m != nil { + return m.CheckTx + } + return nil +} + +func (m *ResponseBroadcastTx) GetDeliverTx() *v1beta2.ResponseDeliverTx { + if m != nil { + return m.DeliverTx + } + return nil +} + +func init() { + proto.RegisterType((*ResponseBroadcastTx)(nil), "cometbft.rpc.grpc.v1beta2.ResponseBroadcastTx") +} + +func init() { + proto.RegisterFile("cometbft/rpc/grpc/v1beta2/types.proto", fileDescriptor_cc9b252f8c29b3ef) +} + +var fileDescriptor_cc9b252f8c29b3ef = []byte{ + // 303 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x2a, 0x48, 0xd6, 0x4f, 0x07, 0x11, 0x65, 0x86, 0x49, 0xa9, + 0x25, 0x89, 0x46, 0xfa, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, + 0x92, 0x30, 0x65, 0x7a, 0x45, 0x05, 0xc9, 0x7a, 0x20, 0x65, 0x7a, 0x50, 0x65, 0x52, 0x38, 0x4d, + 0x30, 0x44, 0x36, 0x41, 0x4a, 0x11, 0xae, 0x2c, 0x31, 0x29, 0x39, 0x13, 0x9b, 0x25, 0x4a, 0x0b, + 0x19, 0xb9, 0x84, 0x83, 0x52, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x9d, 0x8a, 0xf2, 0x13, 0x53, + 0x92, 0x13, 0x8b, 0x4b, 0x42, 0x2a, 0x84, 0x1c, 0xb9, 0x38, 0x92, 0x33, 0x52, 0x93, 0xb3, 0xe3, + 0x4b, 0x2a, 0x24, 0x18, 0x15, 0x18, 0x35, 0xb8, 0x8d, 0xd4, 0xf4, 0xe0, 0xee, 0x01, 0x99, 0x06, + 0x73, 0x8b, 0x1e, 0x4c, 0xb7, 0x33, 0x48, 0x79, 0x48, 0x45, 0x10, 0x7b, 0x32, 0x84, 0x21, 0xe4, + 0xce, 0xc5, 0x95, 0x92, 0x9a, 0x93, 0x59, 0x96, 0x5a, 0x04, 0x32, 0x84, 0x09, 0x6c, 0x88, 0x06, + 0x01, 0x43, 0x5c, 0x20, 0x1a, 0x42, 0x2a, 0x82, 0x38, 0x53, 0x60, 0x4c, 0xa3, 0xab, 0x8c, 0x5c, + 0x3c, 0x70, 0xb7, 0x39, 0x06, 0x78, 0x0a, 0x85, 0x73, 0xb1, 0x04, 0x64, 0xe6, 0xa5, 0x0b, 0x21, + 0x39, 0x09, 0x2d, 0x88, 0x0c, 0xf5, 0x82, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x40, 0xea, 0xa4, + 0xd4, 0xf1, 0xaa, 0x83, 0xd8, 0x0c, 0x36, 0x30, 0x87, 0x8b, 0x1b, 0x39, 0x10, 0x74, 0x09, 0x9b, + 0x8f, 0xa4, 0x5c, 0x4a, 0x0f, 0xa7, 0x72, 0x84, 0x07, 0x91, 0xd4, 0x3b, 0x85, 0x9c, 0x78, 0x24, + 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, + 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x55, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x12, 0xc8, + 0x3c, 0x7d, 0x78, 0x1c, 0x22, 0x22, 0xb3, 0x20, 0x53, 0x1f, 0x67, 0x12, 0x4a, 0x62, 0x03, 0x47, + 0xac, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x30, 0x2b, 0x71, 0x66, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// BroadcastAPIClient is the client API for BroadcastAPI service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type BroadcastAPIClient interface { + // Ping the connection. + Ping(ctx context.Context, in *v1beta1.RequestPing, opts ...grpc.CallOption) (*v1beta1.ResponsePing, error) + // BroadcastTx broadcasts the transaction. + BroadcastTx(ctx context.Context, in *v1beta1.RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) +} + +type broadcastAPIClient struct { + cc grpc1.ClientConn +} + +func NewBroadcastAPIClient(cc grpc1.ClientConn) BroadcastAPIClient { + return &broadcastAPIClient{cc} +} + +func (c *broadcastAPIClient) Ping(ctx context.Context, in *v1beta1.RequestPing, opts ...grpc.CallOption) (*v1beta1.ResponsePing, error) { + out := new(v1beta1.ResponsePing) + err := c.cc.Invoke(ctx, "/cometbft.rpc.grpc.v1beta2.BroadcastAPI/Ping", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *broadcastAPIClient) BroadcastTx(ctx context.Context, in *v1beta1.RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) { + out := new(ResponseBroadcastTx) + err := c.cc.Invoke(ctx, "/cometbft.rpc.grpc.v1beta2.BroadcastAPI/BroadcastTx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// BroadcastAPIServer is the server API for BroadcastAPI service. +type BroadcastAPIServer interface { + // Ping the connection. + Ping(context.Context, *v1beta1.RequestPing) (*v1beta1.ResponsePing, error) + // BroadcastTx broadcasts the transaction. + BroadcastTx(context.Context, *v1beta1.RequestBroadcastTx) (*ResponseBroadcastTx, error) +} + +// UnimplementedBroadcastAPIServer can be embedded to have forward compatible implementations. +type UnimplementedBroadcastAPIServer struct { +} + +func (*UnimplementedBroadcastAPIServer) Ping(ctx context.Context, req *v1beta1.RequestPing) (*v1beta1.ResponsePing, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (*UnimplementedBroadcastAPIServer) BroadcastTx(ctx context.Context, req *v1beta1.RequestBroadcastTx) (*ResponseBroadcastTx, error) { + return nil, status.Errorf(codes.Unimplemented, "method BroadcastTx not implemented") +} + +func RegisterBroadcastAPIServer(s grpc1.Server, srv BroadcastAPIServer) { + s.RegisterService(&_BroadcastAPI_serviceDesc, srv) +} + +func _BroadcastAPI_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestPing) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BroadcastAPIServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.rpc.grpc.v1beta2.BroadcastAPI/Ping", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BroadcastAPIServer).Ping(ctx, req.(*v1beta1.RequestPing)) + } + return interceptor(ctx, in, info, handler) +} + +func _BroadcastAPI_BroadcastTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestBroadcastTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BroadcastAPIServer).BroadcastTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.rpc.grpc.v1beta2.BroadcastAPI/BroadcastTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BroadcastAPIServer).BroadcastTx(ctx, req.(*v1beta1.RequestBroadcastTx)) + } + return interceptor(ctx, in, info, handler) +} + +var _BroadcastAPI_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.rpc.grpc.v1beta2.BroadcastAPI", + HandlerType: (*BroadcastAPIServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _BroadcastAPI_Ping_Handler, + }, + { + MethodName: "BroadcastTx", + Handler: _BroadcastAPI_BroadcastTx_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/rpc/grpc/v1beta2/types.proto", +} + +func (m *ResponseBroadcastTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseBroadcastTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseBroadcastTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.DeliverTx != nil { + { + size, err := m.DeliverTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.CheckTx != nil { + { + size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ResponseBroadcastTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.DeliverTx != nil { + l = m.DeliverTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ResponseBroadcastTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseBroadcastTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseBroadcastTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CheckTx == nil { + m.CheckTx = &v1beta2.ResponseCheckTx{} + } + if err := m.CheckTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DeliverTx == nil { + m.DeliverTx = &v1beta2.ResponseDeliverTx{} + } + if err := m.DeliverTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/rpc/grpc/v1beta3/types.pb.go b/api/cometbft/rpc/grpc/v1beta3/types.pb.go new file mode 100644 index 00000000000..17aefdacfe1 --- /dev/null +++ b/api/cometbft/rpc/grpc/v1beta3/types.pb.go @@ -0,0 +1,523 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/rpc/grpc/v1beta3/types.proto + +package v1beta3 + +import ( + context "context" + fmt "fmt" + v1beta3 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta3" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/rpc/grpc/v1beta1" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ResponseBroadcastTx is a response of broadcasting the transaction. +type ResponseBroadcastTx struct { + CheckTx *v1beta3.ResponseCheckTx `protobuf:"bytes,1,opt,name=check_tx,json=checkTx,proto3" json:"check_tx,omitempty"` + TxResult *v1beta3.ExecTxResult `protobuf:"bytes,2,opt,name=tx_result,json=txResult,proto3" json:"tx_result,omitempty"` +} + +func (m *ResponseBroadcastTx) Reset() { *m = ResponseBroadcastTx{} } +func (m *ResponseBroadcastTx) String() string { return proto.CompactTextString(m) } +func (*ResponseBroadcastTx) ProtoMessage() {} +func (*ResponseBroadcastTx) Descriptor() ([]byte, []int) { + return fileDescriptor_e521bcdb5edbf680, []int{0} +} +func (m *ResponseBroadcastTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseBroadcastTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseBroadcastTx.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseBroadcastTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseBroadcastTx.Merge(m, src) +} +func (m *ResponseBroadcastTx) XXX_Size() int { + return m.Size() +} +func (m *ResponseBroadcastTx) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseBroadcastTx.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseBroadcastTx proto.InternalMessageInfo + +func (m *ResponseBroadcastTx) GetCheckTx() *v1beta3.ResponseCheckTx { + if m != nil { + return m.CheckTx + } + return nil +} + +func (m *ResponseBroadcastTx) GetTxResult() *v1beta3.ExecTxResult { + if m != nil { + return m.TxResult + } + return nil +} + +func init() { + proto.RegisterType((*ResponseBroadcastTx)(nil), "cometbft.rpc.grpc.v1beta3.ResponseBroadcastTx") +} + +func init() { + proto.RegisterFile("cometbft/rpc/grpc/v1beta3/types.proto", fileDescriptor_e521bcdb5edbf680) +} + +var fileDescriptor_e521bcdb5edbf680 = []byte{ + // 308 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x2a, 0x48, 0xd6, 0x4f, 0x07, 0x11, 0x65, 0x86, 0x49, 0xa9, + 0x25, 0x89, 0xc6, 0xfa, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, + 0x92, 0x30, 0x65, 0x7a, 0x45, 0x05, 0xc9, 0x7a, 0x20, 0x65, 0x7a, 0x50, 0x65, 0x52, 0x38, 0x4d, + 0x30, 0x44, 0x36, 0x41, 0x4a, 0x11, 0xae, 0x2c, 0x31, 0x29, 0x39, 0x13, 0x9b, 0x25, 0x4a, 0xb3, + 0x18, 0xb9, 0x84, 0x83, 0x52, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x9d, 0x8a, 0xf2, 0x13, 0x53, + 0x92, 0x13, 0x8b, 0x4b, 0x42, 0x2a, 0x84, 0x1c, 0xb9, 0x38, 0x92, 0x33, 0x52, 0x93, 0xb3, 0xe3, + 0x4b, 0x2a, 0x24, 0x18, 0x15, 0x18, 0x35, 0xb8, 0x8d, 0xd4, 0xf4, 0xe0, 0xee, 0x01, 0x99, 0x06, + 0x73, 0x8b, 0x1e, 0x4c, 0xb7, 0x33, 0x48, 0x79, 0x48, 0x45, 0x10, 0x7b, 0x32, 0x84, 0x21, 0xe4, + 0xc0, 0xc5, 0x59, 0x52, 0x11, 0x5f, 0x94, 0x5a, 0x5c, 0x9a, 0x53, 0x22, 0xc1, 0x04, 0x36, 0x43, + 0x19, 0x87, 0x19, 0xae, 0x15, 0xa9, 0xc9, 0x21, 0x15, 0x41, 0x60, 0xa5, 0x41, 0x1c, 0x25, 0x50, + 0x96, 0xd1, 0x55, 0x46, 0x2e, 0x1e, 0xb8, 0xa3, 0x1c, 0x03, 0x3c, 0x85, 0xc2, 0xb9, 0x58, 0x02, + 0x32, 0xf3, 0xd2, 0x85, 0x90, 0xdc, 0x82, 0x16, 0x36, 0x86, 0x7a, 0x41, 0xa9, 0x85, 0xa5, 0xa9, + 0xc5, 0x25, 0x20, 0x75, 0x52, 0xea, 0x78, 0xd5, 0x41, 0xdc, 0x0d, 0x36, 0x30, 0x87, 0x8b, 0x1b, + 0xd9, 0xf7, 0xba, 0x84, 0xcd, 0x47, 0x52, 0x2e, 0xa5, 0x87, 0x53, 0x39, 0x22, 0x78, 0x90, 0xd4, + 0x3b, 0x85, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, + 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x55, 0x7a, 0x66, + 0x49, 0x46, 0x69, 0x12, 0xc8, 0x3c, 0x7d, 0x78, 0xe4, 0x21, 0x62, 0xb1, 0x20, 0x53, 0x1f, 0x67, + 0xda, 0x49, 0x62, 0x03, 0xc7, 0xa8, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xc2, 0xcf, 0xef, 0x1f, + 0x5f, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// BroadcastAPIClient is the client API for BroadcastAPI service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type BroadcastAPIClient interface { + // Ping the connection. + Ping(ctx context.Context, in *v1beta1.RequestPing, opts ...grpc.CallOption) (*v1beta1.ResponsePing, error) + // BroadcastTx broadcasts a transaction. + BroadcastTx(ctx context.Context, in *v1beta1.RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) +} + +type broadcastAPIClient struct { + cc grpc1.ClientConn +} + +func NewBroadcastAPIClient(cc grpc1.ClientConn) BroadcastAPIClient { + return &broadcastAPIClient{cc} +} + +func (c *broadcastAPIClient) Ping(ctx context.Context, in *v1beta1.RequestPing, opts ...grpc.CallOption) (*v1beta1.ResponsePing, error) { + out := new(v1beta1.ResponsePing) + err := c.cc.Invoke(ctx, "/cometbft.rpc.grpc.v1beta3.BroadcastAPI/Ping", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *broadcastAPIClient) BroadcastTx(ctx context.Context, in *v1beta1.RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) { + out := new(ResponseBroadcastTx) + err := c.cc.Invoke(ctx, "/cometbft.rpc.grpc.v1beta3.BroadcastAPI/BroadcastTx", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// BroadcastAPIServer is the server API for BroadcastAPI service. +type BroadcastAPIServer interface { + // Ping the connection. + Ping(context.Context, *v1beta1.RequestPing) (*v1beta1.ResponsePing, error) + // BroadcastTx broadcasts a transaction. + BroadcastTx(context.Context, *v1beta1.RequestBroadcastTx) (*ResponseBroadcastTx, error) +} + +// UnimplementedBroadcastAPIServer can be embedded to have forward compatible implementations. +type UnimplementedBroadcastAPIServer struct { +} + +func (*UnimplementedBroadcastAPIServer) Ping(ctx context.Context, req *v1beta1.RequestPing) (*v1beta1.ResponsePing, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (*UnimplementedBroadcastAPIServer) BroadcastTx(ctx context.Context, req *v1beta1.RequestBroadcastTx) (*ResponseBroadcastTx, error) { + return nil, status.Errorf(codes.Unimplemented, "method BroadcastTx not implemented") +} + +func RegisterBroadcastAPIServer(s grpc1.Server, srv BroadcastAPIServer) { + s.RegisterService(&_BroadcastAPI_serviceDesc, srv) +} + +func _BroadcastAPI_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestPing) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BroadcastAPIServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.rpc.grpc.v1beta3.BroadcastAPI/Ping", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BroadcastAPIServer).Ping(ctx, req.(*v1beta1.RequestPing)) + } + return interceptor(ctx, in, info, handler) +} + +func _BroadcastAPI_BroadcastTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(v1beta1.RequestBroadcastTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BroadcastAPIServer).BroadcastTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.rpc.grpc.v1beta3.BroadcastAPI/BroadcastTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BroadcastAPIServer).BroadcastTx(ctx, req.(*v1beta1.RequestBroadcastTx)) + } + return interceptor(ctx, in, info, handler) +} + +var _BroadcastAPI_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.rpc.grpc.v1beta3.BroadcastAPI", + HandlerType: (*BroadcastAPIServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _BroadcastAPI_Ping_Handler, + }, + { + MethodName: "BroadcastTx", + Handler: _BroadcastAPI_BroadcastTx_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/rpc/grpc/v1beta3/types.proto", +} + +func (m *ResponseBroadcastTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseBroadcastTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseBroadcastTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TxResult != nil { + { + size, err := m.TxResult.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.CheckTx != nil { + { + size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ResponseBroadcastTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.TxResult != nil { + l = m.TxResult.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ResponseBroadcastTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseBroadcastTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseBroadcastTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CheckTx == nil { + m.CheckTx = &v1beta3.ResponseCheckTx{} + } + if err := m.CheckTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxResult", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TxResult == nil { + m.TxResult = &v1beta3.ExecTxResult{} + } + if err := m.TxResult.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/services/block/v1/block.pb.go b/api/cometbft/services/block/v1/block.pb.go new file mode 100644 index 00000000000..a1cfd20bbe8 --- /dev/null +++ b/api/cometbft/services/block/v1/block.pb.go @@ -0,0 +1,827 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/services/block/v1/block.proto + +package v1 + +import ( + fmt "fmt" + v1 "github.com/cometbft/cometbft/api/cometbft/types/v1" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GetByHeightRequest is a request for a block at the specified height. +type GetByHeightRequest struct { + // The height of the block requested. + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *GetByHeightRequest) Reset() { *m = GetByHeightRequest{} } +func (m *GetByHeightRequest) String() string { return proto.CompactTextString(m) } +func (*GetByHeightRequest) ProtoMessage() {} +func (*GetByHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_a30eb8f0c11b1783, []int{0} +} +func (m *GetByHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetByHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetByHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetByHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetByHeightRequest.Merge(m, src) +} +func (m *GetByHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *GetByHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetByHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetByHeightRequest proto.InternalMessageInfo + +func (m *GetByHeightRequest) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +// GetByHeightResponse contains the block ID and the block at the specified height. +type GetByHeightResponse struct { + BlockId *v1.BlockID `protobuf:"bytes,1,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` + Block *v1.Block `protobuf:"bytes,2,opt,name=block,proto3" json:"block,omitempty"` +} + +func (m *GetByHeightResponse) Reset() { *m = GetByHeightResponse{} } +func (m *GetByHeightResponse) String() string { return proto.CompactTextString(m) } +func (*GetByHeightResponse) ProtoMessage() {} +func (*GetByHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_a30eb8f0c11b1783, []int{1} +} +func (m *GetByHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetByHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetByHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetByHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetByHeightResponse.Merge(m, src) +} +func (m *GetByHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *GetByHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetByHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetByHeightResponse proto.InternalMessageInfo + +func (m *GetByHeightResponse) GetBlockId() *v1.BlockID { + if m != nil { + return m.BlockId + } + return nil +} + +func (m *GetByHeightResponse) GetBlock() *v1.Block { + if m != nil { + return m.Block + } + return nil +} + +// GetLatestHeightRequest - empty message since no parameter is required +type GetLatestHeightRequest struct { +} + +func (m *GetLatestHeightRequest) Reset() { *m = GetLatestHeightRequest{} } +func (m *GetLatestHeightRequest) String() string { return proto.CompactTextString(m) } +func (*GetLatestHeightRequest) ProtoMessage() {} +func (*GetLatestHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_a30eb8f0c11b1783, []int{2} +} +func (m *GetLatestHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetLatestHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetLatestHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetLatestHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetLatestHeightRequest.Merge(m, src) +} +func (m *GetLatestHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *GetLatestHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetLatestHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetLatestHeightRequest proto.InternalMessageInfo + +// GetLatestHeightResponse provides the height of the latest committed block. +type GetLatestHeightResponse struct { + // The height of the latest committed block. Will be 0 if no data has been + // committed yet. + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *GetLatestHeightResponse) Reset() { *m = GetLatestHeightResponse{} } +func (m *GetLatestHeightResponse) String() string { return proto.CompactTextString(m) } +func (*GetLatestHeightResponse) ProtoMessage() {} +func (*GetLatestHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_a30eb8f0c11b1783, []int{3} +} +func (m *GetLatestHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetLatestHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetLatestHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetLatestHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetLatestHeightResponse.Merge(m, src) +} +func (m *GetLatestHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *GetLatestHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetLatestHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetLatestHeightResponse proto.InternalMessageInfo + +func (m *GetLatestHeightResponse) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func init() { + proto.RegisterType((*GetByHeightRequest)(nil), "cometbft.services.block.v1.GetByHeightRequest") + proto.RegisterType((*GetByHeightResponse)(nil), "cometbft.services.block.v1.GetByHeightResponse") + proto.RegisterType((*GetLatestHeightRequest)(nil), "cometbft.services.block.v1.GetLatestHeightRequest") + proto.RegisterType((*GetLatestHeightResponse)(nil), "cometbft.services.block.v1.GetLatestHeightResponse") +} + +func init() { + proto.RegisterFile("cometbft/services/block/v1/block.proto", fileDescriptor_a30eb8f0c11b1783) +} + +var fileDescriptor_a30eb8f0c11b1783 = []byte{ + // 271 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4b, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x2d, 0xd6, 0x4f, 0xca, + 0xc9, 0x4f, 0xce, 0xd6, 0x2f, 0x33, 0x84, 0x30, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0xa4, + 0x60, 0xea, 0xf4, 0x60, 0xea, 0xf4, 0x20, 0xd2, 0x65, 0x86, 0x52, 0xb2, 0x70, 0x33, 0x4a, 0x2a, + 0x0b, 0x52, 0x8b, 0x41, 0x5a, 0xc1, 0x0c, 0x88, 0x56, 0x6c, 0xd2, 0x48, 0x26, 0x2b, 0xe9, 0x70, + 0x09, 0xb9, 0xa7, 0x96, 0x38, 0x55, 0x7a, 0xa4, 0x66, 0xa6, 0x67, 0x94, 0x04, 0xa5, 0x16, 0x96, + 0xa6, 0x16, 0x97, 0x08, 0x89, 0x71, 0xb1, 0x65, 0x80, 0x05, 0x24, 0x18, 0x15, 0x18, 0x35, 0x98, + 0x83, 0xa0, 0x3c, 0xa5, 0x1a, 0x2e, 0x61, 0x14, 0xd5, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, + 0xa6, 0x5c, 0x1c, 0x60, 0x33, 0xe3, 0x33, 0x53, 0xc0, 0x1a, 0xb8, 0x8d, 0xa4, 0xf4, 0xe0, 0x2e, + 0x86, 0x38, 0xa6, 0xcc, 0x50, 0xcf, 0x09, 0xa4, 0xc4, 0xd3, 0x25, 0x88, 0x1d, 0xac, 0xd6, 0x33, + 0x45, 0x48, 0x8f, 0x8b, 0x15, 0xcc, 0x94, 0x60, 0x02, 0xeb, 0x91, 0xc0, 0xa5, 0x27, 0x08, 0xa2, + 0x4c, 0x49, 0x82, 0x4b, 0xcc, 0x3d, 0xb5, 0xc4, 0x27, 0xb1, 0x24, 0xb5, 0xb8, 0x04, 0xc5, 0xbd, + 0x4a, 0x86, 0x5c, 0xe2, 0x18, 0x32, 0x50, 0xb7, 0xe1, 0xf0, 0x8a, 0x53, 0xe8, 0x89, 0x47, 0x72, + 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, + 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x59, 0xa7, 0x67, 0x96, 0x64, 0x94, 0x26, 0x81, 0x5c, + 0xa3, 0x0f, 0x0f, 0x3c, 0x38, 0x23, 0xb1, 0x20, 0x53, 0x1f, 0x77, 0xac, 0x25, 0xb1, 0x81, 0x83, + 0xd5, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x65, 0xb5, 0xa5, 0x74, 0xda, 0x01, 0x00, 0x00, +} + +func (m *GetByHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetByHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetByHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintBlock(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *GetByHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetByHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetByHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Block != nil { + { + size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.BlockId != nil { + { + size, err := m.BlockId.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GetLatestHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetLatestHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetLatestHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetLatestHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetLatestHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetLatestHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintBlock(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintBlock(dAtA []byte, offset int, v uint64) int { + offset -= sovBlock(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GetByHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovBlock(uint64(m.Height)) + } + return n +} + +func (m *GetByHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BlockId != nil { + l = m.BlockId.Size() + n += 1 + l + sovBlock(uint64(l)) + } + if m.Block != nil { + l = m.Block.Size() + n += 1 + l + sovBlock(uint64(l)) + } + return n +} + +func (m *GetLatestHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetLatestHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovBlock(uint64(m.Height)) + } + return n +} + +func sovBlock(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozBlock(x uint64) (n int) { + return sovBlock(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GetByHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetByHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetByHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBlock(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBlock + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetByHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetByHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetByHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockId", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BlockId == nil { + m.BlockId = &v1.BlockID{} + } + if err := m.BlockId.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Block == nil { + m.Block = &v1.Block{} + } + if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBlock(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBlock + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetLatestHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetLatestHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetLatestHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipBlock(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBlock + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetLatestHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetLatestHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetLatestHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBlock(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBlock + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipBlock(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlock + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlock + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlock + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthBlock + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupBlock + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthBlock + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthBlock = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowBlock = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupBlock = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/services/block/v1/block_service.pb.go b/api/cometbft/services/block/v1/block_service.pb.go new file mode 100644 index 00000000000..bf80ae5b786 --- /dev/null +++ b/api/cometbft/services/block/v1/block_service.pb.go @@ -0,0 +1,202 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/services/block/v1/block_service.proto + +package v1 + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +func init() { + proto.RegisterFile("cometbft/services/block/v1/block_service.proto", fileDescriptor_5768ae424af71eff) +} + +var fileDescriptor_5768ae424af71eff = []byte{ + // 219 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4b, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x2d, 0xd6, 0x4f, 0xca, + 0xc9, 0x4f, 0xce, 0xd6, 0x2f, 0x33, 0x84, 0x30, 0xe2, 0xa1, 0xe2, 0x7a, 0x05, 0x45, 0xf9, 0x25, + 0xf9, 0x42, 0x52, 0x30, 0xf5, 0x7a, 0x30, 0xf5, 0x7a, 0x60, 0x65, 0x7a, 0x65, 0x86, 0x52, 0x6a, + 0x84, 0xcc, 0x82, 0x98, 0x61, 0xf4, 0x87, 0x91, 0x8b, 0xc7, 0x09, 0xc4, 0x0f, 0x86, 0x28, 0x13, + 0xca, 0xe3, 0xe2, 0x76, 0x4f, 0x2d, 0x71, 0xaa, 0xf4, 0x48, 0xcd, 0x4c, 0xcf, 0x28, 0x11, 0xd2, + 0xd3, 0xc3, 0x6d, 0x89, 0x1e, 0x92, 0xc2, 0xa0, 0xd4, 0xc2, 0xd2, 0xd4, 0xe2, 0x12, 0x29, 0x7d, + 0xa2, 0xd5, 0x17, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x0a, 0xd5, 0x70, 0xf1, 0xbb, 0xa7, 0x96, 0xf8, + 0x24, 0x96, 0xa4, 0x16, 0x97, 0x40, 0xed, 0x34, 0x22, 0x60, 0x06, 0xb2, 0x62, 0x98, 0xbd, 0xc6, + 0x24, 0xe9, 0x81, 0xd8, 0x6d, 0xc0, 0xe8, 0x14, 0x7a, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, + 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, + 0x72, 0x0c, 0x51, 0xd6, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x20, 0x63, 0xf5, 0xe1, 0x61, 0x09, + 0x67, 0x24, 0x16, 0x64, 0xea, 0xe3, 0x0e, 0xe1, 0x24, 0x36, 0x70, 0xe0, 0x1a, 0x03, 0x02, 0x00, + 0x00, 0xff, 0xff, 0xab, 0x27, 0xc3, 0x98, 0xd2, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// BlockServiceClient is the client API for BlockService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type BlockServiceClient interface { + // GetBlock retrieves the block information at a particular height. + GetByHeight(ctx context.Context, in *GetByHeightRequest, opts ...grpc.CallOption) (*GetByHeightResponse, error) + // GetLatestHeight returns a stream of the latest block heights committed by + // the network. This is a long-lived stream that is only terminated by the + // server if an error occurs. The caller is expected to handle such + // disconnections and automatically reconnect. + GetLatestHeight(ctx context.Context, in *GetLatestHeightRequest, opts ...grpc.CallOption) (BlockService_GetLatestHeightClient, error) +} + +type blockServiceClient struct { + cc grpc1.ClientConn +} + +func NewBlockServiceClient(cc grpc1.ClientConn) BlockServiceClient { + return &blockServiceClient{cc} +} + +func (c *blockServiceClient) GetByHeight(ctx context.Context, in *GetByHeightRequest, opts ...grpc.CallOption) (*GetByHeightResponse, error) { + out := new(GetByHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.block.v1.BlockService/GetByHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *blockServiceClient) GetLatestHeight(ctx context.Context, in *GetLatestHeightRequest, opts ...grpc.CallOption) (BlockService_GetLatestHeightClient, error) { + stream, err := c.cc.NewStream(ctx, &_BlockService_serviceDesc.Streams[0], "/cometbft.services.block.v1.BlockService/GetLatestHeight", opts...) + if err != nil { + return nil, err + } + x := &blockServiceGetLatestHeightClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type BlockService_GetLatestHeightClient interface { + Recv() (*GetLatestHeightResponse, error) + grpc.ClientStream +} + +type blockServiceGetLatestHeightClient struct { + grpc.ClientStream +} + +func (x *blockServiceGetLatestHeightClient) Recv() (*GetLatestHeightResponse, error) { + m := new(GetLatestHeightResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// BlockServiceServer is the server API for BlockService service. +type BlockServiceServer interface { + // GetBlock retrieves the block information at a particular height. + GetByHeight(context.Context, *GetByHeightRequest) (*GetByHeightResponse, error) + // GetLatestHeight returns a stream of the latest block heights committed by + // the network. This is a long-lived stream that is only terminated by the + // server if an error occurs. The caller is expected to handle such + // disconnections and automatically reconnect. + GetLatestHeight(*GetLatestHeightRequest, BlockService_GetLatestHeightServer) error +} + +// UnimplementedBlockServiceServer can be embedded to have forward compatible implementations. +type UnimplementedBlockServiceServer struct { +} + +func (*UnimplementedBlockServiceServer) GetByHeight(ctx context.Context, req *GetByHeightRequest) (*GetByHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetByHeight not implemented") +} +func (*UnimplementedBlockServiceServer) GetLatestHeight(req *GetLatestHeightRequest, srv BlockService_GetLatestHeightServer) error { + return status.Errorf(codes.Unimplemented, "method GetLatestHeight not implemented") +} + +func RegisterBlockServiceServer(s grpc1.Server, srv BlockServiceServer) { + s.RegisterService(&_BlockService_serviceDesc, srv) +} + +func _BlockService_GetByHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetByHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BlockServiceServer).GetByHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.block.v1.BlockService/GetByHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BlockServiceServer).GetByHeight(ctx, req.(*GetByHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _BlockService_GetLatestHeight_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetLatestHeightRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(BlockServiceServer).GetLatestHeight(m, &blockServiceGetLatestHeightServer{stream}) +} + +type BlockService_GetLatestHeightServer interface { + Send(*GetLatestHeightResponse) error + grpc.ServerStream +} + +type blockServiceGetLatestHeightServer struct { + grpc.ServerStream +} + +func (x *blockServiceGetLatestHeightServer) Send(m *GetLatestHeightResponse) error { + return x.ServerStream.SendMsg(m) +} + +var _BlockService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.services.block.v1.BlockService", + HandlerType: (*BlockServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetByHeight", + Handler: _BlockService_GetByHeight_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "GetLatestHeight", + Handler: _BlockService_GetLatestHeight_Handler, + ServerStreams: true, + }, + }, + Metadata: "cometbft/services/block/v1/block_service.proto", +} diff --git a/api/cometbft/services/block_results/v1/block_results.pb.go b/api/cometbft/services/block_results/v1/block_results.pb.go new file mode 100644 index 00000000000..ea87eebbde3 --- /dev/null +++ b/api/cometbft/services/block_results/v1/block_results.pb.go @@ -0,0 +1,772 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/services/block_results/v1/block_results.proto + +package v1 + +import ( + fmt "fmt" + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" + v11 "github.com/cometbft/cometbft/api/cometbft/types/v1" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GetBlockResults is a request for the BlockResults of a given height. +type GetBlockResultsRequest struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *GetBlockResultsRequest) Reset() { *m = GetBlockResultsRequest{} } +func (m *GetBlockResultsRequest) String() string { return proto.CompactTextString(m) } +func (*GetBlockResultsRequest) ProtoMessage() {} +func (*GetBlockResultsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_3fd862496bf20f1b, []int{0} +} +func (m *GetBlockResultsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetBlockResultsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetBlockResultsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetBlockResultsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetBlockResultsRequest.Merge(m, src) +} +func (m *GetBlockResultsRequest) XXX_Size() int { + return m.Size() +} +func (m *GetBlockResultsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetBlockResultsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetBlockResultsRequest proto.InternalMessageInfo + +func (m *GetBlockResultsRequest) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +// GetBlockResultsResponse contains the block results for the given height. +type GetBlockResultsResponse struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + TxResults []*v1.ExecTxResult `protobuf:"bytes,2,rep,name=tx_results,json=txResults,proto3" json:"tx_results,omitempty"` + FinalizeBlockEvents []*v1.Event `protobuf:"bytes,3,rep,name=finalize_block_events,json=finalizeBlockEvents,proto3" json:"finalize_block_events,omitempty"` + ValidatorUpdates []*v1.ValidatorUpdate `protobuf:"bytes,4,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates,omitempty"` + ConsensusParamUpdates *v11.ConsensusParams `protobuf:"bytes,5,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` + AppHash []byte `protobuf:"bytes,6,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *GetBlockResultsResponse) Reset() { *m = GetBlockResultsResponse{} } +func (m *GetBlockResultsResponse) String() string { return proto.CompactTextString(m) } +func (*GetBlockResultsResponse) ProtoMessage() {} +func (*GetBlockResultsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3fd862496bf20f1b, []int{1} +} +func (m *GetBlockResultsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetBlockResultsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetBlockResultsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetBlockResultsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetBlockResultsResponse.Merge(m, src) +} +func (m *GetBlockResultsResponse) XXX_Size() int { + return m.Size() +} +func (m *GetBlockResultsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetBlockResultsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetBlockResultsResponse proto.InternalMessageInfo + +func (m *GetBlockResultsResponse) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *GetBlockResultsResponse) GetTxResults() []*v1.ExecTxResult { + if m != nil { + return m.TxResults + } + return nil +} + +func (m *GetBlockResultsResponse) GetFinalizeBlockEvents() []*v1.Event { + if m != nil { + return m.FinalizeBlockEvents + } + return nil +} + +func (m *GetBlockResultsResponse) GetValidatorUpdates() []*v1.ValidatorUpdate { + if m != nil { + return m.ValidatorUpdates + } + return nil +} + +func (m *GetBlockResultsResponse) GetConsensusParamUpdates() *v11.ConsensusParams { + if m != nil { + return m.ConsensusParamUpdates + } + return nil +} + +func (m *GetBlockResultsResponse) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +func init() { + proto.RegisterType((*GetBlockResultsRequest)(nil), "cometbft.services.block_results.v1.GetBlockResultsRequest") + proto.RegisterType((*GetBlockResultsResponse)(nil), "cometbft.services.block_results.v1.GetBlockResultsResponse") +} + +func init() { + proto.RegisterFile("cometbft/services/block_results/v1/block_results.proto", fileDescriptor_3fd862496bf20f1b) +} + +var fileDescriptor_3fd862496bf20f1b = []byte{ + // 396 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0x4f, 0xcf, 0x93, 0x40, + 0x10, 0xc6, 0x8b, 0x68, 0xd5, 0x7d, 0x3d, 0x28, 0xe6, 0x6d, 0xb1, 0x31, 0x1b, 0xe4, 0xc4, 0x09, + 0xa4, 0x26, 0xde, 0xbc, 0xb4, 0x31, 0x9a, 0x98, 0x18, 0xb3, 0x51, 0x0f, 0x4d, 0x0c, 0x59, 0xe8, + 0xb6, 0x6c, 0xa4, 0xb0, 0x32, 0xcb, 0xa6, 0x7a, 0xf6, 0x03, 0xf8, 0xb1, 0x3c, 0xf6, 0xe8, 0xd1, + 0xb4, 0x5f, 0xc4, 0xb0, 0xfc, 0x69, 0x48, 0x35, 0xde, 0xe0, 0x79, 0xe6, 0xf9, 0x31, 0xc3, 0x0c, + 0x7a, 0x9e, 0x14, 0x3b, 0x26, 0xe3, 0x8d, 0x0c, 0x80, 0x95, 0x8a, 0x27, 0x0c, 0x82, 0x38, 0x2b, + 0x92, 0xcf, 0x51, 0xc9, 0xa0, 0xca, 0x24, 0x04, 0x2a, 0x1c, 0x0a, 0xbe, 0x28, 0x0b, 0x59, 0x58, + 0x6e, 0x97, 0xf3, 0xbb, 0x9c, 0x3f, 0x2c, 0x53, 0xe1, 0xec, 0x71, 0xcf, 0xa6, 0x71, 0xc2, 0x6b, + 0x92, 0xfc, 0x2a, 0x58, 0x4b, 0x98, 0xe1, 0xde, 0xd5, 0x6a, 0x6d, 0x0b, 0x5a, 0xd2, 0x5d, 0xeb, + 0xbb, 0x4f, 0xd1, 0xe4, 0x15, 0x93, 0x8b, 0x1a, 0x4a, 0x1a, 0x26, 0x61, 0x5f, 0x2a, 0x06, 0xd2, + 0x9a, 0xa0, 0x71, 0xca, 0xf8, 0x36, 0x95, 0xb6, 0xe1, 0x18, 0x9e, 0x49, 0xda, 0x37, 0xf7, 0xbb, + 0x89, 0xa6, 0x17, 0x11, 0x10, 0x45, 0x0e, 0xec, 0x5f, 0x19, 0xeb, 0x05, 0x42, 0x72, 0xdf, 0x35, + 0x6d, 0xdf, 0x70, 0x4c, 0xef, 0x6a, 0x8e, 0xfd, 0x7e, 0xb8, 0xba, 0x71, 0x5f, 0x85, 0xfe, 0xcb, + 0x3d, 0x4b, 0xde, 0xef, 0x1b, 0x28, 0xb9, 0x2b, 0xdb, 0x27, 0xb0, 0xde, 0xa0, 0xeb, 0x0d, 0xcf, + 0x69, 0xc6, 0xbf, 0xb1, 0xa8, 0x99, 0x9f, 0x29, 0x96, 0x4b, 0xb0, 0x4d, 0x4d, 0x9a, 0xfe, 0x85, + 0x54, 0xfb, 0xe4, 0x61, 0x97, 0xd2, 0xcd, 0x6a, 0x0d, 0xac, 0xb7, 0xe8, 0x81, 0xa2, 0x19, 0x5f, + 0x53, 0x59, 0x94, 0x51, 0x25, 0xd6, 0x54, 0x32, 0xb0, 0x6f, 0x6a, 0xd0, 0x93, 0x4b, 0xd0, 0xc7, + 0xae, 0xf4, 0x83, 0xae, 0x24, 0xf7, 0xd5, 0x50, 0x00, 0x6b, 0x85, 0xa6, 0x49, 0x3d, 0x7c, 0x0e, + 0x15, 0x44, 0xfa, 0xdf, 0xf6, 0xd4, 0x5b, 0x8e, 0xe1, 0x5d, 0xcd, 0xdd, 0x33, 0xb5, 0xd9, 0x8c, + 0x0a, 0xfd, 0x65, 0x97, 0x78, 0xa7, 0x97, 0x41, 0xae, 0x93, 0x81, 0xd0, 0xb1, 0x1f, 0xa1, 0x3b, + 0x54, 0x88, 0x28, 0xa5, 0x90, 0xda, 0x63, 0xc7, 0xf0, 0xee, 0x91, 0xdb, 0x54, 0x88, 0xd7, 0x14, + 0xd2, 0xc5, 0xa7, 0x9f, 0x47, 0x6c, 0x1c, 0x8e, 0xd8, 0xf8, 0x7d, 0xc4, 0xc6, 0x8f, 0x13, 0x1e, + 0x1d, 0x4e, 0x78, 0xf4, 0xeb, 0x84, 0x47, 0xab, 0xe5, 0x96, 0xcb, 0xb4, 0x8a, 0xeb, 0xaf, 0x06, + 0xfd, 0xf6, 0xcf, 0x47, 0x22, 0x78, 0xf0, 0xff, 0x6b, 0x8c, 0xc7, 0xfa, 0x3c, 0x9e, 0xfd, 0x09, + 0x00, 0x00, 0xff, 0xff, 0xf5, 0x7a, 0x3e, 0x1d, 0xba, 0x02, 0x00, 0x00, +} + +func (m *GetBlockResultsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetBlockResultsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetBlockResultsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintBlockResults(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *GetBlockResultsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetBlockResultsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetBlockResultsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintBlockResults(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x32 + } + if m.ConsensusParamUpdates != nil { + { + size, err := m.ConsensusParamUpdates.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlockResults(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if len(m.ValidatorUpdates) > 0 { + for iNdEx := len(m.ValidatorUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ValidatorUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlockResults(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.FinalizeBlockEvents) > 0 { + for iNdEx := len(m.FinalizeBlockEvents) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FinalizeBlockEvents[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlockResults(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.TxResults) > 0 { + for iNdEx := len(m.TxResults) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TxResults[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlockResults(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Height != 0 { + i = encodeVarintBlockResults(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintBlockResults(dAtA []byte, offset int, v uint64) int { + offset -= sovBlockResults(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GetBlockResultsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovBlockResults(uint64(m.Height)) + } + return n +} + +func (m *GetBlockResultsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovBlockResults(uint64(m.Height)) + } + if len(m.TxResults) > 0 { + for _, e := range m.TxResults { + l = e.Size() + n += 1 + l + sovBlockResults(uint64(l)) + } + } + if len(m.FinalizeBlockEvents) > 0 { + for _, e := range m.FinalizeBlockEvents { + l = e.Size() + n += 1 + l + sovBlockResults(uint64(l)) + } + } + if len(m.ValidatorUpdates) > 0 { + for _, e := range m.ValidatorUpdates { + l = e.Size() + n += 1 + l + sovBlockResults(uint64(l)) + } + } + if m.ConsensusParamUpdates != nil { + l = m.ConsensusParamUpdates.Size() + n += 1 + l + sovBlockResults(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovBlockResults(uint64(l)) + } + return n +} + +func sovBlockResults(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozBlockResults(x uint64) (n int) { + return sovBlockResults(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GetBlockResultsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetBlockResultsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetBlockResultsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBlockResults(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBlockResults + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetBlockResultsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetBlockResultsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetBlockResultsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxResults", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlockResults + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlockResults + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TxResults = append(m.TxResults, &v1.ExecTxResult{}) + if err := m.TxResults[len(m.TxResults)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FinalizeBlockEvents", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlockResults + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlockResults + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FinalizeBlockEvents = append(m.FinalizeBlockEvents, &v1.Event{}) + if err := m.FinalizeBlockEvents[len(m.FinalizeBlockEvents)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlockResults + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlockResults + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorUpdates = append(m.ValidatorUpdates, &v1.ValidatorUpdate{}) + if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlockResults + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlockResults + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParamUpdates == nil { + m.ConsensusParamUpdates = &v11.ConsensusParams{} + } + if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlockResults + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthBlockResults + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthBlockResults + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBlockResults(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBlockResults + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipBlockResults(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlockResults + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlockResults + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlockResults + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthBlockResults + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupBlockResults + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthBlockResults + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthBlockResults = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowBlockResults = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupBlockResults = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/services/block_results/v1/block_results_service.pb.go b/api/cometbft/services/block_results/v1/block_results_service.pb.go new file mode 100644 index 00000000000..c5c97a4af67 --- /dev/null +++ b/api/cometbft/services/block_results/v1/block_results_service.pb.go @@ -0,0 +1,129 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/services/block_results/v1/block_results_service.proto + +package v1 + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +func init() { + proto.RegisterFile("cometbft/services/block_results/v1/block_results_service.proto", fileDescriptor_03cd7b7c1632b595) +} + +var fileDescriptor_03cd7b7c1632b595 = []byte{ + // 195 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4b, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x2d, 0xd6, 0x4f, 0xca, + 0xc9, 0x4f, 0xce, 0x8e, 0x2f, 0x4a, 0x2d, 0x2e, 0xcd, 0x29, 0x29, 0xd6, 0x2f, 0x33, 0x44, 0x15, + 0x88, 0x87, 0xaa, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x82, 0xe9, 0xd7, 0x83, 0xe9, + 0xd7, 0x43, 0x51, 0xae, 0x57, 0x66, 0x28, 0x65, 0x46, 0xaa, 0x1d, 0x10, 0xb3, 0x8d, 0x16, 0x31, + 0x72, 0x09, 0x3b, 0x81, 0xc4, 0x83, 0x20, 0xc2, 0xc1, 0x10, 0xdd, 0x42, 0x5d, 0x8c, 0x5c, 0xfc, + 0xee, 0xa9, 0x25, 0xc8, 0x52, 0x42, 0x56, 0x7a, 0x84, 0x1d, 0xa2, 0x87, 0xa6, 0x29, 0x28, 0xb5, + 0xb0, 0x34, 0xb5, 0xb8, 0x44, 0xca, 0x9a, 0x2c, 0xbd, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x4e, + 0xb1, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, + 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xe5, 0x9c, 0x9e, 0x59, 0x92, + 0x51, 0x9a, 0x04, 0x32, 0x5c, 0x1f, 0x1e, 0x02, 0x70, 0x46, 0x62, 0x41, 0xa6, 0x3e, 0xe1, 0x70, + 0x49, 0x62, 0x03, 0x07, 0x85, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xbb, 0xc2, 0x14, 0x1e, 0xa8, + 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// BlockResultsServiceClient is the client API for BlockResultsService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type BlockResultsServiceClient interface { + // GetBlockResults returns the BlockResults of the requested height. + GetBlockResults(ctx context.Context, in *GetBlockResultsRequest, opts ...grpc.CallOption) (*GetBlockResultsResponse, error) +} + +type blockResultsServiceClient struct { + cc grpc1.ClientConn +} + +func NewBlockResultsServiceClient(cc grpc1.ClientConn) BlockResultsServiceClient { + return &blockResultsServiceClient{cc} +} + +func (c *blockResultsServiceClient) GetBlockResults(ctx context.Context, in *GetBlockResultsRequest, opts ...grpc.CallOption) (*GetBlockResultsResponse, error) { + out := new(GetBlockResultsResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.block_results.v1.BlockResultsService/GetBlockResults", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// BlockResultsServiceServer is the server API for BlockResultsService service. +type BlockResultsServiceServer interface { + // GetBlockResults returns the BlockResults of the requested height. + GetBlockResults(context.Context, *GetBlockResultsRequest) (*GetBlockResultsResponse, error) +} + +// UnimplementedBlockResultsServiceServer can be embedded to have forward compatible implementations. +type UnimplementedBlockResultsServiceServer struct { +} + +func (*UnimplementedBlockResultsServiceServer) GetBlockResults(ctx context.Context, req *GetBlockResultsRequest) (*GetBlockResultsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBlockResults not implemented") +} + +func RegisterBlockResultsServiceServer(s grpc1.Server, srv BlockResultsServiceServer) { + s.RegisterService(&_BlockResultsService_serviceDesc, srv) +} + +func _BlockResultsService_GetBlockResults_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBlockResultsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BlockResultsServiceServer).GetBlockResults(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.block_results.v1.BlockResultsService/GetBlockResults", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BlockResultsServiceServer).GetBlockResults(ctx, req.(*GetBlockResultsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _BlockResultsService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.services.block_results.v1.BlockResultsService", + HandlerType: (*BlockResultsServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetBlockResults", + Handler: _BlockResultsService_GetBlockResults_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/services/block_results/v1/block_results_service.proto", +} diff --git a/api/cometbft/services/pruning/v1/pruning.pb.go b/api/cometbft/services/pruning/v1/pruning.pb.go new file mode 100644 index 00000000000..2af72387cf1 --- /dev/null +++ b/api/cometbft/services/pruning/v1/pruning.pb.go @@ -0,0 +1,2397 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/services/pruning/v1/pruning.proto + +package cometbft_services_pruning_v1 + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// SetBlockRetainHeightRequest sets the retain height for blocks. +type SetBlockRetainHeightRequest struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *SetBlockRetainHeightRequest) Reset() { *m = SetBlockRetainHeightRequest{} } +func (m *SetBlockRetainHeightRequest) String() string { return proto.CompactTextString(m) } +func (*SetBlockRetainHeightRequest) ProtoMessage() {} +func (*SetBlockRetainHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{0} +} +func (m *SetBlockRetainHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetBlockRetainHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetBlockRetainHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetBlockRetainHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetBlockRetainHeightRequest.Merge(m, src) +} +func (m *SetBlockRetainHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *SetBlockRetainHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SetBlockRetainHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SetBlockRetainHeightRequest proto.InternalMessageInfo + +func (m *SetBlockRetainHeightRequest) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +// SetBlockRetainHeightResponse is empty. +type SetBlockRetainHeightResponse struct { +} + +func (m *SetBlockRetainHeightResponse) Reset() { *m = SetBlockRetainHeightResponse{} } +func (m *SetBlockRetainHeightResponse) String() string { return proto.CompactTextString(m) } +func (*SetBlockRetainHeightResponse) ProtoMessage() {} +func (*SetBlockRetainHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{1} +} +func (m *SetBlockRetainHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetBlockRetainHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetBlockRetainHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetBlockRetainHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetBlockRetainHeightResponse.Merge(m, src) +} +func (m *SetBlockRetainHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *SetBlockRetainHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SetBlockRetainHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SetBlockRetainHeightResponse proto.InternalMessageInfo + +// GetBlockRetainHeightRequest is a request for the retain height. +type GetBlockRetainHeightRequest struct { +} + +func (m *GetBlockRetainHeightRequest) Reset() { *m = GetBlockRetainHeightRequest{} } +func (m *GetBlockRetainHeightRequest) String() string { return proto.CompactTextString(m) } +func (*GetBlockRetainHeightRequest) ProtoMessage() {} +func (*GetBlockRetainHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{2} +} +func (m *GetBlockRetainHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetBlockRetainHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetBlockRetainHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetBlockRetainHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetBlockRetainHeightRequest.Merge(m, src) +} +func (m *GetBlockRetainHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *GetBlockRetainHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetBlockRetainHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetBlockRetainHeightRequest proto.InternalMessageInfo + +// GetBlockRetainHeightResponse returns the retain height for blocks. +type GetBlockRetainHeightResponse struct { + // The retain height set by the application. + AppRetainHeight uint64 `protobuf:"varint,1,opt,name=app_retain_height,json=appRetainHeight,proto3" json:"app_retain_height,omitempty"` + // The retain height set via the pruning service (e.g. by the data + // companion) specifically for blocks. + PruningServiceRetainHeight uint64 `protobuf:"varint,2,opt,name=pruning_service_retain_height,json=pruningServiceRetainHeight,proto3" json:"pruning_service_retain_height,omitempty"` +} + +func (m *GetBlockRetainHeightResponse) Reset() { *m = GetBlockRetainHeightResponse{} } +func (m *GetBlockRetainHeightResponse) String() string { return proto.CompactTextString(m) } +func (*GetBlockRetainHeightResponse) ProtoMessage() {} +func (*GetBlockRetainHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{3} +} +func (m *GetBlockRetainHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetBlockRetainHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetBlockRetainHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetBlockRetainHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetBlockRetainHeightResponse.Merge(m, src) +} +func (m *GetBlockRetainHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *GetBlockRetainHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetBlockRetainHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetBlockRetainHeightResponse proto.InternalMessageInfo + +func (m *GetBlockRetainHeightResponse) GetAppRetainHeight() uint64 { + if m != nil { + return m.AppRetainHeight + } + return 0 +} + +func (m *GetBlockRetainHeightResponse) GetPruningServiceRetainHeight() uint64 { + if m != nil { + return m.PruningServiceRetainHeight + } + return 0 +} + +// SetBlockResultsRetainHeightRequest sets the retain height for block results. +type SetBlockResultsRetainHeightRequest struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *SetBlockResultsRetainHeightRequest) Reset() { *m = SetBlockResultsRetainHeightRequest{} } +func (m *SetBlockResultsRetainHeightRequest) String() string { return proto.CompactTextString(m) } +func (*SetBlockResultsRetainHeightRequest) ProtoMessage() {} +func (*SetBlockResultsRetainHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{4} +} +func (m *SetBlockResultsRetainHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetBlockResultsRetainHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetBlockResultsRetainHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetBlockResultsRetainHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetBlockResultsRetainHeightRequest.Merge(m, src) +} +func (m *SetBlockResultsRetainHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *SetBlockResultsRetainHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SetBlockResultsRetainHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SetBlockResultsRetainHeightRequest proto.InternalMessageInfo + +func (m *SetBlockResultsRetainHeightRequest) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +// SetBlockResultsRetainHeightResponse is empty. +type SetBlockResultsRetainHeightResponse struct { +} + +func (m *SetBlockResultsRetainHeightResponse) Reset() { *m = SetBlockResultsRetainHeightResponse{} } +func (m *SetBlockResultsRetainHeightResponse) String() string { return proto.CompactTextString(m) } +func (*SetBlockResultsRetainHeightResponse) ProtoMessage() {} +func (*SetBlockResultsRetainHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{5} +} +func (m *SetBlockResultsRetainHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetBlockResultsRetainHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetBlockResultsRetainHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetBlockResultsRetainHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetBlockResultsRetainHeightResponse.Merge(m, src) +} +func (m *SetBlockResultsRetainHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *SetBlockResultsRetainHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SetBlockResultsRetainHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SetBlockResultsRetainHeightResponse proto.InternalMessageInfo + +// GetBlockResultsRetainHeightRequest is a request for the retain height. +type GetBlockResultsRetainHeightRequest struct { +} + +func (m *GetBlockResultsRetainHeightRequest) Reset() { *m = GetBlockResultsRetainHeightRequest{} } +func (m *GetBlockResultsRetainHeightRequest) String() string { return proto.CompactTextString(m) } +func (*GetBlockResultsRetainHeightRequest) ProtoMessage() {} +func (*GetBlockResultsRetainHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{6} +} +func (m *GetBlockResultsRetainHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetBlockResultsRetainHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetBlockResultsRetainHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetBlockResultsRetainHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetBlockResultsRetainHeightRequest.Merge(m, src) +} +func (m *GetBlockResultsRetainHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *GetBlockResultsRetainHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetBlockResultsRetainHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetBlockResultsRetainHeightRequest proto.InternalMessageInfo + +// GetBlockResultsRetainHeightResponse returns the retain height for block results. +type GetBlockResultsRetainHeightResponse struct { + // The retain height set by the pruning service (e.g. by the data + // companion) specifically for block results. + PruningServiceRetainHeight uint64 `protobuf:"varint,1,opt,name=pruning_service_retain_height,json=pruningServiceRetainHeight,proto3" json:"pruning_service_retain_height,omitempty"` +} + +func (m *GetBlockResultsRetainHeightResponse) Reset() { *m = GetBlockResultsRetainHeightResponse{} } +func (m *GetBlockResultsRetainHeightResponse) String() string { return proto.CompactTextString(m) } +func (*GetBlockResultsRetainHeightResponse) ProtoMessage() {} +func (*GetBlockResultsRetainHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{7} +} +func (m *GetBlockResultsRetainHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetBlockResultsRetainHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetBlockResultsRetainHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetBlockResultsRetainHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetBlockResultsRetainHeightResponse.Merge(m, src) +} +func (m *GetBlockResultsRetainHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *GetBlockResultsRetainHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetBlockResultsRetainHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetBlockResultsRetainHeightResponse proto.InternalMessageInfo + +func (m *GetBlockResultsRetainHeightResponse) GetPruningServiceRetainHeight() uint64 { + if m != nil { + return m.PruningServiceRetainHeight + } + return 0 +} + +// SetTxIndexerRetainHeightRequest sets the retain height for the tx indexer. +type SetTxIndexerRetainHeightRequest struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *SetTxIndexerRetainHeightRequest) Reset() { *m = SetTxIndexerRetainHeightRequest{} } +func (m *SetTxIndexerRetainHeightRequest) String() string { return proto.CompactTextString(m) } +func (*SetTxIndexerRetainHeightRequest) ProtoMessage() {} +func (*SetTxIndexerRetainHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{8} +} +func (m *SetTxIndexerRetainHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetTxIndexerRetainHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetTxIndexerRetainHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetTxIndexerRetainHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetTxIndexerRetainHeightRequest.Merge(m, src) +} +func (m *SetTxIndexerRetainHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *SetTxIndexerRetainHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SetTxIndexerRetainHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SetTxIndexerRetainHeightRequest proto.InternalMessageInfo + +func (m *SetTxIndexerRetainHeightRequest) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +// SetTxIndexerRetainHeightResponse is empty. +type SetTxIndexerRetainHeightResponse struct { +} + +func (m *SetTxIndexerRetainHeightResponse) Reset() { *m = SetTxIndexerRetainHeightResponse{} } +func (m *SetTxIndexerRetainHeightResponse) String() string { return proto.CompactTextString(m) } +func (*SetTxIndexerRetainHeightResponse) ProtoMessage() {} +func (*SetTxIndexerRetainHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{9} +} +func (m *SetTxIndexerRetainHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetTxIndexerRetainHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetTxIndexerRetainHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetTxIndexerRetainHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetTxIndexerRetainHeightResponse.Merge(m, src) +} +func (m *SetTxIndexerRetainHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *SetTxIndexerRetainHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SetTxIndexerRetainHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SetTxIndexerRetainHeightResponse proto.InternalMessageInfo + +// GetTxIndexerRetainHeightRequest is a request for the retain height. +type GetTxIndexerRetainHeightRequest struct { +} + +func (m *GetTxIndexerRetainHeightRequest) Reset() { *m = GetTxIndexerRetainHeightRequest{} } +func (m *GetTxIndexerRetainHeightRequest) String() string { return proto.CompactTextString(m) } +func (*GetTxIndexerRetainHeightRequest) ProtoMessage() {} +func (*GetTxIndexerRetainHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{10} +} +func (m *GetTxIndexerRetainHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetTxIndexerRetainHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetTxIndexerRetainHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetTxIndexerRetainHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetTxIndexerRetainHeightRequest.Merge(m, src) +} +func (m *GetTxIndexerRetainHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *GetTxIndexerRetainHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetTxIndexerRetainHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetTxIndexerRetainHeightRequest proto.InternalMessageInfo + +// GetTxIndexerRetainHeightResponse returns the retain height for the tx indexer. +type GetTxIndexerRetainHeightResponse struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *GetTxIndexerRetainHeightResponse) Reset() { *m = GetTxIndexerRetainHeightResponse{} } +func (m *GetTxIndexerRetainHeightResponse) String() string { return proto.CompactTextString(m) } +func (*GetTxIndexerRetainHeightResponse) ProtoMessage() {} +func (*GetTxIndexerRetainHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{11} +} +func (m *GetTxIndexerRetainHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetTxIndexerRetainHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetTxIndexerRetainHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetTxIndexerRetainHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetTxIndexerRetainHeightResponse.Merge(m, src) +} +func (m *GetTxIndexerRetainHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *GetTxIndexerRetainHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetTxIndexerRetainHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetTxIndexerRetainHeightResponse proto.InternalMessageInfo + +func (m *GetTxIndexerRetainHeightResponse) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +// SetBlockIndexerRetainHeightRequest sets the retain height for the block indexer. +type SetBlockIndexerRetainHeightRequest struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *SetBlockIndexerRetainHeightRequest) Reset() { *m = SetBlockIndexerRetainHeightRequest{} } +func (m *SetBlockIndexerRetainHeightRequest) String() string { return proto.CompactTextString(m) } +func (*SetBlockIndexerRetainHeightRequest) ProtoMessage() {} +func (*SetBlockIndexerRetainHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{12} +} +func (m *SetBlockIndexerRetainHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetBlockIndexerRetainHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetBlockIndexerRetainHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetBlockIndexerRetainHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetBlockIndexerRetainHeightRequest.Merge(m, src) +} +func (m *SetBlockIndexerRetainHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *SetBlockIndexerRetainHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_SetBlockIndexerRetainHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_SetBlockIndexerRetainHeightRequest proto.InternalMessageInfo + +func (m *SetBlockIndexerRetainHeightRequest) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +// SetBlockIndexerRetainHeightResponse is empty. +type SetBlockIndexerRetainHeightResponse struct { +} + +func (m *SetBlockIndexerRetainHeightResponse) Reset() { *m = SetBlockIndexerRetainHeightResponse{} } +func (m *SetBlockIndexerRetainHeightResponse) String() string { return proto.CompactTextString(m) } +func (*SetBlockIndexerRetainHeightResponse) ProtoMessage() {} +func (*SetBlockIndexerRetainHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{13} +} +func (m *SetBlockIndexerRetainHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SetBlockIndexerRetainHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SetBlockIndexerRetainHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SetBlockIndexerRetainHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetBlockIndexerRetainHeightResponse.Merge(m, src) +} +func (m *SetBlockIndexerRetainHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *SetBlockIndexerRetainHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_SetBlockIndexerRetainHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_SetBlockIndexerRetainHeightResponse proto.InternalMessageInfo + +// GetBlockIndexerRetainHeightRequest is a request for the retain height. +type GetBlockIndexerRetainHeightRequest struct { +} + +func (m *GetBlockIndexerRetainHeightRequest) Reset() { *m = GetBlockIndexerRetainHeightRequest{} } +func (m *GetBlockIndexerRetainHeightRequest) String() string { return proto.CompactTextString(m) } +func (*GetBlockIndexerRetainHeightRequest) ProtoMessage() {} +func (*GetBlockIndexerRetainHeightRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{14} +} +func (m *GetBlockIndexerRetainHeightRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetBlockIndexerRetainHeightRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetBlockIndexerRetainHeightRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetBlockIndexerRetainHeightRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetBlockIndexerRetainHeightRequest.Merge(m, src) +} +func (m *GetBlockIndexerRetainHeightRequest) XXX_Size() int { + return m.Size() +} +func (m *GetBlockIndexerRetainHeightRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetBlockIndexerRetainHeightRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetBlockIndexerRetainHeightRequest proto.InternalMessageInfo + +// GetBlockIndexerRetainHeightResponse returns the retain height for the block indexer. +type GetBlockIndexerRetainHeightResponse struct { + Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *GetBlockIndexerRetainHeightResponse) Reset() { *m = GetBlockIndexerRetainHeightResponse{} } +func (m *GetBlockIndexerRetainHeightResponse) String() string { return proto.CompactTextString(m) } +func (*GetBlockIndexerRetainHeightResponse) ProtoMessage() {} +func (*GetBlockIndexerRetainHeightResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_14bf9cf2a477c5d2, []int{15} +} +func (m *GetBlockIndexerRetainHeightResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetBlockIndexerRetainHeightResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetBlockIndexerRetainHeightResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetBlockIndexerRetainHeightResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetBlockIndexerRetainHeightResponse.Merge(m, src) +} +func (m *GetBlockIndexerRetainHeightResponse) XXX_Size() int { + return m.Size() +} +func (m *GetBlockIndexerRetainHeightResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetBlockIndexerRetainHeightResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetBlockIndexerRetainHeightResponse proto.InternalMessageInfo + +func (m *GetBlockIndexerRetainHeightResponse) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func init() { + proto.RegisterType((*SetBlockRetainHeightRequest)(nil), "cometbft.services.pruning.v1.SetBlockRetainHeightRequest") + proto.RegisterType((*SetBlockRetainHeightResponse)(nil), "cometbft.services.pruning.v1.SetBlockRetainHeightResponse") + proto.RegisterType((*GetBlockRetainHeightRequest)(nil), "cometbft.services.pruning.v1.GetBlockRetainHeightRequest") + proto.RegisterType((*GetBlockRetainHeightResponse)(nil), "cometbft.services.pruning.v1.GetBlockRetainHeightResponse") + proto.RegisterType((*SetBlockResultsRetainHeightRequest)(nil), "cometbft.services.pruning.v1.SetBlockResultsRetainHeightRequest") + proto.RegisterType((*SetBlockResultsRetainHeightResponse)(nil), "cometbft.services.pruning.v1.SetBlockResultsRetainHeightResponse") + proto.RegisterType((*GetBlockResultsRetainHeightRequest)(nil), "cometbft.services.pruning.v1.GetBlockResultsRetainHeightRequest") + proto.RegisterType((*GetBlockResultsRetainHeightResponse)(nil), "cometbft.services.pruning.v1.GetBlockResultsRetainHeightResponse") + proto.RegisterType((*SetTxIndexerRetainHeightRequest)(nil), "cometbft.services.pruning.v1.SetTxIndexerRetainHeightRequest") + proto.RegisterType((*SetTxIndexerRetainHeightResponse)(nil), "cometbft.services.pruning.v1.SetTxIndexerRetainHeightResponse") + proto.RegisterType((*GetTxIndexerRetainHeightRequest)(nil), "cometbft.services.pruning.v1.GetTxIndexerRetainHeightRequest") + proto.RegisterType((*GetTxIndexerRetainHeightResponse)(nil), "cometbft.services.pruning.v1.GetTxIndexerRetainHeightResponse") + proto.RegisterType((*SetBlockIndexerRetainHeightRequest)(nil), "cometbft.services.pruning.v1.SetBlockIndexerRetainHeightRequest") + proto.RegisterType((*SetBlockIndexerRetainHeightResponse)(nil), "cometbft.services.pruning.v1.SetBlockIndexerRetainHeightResponse") + proto.RegisterType((*GetBlockIndexerRetainHeightRequest)(nil), "cometbft.services.pruning.v1.GetBlockIndexerRetainHeightRequest") + proto.RegisterType((*GetBlockIndexerRetainHeightResponse)(nil), "cometbft.services.pruning.v1.GetBlockIndexerRetainHeightResponse") +} + +func init() { + proto.RegisterFile("cometbft/services/pruning/v1/pruning.proto", fileDescriptor_14bf9cf2a477c5d2) +} + +var fileDescriptor_14bf9cf2a477c5d2 = []byte{ + // 328 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4a, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x2d, 0xd6, 0x2f, 0x28, + 0x2a, 0xcd, 0xcb, 0xcc, 0x4b, 0xd7, 0x2f, 0x33, 0x84, 0x31, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, + 0x85, 0x64, 0x60, 0x6a, 0xf5, 0x60, 0x6a, 0xf5, 0x60, 0x0a, 0xca, 0x0c, 0x95, 0x4c, 0xb9, 0xa4, + 0x83, 0x53, 0x4b, 0x9c, 0x72, 0xf2, 0x93, 0xb3, 0x83, 0x52, 0x4b, 0x12, 0x33, 0xf3, 0x3c, 0x52, + 0x33, 0xd3, 0x33, 0x4a, 0x82, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, 0xc4, 0xb8, 0xd8, 0x32, + 0xc0, 0x02, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x2c, 0x41, 0x50, 0x9e, 0x92, 0x1c, 0x97, 0x0c, 0x76, + 0x6d, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x4a, 0xb2, 0x5c, 0xd2, 0xee, 0xb8, 0x8d, 0x55, 0xea, + 0x65, 0xe4, 0x92, 0x71, 0xc7, 0xa3, 0x5f, 0x48, 0x8b, 0x4b, 0x30, 0xb1, 0xa0, 0x20, 0xbe, 0x08, + 0x2c, 0x17, 0x8f, 0xe2, 0x04, 0xfe, 0xc4, 0x82, 0x02, 0x64, 0x3d, 0x42, 0x8e, 0x5c, 0xb2, 0x50, + 0x0f, 0xc5, 0x43, 0x7d, 0x88, 0xa6, 0x8f, 0x09, 0xac, 0x4f, 0x0a, 0xaa, 0x28, 0x18, 0xa2, 0x06, + 0xd9, 0x08, 0x25, 0x1b, 0x2e, 0x25, 0x84, 0x77, 0x8a, 0x4b, 0x73, 0x4a, 0x8a, 0x49, 0x09, 0x0c, + 0x55, 0x2e, 0x65, 0xbc, 0xba, 0xa1, 0x61, 0xa2, 0xc2, 0xa5, 0xe4, 0x4e, 0xd0, 0x12, 0xa5, 0x0c, + 0x2e, 0x65, 0x77, 0xc2, 0x86, 0x11, 0xf6, 0x34, 0x23, 0x41, 0x4f, 0x5b, 0x72, 0xc9, 0x07, 0xa7, + 0x96, 0x84, 0x54, 0x78, 0xe6, 0xa5, 0xa4, 0x56, 0xa4, 0x16, 0x91, 0xe2, 0x63, 0x25, 0x2e, 0x05, + 0xdc, 0x5a, 0xa1, 0xde, 0x55, 0xe4, 0x92, 0x77, 0xc7, 0x6f, 0xbc, 0x92, 0x15, 0x97, 0x82, 0x3b, + 0x01, 0x63, 0x70, 0x3a, 0x01, 0x29, 0xca, 0xc8, 0xf0, 0x00, 0x52, 0x94, 0xe1, 0xf3, 0x03, 0x52, + 0x94, 0xe1, 0xf1, 0x86, 0x2d, 0x22, 0xca, 0xc8, 0xf0, 0x89, 0x93, 0xc4, 0x89, 0x47, 0x72, 0x8c, + 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, + 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x24, 0xb1, 0x81, 0x73, 0xb0, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, + 0xfc, 0xe3, 0x82, 0x21, 0xef, 0x03, 0x00, 0x00, +} + +func (m *SetBlockRetainHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetBlockRetainHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetBlockRetainHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SetBlockRetainHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetBlockRetainHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetBlockRetainHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetBlockRetainHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetBlockRetainHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetBlockRetainHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetBlockRetainHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetBlockRetainHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetBlockRetainHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PruningServiceRetainHeight != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.PruningServiceRetainHeight)) + i-- + dAtA[i] = 0x10 + } + if m.AppRetainHeight != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.AppRetainHeight)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SetBlockResultsRetainHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetBlockResultsRetainHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetBlockResultsRetainHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SetBlockResultsRetainHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetBlockResultsRetainHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetBlockResultsRetainHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetBlockResultsRetainHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetBlockResultsRetainHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetBlockResultsRetainHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetBlockResultsRetainHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetBlockResultsRetainHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetBlockResultsRetainHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PruningServiceRetainHeight != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.PruningServiceRetainHeight)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SetTxIndexerRetainHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetTxIndexerRetainHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetTxIndexerRetainHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SetTxIndexerRetainHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetTxIndexerRetainHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetTxIndexerRetainHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetTxIndexerRetainHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetTxIndexerRetainHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetTxIndexerRetainHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetTxIndexerRetainHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetTxIndexerRetainHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetTxIndexerRetainHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SetBlockIndexerRetainHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetBlockIndexerRetainHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetBlockIndexerRetainHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SetBlockIndexerRetainHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SetBlockIndexerRetainHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SetBlockIndexerRetainHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetBlockIndexerRetainHeightRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetBlockIndexerRetainHeightRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetBlockIndexerRetainHeightRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetBlockIndexerRetainHeightResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetBlockIndexerRetainHeightResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetBlockIndexerRetainHeightResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintPruning(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintPruning(dAtA []byte, offset int, v uint64) int { + offset -= sovPruning(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *SetBlockRetainHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovPruning(uint64(m.Height)) + } + return n +} + +func (m *SetBlockRetainHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetBlockRetainHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetBlockRetainHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AppRetainHeight != 0 { + n += 1 + sovPruning(uint64(m.AppRetainHeight)) + } + if m.PruningServiceRetainHeight != 0 { + n += 1 + sovPruning(uint64(m.PruningServiceRetainHeight)) + } + return n +} + +func (m *SetBlockResultsRetainHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovPruning(uint64(m.Height)) + } + return n +} + +func (m *SetBlockResultsRetainHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetBlockResultsRetainHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetBlockResultsRetainHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PruningServiceRetainHeight != 0 { + n += 1 + sovPruning(uint64(m.PruningServiceRetainHeight)) + } + return n +} + +func (m *SetTxIndexerRetainHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovPruning(uint64(m.Height)) + } + return n +} + +func (m *SetTxIndexerRetainHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetTxIndexerRetainHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetTxIndexerRetainHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovPruning(uint64(m.Height)) + } + return n +} + +func (m *SetBlockIndexerRetainHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovPruning(uint64(m.Height)) + } + return n +} + +func (m *SetBlockIndexerRetainHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetBlockIndexerRetainHeightRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetBlockIndexerRetainHeightResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovPruning(uint64(m.Height)) + } + return n +} + +func sovPruning(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozPruning(x uint64) (n int) { + return sovPruning(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *SetBlockRetainHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetBlockRetainHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetBlockRetainHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetBlockRetainHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetBlockRetainHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetBlockRetainHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetBlockRetainHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetBlockRetainHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetBlockRetainHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetBlockRetainHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetBlockRetainHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetBlockRetainHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AppRetainHeight", wireType) + } + m.AppRetainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.AppRetainHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PruningServiceRetainHeight", wireType) + } + m.PruningServiceRetainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PruningServiceRetainHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetBlockResultsRetainHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetBlockResultsRetainHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetBlockResultsRetainHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetBlockResultsRetainHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetBlockResultsRetainHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetBlockResultsRetainHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetBlockResultsRetainHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetBlockResultsRetainHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetBlockResultsRetainHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetBlockResultsRetainHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetBlockResultsRetainHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetBlockResultsRetainHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PruningServiceRetainHeight", wireType) + } + m.PruningServiceRetainHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PruningServiceRetainHeight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetTxIndexerRetainHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetTxIndexerRetainHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetTxIndexerRetainHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetTxIndexerRetainHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetTxIndexerRetainHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetTxIndexerRetainHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetTxIndexerRetainHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetTxIndexerRetainHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetTxIndexerRetainHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetTxIndexerRetainHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetTxIndexerRetainHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetTxIndexerRetainHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetBlockIndexerRetainHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetBlockIndexerRetainHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetBlockIndexerRetainHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SetBlockIndexerRetainHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SetBlockIndexerRetainHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SetBlockIndexerRetainHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetBlockIndexerRetainHeightRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetBlockIndexerRetainHeightRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetBlockIndexerRetainHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetBlockIndexerRetainHeightResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetBlockIndexerRetainHeightResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetBlockIndexerRetainHeightResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPruning + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPruning(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPruning + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipPruning(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPruning + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPruning + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowPruning + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthPruning + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupPruning + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthPruning + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthPruning = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowPruning = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupPruning = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/services/pruning/v1/service.pb.go b/api/cometbft/services/pruning/v1/service.pb.go new file mode 100644 index 00000000000..746af0cb42a --- /dev/null +++ b/api/cometbft/services/pruning/v1/service.pb.go @@ -0,0 +1,431 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/services/pruning/v1/service.proto + +package cometbft_services_pruning_v1 + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +func init() { + proto.RegisterFile("cometbft/services/pruning/v1/service.proto", fileDescriptor_58672b711a903587) +} + +var fileDescriptor_58672b711a903587 = []byte{ + // 298 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4a, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x2d, 0xd6, 0x2f, 0x28, + 0x2a, 0xcd, 0xcb, 0xcc, 0x4b, 0xd7, 0x2f, 0x33, 0x84, 0x89, 0xe9, 0x15, 0x14, 0xe5, 0x97, 0xe4, + 0x0b, 0xc9, 0xc0, 0xd4, 0xea, 0xc1, 0xd4, 0xea, 0x41, 0xd5, 0xea, 0x95, 0x19, 0x4a, 0xe1, 0x37, + 0x09, 0xa6, 0x10, 0x6c, 0x92, 0xd1, 0x1f, 0x4e, 0x2e, 0xbe, 0x00, 0x88, 0x48, 0x30, 0x44, 0xb1, + 0x50, 0x2f, 0x23, 0x97, 0x48, 0x70, 0x6a, 0x89, 0x53, 0x4e, 0x7e, 0x72, 0x76, 0x50, 0x6a, 0x49, + 0x62, 0x66, 0x9e, 0x47, 0x6a, 0x66, 0x7a, 0x46, 0x89, 0x90, 0xa5, 0x1e, 0x3e, 0x6b, 0xf5, 0xb0, + 0xe9, 0x09, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x91, 0xb2, 0x22, 0x47, 0x6b, 0x71, 0x41, 0x7e, + 0x5e, 0x31, 0xc4, 0x3d, 0xee, 0x64, 0xb8, 0xc7, 0x9d, 0x7c, 0xf7, 0xb8, 0xe3, 0x73, 0xcf, 0x22, + 0x46, 0x2e, 0x69, 0x84, 0x83, 0x8b, 0x4b, 0x73, 0x4a, 0x8a, 0x51, 0x9c, 0xe5, 0x40, 0xac, 0x5f, + 0x31, 0xb4, 0xc2, 0x5c, 0xe7, 0x48, 0x81, 0x09, 0x48, 0x8e, 0x74, 0x27, 0xdf, 0x91, 0xee, 0x14, + 0x3b, 0xd2, 0x9d, 0x08, 0x47, 0xce, 0x64, 0xe4, 0x92, 0x08, 0x4e, 0x2d, 0x09, 0xa9, 0xf0, 0xcc, + 0x4b, 0x49, 0xad, 0x48, 0x2d, 0x42, 0x71, 0xa1, 0x2d, 0xc1, 0x40, 0xc0, 0xaa, 0x0f, 0xe6, 0x3c, + 0x3b, 0x72, 0xb5, 0x23, 0xb9, 0xcd, 0x9d, 0x4c, 0xb7, 0xb9, 0x53, 0xe6, 0x36, 0x77, 0x42, 0x6e, + 0x43, 0x4e, 0x81, 0xd8, 0x9c, 0x47, 0x64, 0x0a, 0xc4, 0xe3, 0x42, 0x47, 0x0a, 0x4c, 0xc0, 0x92, + 0x02, 0xc9, 0x70, 0xa4, 0x3b, 0xc5, 0x8e, 0x74, 0x27, 0xec, 0x48, 0x27, 0x89, 0x13, 0x8f, 0xe4, + 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, + 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x48, 0x62, 0x03, 0x97, 0x8f, 0xc6, 0x80, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7b, 0x8e, 0x2b, 0x5d, 0x97, 0x05, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// PruningServiceClient is the client API for PruningService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type PruningServiceClient interface { + // SetBlockRetainHeightRequest indicates to the node that it can safely + // prune all block data up to the specified retain height. + // + // The lower of this retain height and that set by the application in its + // Commit response will be used by the node to determine which heights' data + // can be pruned. + SetBlockRetainHeight(ctx context.Context, in *SetBlockRetainHeightRequest, opts ...grpc.CallOption) (*SetBlockRetainHeightResponse, error) + // GetBlockRetainHeight returns information about the retain height + // parameters used by the node to influence block retention/pruning. + GetBlockRetainHeight(ctx context.Context, in *GetBlockRetainHeightRequest, opts ...grpc.CallOption) (*GetBlockRetainHeightResponse, error) + // SetBlockResultsRetainHeightRequest indicates to the node that it can + // safely prune all block results data up to the specified height. + // + // The node will always store the block results for the latest height to + // help facilitate crash recovery. + SetBlockResultsRetainHeight(ctx context.Context, in *SetBlockResultsRetainHeightRequest, opts ...grpc.CallOption) (*SetBlockResultsRetainHeightResponse, error) + // GetBlockResultsRetainHeight returns information about the retain height + // parameters used by the node to influence block results retention/pruning. + GetBlockResultsRetainHeight(ctx context.Context, in *GetBlockResultsRetainHeightRequest, opts ...grpc.CallOption) (*GetBlockResultsRetainHeightResponse, error) + // SetTxIndexerRetainHeightRequest indicates to the node that it can safely + // prune all tx indices up to the specified retain height. + SetTxIndexerRetainHeight(ctx context.Context, in *SetTxIndexerRetainHeightRequest, opts ...grpc.CallOption) (*SetTxIndexerRetainHeightResponse, error) + // GetTxIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence TxIndexer pruning + GetTxIndexerRetainHeight(ctx context.Context, in *GetTxIndexerRetainHeightRequest, opts ...grpc.CallOption) (*GetTxIndexerRetainHeightResponse, error) + // SetBlockIndexerRetainHeightRequest indicates to the node that it can safely + // prune all block indices up to the specified retain height. + SetBlockIndexerRetainHeight(ctx context.Context, in *SetBlockIndexerRetainHeightRequest, opts ...grpc.CallOption) (*SetBlockIndexerRetainHeightResponse, error) + // GetBlockIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence BlockIndexer pruning + GetBlockIndexerRetainHeight(ctx context.Context, in *GetBlockIndexerRetainHeightRequest, opts ...grpc.CallOption) (*GetBlockIndexerRetainHeightResponse, error) +} + +type pruningServiceClient struct { + cc grpc1.ClientConn +} + +func NewPruningServiceClient(cc grpc1.ClientConn) PruningServiceClient { + return &pruningServiceClient{cc} +} + +func (c *pruningServiceClient) SetBlockRetainHeight(ctx context.Context, in *SetBlockRetainHeightRequest, opts ...grpc.CallOption) (*SetBlockRetainHeightResponse, error) { + out := new(SetBlockRetainHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.pruning.v1.PruningService/SetBlockRetainHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pruningServiceClient) GetBlockRetainHeight(ctx context.Context, in *GetBlockRetainHeightRequest, opts ...grpc.CallOption) (*GetBlockRetainHeightResponse, error) { + out := new(GetBlockRetainHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.pruning.v1.PruningService/GetBlockRetainHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pruningServiceClient) SetBlockResultsRetainHeight(ctx context.Context, in *SetBlockResultsRetainHeightRequest, opts ...grpc.CallOption) (*SetBlockResultsRetainHeightResponse, error) { + out := new(SetBlockResultsRetainHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.pruning.v1.PruningService/SetBlockResultsRetainHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pruningServiceClient) GetBlockResultsRetainHeight(ctx context.Context, in *GetBlockResultsRetainHeightRequest, opts ...grpc.CallOption) (*GetBlockResultsRetainHeightResponse, error) { + out := new(GetBlockResultsRetainHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.pruning.v1.PruningService/GetBlockResultsRetainHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pruningServiceClient) SetTxIndexerRetainHeight(ctx context.Context, in *SetTxIndexerRetainHeightRequest, opts ...grpc.CallOption) (*SetTxIndexerRetainHeightResponse, error) { + out := new(SetTxIndexerRetainHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.pruning.v1.PruningService/SetTxIndexerRetainHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pruningServiceClient) GetTxIndexerRetainHeight(ctx context.Context, in *GetTxIndexerRetainHeightRequest, opts ...grpc.CallOption) (*GetTxIndexerRetainHeightResponse, error) { + out := new(GetTxIndexerRetainHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.pruning.v1.PruningService/GetTxIndexerRetainHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pruningServiceClient) SetBlockIndexerRetainHeight(ctx context.Context, in *SetBlockIndexerRetainHeightRequest, opts ...grpc.CallOption) (*SetBlockIndexerRetainHeightResponse, error) { + out := new(SetBlockIndexerRetainHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.pruning.v1.PruningService/SetBlockIndexerRetainHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *pruningServiceClient) GetBlockIndexerRetainHeight(ctx context.Context, in *GetBlockIndexerRetainHeightRequest, opts ...grpc.CallOption) (*GetBlockIndexerRetainHeightResponse, error) { + out := new(GetBlockIndexerRetainHeightResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.pruning.v1.PruningService/GetBlockIndexerRetainHeight", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// PruningServiceServer is the server API for PruningService service. +type PruningServiceServer interface { + // SetBlockRetainHeightRequest indicates to the node that it can safely + // prune all block data up to the specified retain height. + // + // The lower of this retain height and that set by the application in its + // Commit response will be used by the node to determine which heights' data + // can be pruned. + SetBlockRetainHeight(context.Context, *SetBlockRetainHeightRequest) (*SetBlockRetainHeightResponse, error) + // GetBlockRetainHeight returns information about the retain height + // parameters used by the node to influence block retention/pruning. + GetBlockRetainHeight(context.Context, *GetBlockRetainHeightRequest) (*GetBlockRetainHeightResponse, error) + // SetBlockResultsRetainHeightRequest indicates to the node that it can + // safely prune all block results data up to the specified height. + // + // The node will always store the block results for the latest height to + // help facilitate crash recovery. + SetBlockResultsRetainHeight(context.Context, *SetBlockResultsRetainHeightRequest) (*SetBlockResultsRetainHeightResponse, error) + // GetBlockResultsRetainHeight returns information about the retain height + // parameters used by the node to influence block results retention/pruning. + GetBlockResultsRetainHeight(context.Context, *GetBlockResultsRetainHeightRequest) (*GetBlockResultsRetainHeightResponse, error) + // SetTxIndexerRetainHeightRequest indicates to the node that it can safely + // prune all tx indices up to the specified retain height. + SetTxIndexerRetainHeight(context.Context, *SetTxIndexerRetainHeightRequest) (*SetTxIndexerRetainHeightResponse, error) + // GetTxIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence TxIndexer pruning + GetTxIndexerRetainHeight(context.Context, *GetTxIndexerRetainHeightRequest) (*GetTxIndexerRetainHeightResponse, error) + // SetBlockIndexerRetainHeightRequest indicates to the node that it can safely + // prune all block indices up to the specified retain height. + SetBlockIndexerRetainHeight(context.Context, *SetBlockIndexerRetainHeightRequest) (*SetBlockIndexerRetainHeightResponse, error) + // GetBlockIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence BlockIndexer pruning + GetBlockIndexerRetainHeight(context.Context, *GetBlockIndexerRetainHeightRequest) (*GetBlockIndexerRetainHeightResponse, error) +} + +// UnimplementedPruningServiceServer can be embedded to have forward compatible implementations. +type UnimplementedPruningServiceServer struct { +} + +func (*UnimplementedPruningServiceServer) SetBlockRetainHeight(ctx context.Context, req *SetBlockRetainHeightRequest) (*SetBlockRetainHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetBlockRetainHeight not implemented") +} +func (*UnimplementedPruningServiceServer) GetBlockRetainHeight(ctx context.Context, req *GetBlockRetainHeightRequest) (*GetBlockRetainHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBlockRetainHeight not implemented") +} +func (*UnimplementedPruningServiceServer) SetBlockResultsRetainHeight(ctx context.Context, req *SetBlockResultsRetainHeightRequest) (*SetBlockResultsRetainHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetBlockResultsRetainHeight not implemented") +} +func (*UnimplementedPruningServiceServer) GetBlockResultsRetainHeight(ctx context.Context, req *GetBlockResultsRetainHeightRequest) (*GetBlockResultsRetainHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBlockResultsRetainHeight not implemented") +} +func (*UnimplementedPruningServiceServer) SetTxIndexerRetainHeight(ctx context.Context, req *SetTxIndexerRetainHeightRequest) (*SetTxIndexerRetainHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetTxIndexerRetainHeight not implemented") +} +func (*UnimplementedPruningServiceServer) GetTxIndexerRetainHeight(ctx context.Context, req *GetTxIndexerRetainHeightRequest) (*GetTxIndexerRetainHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTxIndexerRetainHeight not implemented") +} +func (*UnimplementedPruningServiceServer) SetBlockIndexerRetainHeight(ctx context.Context, req *SetBlockIndexerRetainHeightRequest) (*SetBlockIndexerRetainHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetBlockIndexerRetainHeight not implemented") +} +func (*UnimplementedPruningServiceServer) GetBlockIndexerRetainHeight(ctx context.Context, req *GetBlockIndexerRetainHeightRequest) (*GetBlockIndexerRetainHeightResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBlockIndexerRetainHeight not implemented") +} + +func RegisterPruningServiceServer(s grpc1.Server, srv PruningServiceServer) { + s.RegisterService(&_PruningService_serviceDesc, srv) +} + +func _PruningService_SetBlockRetainHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetBlockRetainHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PruningServiceServer).SetBlockRetainHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.pruning.v1.PruningService/SetBlockRetainHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PruningServiceServer).SetBlockRetainHeight(ctx, req.(*SetBlockRetainHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PruningService_GetBlockRetainHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBlockRetainHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PruningServiceServer).GetBlockRetainHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.pruning.v1.PruningService/GetBlockRetainHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PruningServiceServer).GetBlockRetainHeight(ctx, req.(*GetBlockRetainHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PruningService_SetBlockResultsRetainHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetBlockResultsRetainHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PruningServiceServer).SetBlockResultsRetainHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.pruning.v1.PruningService/SetBlockResultsRetainHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PruningServiceServer).SetBlockResultsRetainHeight(ctx, req.(*SetBlockResultsRetainHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PruningService_GetBlockResultsRetainHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBlockResultsRetainHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PruningServiceServer).GetBlockResultsRetainHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.pruning.v1.PruningService/GetBlockResultsRetainHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PruningServiceServer).GetBlockResultsRetainHeight(ctx, req.(*GetBlockResultsRetainHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PruningService_SetTxIndexerRetainHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetTxIndexerRetainHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PruningServiceServer).SetTxIndexerRetainHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.pruning.v1.PruningService/SetTxIndexerRetainHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PruningServiceServer).SetTxIndexerRetainHeight(ctx, req.(*SetTxIndexerRetainHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PruningService_GetTxIndexerRetainHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTxIndexerRetainHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PruningServiceServer).GetTxIndexerRetainHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.pruning.v1.PruningService/GetTxIndexerRetainHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PruningServiceServer).GetTxIndexerRetainHeight(ctx, req.(*GetTxIndexerRetainHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PruningService_SetBlockIndexerRetainHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetBlockIndexerRetainHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PruningServiceServer).SetBlockIndexerRetainHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.pruning.v1.PruningService/SetBlockIndexerRetainHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PruningServiceServer).SetBlockIndexerRetainHeight(ctx, req.(*SetBlockIndexerRetainHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _PruningService_GetBlockIndexerRetainHeight_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBlockIndexerRetainHeightRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PruningServiceServer).GetBlockIndexerRetainHeight(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.pruning.v1.PruningService/GetBlockIndexerRetainHeight", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PruningServiceServer).GetBlockIndexerRetainHeight(ctx, req.(*GetBlockIndexerRetainHeightRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _PruningService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.services.pruning.v1.PruningService", + HandlerType: (*PruningServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SetBlockRetainHeight", + Handler: _PruningService_SetBlockRetainHeight_Handler, + }, + { + MethodName: "GetBlockRetainHeight", + Handler: _PruningService_GetBlockRetainHeight_Handler, + }, + { + MethodName: "SetBlockResultsRetainHeight", + Handler: _PruningService_SetBlockResultsRetainHeight_Handler, + }, + { + MethodName: "GetBlockResultsRetainHeight", + Handler: _PruningService_GetBlockResultsRetainHeight_Handler, + }, + { + MethodName: "SetTxIndexerRetainHeight", + Handler: _PruningService_SetTxIndexerRetainHeight_Handler, + }, + { + MethodName: "GetTxIndexerRetainHeight", + Handler: _PruningService_GetTxIndexerRetainHeight_Handler, + }, + { + MethodName: "SetBlockIndexerRetainHeight", + Handler: _PruningService_SetBlockIndexerRetainHeight_Handler, + }, + { + MethodName: "GetBlockIndexerRetainHeight", + Handler: _PruningService_GetBlockIndexerRetainHeight_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/services/pruning/v1/service.proto", +} diff --git a/api/cometbft/services/version/v1/version.pb.go b/api/cometbft/services/version/v1/version.pb.go new file mode 100644 index 00000000000..db93157155a --- /dev/null +++ b/api/cometbft/services/version/v1/version.pb.go @@ -0,0 +1,562 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/services/version/v1/version.proto + +package v1 + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GetVersionRequest is the request for the ABCI version. +type GetVersionRequest struct { +} + +func (m *GetVersionRequest) Reset() { *m = GetVersionRequest{} } +func (m *GetVersionRequest) String() string { return proto.CompactTextString(m) } +func (*GetVersionRequest) ProtoMessage() {} +func (*GetVersionRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_0d34df0ab45614ed, []int{0} +} +func (m *GetVersionRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetVersionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetVersionRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetVersionRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetVersionRequest.Merge(m, src) +} +func (m *GetVersionRequest) XXX_Size() int { + return m.Size() +} +func (m *GetVersionRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetVersionRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetVersionRequest proto.InternalMessageInfo + +// GetVersionResponse contains the ABCI application version info. +type GetVersionResponse struct { + Node string `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` + Abci string `protobuf:"bytes,2,opt,name=abci,proto3" json:"abci,omitempty"` + P2P uint64 `protobuf:"varint,3,opt,name=p2p,proto3" json:"p2p,omitempty"` + Block uint64 `protobuf:"varint,4,opt,name=block,proto3" json:"block,omitempty"` +} + +func (m *GetVersionResponse) Reset() { *m = GetVersionResponse{} } +func (m *GetVersionResponse) String() string { return proto.CompactTextString(m) } +func (*GetVersionResponse) ProtoMessage() {} +func (*GetVersionResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_0d34df0ab45614ed, []int{1} +} +func (m *GetVersionResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GetVersionResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GetVersionResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GetVersionResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetVersionResponse.Merge(m, src) +} +func (m *GetVersionResponse) XXX_Size() int { + return m.Size() +} +func (m *GetVersionResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetVersionResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetVersionResponse proto.InternalMessageInfo + +func (m *GetVersionResponse) GetNode() string { + if m != nil { + return m.Node + } + return "" +} + +func (m *GetVersionResponse) GetAbci() string { + if m != nil { + return m.Abci + } + return "" +} + +func (m *GetVersionResponse) GetP2P() uint64 { + if m != nil { + return m.P2P + } + return 0 +} + +func (m *GetVersionResponse) GetBlock() uint64 { + if m != nil { + return m.Block + } + return 0 +} + +func init() { + proto.RegisterType((*GetVersionRequest)(nil), "cometbft.services.version.v1.GetVersionRequest") + proto.RegisterType((*GetVersionResponse)(nil), "cometbft.services.version.v1.GetVersionResponse") +} + +func init() { + proto.RegisterFile("cometbft/services/version/v1/version.proto", fileDescriptor_0d34df0ab45614ed) +} + +var fileDescriptor_0d34df0ab45614ed = []byte{ + // 218 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4a, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x2d, 0xd6, 0x2f, 0x4b, + 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0xd3, 0x2f, 0x33, 0x84, 0x31, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, + 0x85, 0x64, 0x60, 0x6a, 0xf5, 0x60, 0x6a, 0xf5, 0x60, 0x0a, 0xca, 0x0c, 0x95, 0x84, 0xb9, 0x04, + 0xdd, 0x53, 0x4b, 0xc2, 0x20, 0x02, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x4a, 0x29, 0x5c, + 0x42, 0xc8, 0x82, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x42, 0x5c, 0x2c, 0x79, 0xf9, 0x29, + 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0x36, 0x48, 0x2c, 0x31, 0x29, 0x39, 0x53, + 0x82, 0x09, 0x22, 0x06, 0x62, 0x0b, 0x09, 0x70, 0x31, 0x17, 0x18, 0x15, 0x48, 0x30, 0x2b, 0x30, + 0x6a, 0xb0, 0x04, 0x81, 0x98, 0x42, 0x22, 0x5c, 0xac, 0x49, 0x39, 0xf9, 0xc9, 0xd9, 0x12, 0x2c, + 0x60, 0x31, 0x08, 0xc7, 0x29, 0xfc, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, + 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, + 0x6c, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xe1, 0x3e, 0x85, 0x33, + 0x12, 0x0b, 0x32, 0xf5, 0xf1, 0xf9, 0x3f, 0x89, 0x0d, 0xec, 0x71, 0x63, 0x40, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xb1, 0x8f, 0xf3, 0x3e, 0x26, 0x01, 0x00, 0x00, +} + +func (m *GetVersionRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetVersionRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetVersionRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GetVersionResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetVersionResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GetVersionResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Block != 0 { + i = encodeVarintVersion(dAtA, i, uint64(m.Block)) + i-- + dAtA[i] = 0x20 + } + if m.P2P != 0 { + i = encodeVarintVersion(dAtA, i, uint64(m.P2P)) + i-- + dAtA[i] = 0x18 + } + if len(m.Abci) > 0 { + i -= len(m.Abci) + copy(dAtA[i:], m.Abci) + i = encodeVarintVersion(dAtA, i, uint64(len(m.Abci))) + i-- + dAtA[i] = 0x12 + } + if len(m.Node) > 0 { + i -= len(m.Node) + copy(dAtA[i:], m.Node) + i = encodeVarintVersion(dAtA, i, uint64(len(m.Node))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintVersion(dAtA []byte, offset int, v uint64) int { + offset -= sovVersion(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GetVersionRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GetVersionResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Node) + if l > 0 { + n += 1 + l + sovVersion(uint64(l)) + } + l = len(m.Abci) + if l > 0 { + n += 1 + l + sovVersion(uint64(l)) + } + if m.P2P != 0 { + n += 1 + sovVersion(uint64(m.P2P)) + } + if m.Block != 0 { + n += 1 + sovVersion(uint64(m.Block)) + } + return n +} + +func sovVersion(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozVersion(x uint64) (n int) { + return sovVersion(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GetVersionRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVersion + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetVersionRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetVersionRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipVersion(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthVersion + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetVersionResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVersion + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetVersionResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetVersionResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Node", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVersion + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthVersion + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthVersion + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Node = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Abci", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVersion + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthVersion + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthVersion + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Abci = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field P2P", wireType) + } + m.P2P = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVersion + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.P2P |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) + } + m.Block = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVersion + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Block |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipVersion(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthVersion + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipVersion(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVersion + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVersion + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVersion + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthVersion + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupVersion + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthVersion + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthVersion = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowVersion = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupVersion = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/services/version/v1/version_service.pb.go b/api/cometbft/services/version/v1/version_service.pb.go new file mode 100644 index 00000000000..16a6b5956d1 --- /dev/null +++ b/api/cometbft/services/version/v1/version_service.pb.go @@ -0,0 +1,130 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/services/version/v1/version_service.proto + +package v1 + +import ( + context "context" + fmt "fmt" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +func init() { + proto.RegisterFile("cometbft/services/version/v1/version_service.proto", fileDescriptor_054267f78f0fa7a9) +} + +var fileDescriptor_054267f78f0fa7a9 = []byte{ + // 184 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x4a, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x2d, 0xd6, 0x2f, 0x4b, + 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0xd3, 0x2f, 0x33, 0x84, 0x31, 0xe3, 0xa1, 0x72, 0x7a, 0x05, 0x45, + 0xf9, 0x25, 0xf9, 0x42, 0x32, 0x30, 0x3d, 0x7a, 0x30, 0x3d, 0x7a, 0x50, 0x85, 0x7a, 0x65, 0x86, + 0x52, 0x5a, 0xc4, 0x98, 0x08, 0x31, 0xc9, 0xa8, 0x91, 0x91, 0x8b, 0x2f, 0x0c, 0x22, 0x12, 0x0c, + 0x51, 0x2c, 0x94, 0xcf, 0xc5, 0xe5, 0x9e, 0x5a, 0x02, 0x15, 0x14, 0xd2, 0xd7, 0xc3, 0x67, 0x97, + 0x1e, 0x42, 0x65, 0x50, 0x6a, 0x61, 0x69, 0x6a, 0x71, 0x89, 0x94, 0x01, 0xf1, 0x1a, 0x8a, 0x0b, + 0xf2, 0xf3, 0x8a, 0x53, 0x9d, 0xc2, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, + 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, + 0xca, 0x36, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x09, 0x64, 0xa2, 0x3e, 0xdc, 0x53, 0x70, 0x46, 0x62, + 0x41, 0xa6, 0x3e, 0x3e, 0xaf, 0x26, 0xb1, 0x81, 0xfd, 0x68, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, + 0xbb, 0x08, 0xe5, 0x2b, 0x63, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// VersionServiceClient is the client API for VersionService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type VersionServiceClient interface { + // GetVersion retrieves version information about the node and the protocols + // it implements. + GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) +} + +type versionServiceClient struct { + cc grpc1.ClientConn +} + +func NewVersionServiceClient(cc grpc1.ClientConn) VersionServiceClient { + return &versionServiceClient{cc} +} + +func (c *versionServiceClient) GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) { + out := new(GetVersionResponse) + err := c.cc.Invoke(ctx, "/cometbft.services.version.v1.VersionService/GetVersion", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// VersionServiceServer is the server API for VersionService service. +type VersionServiceServer interface { + // GetVersion retrieves version information about the node and the protocols + // it implements. + GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) +} + +// UnimplementedVersionServiceServer can be embedded to have forward compatible implementations. +type UnimplementedVersionServiceServer struct { +} + +func (*UnimplementedVersionServiceServer) GetVersion(ctx context.Context, req *GetVersionRequest) (*GetVersionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented") +} + +func RegisterVersionServiceServer(s grpc1.Server, srv VersionServiceServer) { + s.RegisterService(&_VersionService_serviceDesc, srv) +} + +func _VersionService_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetVersionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VersionServiceServer).GetVersion(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cometbft.services.version.v1.VersionService/GetVersion", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VersionServiceServer).GetVersion(ctx, req.(*GetVersionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _VersionService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cometbft.services.version.v1.VersionService", + HandlerType: (*VersionServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetVersion", + Handler: _VersionService_GetVersion_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cometbft/services/version/v1/version_service.proto", +} diff --git a/proto/tendermint/state/types.pb.go b/api/cometbft/state/v1/types.pb.go similarity index 81% rename from proto/tendermint/state/types.pb.go rename to api/cometbft/state/v1/types.pb.go index 4426543ed9b..feafa3bbe96 100644 --- a/proto/tendermint/state/types.pb.go +++ b/api/cometbft/state/v1/types.pb.go @@ -1,13 +1,13 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/state/types.proto +// source: cometbft/state/v1/types.proto -package state +package v1 import ( fmt "fmt" - types "github.com/cometbft/cometbft/abci/types" - types1 "github.com/cometbft/cometbft/proto/tendermint/types" - version "github.com/cometbft/cometbft/proto/tendermint/version" + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" + v11 "github.com/cometbft/cometbft/api/cometbft/types/v1" + v12 "github.com/cometbft/cometbft/api/cometbft/version/v1" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" _ "github.com/cosmos/gogoproto/types" @@ -35,16 +35,16 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Note ReponseDeliverTx is renamed to ExecTxResult but they are semantically the same // Kept for backwards compatibility for versions prior to v0.38 type LegacyABCIResponses struct { - DeliverTxs []*types.ExecTxResult `protobuf:"bytes,1,rep,name=deliver_txs,json=deliverTxs,proto3" json:"deliver_txs,omitempty"` - EndBlock *ResponseEndBlock `protobuf:"bytes,2,opt,name=end_block,json=endBlock,proto3" json:"end_block,omitempty"` - BeginBlock *ResponseBeginBlock `protobuf:"bytes,3,opt,name=begin_block,json=beginBlock,proto3" json:"begin_block,omitempty"` + DeliverTxs []*v1.ExecTxResult `protobuf:"bytes,1,rep,name=deliver_txs,json=deliverTxs,proto3" json:"deliver_txs,omitempty"` + EndBlock *ResponseEndBlock `protobuf:"bytes,2,opt,name=end_block,json=endBlock,proto3" json:"end_block,omitempty"` + BeginBlock *ResponseBeginBlock `protobuf:"bytes,3,opt,name=begin_block,json=beginBlock,proto3" json:"begin_block,omitempty"` } func (m *LegacyABCIResponses) Reset() { *m = LegacyABCIResponses{} } func (m *LegacyABCIResponses) String() string { return proto.CompactTextString(m) } func (*LegacyABCIResponses) ProtoMessage() {} func (*LegacyABCIResponses) Descriptor() ([]byte, []int) { - return fileDescriptor_ccfacf933f22bf93, []int{0} + return fileDescriptor_eb6b2e03ecdbc0c2, []int{0} } func (m *LegacyABCIResponses) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -73,7 +73,7 @@ func (m *LegacyABCIResponses) XXX_DiscardUnknown() { var xxx_messageInfo_LegacyABCIResponses proto.InternalMessageInfo -func (m *LegacyABCIResponses) GetDeliverTxs() []*types.ExecTxResult { +func (m *LegacyABCIResponses) GetDeliverTxs() []*v1.ExecTxResult { if m != nil { return m.DeliverTxs } @@ -94,16 +94,17 @@ func (m *LegacyABCIResponses) GetBeginBlock() *ResponseBeginBlock { return nil } -// ResponseBeginBlock is kept for backwards compatibility for versions prior to v0.38 +// ResponseBeginBlock is kept for backward compatibility for versions prior to v0.38, +// as it was then defined in the cometbft.abci packages. type ResponseBeginBlock struct { - Events []types.Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` + Events []v1.Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` } func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } func (*ResponseBeginBlock) ProtoMessage() {} func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_ccfacf933f22bf93, []int{1} + return fileDescriptor_eb6b2e03ecdbc0c2, []int{1} } func (m *ResponseBeginBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -132,25 +133,28 @@ func (m *ResponseBeginBlock) XXX_DiscardUnknown() { var xxx_messageInfo_ResponseBeginBlock proto.InternalMessageInfo -func (m *ResponseBeginBlock) GetEvents() []types.Event { +func (m *ResponseBeginBlock) GetEvents() []v1.Event { if m != nil { return m.Events } return nil } -// ResponseEndBlock is kept for backwards compatibility for versions prior to v0.38 +// ResponseEndBlock is kept for backward compatibility for versions prior to v0.38, +// its earlier revisions were defined in the cometbft.abci packages. +// It uses an updated definition for the consensus_param_updates field to keep the +// generated data types interoperable with the latest protocol. type ResponseEndBlock struct { - ValidatorUpdates []types.ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` - ConsensusParamUpdates *types1.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` - Events []types.Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` + ValidatorUpdates []v1.ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` + ConsensusParamUpdates *v11.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` + Events []v1.Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` } func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } func (*ResponseEndBlock) ProtoMessage() {} func (*ResponseEndBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_ccfacf933f22bf93, []int{2} + return fileDescriptor_eb6b2e03ecdbc0c2, []int{2} } func (m *ResponseEndBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -179,21 +183,21 @@ func (m *ResponseEndBlock) XXX_DiscardUnknown() { var xxx_messageInfo_ResponseEndBlock proto.InternalMessageInfo -func (m *ResponseEndBlock) GetValidatorUpdates() []types.ValidatorUpdate { +func (m *ResponseEndBlock) GetValidatorUpdates() []v1.ValidatorUpdate { if m != nil { return m.ValidatorUpdates } return nil } -func (m *ResponseEndBlock) GetConsensusParamUpdates() *types1.ConsensusParams { +func (m *ResponseEndBlock) GetConsensusParamUpdates() *v11.ConsensusParams { if m != nil { return m.ConsensusParamUpdates } return nil } -func (m *ResponseEndBlock) GetEvents() []types.Event { +func (m *ResponseEndBlock) GetEvents() []v1.Event { if m != nil { return m.Events } @@ -202,15 +206,15 @@ func (m *ResponseEndBlock) GetEvents() []types.Event { // ValidatorsInfo represents the latest validator set, or the last height it changed type ValidatorsInfo struct { - ValidatorSet *types1.ValidatorSet `protobuf:"bytes,1,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty"` - LastHeightChanged int64 `protobuf:"varint,2,opt,name=last_height_changed,json=lastHeightChanged,proto3" json:"last_height_changed,omitempty"` + ValidatorSet *v11.ValidatorSet `protobuf:"bytes,1,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty"` + LastHeightChanged int64 `protobuf:"varint,2,opt,name=last_height_changed,json=lastHeightChanged,proto3" json:"last_height_changed,omitempty"` } func (m *ValidatorsInfo) Reset() { *m = ValidatorsInfo{} } func (m *ValidatorsInfo) String() string { return proto.CompactTextString(m) } func (*ValidatorsInfo) ProtoMessage() {} func (*ValidatorsInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_ccfacf933f22bf93, []int{3} + return fileDescriptor_eb6b2e03ecdbc0c2, []int{3} } func (m *ValidatorsInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -239,7 +243,7 @@ func (m *ValidatorsInfo) XXX_DiscardUnknown() { var xxx_messageInfo_ValidatorsInfo proto.InternalMessageInfo -func (m *ValidatorsInfo) GetValidatorSet() *types1.ValidatorSet { +func (m *ValidatorsInfo) GetValidatorSet() *v11.ValidatorSet { if m != nil { return m.ValidatorSet } @@ -255,15 +259,15 @@ func (m *ValidatorsInfo) GetLastHeightChanged() int64 { // ConsensusParamsInfo represents the latest consensus params, or the last height it changed type ConsensusParamsInfo struct { - ConsensusParams types1.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` - LastHeightChanged int64 `protobuf:"varint,2,opt,name=last_height_changed,json=lastHeightChanged,proto3" json:"last_height_changed,omitempty"` + ConsensusParams v11.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightChanged int64 `protobuf:"varint,2,opt,name=last_height_changed,json=lastHeightChanged,proto3" json:"last_height_changed,omitempty"` } func (m *ConsensusParamsInfo) Reset() { *m = ConsensusParamsInfo{} } func (m *ConsensusParamsInfo) String() string { return proto.CompactTextString(m) } func (*ConsensusParamsInfo) ProtoMessage() {} func (*ConsensusParamsInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_ccfacf933f22bf93, []int{4} + return fileDescriptor_eb6b2e03ecdbc0c2, []int{4} } func (m *ConsensusParamsInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -292,11 +296,11 @@ func (m *ConsensusParamsInfo) XXX_DiscardUnknown() { var xxx_messageInfo_ConsensusParamsInfo proto.InternalMessageInfo -func (m *ConsensusParamsInfo) GetConsensusParams() types1.ConsensusParams { +func (m *ConsensusParamsInfo) GetConsensusParams() v11.ConsensusParams { if m != nil { return m.ConsensusParams } - return types1.ConsensusParams{} + return v11.ConsensusParams{} } func (m *ConsensusParamsInfo) GetLastHeightChanged() int64 { @@ -306,17 +310,19 @@ func (m *ConsensusParamsInfo) GetLastHeightChanged() int64 { return 0 } +// ABCIResponsesInfo retains the responses of the ABCI calls during block processing. type ABCIResponsesInfo struct { - LegacyAbciResponses *LegacyABCIResponses `protobuf:"bytes,1,opt,name=legacy_abci_responses,json=legacyAbciResponses,proto3" json:"legacy_abci_responses,omitempty"` - Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` - ResponseFinalizeBlock *types.ResponseFinalizeBlock `protobuf:"bytes,3,opt,name=response_finalize_block,json=responseFinalizeBlock,proto3" json:"response_finalize_block,omitempty"` + // Retains the responses of the legacy ABCI calls during block processing. + LegacyAbciResponses *LegacyABCIResponses `protobuf:"bytes,1,opt,name=legacy_abci_responses,json=legacyAbciResponses,proto3" json:"legacy_abci_responses,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + FinalizeBlock *v1.FinalizeBlockResponse `protobuf:"bytes,3,opt,name=finalize_block,json=finalizeBlock,proto3" json:"finalize_block,omitempty"` } func (m *ABCIResponsesInfo) Reset() { *m = ABCIResponsesInfo{} } func (m *ABCIResponsesInfo) String() string { return proto.CompactTextString(m) } func (*ABCIResponsesInfo) ProtoMessage() {} func (*ABCIResponsesInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_ccfacf933f22bf93, []int{5} + return fileDescriptor_eb6b2e03ecdbc0c2, []int{5} } func (m *ABCIResponsesInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -359,23 +365,24 @@ func (m *ABCIResponsesInfo) GetHeight() int64 { return 0 } -func (m *ABCIResponsesInfo) GetResponseFinalizeBlock() *types.ResponseFinalizeBlock { +func (m *ABCIResponsesInfo) GetFinalizeBlock() *v1.FinalizeBlockResponse { if m != nil { - return m.ResponseFinalizeBlock + return m.FinalizeBlock } return nil } +// Version is a message for storing versioning information. type Version struct { - Consensus version.Consensus `protobuf:"bytes,1,opt,name=consensus,proto3" json:"consensus"` - Software string `protobuf:"bytes,2,opt,name=software,proto3" json:"software,omitempty"` + Consensus v12.Consensus `protobuf:"bytes,1,opt,name=consensus,proto3" json:"consensus"` + Software string `protobuf:"bytes,2,opt,name=software,proto3" json:"software,omitempty"` } func (m *Version) Reset() { *m = Version{} } func (m *Version) String() string { return proto.CompactTextString(m) } func (*Version) ProtoMessage() {} func (*Version) Descriptor() ([]byte, []int) { - return fileDescriptor_ccfacf933f22bf93, []int{6} + return fileDescriptor_eb6b2e03ecdbc0c2, []int{6} } func (m *Version) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -404,11 +411,11 @@ func (m *Version) XXX_DiscardUnknown() { var xxx_messageInfo_Version proto.InternalMessageInfo -func (m *Version) GetConsensus() version.Consensus { +func (m *Version) GetConsensus() v12.Consensus { if m != nil { return m.Consensus } - return version.Consensus{} + return v12.Consensus{} } func (m *Version) GetSoftware() string { @@ -418,29 +425,30 @@ func (m *Version) GetSoftware() string { return "" } +// State represents the state of the blockchain. type State struct { Version Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version"` // immutable ChainID string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` InitialHeight int64 `protobuf:"varint,14,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) - LastBlockHeight int64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` - LastBlockID types1.BlockID `protobuf:"bytes,4,opt,name=last_block_id,json=lastBlockId,proto3" json:"last_block_id"` - LastBlockTime time.Time `protobuf:"bytes,5,opt,name=last_block_time,json=lastBlockTime,proto3,stdtime" json:"last_block_time"` + LastBlockHeight int64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` + LastBlockID v11.BlockID `protobuf:"bytes,4,opt,name=last_block_id,json=lastBlockId,proto3" json:"last_block_id"` + LastBlockTime time.Time `protobuf:"bytes,5,opt,name=last_block_time,json=lastBlockTime,proto3,stdtime" json:"last_block_time"` // LastValidators is used to validate block.LastCommit. // Validators are persisted to the database separately every time they change, // so we can query for historical validator sets. // Note that if s.LastBlockHeight causes a valset change, // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 // Extra +1 due to nextValSet delay. - NextValidators *types1.ValidatorSet `protobuf:"bytes,6,opt,name=next_validators,json=nextValidators,proto3" json:"next_validators,omitempty"` - Validators *types1.ValidatorSet `protobuf:"bytes,7,opt,name=validators,proto3" json:"validators,omitempty"` - LastValidators *types1.ValidatorSet `protobuf:"bytes,8,opt,name=last_validators,json=lastValidators,proto3" json:"last_validators,omitempty"` - LastHeightValidatorsChanged int64 `protobuf:"varint,9,opt,name=last_height_validators_changed,json=lastHeightValidatorsChanged,proto3" json:"last_height_validators_changed,omitempty"` + NextValidators *v11.ValidatorSet `protobuf:"bytes,6,opt,name=next_validators,json=nextValidators,proto3" json:"next_validators,omitempty"` + Validators *v11.ValidatorSet `protobuf:"bytes,7,opt,name=validators,proto3" json:"validators,omitempty"` + LastValidators *v11.ValidatorSet `protobuf:"bytes,8,opt,name=last_validators,json=lastValidators,proto3" json:"last_validators,omitempty"` + LastHeightValidatorsChanged int64 `protobuf:"varint,9,opt,name=last_height_validators_changed,json=lastHeightValidatorsChanged,proto3" json:"last_height_validators_changed,omitempty"` // Consensus parameters used for validating blocks. // Changes returned by EndBlock and updated after Commit. - ConsensusParams types1.ConsensusParams `protobuf:"bytes,10,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` - LastHeightConsensusParamsChanged int64 `protobuf:"varint,11,opt,name=last_height_consensus_params_changed,json=lastHeightConsensusParamsChanged,proto3" json:"last_height_consensus_params_changed,omitempty"` + ConsensusParams v11.ConsensusParams `protobuf:"bytes,10,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightConsensusParamsChanged int64 `protobuf:"varint,11,opt,name=last_height_consensus_params_changed,json=lastHeightConsensusParamsChanged,proto3" json:"last_height_consensus_params_changed,omitempty"` // Merkle root of the results from executing prev block LastResultsHash []byte `protobuf:"bytes,12,opt,name=last_results_hash,json=lastResultsHash,proto3" json:"last_results_hash,omitempty"` // the latest AppHash we've received from calling abci.Commit() @@ -451,7 +459,7 @@ func (m *State) Reset() { *m = State{} } func (m *State) String() string { return proto.CompactTextString(m) } func (*State) ProtoMessage() {} func (*State) Descriptor() ([]byte, []int) { - return fileDescriptor_ccfacf933f22bf93, []int{7} + return fileDescriptor_eb6b2e03ecdbc0c2, []int{7} } func (m *State) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -508,11 +516,11 @@ func (m *State) GetLastBlockHeight() int64 { return 0 } -func (m *State) GetLastBlockID() types1.BlockID { +func (m *State) GetLastBlockID() v11.BlockID { if m != nil { return m.LastBlockID } - return types1.BlockID{} + return v11.BlockID{} } func (m *State) GetLastBlockTime() time.Time { @@ -522,21 +530,21 @@ func (m *State) GetLastBlockTime() time.Time { return time.Time{} } -func (m *State) GetNextValidators() *types1.ValidatorSet { +func (m *State) GetNextValidators() *v11.ValidatorSet { if m != nil { return m.NextValidators } return nil } -func (m *State) GetValidators() *types1.ValidatorSet { +func (m *State) GetValidators() *v11.ValidatorSet { if m != nil { return m.Validators } return nil } -func (m *State) GetLastValidators() *types1.ValidatorSet { +func (m *State) GetLastValidators() *v11.ValidatorSet { if m != nil { return m.LastValidators } @@ -550,11 +558,11 @@ func (m *State) GetLastHeightValidatorsChanged() int64 { return 0 } -func (m *State) GetConsensusParams() types1.ConsensusParams { +func (m *State) GetConsensusParams() v11.ConsensusParams { if m != nil { return m.ConsensusParams } - return types1.ConsensusParams{} + return v11.ConsensusParams{} } func (m *State) GetLastHeightConsensusParamsChanged() int64 { @@ -579,81 +587,81 @@ func (m *State) GetAppHash() []byte { } func init() { - proto.RegisterType((*LegacyABCIResponses)(nil), "tendermint.state.LegacyABCIResponses") - proto.RegisterType((*ResponseBeginBlock)(nil), "tendermint.state.ResponseBeginBlock") - proto.RegisterType((*ResponseEndBlock)(nil), "tendermint.state.ResponseEndBlock") - proto.RegisterType((*ValidatorsInfo)(nil), "tendermint.state.ValidatorsInfo") - proto.RegisterType((*ConsensusParamsInfo)(nil), "tendermint.state.ConsensusParamsInfo") - proto.RegisterType((*ABCIResponsesInfo)(nil), "tendermint.state.ABCIResponsesInfo") - proto.RegisterType((*Version)(nil), "tendermint.state.Version") - proto.RegisterType((*State)(nil), "tendermint.state.State") -} - -func init() { proto.RegisterFile("tendermint/state/types.proto", fileDescriptor_ccfacf933f22bf93) } - -var fileDescriptor_ccfacf933f22bf93 = []byte{ - // 963 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x4b, 0x6f, 0xdb, 0x46, - 0x17, 0x35, 0xe3, 0x44, 0x8f, 0x2b, 0xcb, 0x96, 0x47, 0x9f, 0x13, 0x45, 0xf9, 0x22, 0xa9, 0x42, - 0x12, 0x18, 0x45, 0x41, 0x01, 0xc9, 0xaa, 0x9b, 0x14, 0x96, 0xec, 0xd6, 0x02, 0xdc, 0xa2, 0xa0, - 0xdd, 0x00, 0xe9, 0x22, 0xc4, 0x88, 0x1c, 0x49, 0x83, 0x4a, 0x24, 0xc1, 0x19, 0xa9, 0x72, 0xf7, - 0xdd, 0x75, 0x91, 0x6d, 0xff, 0x51, 0x96, 0x59, 0x76, 0x53, 0xb7, 0x95, 0x81, 0x2e, 0xfa, 0x2b, - 0x8a, 0x79, 0xf0, 0x25, 0xba, 0xa8, 0x8b, 0xec, 0xc8, 0xb9, 0xe7, 0x9e, 0x7b, 0xee, 0x99, 0xb9, - 0x43, 0xc2, 0xff, 0x39, 0xf1, 0x5c, 0x12, 0xce, 0xa9, 0xc7, 0x7b, 0x8c, 0x63, 0x4e, 0x7a, 0xfc, - 0x32, 0x20, 0xcc, 0x0c, 0x42, 0x9f, 0xfb, 0xa8, 0x96, 0x44, 0x4d, 0x19, 0x6d, 0xfe, 0x6f, 0xe2, - 0x4f, 0x7c, 0x19, 0xec, 0x89, 0x27, 0x85, 0x6b, 0x3e, 0x4a, 0xb1, 0xe0, 0x91, 0x43, 0xd3, 0x24, - 0xcd, 0x74, 0x09, 0xb9, 0x9e, 0x89, 0x76, 0x72, 0xd1, 0x25, 0x9e, 0x51, 0x17, 0x73, 0x3f, 0xd4, - 0x88, 0xc7, 0x39, 0x44, 0x80, 0x43, 0x3c, 0x8f, 0x08, 0x5a, 0xa9, 0xf0, 0x92, 0x84, 0x8c, 0xfa, - 0x5e, 0xa6, 0x40, 0x7b, 0xe2, 0xfb, 0x93, 0x19, 0xe9, 0xc9, 0xb7, 0xd1, 0x62, 0xdc, 0xe3, 0x74, - 0x4e, 0x18, 0xc7, 0xf3, 0x40, 0x01, 0xba, 0xbf, 0x1a, 0x50, 0x3f, 0x23, 0x13, 0xec, 0x5c, 0x1e, - 0xf5, 0x07, 0x43, 0x8b, 0xb0, 0xc0, 0xf7, 0x18, 0x61, 0xe8, 0x25, 0x54, 0x5c, 0x32, 0xa3, 0x4b, - 0x12, 0xda, 0x7c, 0xc5, 0x1a, 0x46, 0x67, 0xfb, 0xb0, 0xf2, 0xfc, 0xb1, 0x99, 0xb2, 0x44, 0xb4, - 0x6a, 0x9e, 0xac, 0x88, 0x73, 0xb1, 0xb2, 0x08, 0x5b, 0xcc, 0xb8, 0x05, 0x3a, 0xe3, 0x62, 0xc5, - 0xd0, 0x67, 0x50, 0x26, 0x9e, 0x6b, 0x8f, 0x66, 0xbe, 0xf3, 0x5d, 0xe3, 0x4e, 0xc7, 0x38, 0xac, - 0x3c, 0xef, 0x9a, 0x9b, 0x86, 0x9a, 0x51, 0xbd, 0x13, 0xcf, 0xed, 0x0b, 0xa4, 0x55, 0x22, 0xfa, - 0x09, 0x9d, 0x40, 0x65, 0x44, 0x26, 0xd4, 0xd3, 0x14, 0xdb, 0x92, 0xe2, 0xc9, 0x3f, 0x53, 0xf4, - 0x05, 0x58, 0x91, 0xc0, 0x28, 0x7e, 0xee, 0xbe, 0x01, 0x94, 0x47, 0xa0, 0x53, 0x28, 0x90, 0x25, - 0xf1, 0x78, 0xd4, 0xd8, 0xfd, 0x7c, 0x63, 0x22, 0xdc, 0x6f, 0xbc, 0xbb, 0x6a, 0x6f, 0xfd, 0x75, - 0xd5, 0xae, 0x29, 0xf4, 0x27, 0xfe, 0x9c, 0x72, 0x32, 0x0f, 0xf8, 0xa5, 0xa5, 0xf3, 0xbb, 0x3f, - 0xdd, 0x81, 0xda, 0x66, 0x17, 0xe8, 0x1c, 0xf6, 0xe3, 0x7d, 0xb4, 0x17, 0x81, 0x8b, 0x39, 0x89, - 0x2a, 0x75, 0x72, 0x95, 0x5e, 0x45, 0xc8, 0x6f, 0x24, 0xb0, 0x7f, 0x57, 0xd4, 0xb4, 0x6a, 0xcb, - 0xec, 0x32, 0x43, 0xaf, 0xe1, 0x81, 0x23, 0xaa, 0x78, 0x6c, 0xc1, 0x6c, 0x79, 0x08, 0x62, 0x6a, - 0xe5, 0xef, 0x47, 0x69, 0x6a, 0x75, 0x08, 0x06, 0x51, 0xc2, 0xd7, 0xf2, 0xd0, 0x58, 0x07, 0x4e, - 0x66, 0x21, 0xa2, 0x4e, 0xec, 0xd8, 0xfe, 0x40, 0x3b, 0x7e, 0x34, 0x60, 0x37, 0x6e, 0x88, 0x0d, - 0xbd, 0xb1, 0x8f, 0x06, 0x50, 0x4d, 0xcc, 0x60, 0x84, 0x37, 0x0c, 0xa9, 0xb6, 0x95, 0x57, 0x1b, - 0x27, 0x9e, 0x13, 0x6e, 0xed, 0x2c, 0x53, 0x6f, 0xc8, 0x84, 0xfa, 0x0c, 0x33, 0x6e, 0x4f, 0x09, - 0x9d, 0x4c, 0xb9, 0xed, 0x4c, 0xb1, 0x37, 0x21, 0xae, 0x6c, 0x7c, 0xdb, 0xda, 0x17, 0xa1, 0x53, - 0x19, 0x19, 0xa8, 0x40, 0xf7, 0x67, 0x03, 0xea, 0x1b, 0xcd, 0x4b, 0x31, 0x16, 0xd4, 0x36, 0x4c, - 0x64, 0x5a, 0xcf, 0xbf, 0xbb, 0xa7, 0x77, 0x66, 0x2f, 0xeb, 0x21, 0xfb, 0xcf, 0xda, 0xfe, 0x34, - 0x60, 0x3f, 0x33, 0x6c, 0x52, 0xd9, 0x6b, 0x38, 0x98, 0xc9, 0x39, 0xb4, 0x85, 0xe1, 0x76, 0x18, - 0x05, 0xb5, 0xbc, 0xa7, 0xf9, 0x93, 0x7f, 0xc3, 0xd8, 0x5a, 0x75, 0xc5, 0x71, 0x34, 0x72, 0x68, - 0x32, 0xcb, 0xf7, 0xa1, 0xa0, 0xb4, 0x69, 0x4d, 0xfa, 0x0d, 0xbd, 0x81, 0x07, 0x51, 0x19, 0x7b, - 0x4c, 0x3d, 0x3c, 0xa3, 0x3f, 0x90, 0xcc, 0xb8, 0x3d, 0xcb, 0x9d, 0x83, 0x88, 0xf4, 0x73, 0x0d, - 0x57, 0x03, 0x77, 0x10, 0xde, 0xb4, 0xdc, 0x9d, 0x42, 0xf1, 0x95, 0xba, 0x93, 0xd0, 0x11, 0x94, - 0x63, 0xdb, 0x74, 0x47, 0x99, 0xcb, 0x44, 0xdf, 0x5d, 0x89, 0xe5, 0xda, 0xec, 0x24, 0x0b, 0x35, - 0xa1, 0xc4, 0xfc, 0x31, 0xff, 0x1e, 0x87, 0x44, 0xf6, 0x51, 0xb6, 0xe2, 0xf7, 0xee, 0x1f, 0x05, - 0xb8, 0x77, 0x2e, 0x4c, 0x41, 0x9f, 0x42, 0x51, 0x73, 0xe9, 0x32, 0x0f, 0xf3, 0xc6, 0x69, 0x51, - 0xba, 0x44, 0x84, 0x47, 0xcf, 0xa0, 0xe4, 0x4c, 0x31, 0xf5, 0x6c, 0xaa, 0x36, 0xaf, 0xdc, 0xaf, - 0xac, 0xaf, 0xda, 0xc5, 0x81, 0x58, 0x1b, 0x1e, 0x5b, 0x45, 0x19, 0x1c, 0xba, 0xe8, 0x29, 0xec, - 0x52, 0x8f, 0x72, 0x8a, 0x67, 0x7a, 0xcb, 0x1b, 0xbb, 0xd2, 0xd6, 0xaa, 0x5e, 0x55, 0xbb, 0x8d, - 0x3e, 0x06, 0xb9, 0xf7, 0xca, 0xd0, 0x08, 0xb9, 0x2d, 0x91, 0x7b, 0x22, 0x20, 0x3d, 0xd2, 0x58, - 0x0b, 0xaa, 0x29, 0x2c, 0x75, 0x1b, 0x77, 0xf3, 0xda, 0xd5, 0x99, 0x94, 0x59, 0xc3, 0xe3, 0x7e, - 0x5d, 0x68, 0x5f, 0x5f, 0xb5, 0x2b, 0x67, 0x11, 0xd5, 0xf0, 0xd8, 0xaa, 0xc4, 0xbc, 0x43, 0x17, - 0x9d, 0xc1, 0x5e, 0x8a, 0x53, 0xdc, 0xfb, 0x8d, 0x7b, 0x92, 0xb5, 0x69, 0xaa, 0x8f, 0x82, 0x19, - 0x7d, 0x14, 0xcc, 0x8b, 0xe8, 0xa3, 0xd0, 0x2f, 0x09, 0xda, 0xb7, 0xbf, 0xb5, 0x0d, 0xab, 0x1a, - 0x73, 0x89, 0x28, 0xfa, 0x02, 0xf6, 0x3c, 0xb2, 0xe2, 0x76, 0x3c, 0x95, 0xac, 0x51, 0xb8, 0xd5, - 0x1c, 0xef, 0x8a, 0xb4, 0xe4, 0x4a, 0x40, 0x2f, 0x01, 0x52, 0x1c, 0xc5, 0x5b, 0x71, 0xa4, 0x32, - 0x84, 0x10, 0xd9, 0x56, 0x8a, 0xa4, 0x74, 0x3b, 0x21, 0x22, 0x2d, 0x25, 0x64, 0x00, 0xad, 0xf4, - 0xd8, 0x26, 0x7c, 0xf1, 0x04, 0x97, 0xe5, 0x66, 0x3d, 0x4a, 0x26, 0x38, 0xc9, 0xd6, 0xb3, 0x7c, - 0xe3, 0x7d, 0x02, 0x1f, 0x78, 0x9f, 0x7c, 0x05, 0x4f, 0x32, 0xf7, 0xc9, 0x06, 0x7f, 0x2c, 0xaf, - 0x22, 0xe5, 0x75, 0x52, 0x17, 0x4c, 0x96, 0x28, 0xd2, 0x18, 0x1d, 0xc4, 0x50, 0x7e, 0xa5, 0x99, - 0x3d, 0xc5, 0x6c, 0xda, 0xd8, 0xe9, 0x18, 0x87, 0x3b, 0xea, 0x20, 0xaa, 0xaf, 0x37, 0x3b, 0xc5, - 0x6c, 0x8a, 0x1e, 0x42, 0x09, 0x07, 0x81, 0x82, 0x54, 0x25, 0xa4, 0x88, 0x83, 0x40, 0x84, 0xfa, - 0x5f, 0xbe, 0x5b, 0xb7, 0x8c, 0xf7, 0xeb, 0x96, 0xf1, 0xfb, 0xba, 0x65, 0xbc, 0xbd, 0x6e, 0x6d, - 0xbd, 0xbf, 0x6e, 0x6d, 0xfd, 0x72, 0xdd, 0xda, 0xfa, 0xf6, 0xc5, 0x84, 0xf2, 0xe9, 0x62, 0x64, - 0x3a, 0xfe, 0xbc, 0xe7, 0xf8, 0x73, 0xc2, 0x47, 0x63, 0x9e, 0x3c, 0xa8, 0xff, 0xa5, 0xcd, 0x3f, - 0xad, 0x51, 0x41, 0xae, 0xbf, 0xf8, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xec, 0x26, 0xcf, 0x93, 0x84, - 0x09, 0x00, 0x00, + proto.RegisterType((*LegacyABCIResponses)(nil), "cometbft.state.v1.LegacyABCIResponses") + proto.RegisterType((*ResponseBeginBlock)(nil), "cometbft.state.v1.ResponseBeginBlock") + proto.RegisterType((*ResponseEndBlock)(nil), "cometbft.state.v1.ResponseEndBlock") + proto.RegisterType((*ValidatorsInfo)(nil), "cometbft.state.v1.ValidatorsInfo") + proto.RegisterType((*ConsensusParamsInfo)(nil), "cometbft.state.v1.ConsensusParamsInfo") + proto.RegisterType((*ABCIResponsesInfo)(nil), "cometbft.state.v1.ABCIResponsesInfo") + proto.RegisterType((*Version)(nil), "cometbft.state.v1.Version") + proto.RegisterType((*State)(nil), "cometbft.state.v1.State") +} + +func init() { proto.RegisterFile("cometbft/state/v1/types.proto", fileDescriptor_eb6b2e03ecdbc0c2) } + +var fileDescriptor_eb6b2e03ecdbc0c2 = []byte{ + // 964 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xcd, 0x6e, 0xdb, 0x46, + 0x10, 0x36, 0xa3, 0x44, 0x3f, 0x23, 0x4b, 0xb6, 0x57, 0x4d, 0xa3, 0xba, 0x8d, 0xe4, 0xa8, 0x4d, + 0x6a, 0x14, 0x05, 0x05, 0xbb, 0xb7, 0x5e, 0xd2, 0x50, 0x4e, 0x60, 0x01, 0x46, 0x50, 0xd0, 0x6e, + 0x0e, 0xbe, 0x10, 0x2b, 0x6a, 0x45, 0x2d, 0x4a, 0x91, 0x84, 0x76, 0xc5, 0xca, 0x7d, 0x80, 0x5e, + 0x9b, 0x73, 0x9f, 0x28, 0xc7, 0xdc, 0xda, 0x93, 0x1b, 0xc8, 0x87, 0x02, 0x7d, 0x8a, 0x62, 0x97, + 0xcb, 0x25, 0xf5, 0x83, 0xc2, 0x81, 0x6f, 0xdc, 0x9d, 0x99, 0x6f, 0xbf, 0xf9, 0x76, 0x66, 0x96, + 0xf0, 0xd8, 0x0d, 0x27, 0x84, 0x0f, 0x46, 0xbc, 0xcb, 0x38, 0xe6, 0xa4, 0x1b, 0x1f, 0x75, 0xf9, + 0x55, 0x44, 0x98, 0x19, 0x4d, 0x43, 0x1e, 0xa2, 0xbd, 0xd4, 0x6c, 0x4a, 0xb3, 0x19, 0x1f, 0xed, + 0x7f, 0xa1, 0x23, 0xf0, 0xc0, 0xa5, 0x2b, 0x01, 0xfb, 0x2d, 0x6d, 0x95, 0xbb, 0xc2, 0x1c, 0xe1, + 0x29, 0x9e, 0xa4, 0xf6, 0xc7, 0xeb, 0xf6, 0x7c, 0xf8, 0x93, 0x75, 0x73, 0x8c, 0x7d, 0x3a, 0xc4, + 0x3c, 0x9c, 0x2a, 0x97, 0xb6, 0x76, 0x89, 0xc9, 0x94, 0xd1, 0x30, 0x58, 0xc5, 0xf8, 0xc4, 0x0b, + 0xbd, 0x50, 0x7e, 0x76, 0xc5, 0x57, 0x1a, 0xe6, 0x85, 0xa1, 0xe7, 0x93, 0xae, 0x5c, 0x0d, 0x66, + 0xa3, 0x2e, 0xa7, 0x13, 0xc2, 0x38, 0x9e, 0x44, 0x89, 0x43, 0xe7, 0x83, 0x01, 0x8d, 0x33, 0xe2, + 0x61, 0xf7, 0xea, 0x85, 0xd5, 0xeb, 0xdb, 0x84, 0x45, 0x61, 0xc0, 0x08, 0x43, 0xcf, 0xa1, 0x3a, + 0x24, 0x3e, 0x8d, 0xc9, 0xd4, 0xe1, 0x73, 0xd6, 0x34, 0x0e, 0x0a, 0x87, 0xd5, 0xe3, 0x96, 0xa9, + 0x85, 0x11, 0x2a, 0x98, 0xf1, 0x91, 0xf9, 0x72, 0x4e, 0xdc, 0x8b, 0xb9, 0x4d, 0xd8, 0xcc, 0xe7, + 0x36, 0xa8, 0x90, 0x8b, 0x39, 0x43, 0x3f, 0x40, 0x85, 0x04, 0x43, 0x67, 0xe0, 0x87, 0xee, 0xcf, + 0xcd, 0x7b, 0x07, 0xc6, 0x61, 0xf5, 0xf8, 0x4b, 0x73, 0x4d, 0x57, 0x33, 0x3d, 0xf1, 0x65, 0x30, + 0xb4, 0x84, 0xab, 0x5d, 0x26, 0xea, 0x0b, 0xbd, 0x82, 0xea, 0x80, 0x78, 0x34, 0x50, 0x18, 0x05, + 0x89, 0xf1, 0xf4, 0x7f, 0x30, 0x2c, 0xe1, 0x9d, 0xa0, 0xc0, 0x40, 0x7f, 0x77, 0x1c, 0x40, 0xeb, + 0x1e, 0xa8, 0x0f, 0x45, 0x12, 0x93, 0x80, 0xa7, 0xb9, 0x3d, 0xda, 0x90, 0x9b, 0xb0, 0x5b, 0xcd, + 0x77, 0xd7, 0xed, 0xad, 0x7f, 0xaf, 0xdb, 0xbb, 0x89, 0xfb, 0xb7, 0xe1, 0x84, 0x72, 0x32, 0x89, + 0xf8, 0x95, 0xad, 0x00, 0x3a, 0xbf, 0xdf, 0x83, 0xdd, 0xd5, 0x3c, 0xd0, 0x05, 0xec, 0xe9, 0x3b, + 0x74, 0x66, 0xd1, 0x10, 0x73, 0x92, 0x1e, 0xf5, 0x64, 0xfd, 0xa8, 0x37, 0xa9, 0xeb, 0x4f, 0xd2, + 0xd3, 0xba, 0x2f, 0x0e, 0xb5, 0x77, 0xe3, 0xe5, 0x6d, 0x86, 0x2e, 0xe1, 0x91, 0x2b, 0x8e, 0x09, + 0xd8, 0x8c, 0x39, 0xb2, 0xc4, 0x34, 0x76, 0xa2, 0x71, 0x27, 0xc3, 0x4e, 0xaa, 0x23, 0x3e, 0x32, + 0x7b, 0x69, 0xc4, 0x8f, 0xb2, 0x26, 0xed, 0x87, 0xee, 0xd2, 0x46, 0x8a, 0x9d, 0x29, 0x52, 0xb8, + 0xab, 0x22, 0xbf, 0x19, 0x50, 0xd7, 0x29, 0xb1, 0x7e, 0x30, 0x0a, 0xd1, 0x09, 0xd4, 0x32, 0x3d, + 0x18, 0xe1, 0x4d, 0x43, 0xf2, 0x6d, 0x6f, 0xe0, 0xab, 0x23, 0xcf, 0x09, 0xb7, 0xb7, 0xe3, 0xdc, + 0x0a, 0x99, 0xd0, 0xf0, 0x31, 0xe3, 0xce, 0x98, 0x50, 0x6f, 0xcc, 0x1d, 0x77, 0x8c, 0x03, 0x8f, + 0x0c, 0x65, 0xee, 0x05, 0x7b, 0x4f, 0x98, 0x4e, 0xa5, 0xa5, 0x97, 0x18, 0x3a, 0x7f, 0x18, 0xd0, + 0x58, 0x49, 0x5f, 0xb2, 0x39, 0x87, 0xdd, 0x15, 0x1d, 0x99, 0x22, 0x74, 0x0b, 0x01, 0xd5, 0xed, + 0xec, 0x2c, 0xcb, 0xc8, 0x3e, 0x9a, 0xdc, 0x9f, 0x06, 0xec, 0x2d, 0x75, 0x9d, 0xa4, 0x76, 0x09, + 0x0f, 0x7d, 0xd9, 0x90, 0x8e, 0x50, 0xdd, 0x99, 0xa6, 0x46, 0xc5, 0xef, 0xd9, 0x86, 0x06, 0xd8, + 0xd0, 0xc0, 0x76, 0x23, 0x01, 0x79, 0x31, 0x70, 0x69, 0xd6, 0xd5, 0x9f, 0x42, 0x31, 0x21, 0xa7, + 0x48, 0xa9, 0x15, 0x7a, 0x0d, 0xf5, 0x11, 0x0d, 0xb0, 0x4f, 0x7f, 0x25, 0x4b, 0xdd, 0xf6, 0xf5, + 0x7a, 0x09, 0xbc, 0x52, 0x7e, 0x49, 0x9f, 0x29, 0x64, 0xbb, 0x36, 0xca, 0x6f, 0x77, 0x28, 0x94, + 0xde, 0x24, 0x63, 0x0a, 0x59, 0x50, 0xd1, 0x3a, 0xa9, 0x14, 0x72, 0x63, 0x44, 0x0d, 0xb3, 0x25, + 0x91, 0x95, 0xbc, 0x59, 0x18, 0xda, 0x87, 0x32, 0x0b, 0x47, 0xfc, 0x17, 0x3c, 0x25, 0x92, 0x78, + 0xc5, 0xd6, 0xeb, 0xce, 0x3f, 0x45, 0x78, 0x70, 0x2e, 0x84, 0x40, 0xdf, 0x43, 0x49, 0xc1, 0xa9, + 0x73, 0xf6, 0x37, 0x48, 0xa5, 0x68, 0xa9, 0x33, 0xd2, 0x00, 0xf4, 0x0c, 0xca, 0xee, 0x18, 0xd3, + 0xc0, 0xa1, 0xc9, 0x7d, 0x55, 0xac, 0xea, 0xe2, 0xba, 0x5d, 0xea, 0x89, 0xbd, 0xfe, 0x89, 0x5d, + 0x92, 0xc6, 0xfe, 0x10, 0x3d, 0x85, 0x3a, 0x0d, 0x28, 0xa7, 0xd8, 0x57, 0xb7, 0xdc, 0xac, 0x4b, + 0x21, 0x6b, 0x6a, 0x37, 0xb9, 0x60, 0xf4, 0x0d, 0xc8, 0xeb, 0x4e, 0xb4, 0x4c, 0x3d, 0x0b, 0xd2, + 0x73, 0x47, 0x18, 0xa4, 0x4a, 0xca, 0xf7, 0x1c, 0x6a, 0x39, 0x5f, 0x3a, 0x6c, 0xde, 0x5f, 0x25, + 0xaf, 0xeb, 0x50, 0x86, 0xf5, 0x4f, 0xac, 0x86, 0x20, 0xbf, 0xb8, 0x6e, 0x57, 0xcf, 0x52, 0xac, + 0xfe, 0x89, 0x5d, 0xd5, 0xc0, 0xfd, 0x21, 0x3a, 0x83, 0x9d, 0x1c, 0xa8, 0x18, 0xfa, 0xcd, 0x07, + 0x0a, 0x36, 0x79, 0x11, 0xcc, 0xf4, 0x45, 0x30, 0x2f, 0xd2, 0x17, 0xc1, 0x2a, 0x0b, 0xd8, 0xb7, + 0x7f, 0xb7, 0x0d, 0xbb, 0xa6, 0xb1, 0x84, 0x15, 0x9d, 0xc2, 0x4e, 0x40, 0xe6, 0xdc, 0xd1, 0xad, + 0xc8, 0x9a, 0xc5, 0xdb, 0x75, 0x6f, 0x5d, 0xc4, 0x65, 0x93, 0x00, 0x3d, 0x07, 0xc8, 0x81, 0x94, + 0x6e, 0x07, 0x92, 0x0b, 0x11, 0x54, 0x64, 0x62, 0x39, 0x94, 0xf2, 0x2d, 0xa9, 0x88, 0xb8, 0x1c, + 0x95, 0x1e, 0xb4, 0xf2, 0xdd, 0x9a, 0x01, 0xea, 0xc6, 0xad, 0xc8, 0x0b, 0xfb, 0x3c, 0x6b, 0xdc, + 0x2c, 0x5a, 0xb5, 0xf0, 0xc6, 0x39, 0x02, 0x77, 0x9d, 0x23, 0xaf, 0xe1, 0xab, 0xa5, 0x39, 0xb2, + 0x72, 0x80, 0xe6, 0x57, 0x95, 0xfc, 0x0e, 0x72, 0x83, 0x65, 0x19, 0x28, 0x25, 0x99, 0x56, 0xe3, + 0x54, 0xbe, 0xd2, 0xcc, 0x19, 0x63, 0x36, 0x6e, 0x6e, 0x1f, 0x18, 0x87, 0xdb, 0x49, 0x35, 0x26, + 0xaf, 0x37, 0x3b, 0xc5, 0x6c, 0x8c, 0x3e, 0x83, 0x32, 0x8e, 0xa2, 0xc4, 0xa5, 0x26, 0x5d, 0x4a, + 0x38, 0x8a, 0x84, 0xc9, 0x3a, 0x7b, 0xb7, 0x68, 0x19, 0xef, 0x17, 0x2d, 0xe3, 0xc3, 0xa2, 0x65, + 0xbc, 0xbd, 0x69, 0x6d, 0xbd, 0xbf, 0x69, 0x6d, 0xfd, 0x75, 0xd3, 0xda, 0xba, 0x3c, 0xf6, 0x28, + 0x1f, 0xcf, 0x06, 0x22, 0xe3, 0xae, 0xfe, 0x4f, 0xc9, 0x7e, 0x98, 0x22, 0xda, 0x5d, 0xfb, 0xdf, + 0x1a, 0x14, 0x65, 0x01, 0x7e, 0xf7, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xad, 0x74, 0x0f, 0x1b, + 0x8b, 0x09, 0x00, 0x00, } func (m *LegacyABCIResponses) Marshal() (dAtA []byte, err error) { @@ -915,9 +923,9 @@ func (m *ABCIResponsesInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.ResponseFinalizeBlock != nil { + if m.FinalizeBlock != nil { { - size, err := m.ResponseFinalizeBlock.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.FinalizeBlock.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -1242,8 +1250,8 @@ func (m *ABCIResponsesInfo) Size() (n int) { if m.Height != 0 { n += 1 + sovTypes(uint64(m.Height)) } - if m.ResponseFinalizeBlock != nil { - l = m.ResponseFinalizeBlock.Size() + if m.FinalizeBlock != nil { + l = m.FinalizeBlock.Size() n += 1 + l + sovTypes(uint64(l)) } return n @@ -1381,7 +1389,7 @@ func (m *LegacyABCIResponses) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.DeliverTxs = append(m.DeliverTxs, &types.ExecTxResult{}) + m.DeliverTxs = append(m.DeliverTxs, &v1.ExecTxResult{}) if err := m.DeliverTxs[len(m.DeliverTxs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1537,7 +1545,7 @@ func (m *ResponseBeginBlock) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Events = append(m.Events, types.Event{}) + m.Events = append(m.Events, v1.Event{}) if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1621,7 +1629,7 @@ func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.ValidatorUpdates = append(m.ValidatorUpdates, types.ValidatorUpdate{}) + m.ValidatorUpdates = append(m.ValidatorUpdates, v1.ValidatorUpdate{}) if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1656,7 +1664,7 @@ func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ConsensusParamUpdates == nil { - m.ConsensusParamUpdates = &types1.ConsensusParams{} + m.ConsensusParamUpdates = &v11.ConsensusParams{} } if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -1691,7 +1699,7 @@ func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Events = append(m.Events, types.Event{}) + m.Events = append(m.Events, v1.Event{}) if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1776,7 +1784,7 @@ func (m *ValidatorsInfo) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.ValidatorSet == nil { - m.ValidatorSet = &types1.ValidatorSet{} + m.ValidatorSet = &v11.ValidatorSet{} } if err := m.ValidatorSet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -2010,7 +2018,7 @@ func (m *ABCIResponsesInfo) Unmarshal(dAtA []byte) error { } case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ResponseFinalizeBlock", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field FinalizeBlock", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2037,10 +2045,10 @@ func (m *ABCIResponsesInfo) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.ResponseFinalizeBlock == nil { - m.ResponseFinalizeBlock = &types.ResponseFinalizeBlock{} + if m.FinalizeBlock == nil { + m.FinalizeBlock = &v1.FinalizeBlockResponse{} } - if err := m.ResponseFinalizeBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.FinalizeBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2389,7 +2397,7 @@ func (m *State) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.NextValidators == nil { - m.NextValidators = &types1.ValidatorSet{} + m.NextValidators = &v11.ValidatorSet{} } if err := m.NextValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -2425,7 +2433,7 @@ func (m *State) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Validators == nil { - m.Validators = &types1.ValidatorSet{} + m.Validators = &v11.ValidatorSet{} } if err := m.Validators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err @@ -2461,7 +2469,7 @@ func (m *State) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.LastValidators == nil { - m.LastValidators = &types1.ValidatorSet{} + m.LastValidators = &v11.ValidatorSet{} } if err := m.LastValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err diff --git a/api/cometbft/state/v1beta1/types.pb.go b/api/cometbft/state/v1beta1/types.pb.go new file mode 100644 index 00000000000..8da19c6d938 --- /dev/null +++ b/api/cometbft/state/v1beta1/types.pb.go @@ -0,0 +1,2181 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/state/v1beta1/types.proto + +package v1beta1 + +import ( + fmt "fmt" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta1" + v1beta11 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + v1 "github.com/cometbft/cometbft/api/cometbft/version/v1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ABCIResponses retains the responses +// of the various ABCI calls during block processing. +// It is persisted to disk for each height before calling Commit. +type ABCIResponses struct { + DeliverTxs []*v1beta1.ResponseDeliverTx `protobuf:"bytes,1,rep,name=deliver_txs,json=deliverTxs,proto3" json:"deliver_txs,omitempty"` + EndBlock *v1beta1.ResponseEndBlock `protobuf:"bytes,2,opt,name=end_block,json=endBlock,proto3" json:"end_block,omitempty"` + BeginBlock *v1beta1.ResponseBeginBlock `protobuf:"bytes,3,opt,name=begin_block,json=beginBlock,proto3" json:"begin_block,omitempty"` +} + +func (m *ABCIResponses) Reset() { *m = ABCIResponses{} } +func (m *ABCIResponses) String() string { return proto.CompactTextString(m) } +func (*ABCIResponses) ProtoMessage() {} +func (*ABCIResponses) Descriptor() ([]byte, []int) { + return fileDescriptor_3973a75f85b1930f, []int{0} +} +func (m *ABCIResponses) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ABCIResponses) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ABCIResponses.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ABCIResponses) XXX_Merge(src proto.Message) { + xxx_messageInfo_ABCIResponses.Merge(m, src) +} +func (m *ABCIResponses) XXX_Size() int { + return m.Size() +} +func (m *ABCIResponses) XXX_DiscardUnknown() { + xxx_messageInfo_ABCIResponses.DiscardUnknown(m) +} + +var xxx_messageInfo_ABCIResponses proto.InternalMessageInfo + +func (m *ABCIResponses) GetDeliverTxs() []*v1beta1.ResponseDeliverTx { + if m != nil { + return m.DeliverTxs + } + return nil +} + +func (m *ABCIResponses) GetEndBlock() *v1beta1.ResponseEndBlock { + if m != nil { + return m.EndBlock + } + return nil +} + +func (m *ABCIResponses) GetBeginBlock() *v1beta1.ResponseBeginBlock { + if m != nil { + return m.BeginBlock + } + return nil +} + +// ValidatorsInfo represents the latest validator set, or the last height it changed +type ValidatorsInfo struct { + ValidatorSet *v1beta11.ValidatorSet `protobuf:"bytes,1,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty"` + LastHeightChanged int64 `protobuf:"varint,2,opt,name=last_height_changed,json=lastHeightChanged,proto3" json:"last_height_changed,omitempty"` +} + +func (m *ValidatorsInfo) Reset() { *m = ValidatorsInfo{} } +func (m *ValidatorsInfo) String() string { return proto.CompactTextString(m) } +func (*ValidatorsInfo) ProtoMessage() {} +func (*ValidatorsInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_3973a75f85b1930f, []int{1} +} +func (m *ValidatorsInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ValidatorsInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ValidatorsInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ValidatorsInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidatorsInfo.Merge(m, src) +} +func (m *ValidatorsInfo) XXX_Size() int { + return m.Size() +} +func (m *ValidatorsInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ValidatorsInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidatorsInfo proto.InternalMessageInfo + +func (m *ValidatorsInfo) GetValidatorSet() *v1beta11.ValidatorSet { + if m != nil { + return m.ValidatorSet + } + return nil +} + +func (m *ValidatorsInfo) GetLastHeightChanged() int64 { + if m != nil { + return m.LastHeightChanged + } + return 0 +} + +// ConsensusParamsInfo represents the latest consensus params, or the last height it changed +type ConsensusParamsInfo struct { + ConsensusParams v1beta11.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightChanged int64 `protobuf:"varint,2,opt,name=last_height_changed,json=lastHeightChanged,proto3" json:"last_height_changed,omitempty"` +} + +func (m *ConsensusParamsInfo) Reset() { *m = ConsensusParamsInfo{} } +func (m *ConsensusParamsInfo) String() string { return proto.CompactTextString(m) } +func (*ConsensusParamsInfo) ProtoMessage() {} +func (*ConsensusParamsInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_3973a75f85b1930f, []int{2} +} +func (m *ConsensusParamsInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsensusParamsInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsensusParamsInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsensusParamsInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsensusParamsInfo.Merge(m, src) +} +func (m *ConsensusParamsInfo) XXX_Size() int { + return m.Size() +} +func (m *ConsensusParamsInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ConsensusParamsInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsensusParamsInfo proto.InternalMessageInfo + +func (m *ConsensusParamsInfo) GetConsensusParams() v1beta11.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return v1beta11.ConsensusParams{} +} + +func (m *ConsensusParamsInfo) GetLastHeightChanged() int64 { + if m != nil { + return m.LastHeightChanged + } + return 0 +} + +// ABCIResponsesInfo retains the responses of the ABCI calls during block processing. +type ABCIResponsesInfo struct { + AbciResponses *ABCIResponses `protobuf:"bytes,1,opt,name=abci_responses,json=abciResponses,proto3" json:"abci_responses,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *ABCIResponsesInfo) Reset() { *m = ABCIResponsesInfo{} } +func (m *ABCIResponsesInfo) String() string { return proto.CompactTextString(m) } +func (*ABCIResponsesInfo) ProtoMessage() {} +func (*ABCIResponsesInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_3973a75f85b1930f, []int{3} +} +func (m *ABCIResponsesInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ABCIResponsesInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ABCIResponsesInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ABCIResponsesInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ABCIResponsesInfo.Merge(m, src) +} +func (m *ABCIResponsesInfo) XXX_Size() int { + return m.Size() +} +func (m *ABCIResponsesInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ABCIResponsesInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ABCIResponsesInfo proto.InternalMessageInfo + +func (m *ABCIResponsesInfo) GetAbciResponses() *ABCIResponses { + if m != nil { + return m.AbciResponses + } + return nil +} + +func (m *ABCIResponsesInfo) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +// Version is a message for storing versioning information. +type Version struct { + Consensus v1.Consensus `protobuf:"bytes,1,opt,name=consensus,proto3" json:"consensus"` + Software string `protobuf:"bytes,2,opt,name=software,proto3" json:"software,omitempty"` +} + +func (m *Version) Reset() { *m = Version{} } +func (m *Version) String() string { return proto.CompactTextString(m) } +func (*Version) ProtoMessage() {} +func (*Version) Descriptor() ([]byte, []int) { + return fileDescriptor_3973a75f85b1930f, []int{4} +} +func (m *Version) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Version.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Version) XXX_Merge(src proto.Message) { + xxx_messageInfo_Version.Merge(m, src) +} +func (m *Version) XXX_Size() int { + return m.Size() +} +func (m *Version) XXX_DiscardUnknown() { + xxx_messageInfo_Version.DiscardUnknown(m) +} + +var xxx_messageInfo_Version proto.InternalMessageInfo + +func (m *Version) GetConsensus() v1.Consensus { + if m != nil { + return m.Consensus + } + return v1.Consensus{} +} + +func (m *Version) GetSoftware() string { + if m != nil { + return m.Software + } + return "" +} + +// State represents the state of the blockchain. +type State struct { + Version Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version"` + // immutable + ChainID string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + InitialHeight int64 `protobuf:"varint,14,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` + // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) + LastBlockHeight int64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` + LastBlockID v1beta11.BlockID `protobuf:"bytes,4,opt,name=last_block_id,json=lastBlockId,proto3" json:"last_block_id"` + LastBlockTime time.Time `protobuf:"bytes,5,opt,name=last_block_time,json=lastBlockTime,proto3,stdtime" json:"last_block_time"` + // LastValidators is used to validate block.LastCommit. + // Validators are persisted to the database separately every time they change, + // so we can query for historical validator sets. + // Note that if s.LastBlockHeight causes a valset change, + // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 + // Extra +1 due to nextValSet delay. + NextValidators *v1beta11.ValidatorSet `protobuf:"bytes,6,opt,name=next_validators,json=nextValidators,proto3" json:"next_validators,omitempty"` + Validators *v1beta11.ValidatorSet `protobuf:"bytes,7,opt,name=validators,proto3" json:"validators,omitempty"` + LastValidators *v1beta11.ValidatorSet `protobuf:"bytes,8,opt,name=last_validators,json=lastValidators,proto3" json:"last_validators,omitempty"` + LastHeightValidatorsChanged int64 `protobuf:"varint,9,opt,name=last_height_validators_changed,json=lastHeightValidatorsChanged,proto3" json:"last_height_validators_changed,omitempty"` + // Consensus parameters used for validating blocks. + // Changes returned by EndBlock and updated after Commit. + ConsensusParams v1beta11.ConsensusParams `protobuf:"bytes,10,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightConsensusParamsChanged int64 `protobuf:"varint,11,opt,name=last_height_consensus_params_changed,json=lastHeightConsensusParamsChanged,proto3" json:"last_height_consensus_params_changed,omitempty"` + // Merkle root of the results from executing prev block + LastResultsHash []byte `protobuf:"bytes,12,opt,name=last_results_hash,json=lastResultsHash,proto3" json:"last_results_hash,omitempty"` + // the latest AppHash we've received from calling abci.Commit() + AppHash []byte `protobuf:"bytes,13,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *State) Reset() { *m = State{} } +func (m *State) String() string { return proto.CompactTextString(m) } +func (*State) ProtoMessage() {} +func (*State) Descriptor() ([]byte, []int) { + return fileDescriptor_3973a75f85b1930f, []int{5} +} +func (m *State) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *State) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_State.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *State) XXX_Merge(src proto.Message) { + xxx_messageInfo_State.Merge(m, src) +} +func (m *State) XXX_Size() int { + return m.Size() +} +func (m *State) XXX_DiscardUnknown() { + xxx_messageInfo_State.DiscardUnknown(m) +} + +var xxx_messageInfo_State proto.InternalMessageInfo + +func (m *State) GetVersion() Version { + if m != nil { + return m.Version + } + return Version{} +} + +func (m *State) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +func (m *State) GetInitialHeight() int64 { + if m != nil { + return m.InitialHeight + } + return 0 +} + +func (m *State) GetLastBlockHeight() int64 { + if m != nil { + return m.LastBlockHeight + } + return 0 +} + +func (m *State) GetLastBlockID() v1beta11.BlockID { + if m != nil { + return m.LastBlockID + } + return v1beta11.BlockID{} +} + +func (m *State) GetLastBlockTime() time.Time { + if m != nil { + return m.LastBlockTime + } + return time.Time{} +} + +func (m *State) GetNextValidators() *v1beta11.ValidatorSet { + if m != nil { + return m.NextValidators + } + return nil +} + +func (m *State) GetValidators() *v1beta11.ValidatorSet { + if m != nil { + return m.Validators + } + return nil +} + +func (m *State) GetLastValidators() *v1beta11.ValidatorSet { + if m != nil { + return m.LastValidators + } + return nil +} + +func (m *State) GetLastHeightValidatorsChanged() int64 { + if m != nil { + return m.LastHeightValidatorsChanged + } + return 0 +} + +func (m *State) GetConsensusParams() v1beta11.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return v1beta11.ConsensusParams{} +} + +func (m *State) GetLastHeightConsensusParamsChanged() int64 { + if m != nil { + return m.LastHeightConsensusParamsChanged + } + return 0 +} + +func (m *State) GetLastResultsHash() []byte { + if m != nil { + return m.LastResultsHash + } + return nil +} + +func (m *State) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +func init() { + proto.RegisterType((*ABCIResponses)(nil), "cometbft.state.v1beta1.ABCIResponses") + proto.RegisterType((*ValidatorsInfo)(nil), "cometbft.state.v1beta1.ValidatorsInfo") + proto.RegisterType((*ConsensusParamsInfo)(nil), "cometbft.state.v1beta1.ConsensusParamsInfo") + proto.RegisterType((*ABCIResponsesInfo)(nil), "cometbft.state.v1beta1.ABCIResponsesInfo") + proto.RegisterType((*Version)(nil), "cometbft.state.v1beta1.Version") + proto.RegisterType((*State)(nil), "cometbft.state.v1beta1.State") +} + +func init() { + proto.RegisterFile("cometbft/state/v1beta1/types.proto", fileDescriptor_3973a75f85b1930f) +} + +var fileDescriptor_3973a75f85b1930f = []byte{ + // 826 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x6e, 0xdb, 0x46, + 0x10, 0x36, 0xeb, 0xc4, 0x92, 0x86, 0x96, 0xdc, 0xac, 0x8b, 0x80, 0x55, 0x01, 0xca, 0x55, 0xf3, + 0xe3, 0xf6, 0x40, 0x22, 0xe9, 0xa1, 0xc7, 0xa2, 0x94, 0x0a, 0x84, 0x85, 0x5b, 0xb4, 0x4c, 0x10, + 0x04, 0xbd, 0x10, 0x4b, 0x71, 0x4d, 0x2e, 0x2a, 0x93, 0x04, 0x77, 0xad, 0x3a, 0x0f, 0xd0, 0x53, + 0x2f, 0x79, 0x83, 0xbe, 0x4e, 0x8e, 0x39, 0xf6, 0xe4, 0x16, 0xf2, 0xb5, 0x0f, 0x51, 0xec, 0x1f, + 0x49, 0x19, 0x32, 0x02, 0x03, 0xb9, 0x71, 0x77, 0xbe, 0xf9, 0xe6, 0x9b, 0xd9, 0x99, 0x21, 0x4c, + 0x17, 0xe5, 0x19, 0xe1, 0xc9, 0x29, 0xf7, 0x19, 0xc7, 0x9c, 0xf8, 0xab, 0x27, 0x09, 0xe1, 0xf8, + 0x89, 0xcf, 0x5f, 0x57, 0x84, 0x79, 0x55, 0x5d, 0xf2, 0x12, 0xdd, 0x37, 0x18, 0x4f, 0x62, 0x3c, + 0x8d, 0x19, 0x7f, 0x92, 0x95, 0x59, 0x29, 0x21, 0xbe, 0xf8, 0x52, 0xe8, 0xf1, 0xe7, 0x0d, 0x23, + 0x4e, 0x16, 0x74, 0x1b, 0xe1, 0xb8, 0x0d, 0x2a, 0x6f, 0xb7, 0x62, 0x1e, 0xdd, 0x80, 0x59, 0xe1, + 0x25, 0x4d, 0x31, 0x2f, 0x6b, 0x8d, 0xfb, 0xe2, 0x06, 0x5c, 0x85, 0x6b, 0x7c, 0x66, 0xc8, 0x26, + 0x0d, 0x68, 0x45, 0x6a, 0x46, 0xcb, 0xc2, 0x5f, 0x6d, 0x46, 0x9b, 0x64, 0x65, 0x99, 0x2d, 0x89, + 0x2f, 0x4f, 0xc9, 0xf9, 0xa9, 0xcf, 0xe9, 0x19, 0x61, 0x1c, 0x9f, 0x55, 0x0a, 0x30, 0xfd, 0xcf, + 0x82, 0xe1, 0x77, 0xc1, 0x2c, 0x8c, 0x08, 0xab, 0xca, 0x82, 0x11, 0x86, 0x42, 0xb0, 0x53, 0xb2, + 0xa4, 0x2b, 0x52, 0xc7, 0xfc, 0x82, 0x39, 0xd6, 0xd1, 0xee, 0xb1, 0xfd, 0xf4, 0xd8, 0x6b, 0x6a, + 0x25, 0xb2, 0x37, 0xa5, 0xf2, 0x8c, 0xdb, 0x5c, 0x79, 0xbc, 0xb8, 0x88, 0x20, 0x35, 0x9f, 0x0c, + 0xcd, 0x61, 0x40, 0x8a, 0x34, 0x4e, 0x96, 0xe5, 0xe2, 0x37, 0xe7, 0xa3, 0x23, 0xeb, 0xd8, 0x7e, + 0xfa, 0xf8, 0x3d, 0x44, 0xdf, 0x17, 0x69, 0x20, 0xe0, 0x51, 0x9f, 0xe8, 0x2f, 0xf4, 0x03, 0xd8, + 0x09, 0xc9, 0x68, 0xa1, 0x79, 0x76, 0x25, 0xcf, 0x97, 0xef, 0xe1, 0x09, 0x84, 0x87, 0x62, 0x82, + 0xa4, 0xf9, 0x9e, 0xfe, 0x69, 0xc1, 0xe8, 0xa5, 0xa9, 0x34, 0x0b, 0x8b, 0xd3, 0x12, 0x85, 0x30, + 0x6c, 0x6a, 0x1f, 0x33, 0xc2, 0x1d, 0x4b, 0x06, 0x78, 0xd0, 0x06, 0x50, 0x05, 0x35, 0x11, 0x1a, + 0xf7, 0xe7, 0x84, 0x47, 0xfb, 0xab, 0xce, 0x09, 0x79, 0x70, 0xb8, 0xc4, 0x8c, 0xc7, 0x39, 0xa1, + 0x59, 0xce, 0xe3, 0x45, 0x8e, 0x8b, 0x8c, 0xa4, 0x32, 0xf3, 0xdd, 0xe8, 0x9e, 0x30, 0x3d, 0x93, + 0x96, 0x99, 0x32, 0x4c, 0xff, 0xb2, 0xe0, 0x70, 0x26, 0xd4, 0x16, 0xec, 0x9c, 0xfd, 0x2c, 0x1f, + 0x56, 0x4a, 0x7a, 0x05, 0x1f, 0x2f, 0xcc, 0x75, 0xac, 0x1e, 0x5c, 0xab, 0x7a, 0x7c, 0x93, 0xaa, + 0x6b, 0x34, 0xc1, 0x9d, 0xb7, 0x97, 0x93, 0x9d, 0xe8, 0x60, 0xb1, 0x79, 0x7d, 0x6b, 0x85, 0xaf, + 0xe1, 0xde, 0x46, 0x77, 0x48, 0x79, 0x27, 0x30, 0x12, 0x35, 0x8f, 0x6b, 0x73, 0xab, 0xc5, 0x3d, + 0xf4, 0xb6, 0x0f, 0x94, 0xb7, 0x41, 0x11, 0x0d, 0x85, 0x73, 0xdb, 0x6f, 0xf7, 0x61, 0x4f, 0xa9, + 0xd1, 0x2a, 0xf4, 0x69, 0x4a, 0xa1, 0xf7, 0x52, 0x35, 0x35, 0x0a, 0x60, 0xd0, 0x24, 0xa2, 0x63, + 0xb9, 0x6d, 0x2c, 0xdd, 0xfa, 0xde, 0xaa, 0x53, 0x05, 0x9d, 0x7f, 0xeb, 0x86, 0xc6, 0xd0, 0x67, + 0xe5, 0x29, 0xff, 0x1d, 0xd7, 0x44, 0x06, 0x1a, 0x44, 0xcd, 0x79, 0xfa, 0x47, 0x0f, 0xee, 0x3e, + 0x17, 0x8a, 0xd1, 0xb7, 0xd0, 0xd3, 0x74, 0x3a, 0xce, 0xe4, 0xa6, 0x9c, 0xb4, 0x36, 0x1d, 0xc8, + 0x78, 0xa1, 0x47, 0xd0, 0x5f, 0xe4, 0x98, 0x16, 0x31, 0x55, 0x55, 0x1d, 0x04, 0xf6, 0xfa, 0x72, + 0xd2, 0x9b, 0x89, 0xbb, 0x70, 0x1e, 0xf5, 0xa4, 0x31, 0x4c, 0xd1, 0x43, 0x18, 0xd1, 0x82, 0x72, + 0x8a, 0x97, 0xfa, 0x2d, 0x9c, 0x91, 0xcc, 0x7e, 0xa8, 0x6f, 0xd5, 0x33, 0xa0, 0xaf, 0x40, 0x3e, + 0x8a, 0x6a, 0x7d, 0x83, 0xdc, 0x95, 0xc8, 0x03, 0x61, 0x90, 0x5d, 0xad, 0xb1, 0xaf, 0x60, 0xd8, + 0xc1, 0xd2, 0xd4, 0xb9, 0x73, 0x3d, 0x83, 0xcd, 0x96, 0x91, 0xbe, 0xe1, 0x3c, 0x38, 0x14, 0x19, + 0xac, 0x2f, 0x27, 0xf6, 0x89, 0x21, 0x0c, 0xe7, 0x91, 0xdd, 0xb0, 0x87, 0x29, 0x3a, 0x81, 0x83, + 0x0e, 0xb3, 0x58, 0x21, 0xce, 0x5d, 0xc9, 0x3d, 0xf6, 0xd4, 0x7e, 0xf1, 0xcc, 0x7e, 0xf1, 0x5e, + 0x98, 0xfd, 0x12, 0xf4, 0x05, 0xed, 0x9b, 0x7f, 0x26, 0x56, 0x34, 0x6c, 0xb8, 0x84, 0x15, 0xfd, + 0x08, 0x07, 0x05, 0xb9, 0xe0, 0x71, 0x33, 0x3a, 0xcc, 0xd9, 0xbb, 0xc5, 0xc8, 0x8d, 0x84, 0x73, + 0x3b, 0xc3, 0x68, 0x0e, 0xd0, 0x61, 0xea, 0xdd, 0x82, 0xa9, 0xe3, 0x27, 0x44, 0xc9, 0x14, 0x3b, + 0x54, 0xfd, 0xdb, 0x88, 0x12, 0xce, 0x1d, 0x51, 0x33, 0x70, 0xbb, 0x73, 0xd6, 0xb2, 0x36, 0x23, + 0x37, 0x90, 0x8f, 0xf8, 0x59, 0x3b, 0x72, 0xad, 0xb7, 0x1e, 0xbe, 0xad, 0x6b, 0x00, 0x3e, 0xc8, + 0x1a, 0xf8, 0x09, 0x1e, 0x6c, 0xac, 0x81, 0x6b, 0x51, 0x1a, 0x91, 0xb6, 0x14, 0x79, 0xd4, 0xd9, + 0x0b, 0x9b, 0x44, 0x46, 0xa9, 0x69, 0xd3, 0x9a, 0xb0, 0xf3, 0x25, 0x67, 0x71, 0x8e, 0x59, 0xee, + 0xec, 0x1f, 0x59, 0xc7, 0xfb, 0xaa, 0x4d, 0x23, 0x75, 0xff, 0x0c, 0xb3, 0x1c, 0x7d, 0x0a, 0x7d, + 0x5c, 0x55, 0x0a, 0x32, 0x94, 0x90, 0x1e, 0xae, 0x2a, 0x61, 0x0a, 0x7e, 0x79, 0xbb, 0x76, 0xad, + 0x77, 0x6b, 0xd7, 0xfa, 0x77, 0xed, 0x5a, 0x6f, 0xae, 0xdc, 0x9d, 0x77, 0x57, 0xee, 0xce, 0xdf, + 0x57, 0xee, 0xce, 0xaf, 0xdf, 0x64, 0x94, 0xe7, 0xe7, 0x89, 0x48, 0xdb, 0x6f, 0xfe, 0x79, 0xed, + 0x0f, 0xb9, 0xa2, 0xfe, 0xf6, 0xff, 0x7d, 0xb2, 0x27, 0x3b, 0xf3, 0xeb, 0xff, 0x03, 0x00, 0x00, + 0xff, 0xff, 0x1a, 0xd0, 0x8c, 0x88, 0x10, 0x08, 0x00, 0x00, +} + +func (m *ABCIResponses) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ABCIResponses) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ABCIResponses) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BeginBlock != nil { + { + size, err := m.BeginBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.EndBlock != nil { + { + size, err := m.EndBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.DeliverTxs) > 0 { + for iNdEx := len(m.DeliverTxs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.DeliverTxs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ValidatorsInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorsInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ValidatorsInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LastHeightChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightChanged)) + i-- + dAtA[i] = 0x10 + } + if m.ValidatorSet != nil { + { + size, err := m.ValidatorSet.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ConsensusParamsInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsensusParamsInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsensusParamsInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LastHeightChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightChanged)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ABCIResponsesInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ABCIResponsesInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ABCIResponsesInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if m.AbciResponses != nil { + { + size, err := m.AbciResponses.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Version) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Version) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Version) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Software) > 0 { + i -= len(m.Software) + copy(dAtA[i:], m.Software) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Software))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Consensus.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *State) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *State) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *State) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.InitialHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.InitialHeight)) + i-- + dAtA[i] = 0x70 + } + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x6a + } + if len(m.LastResultsHash) > 0 { + i -= len(m.LastResultsHash) + copy(dAtA[i:], m.LastResultsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.LastResultsHash))) + i-- + dAtA[i] = 0x62 + } + if m.LastHeightConsensusParamsChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightConsensusParamsChanged)) + i-- + dAtA[i] = 0x58 + } + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + if m.LastHeightValidatorsChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightValidatorsChanged)) + i-- + dAtA[i] = 0x48 + } + if m.LastValidators != nil { + { + size, err := m.LastValidators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + if m.Validators != nil { + { + size, err := m.Validators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + if m.NextValidators != nil { + { + size, err := m.NextValidators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + n11, err11 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastBlockTime):]) + if err11 != nil { + return 0, err11 + } + i -= n11 + i = encodeVarintTypes(dAtA, i, uint64(n11)) + i-- + dAtA[i] = 0x2a + { + size, err := m.LastBlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.LastBlockHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastBlockHeight)) + i-- + dAtA[i] = 0x18 + } + if len(m.ChainID) > 0 { + i -= len(m.ChainID) + copy(dAtA[i:], m.ChainID) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainID))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ABCIResponses) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.DeliverTxs) > 0 { + for _, e := range m.DeliverTxs { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ValidatorsInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ValidatorSet != nil { + l = m.ValidatorSet.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastHeightChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightChanged)) + } + return n +} + +func (m *ConsensusParamsInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.LastHeightChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightChanged)) + } + return n +} + +func (m *ABCIResponsesInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AbciResponses != nil { + l = m.AbciResponses.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *Version) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Consensus.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.Software) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *State) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Version.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastBlockHeight != 0 { + n += 1 + sovTypes(uint64(m.LastBlockHeight)) + } + l = m.LastBlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastBlockTime) + n += 1 + l + sovTypes(uint64(l)) + if m.NextValidators != nil { + l = m.NextValidators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Validators != nil { + l = m.Validators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastValidators != nil { + l = m.LastValidators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastHeightValidatorsChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightValidatorsChanged)) + } + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.LastHeightConsensusParamsChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightConsensusParamsChanged)) + } + l = len(m.LastResultsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.InitialHeight != 0 { + n += 1 + sovTypes(uint64(m.InitialHeight)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ABCIResponses) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ABCIResponses: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ABCIResponses: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTxs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DeliverTxs = append(m.DeliverTxs, &v1beta1.ResponseDeliverTx{}) + if err := m.DeliverTxs[len(m.DeliverTxs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.EndBlock == nil { + m.EndBlock = &v1beta1.ResponseEndBlock{} + } + if err := m.EndBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BeginBlock == nil { + m.BeginBlock = &v1beta1.ResponseBeginBlock{} + } + if err := m.BeginBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ValidatorsInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ValidatorsInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorsInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorSet", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ValidatorSet == nil { + m.ValidatorSet = &v1beta11.ValidatorSet{} + } + if err := m.ValidatorSet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightChanged", wireType) + } + m.LastHeightChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConsensusParamsInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsensusParamsInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusParamsInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightChanged", wireType) + } + m.LastHeightChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ABCIResponsesInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ABCIResponsesInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ABCIResponsesInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AbciResponses", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AbciResponses == nil { + m.AbciResponses = &ABCIResponses{} + } + if err := m.AbciResponses.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Version) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Version: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Version: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Consensus", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Consensus.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Software", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Software = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *State) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: State: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: State: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockHeight", wireType) + } + m.LastBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastBlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastBlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.LastBlockTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.NextValidators == nil { + m.NextValidators = &v1beta11.ValidatorSet{} + } + if err := m.NextValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Validators == nil { + m.Validators = &v1beta11.ValidatorSet{} + } + if err := m.Validators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastValidators == nil { + m.LastValidators = &v1beta11.ValidatorSet{} + } + if err := m.LastValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightValidatorsChanged", wireType) + } + m.LastHeightValidatorsChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightValidatorsChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightConsensusParamsChanged", wireType) + } + m.LastHeightConsensusParamsChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightConsensusParamsChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastResultsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastResultsHash = append(m.LastResultsHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastResultsHash == nil { + m.LastResultsHash = []byte{} + } + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialHeight", wireType) + } + m.InitialHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/state/v1beta2/types.pb.go b/api/cometbft/state/v1beta2/types.pb.go new file mode 100644 index 00000000000..af6b09a791f --- /dev/null +++ b/api/cometbft/state/v1beta2/types.pb.go @@ -0,0 +1,1738 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/state/v1beta2/types.proto + +package v1beta2 + +import ( + fmt "fmt" + v1beta2 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta2" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/state/v1beta1" + v1beta11 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + v1beta21 "github.com/cometbft/cometbft/api/cometbft/types/v1beta2" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ABCIResponses retains the responses +// of the various ABCI calls during block processing. +// It is persisted to disk for each height before calling Commit. +type ABCIResponses struct { + DeliverTxs []*v1beta2.ResponseDeliverTx `protobuf:"bytes,1,rep,name=deliver_txs,json=deliverTxs,proto3" json:"deliver_txs,omitempty"` + EndBlock *v1beta2.ResponseEndBlock `protobuf:"bytes,2,opt,name=end_block,json=endBlock,proto3" json:"end_block,omitempty"` + BeginBlock *v1beta2.ResponseBeginBlock `protobuf:"bytes,3,opt,name=begin_block,json=beginBlock,proto3" json:"begin_block,omitempty"` +} + +func (m *ABCIResponses) Reset() { *m = ABCIResponses{} } +func (m *ABCIResponses) String() string { return proto.CompactTextString(m) } +func (*ABCIResponses) ProtoMessage() {} +func (*ABCIResponses) Descriptor() ([]byte, []int) { + return fileDescriptor_f65ea0fc5c80e5be, []int{0} +} +func (m *ABCIResponses) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ABCIResponses) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ABCIResponses.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ABCIResponses) XXX_Merge(src proto.Message) { + xxx_messageInfo_ABCIResponses.Merge(m, src) +} +func (m *ABCIResponses) XXX_Size() int { + return m.Size() +} +func (m *ABCIResponses) XXX_DiscardUnknown() { + xxx_messageInfo_ABCIResponses.DiscardUnknown(m) +} + +var xxx_messageInfo_ABCIResponses proto.InternalMessageInfo + +func (m *ABCIResponses) GetDeliverTxs() []*v1beta2.ResponseDeliverTx { + if m != nil { + return m.DeliverTxs + } + return nil +} + +func (m *ABCIResponses) GetEndBlock() *v1beta2.ResponseEndBlock { + if m != nil { + return m.EndBlock + } + return nil +} + +func (m *ABCIResponses) GetBeginBlock() *v1beta2.ResponseBeginBlock { + if m != nil { + return m.BeginBlock + } + return nil +} + +// ConsensusParamsInfo represents the latest consensus params, or the last height it changed +type ConsensusParamsInfo struct { + ConsensusParams v1beta21.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightChanged int64 `protobuf:"varint,2,opt,name=last_height_changed,json=lastHeightChanged,proto3" json:"last_height_changed,omitempty"` +} + +func (m *ConsensusParamsInfo) Reset() { *m = ConsensusParamsInfo{} } +func (m *ConsensusParamsInfo) String() string { return proto.CompactTextString(m) } +func (*ConsensusParamsInfo) ProtoMessage() {} +func (*ConsensusParamsInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_f65ea0fc5c80e5be, []int{1} +} +func (m *ConsensusParamsInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsensusParamsInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsensusParamsInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsensusParamsInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsensusParamsInfo.Merge(m, src) +} +func (m *ConsensusParamsInfo) XXX_Size() int { + return m.Size() +} +func (m *ConsensusParamsInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ConsensusParamsInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsensusParamsInfo proto.InternalMessageInfo + +func (m *ConsensusParamsInfo) GetConsensusParams() v1beta21.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return v1beta21.ConsensusParams{} +} + +func (m *ConsensusParamsInfo) GetLastHeightChanged() int64 { + if m != nil { + return m.LastHeightChanged + } + return 0 +} + +// ABCIResponsesInfo retains the responses of the ABCI calls during block processing. +type ABCIResponsesInfo struct { + AbciResponses *ABCIResponses `protobuf:"bytes,1,opt,name=abci_responses,json=abciResponses,proto3" json:"abci_responses,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *ABCIResponsesInfo) Reset() { *m = ABCIResponsesInfo{} } +func (m *ABCIResponsesInfo) String() string { return proto.CompactTextString(m) } +func (*ABCIResponsesInfo) ProtoMessage() {} +func (*ABCIResponsesInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_f65ea0fc5c80e5be, []int{2} +} +func (m *ABCIResponsesInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ABCIResponsesInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ABCIResponsesInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ABCIResponsesInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ABCIResponsesInfo.Merge(m, src) +} +func (m *ABCIResponsesInfo) XXX_Size() int { + return m.Size() +} +func (m *ABCIResponsesInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ABCIResponsesInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ABCIResponsesInfo proto.InternalMessageInfo + +func (m *ABCIResponsesInfo) GetAbciResponses() *ABCIResponses { + if m != nil { + return m.AbciResponses + } + return nil +} + +func (m *ABCIResponsesInfo) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +// State represents the state of the blockchain. +type State struct { + Version v1beta1.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version"` + // immutable + ChainID string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + InitialHeight int64 `protobuf:"varint,14,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` + // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) + LastBlockHeight int64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` + LastBlockID v1beta11.BlockID `protobuf:"bytes,4,opt,name=last_block_id,json=lastBlockId,proto3" json:"last_block_id"` + LastBlockTime time.Time `protobuf:"bytes,5,opt,name=last_block_time,json=lastBlockTime,proto3,stdtime" json:"last_block_time"` + // LastValidators is used to validate block.LastCommit. + // Validators are persisted to the database separately every time they change, + // so we can query for historical validator sets. + // Note that if s.LastBlockHeight causes a valset change, + // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 + // Extra +1 due to nextValSet delay. + NextValidators *v1beta11.ValidatorSet `protobuf:"bytes,6,opt,name=next_validators,json=nextValidators,proto3" json:"next_validators,omitempty"` + Validators *v1beta11.ValidatorSet `protobuf:"bytes,7,opt,name=validators,proto3" json:"validators,omitempty"` + LastValidators *v1beta11.ValidatorSet `protobuf:"bytes,8,opt,name=last_validators,json=lastValidators,proto3" json:"last_validators,omitempty"` + LastHeightValidatorsChanged int64 `protobuf:"varint,9,opt,name=last_height_validators_changed,json=lastHeightValidatorsChanged,proto3" json:"last_height_validators_changed,omitempty"` + // Consensus parameters used for validating blocks. + // Changes returned by EndBlock and updated after Commit. + ConsensusParams v1beta21.ConsensusParams `protobuf:"bytes,10,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightConsensusParamsChanged int64 `protobuf:"varint,11,opt,name=last_height_consensus_params_changed,json=lastHeightConsensusParamsChanged,proto3" json:"last_height_consensus_params_changed,omitempty"` + // Merkle root of the results from executing prev block + LastResultsHash []byte `protobuf:"bytes,12,opt,name=last_results_hash,json=lastResultsHash,proto3" json:"last_results_hash,omitempty"` + // the latest AppHash we've received from calling abci.Commit() + AppHash []byte `protobuf:"bytes,13,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *State) Reset() { *m = State{} } +func (m *State) String() string { return proto.CompactTextString(m) } +func (*State) ProtoMessage() {} +func (*State) Descriptor() ([]byte, []int) { + return fileDescriptor_f65ea0fc5c80e5be, []int{3} +} +func (m *State) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *State) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_State.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *State) XXX_Merge(src proto.Message) { + xxx_messageInfo_State.Merge(m, src) +} +func (m *State) XXX_Size() int { + return m.Size() +} +func (m *State) XXX_DiscardUnknown() { + xxx_messageInfo_State.DiscardUnknown(m) +} + +var xxx_messageInfo_State proto.InternalMessageInfo + +func (m *State) GetVersion() v1beta1.Version { + if m != nil { + return m.Version + } + return v1beta1.Version{} +} + +func (m *State) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +func (m *State) GetInitialHeight() int64 { + if m != nil { + return m.InitialHeight + } + return 0 +} + +func (m *State) GetLastBlockHeight() int64 { + if m != nil { + return m.LastBlockHeight + } + return 0 +} + +func (m *State) GetLastBlockID() v1beta11.BlockID { + if m != nil { + return m.LastBlockID + } + return v1beta11.BlockID{} +} + +func (m *State) GetLastBlockTime() time.Time { + if m != nil { + return m.LastBlockTime + } + return time.Time{} +} + +func (m *State) GetNextValidators() *v1beta11.ValidatorSet { + if m != nil { + return m.NextValidators + } + return nil +} + +func (m *State) GetValidators() *v1beta11.ValidatorSet { + if m != nil { + return m.Validators + } + return nil +} + +func (m *State) GetLastValidators() *v1beta11.ValidatorSet { + if m != nil { + return m.LastValidators + } + return nil +} + +func (m *State) GetLastHeightValidatorsChanged() int64 { + if m != nil { + return m.LastHeightValidatorsChanged + } + return 0 +} + +func (m *State) GetConsensusParams() v1beta21.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return v1beta21.ConsensusParams{} +} + +func (m *State) GetLastHeightConsensusParamsChanged() int64 { + if m != nil { + return m.LastHeightConsensusParamsChanged + } + return 0 +} + +func (m *State) GetLastResultsHash() []byte { + if m != nil { + return m.LastResultsHash + } + return nil +} + +func (m *State) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +func init() { + proto.RegisterType((*ABCIResponses)(nil), "cometbft.state.v1beta2.ABCIResponses") + proto.RegisterType((*ConsensusParamsInfo)(nil), "cometbft.state.v1beta2.ConsensusParamsInfo") + proto.RegisterType((*ABCIResponsesInfo)(nil), "cometbft.state.v1beta2.ABCIResponsesInfo") + proto.RegisterType((*State)(nil), "cometbft.state.v1beta2.State") +} + +func init() { + proto.RegisterFile("cometbft/state/v1beta2/types.proto", fileDescriptor_f65ea0fc5c80e5be) +} + +var fileDescriptor_f65ea0fc5c80e5be = []byte{ + // 749 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x8d, 0x49, 0xdb, 0xa4, 0xeb, 0x26, 0xa1, 0x2e, 0xaa, 0x4c, 0x91, 0x92, 0x10, 0xda, 0x12, + 0x38, 0xd8, 0x4a, 0x38, 0x70, 0x44, 0x38, 0x41, 0xaa, 0x51, 0x41, 0xe0, 0x56, 0x55, 0xc5, 0xc5, + 0x5a, 0xc7, 0x5b, 0xdb, 0x22, 0xb1, 0xad, 0xec, 0x26, 0x6a, 0x3f, 0x80, 0x7b, 0xff, 0x80, 0xdf, + 0xe9, 0xb1, 0x47, 0x4e, 0x05, 0xa5, 0x57, 0x3e, 0x02, 0xed, 0xae, 0xd7, 0x71, 0x22, 0x57, 0x55, + 0x25, 0x6e, 0xeb, 0x99, 0x37, 0x6f, 0xdf, 0xcc, 0xce, 0x93, 0x41, 0x6b, 0x10, 0x8d, 0x10, 0x71, + 0xce, 0x88, 0x8e, 0x09, 0x24, 0x48, 0x9f, 0x76, 0x1c, 0x44, 0x60, 0x57, 0x27, 0x17, 0x31, 0xc2, + 0x5a, 0x3c, 0x8e, 0x48, 0xa4, 0x6c, 0x0b, 0x8c, 0xc6, 0x30, 0x5a, 0x82, 0xd9, 0x79, 0x9e, 0xd6, + 0x42, 0x67, 0x10, 0xe4, 0x95, 0xee, 0xe4, 0xd3, 0x77, 0xee, 0xc0, 0xb0, 0x68, 0x2e, 0x66, 0xff, + 0x0e, 0xcc, 0x14, 0x0e, 0x03, 0x17, 0x92, 0x68, 0x9c, 0xe0, 0x5e, 0xe4, 0xe2, 0xba, 0x7a, 0x0c, + 0xc7, 0x70, 0x24, 0xc8, 0x9e, 0x78, 0x91, 0x17, 0xb1, 0xa3, 0x4e, 0x4f, 0x49, 0xb4, 0xe1, 0x45, + 0x91, 0x37, 0x44, 0x3a, 0xfb, 0x72, 0x26, 0x67, 0x3a, 0x09, 0x46, 0x08, 0x13, 0x38, 0x8a, 0x39, + 0xa0, 0xf5, 0x57, 0x02, 0x95, 0xf7, 0x46, 0xcf, 0xb4, 0x10, 0x8e, 0xa3, 0x10, 0x23, 0xac, 0x98, + 0x40, 0x76, 0xd1, 0x30, 0x98, 0xa2, 0xb1, 0x4d, 0xce, 0xb1, 0x2a, 0x35, 0x8b, 0x6d, 0xb9, 0xdb, + 0xd6, 0xd2, 0x71, 0xd1, 0xb1, 0x88, 0x69, 0x69, 0xa2, 0xac, 0xcf, 0x2b, 0x8e, 0xcf, 0x2d, 0xe0, + 0x8a, 0x23, 0x56, 0xfa, 0x60, 0x1d, 0x85, 0xae, 0xed, 0x0c, 0xa3, 0xc1, 0x77, 0xf5, 0x51, 0x53, + 0x6a, 0xcb, 0xdd, 0x97, 0xf7, 0x10, 0x7d, 0x08, 0x5d, 0x83, 0xc2, 0xad, 0x32, 0x4a, 0x4e, 0xca, + 0x47, 0x20, 0x3b, 0xc8, 0x0b, 0xc2, 0x84, 0xa7, 0xc8, 0x78, 0x5e, 0xdd, 0xc3, 0x63, 0xd0, 0x0a, + 0xce, 0x04, 0x9c, 0xf4, 0xdc, 0xfa, 0x29, 0x81, 0xad, 0x1e, 0xcd, 0x87, 0x78, 0x82, 0xbf, 0xb0, + 0xf9, 0x99, 0xe1, 0x59, 0xa4, 0x9c, 0x82, 0xc7, 0x03, 0x11, 0xb6, 0xf9, 0x5c, 0x55, 0x69, 0x59, + 0x30, 0x7f, 0x3b, 0x71, 0xd3, 0x12, 0x8d, 0xb1, 0x72, 0x75, 0xd3, 0x28, 0x58, 0xb5, 0xc1, 0x62, + 0x58, 0xd1, 0xc0, 0xd6, 0x10, 0x62, 0x62, 0xfb, 0x28, 0xf0, 0x7c, 0x62, 0x0f, 0x7c, 0x18, 0x7a, + 0xc8, 0x65, 0xd3, 0x28, 0x5a, 0x9b, 0x34, 0x75, 0xc0, 0x32, 0x3d, 0x9e, 0x68, 0x5d, 0x80, 0xcd, + 0x85, 0xf7, 0x60, 0xf2, 0x0e, 0x41, 0x95, 0x76, 0x69, 0x8f, 0x45, 0x34, 0x11, 0xb7, 0xa7, 0xe5, + 0x6f, 0xb1, 0xb6, 0x40, 0x61, 0x55, 0x68, 0xf1, 0xfc, 0x85, 0xb7, 0xc1, 0x1a, 0x57, 0x93, 0xa8, + 0x48, 0xbe, 0x5a, 0x3f, 0x4a, 0x60, 0xf5, 0x88, 0xd2, 0x28, 0xef, 0x40, 0x69, 0x8a, 0xc6, 0x38, + 0x88, 0xc2, 0xe4, 0xa2, 0x46, 0xfe, 0x45, 0x1d, 0xed, 0x84, 0xc3, 0x92, 0xee, 0x45, 0x95, 0xb2, + 0x0f, 0xca, 0x03, 0x1f, 0x06, 0xa1, 0x1d, 0xf0, 0x56, 0xd7, 0x0d, 0x79, 0x76, 0xd3, 0x28, 0xf5, + 0x68, 0xcc, 0xec, 0x5b, 0x25, 0x96, 0x34, 0x5d, 0x65, 0x0f, 0x54, 0x83, 0x30, 0x20, 0x01, 0x1c, + 0x26, 0x03, 0x52, 0xab, 0x4c, 0x52, 0x25, 0x89, 0xf2, 0xd9, 0x28, 0xaf, 0x01, 0x9b, 0x14, 0xdf, + 0x00, 0x81, 0x2c, 0x32, 0x64, 0x8d, 0x26, 0xd8, 0xe3, 0x26, 0xd8, 0x53, 0x50, 0xc9, 0x60, 0x03, + 0x57, 0x5d, 0x59, 0xee, 0x20, 0xfb, 0x8e, 0x1d, 0x8d, 0xd5, 0x9a, 0x7d, 0x63, 0x8b, 0x76, 0x30, + 0xbb, 0x69, 0xc8, 0x87, 0x82, 0xd0, 0xec, 0x5b, 0x72, 0xca, 0x6e, 0xba, 0xca, 0x21, 0xa8, 0x65, + 0x98, 0xa9, 0x93, 0xd4, 0x55, 0xc6, 0xbd, 0xa3, 0x71, 0x9b, 0x69, 0xc2, 0x66, 0xda, 0xb1, 0xb0, + 0x99, 0x51, 0xa6, 0xb4, 0x97, 0xbf, 0x1b, 0x92, 0x55, 0x49, 0xb9, 0x68, 0x56, 0xf9, 0x04, 0x6a, + 0x21, 0x3a, 0x27, 0x76, 0xea, 0x76, 0xac, 0xae, 0x31, 0xb6, 0xdd, 0xbb, 0x94, 0x9e, 0x08, 0xe4, + 0x11, 0x22, 0x56, 0x95, 0x16, 0xa7, 0x11, 0xea, 0x35, 0x90, 0x61, 0x2a, 0x3d, 0x80, 0x29, 0x53, + 0x47, 0x45, 0xb1, 0x16, 0x33, 0x54, 0xe5, 0x87, 0x88, 0xa2, 0xc5, 0x19, 0x51, 0x3d, 0x50, 0xcf, + 0x2e, 0xff, 0x9c, 0x35, 0xf5, 0xc1, 0x3a, 0x7b, 0xc4, 0x67, 0x73, 0x1f, 0xcc, 0xab, 0x13, 0x47, + 0xe4, 0x7a, 0x13, 0xfc, 0x17, 0x6f, 0x7e, 0x06, 0xbb, 0x0b, 0xde, 0x5c, 0xba, 0x25, 0x15, 0x29, + 0x33, 0x91, 0xcd, 0x8c, 0x59, 0x17, 0x89, 0x84, 0x52, 0xb1, 0xa6, 0x63, 0x84, 0x27, 0x43, 0x82, + 0x6d, 0x1f, 0x62, 0x5f, 0xdd, 0x68, 0x4a, 0xed, 0x0d, 0xbe, 0xa6, 0x16, 0x8f, 0x1f, 0x40, 0xec, + 0x2b, 0x4f, 0x41, 0x19, 0xc6, 0x31, 0x87, 0x54, 0x18, 0xa4, 0x04, 0xe3, 0x98, 0xa6, 0x8c, 0xaf, + 0x57, 0xb3, 0xba, 0x74, 0x3d, 0xab, 0x4b, 0x7f, 0x66, 0x75, 0xe9, 0xf2, 0xb6, 0x5e, 0xb8, 0xbe, + 0xad, 0x17, 0x7e, 0xdd, 0xd6, 0x0b, 0xdf, 0xde, 0x7a, 0x01, 0xf1, 0x27, 0x0e, 0x6d, 0x5b, 0x4f, + 0x7f, 0x0a, 0xf3, 0x1f, 0x56, 0x1c, 0xe8, 0xf9, 0x7f, 0x3e, 0x67, 0x8d, 0x6d, 0xe6, 0x9b, 0x7f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0x60, 0xa6, 0x4a, 0xde, 0x1a, 0x07, 0x00, 0x00, +} + +func (m *ABCIResponses) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ABCIResponses) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ABCIResponses) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BeginBlock != nil { + { + size, err := m.BeginBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.EndBlock != nil { + { + size, err := m.EndBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.DeliverTxs) > 0 { + for iNdEx := len(m.DeliverTxs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.DeliverTxs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ConsensusParamsInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsensusParamsInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsensusParamsInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LastHeightChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightChanged)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ABCIResponsesInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ABCIResponsesInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ABCIResponsesInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if m.AbciResponses != nil { + { + size, err := m.AbciResponses.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *State) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *State) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *State) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.InitialHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.InitialHeight)) + i-- + dAtA[i] = 0x70 + } + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x6a + } + if len(m.LastResultsHash) > 0 { + i -= len(m.LastResultsHash) + copy(dAtA[i:], m.LastResultsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.LastResultsHash))) + i-- + dAtA[i] = 0x62 + } + if m.LastHeightConsensusParamsChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightConsensusParamsChanged)) + i-- + dAtA[i] = 0x58 + } + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + if m.LastHeightValidatorsChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightValidatorsChanged)) + i-- + dAtA[i] = 0x48 + } + if m.LastValidators != nil { + { + size, err := m.LastValidators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + if m.Validators != nil { + { + size, err := m.Validators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + if m.NextValidators != nil { + { + size, err := m.NextValidators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + n9, err9 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastBlockTime):]) + if err9 != nil { + return 0, err9 + } + i -= n9 + i = encodeVarintTypes(dAtA, i, uint64(n9)) + i-- + dAtA[i] = 0x2a + { + size, err := m.LastBlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.LastBlockHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastBlockHeight)) + i-- + dAtA[i] = 0x18 + } + if len(m.ChainID) > 0 { + i -= len(m.ChainID) + copy(dAtA[i:], m.ChainID) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainID))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ABCIResponses) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.DeliverTxs) > 0 { + for _, e := range m.DeliverTxs { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ConsensusParamsInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.LastHeightChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightChanged)) + } + return n +} + +func (m *ABCIResponsesInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AbciResponses != nil { + l = m.AbciResponses.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *State) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Version.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastBlockHeight != 0 { + n += 1 + sovTypes(uint64(m.LastBlockHeight)) + } + l = m.LastBlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastBlockTime) + n += 1 + l + sovTypes(uint64(l)) + if m.NextValidators != nil { + l = m.NextValidators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Validators != nil { + l = m.Validators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastValidators != nil { + l = m.LastValidators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastHeightValidatorsChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightValidatorsChanged)) + } + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.LastHeightConsensusParamsChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightConsensusParamsChanged)) + } + l = len(m.LastResultsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.InitialHeight != 0 { + n += 1 + sovTypes(uint64(m.InitialHeight)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ABCIResponses) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ABCIResponses: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ABCIResponses: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTxs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DeliverTxs = append(m.DeliverTxs, &v1beta2.ResponseDeliverTx{}) + if err := m.DeliverTxs[len(m.DeliverTxs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.EndBlock == nil { + m.EndBlock = &v1beta2.ResponseEndBlock{} + } + if err := m.EndBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BeginBlock == nil { + m.BeginBlock = &v1beta2.ResponseBeginBlock{} + } + if err := m.BeginBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConsensusParamsInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsensusParamsInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusParamsInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightChanged", wireType) + } + m.LastHeightChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ABCIResponsesInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ABCIResponsesInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ABCIResponsesInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AbciResponses", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AbciResponses == nil { + m.AbciResponses = &ABCIResponses{} + } + if err := m.AbciResponses.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *State) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: State: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: State: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockHeight", wireType) + } + m.LastBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastBlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastBlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.LastBlockTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.NextValidators == nil { + m.NextValidators = &v1beta11.ValidatorSet{} + } + if err := m.NextValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Validators == nil { + m.Validators = &v1beta11.ValidatorSet{} + } + if err := m.Validators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastValidators == nil { + m.LastValidators = &v1beta11.ValidatorSet{} + } + if err := m.LastValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightValidatorsChanged", wireType) + } + m.LastHeightValidatorsChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightValidatorsChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightConsensusParamsChanged", wireType) + } + m.LastHeightConsensusParamsChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightConsensusParamsChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastResultsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastResultsHash = append(m.LastResultsHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastResultsHash == nil { + m.LastResultsHash = []byte{} + } + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialHeight", wireType) + } + m.InitialHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/state/v1beta3/types.pb.go b/api/cometbft/state/v1beta3/types.pb.go new file mode 100644 index 00000000000..aa3e36e3b9c --- /dev/null +++ b/api/cometbft/state/v1beta3/types.pb.go @@ -0,0 +1,2303 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/state/v1beta3/types.proto + +package v1beta3 + +import ( + fmt "fmt" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta1" + v1beta2 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta2" + v1beta3 "github.com/cometbft/cometbft/api/cometbft/abci/v1beta3" + v1beta11 "github.com/cometbft/cometbft/api/cometbft/state/v1beta1" + v1 "github.com/cometbft/cometbft/api/cometbft/types/v1" + v1beta12 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// LegacyABCIResponses retains the responses +// of the legacy ABCI calls during block processing. +// Note ReponseDeliverTx is renamed to ExecTxResult but they are semantically the same +// Kept for backwards compatibility for versions prior to v0.38 +type LegacyABCIResponses struct { + DeliverTxs []*v1beta3.ExecTxResult `protobuf:"bytes,1,rep,name=deliver_txs,json=deliverTxs,proto3" json:"deliver_txs,omitempty"` + EndBlock *ResponseEndBlock `protobuf:"bytes,2,opt,name=end_block,json=endBlock,proto3" json:"end_block,omitempty"` + BeginBlock *ResponseBeginBlock `protobuf:"bytes,3,opt,name=begin_block,json=beginBlock,proto3" json:"begin_block,omitempty"` +} + +func (m *LegacyABCIResponses) Reset() { *m = LegacyABCIResponses{} } +func (m *LegacyABCIResponses) String() string { return proto.CompactTextString(m) } +func (*LegacyABCIResponses) ProtoMessage() {} +func (*LegacyABCIResponses) Descriptor() ([]byte, []int) { + return fileDescriptor_941a8825417feee0, []int{0} +} +func (m *LegacyABCIResponses) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LegacyABCIResponses) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LegacyABCIResponses.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LegacyABCIResponses) XXX_Merge(src proto.Message) { + xxx_messageInfo_LegacyABCIResponses.Merge(m, src) +} +func (m *LegacyABCIResponses) XXX_Size() int { + return m.Size() +} +func (m *LegacyABCIResponses) XXX_DiscardUnknown() { + xxx_messageInfo_LegacyABCIResponses.DiscardUnknown(m) +} + +var xxx_messageInfo_LegacyABCIResponses proto.InternalMessageInfo + +func (m *LegacyABCIResponses) GetDeliverTxs() []*v1beta3.ExecTxResult { + if m != nil { + return m.DeliverTxs + } + return nil +} + +func (m *LegacyABCIResponses) GetEndBlock() *ResponseEndBlock { + if m != nil { + return m.EndBlock + } + return nil +} + +func (m *LegacyABCIResponses) GetBeginBlock() *ResponseBeginBlock { + if m != nil { + return m.BeginBlock + } + return nil +} + +// ResponseBeginBlock is kept for backward compatibility for versions prior to v0.38, +// as it was then defined in the cometbft.abci packages. +type ResponseBeginBlock struct { + Events []v1beta2.Event `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` +} + +func (m *ResponseBeginBlock) Reset() { *m = ResponseBeginBlock{} } +func (m *ResponseBeginBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseBeginBlock) ProtoMessage() {} +func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_941a8825417feee0, []int{1} +} +func (m *ResponseBeginBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseBeginBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseBeginBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseBeginBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseBeginBlock.Merge(m, src) +} +func (m *ResponseBeginBlock) XXX_Size() int { + return m.Size() +} +func (m *ResponseBeginBlock) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseBeginBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseBeginBlock proto.InternalMessageInfo + +func (m *ResponseBeginBlock) GetEvents() []v1beta2.Event { + if m != nil { + return m.Events + } + return nil +} + +// ResponseEndBlock is kept for backward compatibility for versions prior to v0.38, +// its earlier revisions were defined in the cometbft.abci packages. +// It uses an updated definition for the consensus_param_updates field to keep the +// generated data types interoperable with the latest protocol. +type ResponseEndBlock struct { + ValidatorUpdates []v1beta1.ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` + ConsensusParamUpdates *v1.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` + Events []v1beta2.Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` +} + +func (m *ResponseEndBlock) Reset() { *m = ResponseEndBlock{} } +func (m *ResponseEndBlock) String() string { return proto.CompactTextString(m) } +func (*ResponseEndBlock) ProtoMessage() {} +func (*ResponseEndBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_941a8825417feee0, []int{2} +} +func (m *ResponseEndBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ResponseEndBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ResponseEndBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ResponseEndBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_ResponseEndBlock.Merge(m, src) +} +func (m *ResponseEndBlock) XXX_Size() int { + return m.Size() +} +func (m *ResponseEndBlock) XXX_DiscardUnknown() { + xxx_messageInfo_ResponseEndBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_ResponseEndBlock proto.InternalMessageInfo + +func (m *ResponseEndBlock) GetValidatorUpdates() []v1beta1.ValidatorUpdate { + if m != nil { + return m.ValidatorUpdates + } + return nil +} + +func (m *ResponseEndBlock) GetConsensusParamUpdates() *v1.ConsensusParams { + if m != nil { + return m.ConsensusParamUpdates + } + return nil +} + +func (m *ResponseEndBlock) GetEvents() []v1beta2.Event { + if m != nil { + return m.Events + } + return nil +} + +// ConsensusParamsInfo represents the latest consensus params, or the last height it changed +type ConsensusParamsInfo struct { + ConsensusParams v1.ConsensusParams `protobuf:"bytes,1,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightChanged int64 `protobuf:"varint,2,opt,name=last_height_changed,json=lastHeightChanged,proto3" json:"last_height_changed,omitempty"` +} + +func (m *ConsensusParamsInfo) Reset() { *m = ConsensusParamsInfo{} } +func (m *ConsensusParamsInfo) String() string { return proto.CompactTextString(m) } +func (*ConsensusParamsInfo) ProtoMessage() {} +func (*ConsensusParamsInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_941a8825417feee0, []int{3} +} +func (m *ConsensusParamsInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsensusParamsInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsensusParamsInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsensusParamsInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsensusParamsInfo.Merge(m, src) +} +func (m *ConsensusParamsInfo) XXX_Size() int { + return m.Size() +} +func (m *ConsensusParamsInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ConsensusParamsInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsensusParamsInfo proto.InternalMessageInfo + +func (m *ConsensusParamsInfo) GetConsensusParams() v1.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return v1.ConsensusParams{} +} + +func (m *ConsensusParamsInfo) GetLastHeightChanged() int64 { + if m != nil { + return m.LastHeightChanged + } + return 0 +} + +// ABCIResponsesInfo retains the responses of the ABCI calls during block processing. +type ABCIResponsesInfo struct { + // Retains the responses of the legacy ABCI calls during block processing. + LegacyAbciResponses *LegacyABCIResponses `protobuf:"bytes,1,opt,name=legacy_abci_responses,json=legacyAbciResponses,proto3" json:"legacy_abci_responses,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + ResponseFinalizeBlock *v1beta3.ResponseFinalizeBlock `protobuf:"bytes,3,opt,name=response_finalize_block,json=responseFinalizeBlock,proto3" json:"response_finalize_block,omitempty"` +} + +func (m *ABCIResponsesInfo) Reset() { *m = ABCIResponsesInfo{} } +func (m *ABCIResponsesInfo) String() string { return proto.CompactTextString(m) } +func (*ABCIResponsesInfo) ProtoMessage() {} +func (*ABCIResponsesInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_941a8825417feee0, []int{4} +} +func (m *ABCIResponsesInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ABCIResponsesInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ABCIResponsesInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ABCIResponsesInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ABCIResponsesInfo.Merge(m, src) +} +func (m *ABCIResponsesInfo) XXX_Size() int { + return m.Size() +} +func (m *ABCIResponsesInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ABCIResponsesInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ABCIResponsesInfo proto.InternalMessageInfo + +func (m *ABCIResponsesInfo) GetLegacyAbciResponses() *LegacyABCIResponses { + if m != nil { + return m.LegacyAbciResponses + } + return nil +} + +func (m *ABCIResponsesInfo) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *ABCIResponsesInfo) GetResponseFinalizeBlock() *v1beta3.ResponseFinalizeBlock { + if m != nil { + return m.ResponseFinalizeBlock + } + return nil +} + +// State represents the state of the blockchain. +type State struct { + Version v1beta11.Version `protobuf:"bytes,1,opt,name=version,proto3" json:"version"` + // immutable + ChainID string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + InitialHeight int64 `protobuf:"varint,14,opt,name=initial_height,json=initialHeight,proto3" json:"initial_height,omitempty"` + // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) + LastBlockHeight int64 `protobuf:"varint,3,opt,name=last_block_height,json=lastBlockHeight,proto3" json:"last_block_height,omitempty"` + LastBlockID v1beta12.BlockID `protobuf:"bytes,4,opt,name=last_block_id,json=lastBlockId,proto3" json:"last_block_id"` + LastBlockTime time.Time `protobuf:"bytes,5,opt,name=last_block_time,json=lastBlockTime,proto3,stdtime" json:"last_block_time"` + // LastValidators is used to validate block.LastCommit. + // Validators are persisted to the database separately every time they change, + // so we can query for historical validator sets. + // Note that if s.LastBlockHeight causes a valset change, + // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 + // Extra +1 due to nextValSet delay. + NextValidators *v1beta12.ValidatorSet `protobuf:"bytes,6,opt,name=next_validators,json=nextValidators,proto3" json:"next_validators,omitempty"` + Validators *v1beta12.ValidatorSet `protobuf:"bytes,7,opt,name=validators,proto3" json:"validators,omitempty"` + LastValidators *v1beta12.ValidatorSet `protobuf:"bytes,8,opt,name=last_validators,json=lastValidators,proto3" json:"last_validators,omitempty"` + LastHeightValidatorsChanged int64 `protobuf:"varint,9,opt,name=last_height_validators_changed,json=lastHeightValidatorsChanged,proto3" json:"last_height_validators_changed,omitempty"` + // Consensus parameters used for validating blocks. + // Changes returned by EndBlock and updated after Commit. + ConsensusParams v1.ConsensusParams `protobuf:"bytes,10,opt,name=consensus_params,json=consensusParams,proto3" json:"consensus_params"` + LastHeightConsensusParamsChanged int64 `protobuf:"varint,11,opt,name=last_height_consensus_params_changed,json=lastHeightConsensusParamsChanged,proto3" json:"last_height_consensus_params_changed,omitempty"` + // Merkle root of the results from executing prev block + LastResultsHash []byte `protobuf:"bytes,12,opt,name=last_results_hash,json=lastResultsHash,proto3" json:"last_results_hash,omitempty"` + // the latest AppHash we've received from calling abci.Commit() + AppHash []byte `protobuf:"bytes,13,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (m *State) Reset() { *m = State{} } +func (m *State) String() string { return proto.CompactTextString(m) } +func (*State) ProtoMessage() {} +func (*State) Descriptor() ([]byte, []int) { + return fileDescriptor_941a8825417feee0, []int{5} +} +func (m *State) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *State) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_State.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *State) XXX_Merge(src proto.Message) { + xxx_messageInfo_State.Merge(m, src) +} +func (m *State) XXX_Size() int { + return m.Size() +} +func (m *State) XXX_DiscardUnknown() { + xxx_messageInfo_State.DiscardUnknown(m) +} + +var xxx_messageInfo_State proto.InternalMessageInfo + +func (m *State) GetVersion() v1beta11.Version { + if m != nil { + return m.Version + } + return v1beta11.Version{} +} + +func (m *State) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +func (m *State) GetInitialHeight() int64 { + if m != nil { + return m.InitialHeight + } + return 0 +} + +func (m *State) GetLastBlockHeight() int64 { + if m != nil { + return m.LastBlockHeight + } + return 0 +} + +func (m *State) GetLastBlockID() v1beta12.BlockID { + if m != nil { + return m.LastBlockID + } + return v1beta12.BlockID{} +} + +func (m *State) GetLastBlockTime() time.Time { + if m != nil { + return m.LastBlockTime + } + return time.Time{} +} + +func (m *State) GetNextValidators() *v1beta12.ValidatorSet { + if m != nil { + return m.NextValidators + } + return nil +} + +func (m *State) GetValidators() *v1beta12.ValidatorSet { + if m != nil { + return m.Validators + } + return nil +} + +func (m *State) GetLastValidators() *v1beta12.ValidatorSet { + if m != nil { + return m.LastValidators + } + return nil +} + +func (m *State) GetLastHeightValidatorsChanged() int64 { + if m != nil { + return m.LastHeightValidatorsChanged + } + return 0 +} + +func (m *State) GetConsensusParams() v1.ConsensusParams { + if m != nil { + return m.ConsensusParams + } + return v1.ConsensusParams{} +} + +func (m *State) GetLastHeightConsensusParamsChanged() int64 { + if m != nil { + return m.LastHeightConsensusParamsChanged + } + return 0 +} + +func (m *State) GetLastResultsHash() []byte { + if m != nil { + return m.LastResultsHash + } + return nil +} + +func (m *State) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +func init() { + proto.RegisterType((*LegacyABCIResponses)(nil), "cometbft.state.v1beta3.LegacyABCIResponses") + proto.RegisterType((*ResponseBeginBlock)(nil), "cometbft.state.v1beta3.ResponseBeginBlock") + proto.RegisterType((*ResponseEndBlock)(nil), "cometbft.state.v1beta3.ResponseEndBlock") + proto.RegisterType((*ConsensusParamsInfo)(nil), "cometbft.state.v1beta3.ConsensusParamsInfo") + proto.RegisterType((*ABCIResponsesInfo)(nil), "cometbft.state.v1beta3.ABCIResponsesInfo") + proto.RegisterType((*State)(nil), "cometbft.state.v1beta3.State") +} + +func init() { + proto.RegisterFile("cometbft/state/v1beta3/types.proto", fileDescriptor_941a8825417feee0) +} + +var fileDescriptor_941a8825417feee0 = []byte{ + // 921 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4d, 0x6f, 0xdb, 0x46, + 0x10, 0x35, 0xa3, 0xc4, 0x92, 0x57, 0xf1, 0xd7, 0xaa, 0x4e, 0x54, 0xb7, 0x90, 0x5c, 0x35, 0x35, + 0x8c, 0x34, 0x20, 0x21, 0xe7, 0xd0, 0x63, 0x11, 0xca, 0x2e, 0x22, 0xd4, 0x0d, 0x5a, 0xda, 0x0d, + 0xda, 0x5c, 0x88, 0x25, 0xb9, 0xa6, 0x16, 0xa5, 0x48, 0x82, 0xbb, 0x12, 0xe4, 0x9e, 0xfa, 0x13, + 0x72, 0x6d, 0x7f, 0x51, 0x8e, 0x39, 0xf6, 0xe4, 0x16, 0xf2, 0xad, 0x97, 0x02, 0xfd, 0x05, 0xc5, + 0x7e, 0x51, 0xa4, 0x42, 0x21, 0x09, 0xda, 0xdb, 0x6a, 0xf7, 0xcd, 0x9b, 0xf7, 0x66, 0x77, 0x46, + 0x04, 0x3d, 0x3f, 0x19, 0x63, 0xe6, 0x5d, 0x32, 0x8b, 0x32, 0xc4, 0xb0, 0x35, 0xed, 0x7b, 0x98, + 0xa1, 0xc7, 0x16, 0xbb, 0x4a, 0x31, 0x35, 0xd3, 0x2c, 0x61, 0x09, 0xbc, 0xa7, 0x31, 0xa6, 0xc0, + 0x98, 0x0a, 0xb3, 0x5f, 0x1d, 0xdb, 0x2f, 0xc6, 0xee, 0x7f, 0x92, 0x63, 0x90, 0xe7, 0x93, 0x77, + 0x87, 0x1c, 0xbf, 0x1d, 0x52, 0x12, 0x59, 0x10, 0x23, 0x76, 0x2b, 0x33, 0x1d, 0xae, 0xc0, 0x4c, + 0x51, 0x44, 0x02, 0xc4, 0x92, 0x4c, 0xe1, 0x3a, 0x6f, 0xe0, 0xac, 0x14, 0x65, 0x68, 0xac, 0x79, + 0x3e, 0x08, 0x93, 0x30, 0x11, 0x4b, 0x8b, 0xaf, 0xd4, 0x6e, 0x37, 0x4c, 0x92, 0x30, 0xc2, 0x96, + 0xf8, 0xe5, 0x4d, 0x2e, 0x2d, 0x46, 0xc6, 0x98, 0x32, 0x34, 0x4e, 0x25, 0xa0, 0xf7, 0xb7, 0x01, + 0x5a, 0x67, 0x38, 0x44, 0xfe, 0xd5, 0x13, 0x7b, 0x30, 0x74, 0x30, 0x4d, 0x93, 0x98, 0x62, 0x0a, + 0x4f, 0x40, 0x33, 0xc0, 0x11, 0x99, 0xe2, 0xcc, 0x65, 0x33, 0xda, 0x36, 0x0e, 0x6a, 0x47, 0xcd, + 0xe3, 0x4f, 0xcd, 0xbc, 0xea, 0xdc, 0xb3, 0x2e, 0xba, 0x79, 0x3a, 0xc3, 0xfe, 0xc5, 0xcc, 0xc1, + 0x74, 0x12, 0x31, 0x07, 0xa8, 0xb8, 0x8b, 0x19, 0x85, 0xa7, 0x60, 0x03, 0xc7, 0x81, 0xeb, 0x45, + 0x89, 0xff, 0x53, 0xfb, 0xd6, 0x81, 0x71, 0xd4, 0x3c, 0x3e, 0x32, 0xab, 0x6f, 0xce, 0xd4, 0xb9, + 0x4f, 0xe3, 0xc0, 0xe6, 0x78, 0xa7, 0x81, 0xd5, 0x0a, 0x7e, 0x0d, 0x9a, 0x1e, 0x0e, 0x49, 0xac, + 0x88, 0x6a, 0x82, 0xe8, 0xe1, 0xdb, 0x88, 0x6c, 0x1e, 0x22, 0xa9, 0x80, 0x97, 0xaf, 0x7b, 0x01, + 0x80, 0x6f, 0x22, 0xe0, 0x33, 0xb0, 0x8e, 0xa7, 0x38, 0x66, 0xda, 0xea, 0xc7, 0x95, 0x56, 0x8f, + 0xcd, 0x53, 0x0e, 0xb2, 0xdb, 0xaf, 0xae, 0xbb, 0x6b, 0x7f, 0x5d, 0x77, 0x77, 0x64, 0xcc, 0xa3, + 0x64, 0x4c, 0x18, 0x1e, 0xa7, 0xec, 0xca, 0x51, 0x2c, 0xbd, 0x5f, 0x6f, 0x81, 0x9d, 0x65, 0x47, + 0xf0, 0x47, 0xb0, 0x9b, 0x5f, 0xab, 0x3b, 0x49, 0x03, 0xc4, 0xb0, 0xce, 0x77, 0x58, 0x99, 0xaf, + 0x6f, 0x3e, 0xd7, 0xf8, 0xef, 0x05, 0xdc, 0xbe, 0xcd, 0x33, 0x3b, 0x3b, 0xd3, 0xf2, 0x36, 0x85, + 0x2f, 0xc0, 0x7d, 0x9f, 0xe7, 0x8a, 0xe9, 0x84, 0xba, 0xe2, 0x61, 0xe4, 0x09, 0x64, 0xdd, 0x7b, + 0x8b, 0x04, 0xf2, 0xf9, 0x4d, 0xfb, 0xe6, 0x40, 0x47, 0x7c, 0x2b, 0x5e, 0x92, 0xb3, 0xe7, 0x97, + 0x36, 0x34, 0xf7, 0xa2, 0x36, 0xb5, 0xff, 0xa5, 0x36, 0xbf, 0x19, 0xa0, 0xb5, 0x94, 0x7a, 0x18, + 0x5f, 0x26, 0xf0, 0x1c, 0xec, 0x2c, 0x79, 0xe0, 0xd5, 0x79, 0x47, 0xf1, 0xaa, 0x32, 0xdb, 0x65, + 0x0b, 0x14, 0x9a, 0xa0, 0x15, 0x21, 0xca, 0xdc, 0x11, 0x26, 0xe1, 0x88, 0xb9, 0xfe, 0x08, 0xc5, + 0x21, 0x0e, 0x44, 0x51, 0x6a, 0xce, 0x2e, 0x3f, 0x7a, 0x2a, 0x4e, 0x06, 0xf2, 0xa0, 0xf7, 0x8f, + 0x01, 0x76, 0x4b, 0xad, 0x20, 0xa4, 0xb9, 0x60, 0x2f, 0x12, 0x5d, 0xe2, 0x72, 0xc7, 0x6e, 0xa6, + 0x0f, 0x95, 0xbe, 0xcf, 0x57, 0xbd, 0xc5, 0x8a, 0xd6, 0x72, 0x5a, 0x92, 0xe9, 0x89, 0xe7, 0x93, + 0x45, 0xbf, 0xdd, 0x03, 0xeb, 0x52, 0xa1, 0x52, 0xa6, 0x7e, 0xc1, 0x00, 0xdc, 0xd7, 0xc9, 0xdc, + 0x4b, 0x12, 0xa3, 0x88, 0xfc, 0x8c, 0x4b, 0x6d, 0xf0, 0x68, 0x45, 0x4f, 0x6a, 0xea, 0xaf, 0x54, + 0x90, 0x6c, 0x84, 0xbd, 0xac, 0x6a, 0xbb, 0xf7, 0x4b, 0x1d, 0xdc, 0x39, 0xe7, 0xc2, 0xe1, 0x97, + 0xa0, 0x3e, 0xc5, 0x19, 0x25, 0x49, 0xac, 0xac, 0x75, 0xab, 0xad, 0xf5, 0xcd, 0xe7, 0x12, 0xa6, + 0xea, 0xae, 0xa3, 0xe0, 0x21, 0x68, 0xf8, 0x23, 0x44, 0x62, 0x97, 0xc8, 0x22, 0x6f, 0xd8, 0xcd, + 0xf9, 0x75, 0xb7, 0x3e, 0xe0, 0x7b, 0xc3, 0x13, 0xa7, 0x2e, 0x0e, 0x87, 0x01, 0xfc, 0x0c, 0x6c, + 0x91, 0x98, 0x30, 0x82, 0x22, 0x75, 0x35, 0xed, 0x2d, 0x61, 0x7c, 0x53, 0xed, 0xca, 0x5b, 0x81, + 0x0f, 0x81, 0xb8, 0x23, 0x69, 0x59, 0x23, 0x6b, 0x02, 0xb9, 0xcd, 0x0f, 0x84, 0x7e, 0x85, 0xfd, + 0x01, 0x6c, 0x16, 0xb0, 0x24, 0x68, 0xdf, 0x5e, 0x76, 0xa0, 0x1f, 0x8f, 0x74, 0x20, 0x62, 0x87, + 0x27, 0x76, 0x8b, 0x3b, 0x98, 0x5f, 0x77, 0x9b, 0x67, 0x9a, 0x70, 0x78, 0xe2, 0x34, 0x73, 0xf6, + 0x61, 0x00, 0xcf, 0xc0, 0x76, 0x81, 0x99, 0xcf, 0xd0, 0xf6, 0x1d, 0xc1, 0xbd, 0x6f, 0xca, 0x01, + 0x6b, 0xea, 0x01, 0x6b, 0x5e, 0xe8, 0x01, 0x6b, 0x37, 0x38, 0xed, 0xcb, 0x3f, 0xba, 0x86, 0xb3, + 0x99, 0x73, 0xf1, 0x53, 0xf8, 0x0d, 0xd8, 0x8e, 0xf1, 0x8c, 0xb9, 0x79, 0x13, 0xd3, 0xf6, 0xba, + 0x60, 0x7b, 0xb0, 0x4a, 0x69, 0x3e, 0x05, 0xce, 0x31, 0x73, 0xb6, 0x78, 0x70, 0xbe, 0xc3, 0x47, + 0x35, 0x28, 0x30, 0xd5, 0xdf, 0x83, 0xa9, 0x10, 0xc7, 0x45, 0x09, 0x8b, 0x05, 0xaa, 0xc6, 0xfb, + 0x88, 0xe2, 0xc1, 0x05, 0x51, 0x03, 0xd0, 0x29, 0xb6, 0xdd, 0x82, 0x35, 0xef, 0xc0, 0x0d, 0x71, + 0x89, 0x1f, 0x2d, 0x3a, 0x70, 0x11, 0xad, 0x7a, 0xb1, 0x72, 0x20, 0x80, 0xff, 0x3a, 0x10, 0x9e, + 0x81, 0x07, 0xa5, 0x81, 0xb0, 0x94, 0x20, 0xd7, 0xd7, 0x14, 0xfa, 0x0e, 0x0a, 0x13, 0xa2, 0x4c, + 0xa4, 0x45, 0xea, 0x17, 0x9a, 0x89, 0xbf, 0x3f, 0xea, 0x8e, 0x10, 0x1d, 0xb5, 0xef, 0x1e, 0x18, + 0x47, 0x77, 0xe5, 0x0b, 0x95, 0x7f, 0x8b, 0xf4, 0x29, 0xa2, 0x23, 0xf8, 0x21, 0x68, 0xa0, 0x34, + 0x95, 0x90, 0x4d, 0x01, 0xa9, 0xa3, 0x34, 0xe5, 0x47, 0xf6, 0x77, 0xaf, 0xe6, 0x1d, 0xe3, 0xf5, + 0xbc, 0x63, 0xfc, 0x39, 0xef, 0x18, 0x2f, 0x6f, 0x3a, 0x6b, 0xaf, 0x6f, 0x3a, 0x6b, 0xbf, 0xdf, + 0x74, 0xd6, 0x5e, 0x7c, 0x11, 0x12, 0x36, 0x9a, 0x78, 0xdc, 0xb1, 0x95, 0x7f, 0x04, 0x2c, 0x3e, + 0x3e, 0x52, 0x62, 0x55, 0x7f, 0x2f, 0x79, 0xeb, 0xe2, 0x51, 0x3e, 0xfe, 0x37, 0x00, 0x00, 0xff, + 0xff, 0x20, 0xeb, 0x80, 0xec, 0x50, 0x09, 0x00, 0x00, +} + +func (m *LegacyABCIResponses) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LegacyABCIResponses) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LegacyABCIResponses) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BeginBlock != nil { + { + size, err := m.BeginBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.EndBlock != nil { + { + size, err := m.EndBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.DeliverTxs) > 0 { + for iNdEx := len(m.DeliverTxs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.DeliverTxs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResponseBeginBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseBeginBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseBeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ResponseEndBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseEndBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ResponseEndBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Events) > 0 { + for iNdEx := len(m.Events) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Events[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.ConsensusParamUpdates != nil { + { + size, err := m.ConsensusParamUpdates.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.ValidatorUpdates) > 0 { + for iNdEx := len(m.ValidatorUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ValidatorUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ConsensusParamsInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsensusParamsInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsensusParamsInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LastHeightChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightChanged)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ABCIResponsesInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ABCIResponsesInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ABCIResponsesInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ResponseFinalizeBlock != nil { + { + size, err := m.ResponseFinalizeBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if m.LegacyAbciResponses != nil { + { + size, err := m.LegacyAbciResponses.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *State) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *State) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *State) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.InitialHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.InitialHeight)) + i-- + dAtA[i] = 0x70 + } + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x6a + } + if len(m.LastResultsHash) > 0 { + i -= len(m.LastResultsHash) + copy(dAtA[i:], m.LastResultsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.LastResultsHash))) + i-- + dAtA[i] = 0x62 + } + if m.LastHeightConsensusParamsChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightConsensusParamsChanged)) + i-- + dAtA[i] = 0x58 + } + { + size, err := m.ConsensusParams.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + if m.LastHeightValidatorsChanged != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastHeightValidatorsChanged)) + i-- + dAtA[i] = 0x48 + } + if m.LastValidators != nil { + { + size, err := m.LastValidators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + if m.Validators != nil { + { + size, err := m.Validators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + if m.NextValidators != nil { + { + size, err := m.NextValidators.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + n11, err11 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastBlockTime):]) + if err11 != nil { + return 0, err11 + } + i -= n11 + i = encodeVarintTypes(dAtA, i, uint64(n11)) + i-- + dAtA[i] = 0x2a + { + size, err := m.LastBlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.LastBlockHeight != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.LastBlockHeight)) + i-- + dAtA[i] = 0x18 + } + if len(m.ChainID) > 0 { + i -= len(m.ChainID) + copy(dAtA[i:], m.ChainID) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainID))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *LegacyABCIResponses) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.DeliverTxs) > 0 { + for _, e := range m.DeliverTxs { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseBeginBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseEndBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ValidatorUpdates) > 0 { + for _, e := range m.ValidatorUpdates { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.ConsensusParamUpdates != nil { + l = m.ConsensusParamUpdates.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Events) > 0 { + for _, e := range m.Events { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ConsensusParamsInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.LastHeightChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightChanged)) + } + return n +} + +func (m *ABCIResponsesInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LegacyAbciResponses != nil { + l = m.LegacyAbciResponses.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.ResponseFinalizeBlock != nil { + l = m.ResponseFinalizeBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *State) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Version.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastBlockHeight != 0 { + n += 1 + sovTypes(uint64(m.LastBlockHeight)) + } + l = m.LastBlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.LastBlockTime) + n += 1 + l + sovTypes(uint64(l)) + if m.NextValidators != nil { + l = m.NextValidators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Validators != nil { + l = m.Validators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastValidators != nil { + l = m.LastValidators.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastHeightValidatorsChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightValidatorsChanged)) + } + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.LastHeightConsensusParamsChanged != 0 { + n += 1 + sovTypes(uint64(m.LastHeightConsensusParamsChanged)) + } + l = len(m.LastResultsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.InitialHeight != 0 { + n += 1 + sovTypes(uint64(m.InitialHeight)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *LegacyABCIResponses) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LegacyABCIResponses: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LegacyABCIResponses: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTxs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DeliverTxs = append(m.DeliverTxs, &v1beta3.ExecTxResult{}) + if err := m.DeliverTxs[len(m.DeliverTxs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.EndBlock == nil { + m.EndBlock = &ResponseEndBlock{} + } + if err := m.EndBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BeginBlock == nil { + m.BeginBlock = &ResponseBeginBlock{} + } + if err := m.BeginBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseBeginBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseBeginBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseBeginBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, v1beta2.Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseEndBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseEndBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorUpdates = append(m.ValidatorUpdates, v1beta1.ValidatorUpdate{}) + if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParamUpdates == nil { + m.ConsensusParamUpdates = &v1.ConsensusParams{} + } + if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Events", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Events = append(m.Events, v1beta2.Event{}) + if err := m.Events[len(m.Events)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConsensusParamsInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsensusParamsInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusParamsInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightChanged", wireType) + } + m.LastHeightChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ABCIResponsesInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ABCIResponsesInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ABCIResponsesInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LegacyAbciResponses", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LegacyAbciResponses == nil { + m.LegacyAbciResponses = &LegacyABCIResponses{} + } + if err := m.LegacyAbciResponses.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ResponseFinalizeBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ResponseFinalizeBlock == nil { + m.ResponseFinalizeBlock = &v1beta3.ResponseFinalizeBlock{} + } + if err := m.ResponseFinalizeBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *State) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: State: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: State: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockHeight", wireType) + } + m.LastBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastBlockHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastBlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.LastBlockTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.NextValidators == nil { + m.NextValidators = &v1beta12.ValidatorSet{} + } + if err := m.NextValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Validators == nil { + m.Validators = &v1beta12.ValidatorSet{} + } + if err := m.Validators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastValidators == nil { + m.LastValidators = &v1beta12.ValidatorSet{} + } + if err := m.LastValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightValidatorsChanged", wireType) + } + m.LastHeightValidatorsChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightValidatorsChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastHeightConsensusParamsChanged", wireType) + } + m.LastHeightConsensusParamsChanged = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastHeightConsensusParamsChanged |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastResultsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastResultsHash = append(m.LastResultsHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastResultsHash == nil { + m.LastResultsHash = []byte{} + } + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialHeight", wireType) + } + m.InitialHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.InitialHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/tendermint/statesync/message.go b/api/cometbft/statesync/v1/message.go similarity index 84% rename from proto/tendermint/statesync/message.go rename to api/cometbft/statesync/v1/message.go index 357e8eac5c5..af6c0ea1010 100644 --- a/proto/tendermint/statesync/message.go +++ b/api/cometbft/statesync/v1/message.go @@ -1,18 +1,11 @@ -package statesync +package v1 import ( "fmt" "github.com/cosmos/gogoproto/proto" - - "github.com/cometbft/cometbft/p2p" ) -var _ p2p.Wrapper = &ChunkRequest{} -var _ p2p.Wrapper = &ChunkResponse{} -var _ p2p.Wrapper = &SnapshotsRequest{} -var _ p2p.Wrapper = &SnapshotsResponse{} - func (m *SnapshotsResponse) Wrap() proto.Message { sm := &Message{} sm.Sum = &Message_SnapshotsResponse{SnapshotsResponse: m} diff --git a/proto/tendermint/statesync/types.pb.go b/api/cometbft/statesync/v1/types.pb.go similarity index 90% rename from proto/tendermint/statesync/types.pb.go rename to api/cometbft/statesync/v1/types.pb.go index 84a637f5e21..cfdad4a898b 100644 --- a/proto/tendermint/statesync/types.pb.go +++ b/api/cometbft/statesync/v1/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/statesync/types.proto +// source: cometbft/statesync/v1/types.proto -package statesync +package v1 import ( fmt "fmt" @@ -22,7 +22,10 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// Message is the top-level message type for the statesync service. type Message struct { + // The message type. + // // Types that are valid to be assigned to Sum: // // *Message_SnapshotsRequest @@ -36,7 +39,7 @@ func (m *Message) Reset() { *m = Message{} } func (m *Message) String() string { return proto.CompactTextString(m) } func (*Message) ProtoMessage() {} func (*Message) Descriptor() ([]byte, []int) { - return fileDescriptor_a1c2869546ca7914, []int{0} + return fileDescriptor_95fd383b29885bb3, []int{0} } func (m *Message) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -134,6 +137,7 @@ func (*Message) XXX_OneofWrappers() []interface{} { } } +// SnapshotsRequest is sent to request a snapshot. type SnapshotsRequest struct { } @@ -141,7 +145,7 @@ func (m *SnapshotsRequest) Reset() { *m = SnapshotsRequest{} } func (m *SnapshotsRequest) String() string { return proto.CompactTextString(m) } func (*SnapshotsRequest) ProtoMessage() {} func (*SnapshotsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_a1c2869546ca7914, []int{1} + return fileDescriptor_95fd383b29885bb3, []int{1} } func (m *SnapshotsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -170,6 +174,7 @@ func (m *SnapshotsRequest) XXX_DiscardUnknown() { var xxx_messageInfo_SnapshotsRequest proto.InternalMessageInfo +// SnapshotsResponse contains the snapshot metadata. type SnapshotsResponse struct { Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Format uint32 `protobuf:"varint,2,opt,name=format,proto3" json:"format,omitempty"` @@ -182,7 +187,7 @@ func (m *SnapshotsResponse) Reset() { *m = SnapshotsResponse{} } func (m *SnapshotsResponse) String() string { return proto.CompactTextString(m) } func (*SnapshotsResponse) ProtoMessage() {} func (*SnapshotsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_a1c2869546ca7914, []int{2} + return fileDescriptor_95fd383b29885bb3, []int{2} } func (m *SnapshotsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -246,6 +251,7 @@ func (m *SnapshotsResponse) GetMetadata() []byte { return nil } +// ChunkRequest is sent to request a chunk. type ChunkRequest struct { Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Format uint32 `protobuf:"varint,2,opt,name=format,proto3" json:"format,omitempty"` @@ -256,7 +262,7 @@ func (m *ChunkRequest) Reset() { *m = ChunkRequest{} } func (m *ChunkRequest) String() string { return proto.CompactTextString(m) } func (*ChunkRequest) ProtoMessage() {} func (*ChunkRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_a1c2869546ca7914, []int{3} + return fileDescriptor_95fd383b29885bb3, []int{3} } func (m *ChunkRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -306,6 +312,7 @@ func (m *ChunkRequest) GetIndex() uint32 { return 0 } +// ChunkResponse contains a chunk of the snapshot. type ChunkResponse struct { Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Format uint32 `protobuf:"varint,2,opt,name=format,proto3" json:"format,omitempty"` @@ -318,7 +325,7 @@ func (m *ChunkResponse) Reset() { *m = ChunkResponse{} } func (m *ChunkResponse) String() string { return proto.CompactTextString(m) } func (*ChunkResponse) ProtoMessage() {} func (*ChunkResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_a1c2869546ca7914, []int{4} + return fileDescriptor_95fd383b29885bb3, []int{4} } func (m *ChunkResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -383,42 +390,42 @@ func (m *ChunkResponse) GetMissing() bool { } func init() { - proto.RegisterType((*Message)(nil), "tendermint.statesync.Message") - proto.RegisterType((*SnapshotsRequest)(nil), "tendermint.statesync.SnapshotsRequest") - proto.RegisterType((*SnapshotsResponse)(nil), "tendermint.statesync.SnapshotsResponse") - proto.RegisterType((*ChunkRequest)(nil), "tendermint.statesync.ChunkRequest") - proto.RegisterType((*ChunkResponse)(nil), "tendermint.statesync.ChunkResponse") -} - -func init() { proto.RegisterFile("tendermint/statesync/types.proto", fileDescriptor_a1c2869546ca7914) } - -var fileDescriptor_a1c2869546ca7914 = []byte{ - // 397 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0x3f, 0x6b, 0xdb, 0x40, - 0x1c, 0x95, 0xfc, 0x9f, 0x5f, 0xad, 0x62, 0x1f, 0xa6, 0x88, 0x0e, 0xc2, 0xa8, 0xd0, 0x76, 0x92, - 0xa0, 0x1d, 0xba, 0xbb, 0x8b, 0x0b, 0xed, 0xd0, 0x6b, 0x03, 0x21, 0x4b, 0x38, 0xcb, 0x67, 0x49, - 0x04, 0x9d, 0x14, 0xfd, 0x4e, 0x10, 0x7f, 0x80, 0x4c, 0x59, 0xf2, 0xb1, 0x32, 0x7a, 0x0c, 0x99, - 0x82, 0xfd, 0x45, 0x82, 0x4e, 0xb2, 0xac, 0x38, 0x26, 0x21, 0x90, 0xed, 0xde, 0xd3, 0xd3, 0xbb, - 0xf7, 0x1e, 0x1c, 0x8c, 0x25, 0x17, 0x73, 0x9e, 0x46, 0xa1, 0x90, 0x2e, 0x4a, 0x26, 0x39, 0x2e, - 0x85, 0xe7, 0xca, 0x65, 0xc2, 0xd1, 0x49, 0xd2, 0x58, 0xc6, 0x64, 0xb4, 0x53, 0x38, 0x95, 0xc2, - 0xbe, 0x6b, 0x40, 0xf7, 0x0f, 0x47, 0x64, 0x3e, 0x27, 0x47, 0x30, 0x44, 0xc1, 0x12, 0x0c, 0x62, - 0x89, 0xa7, 0x29, 0x3f, 0xcf, 0x38, 0x4a, 0x53, 0x1f, 0xeb, 0x5f, 0xdf, 0x7d, 0xfb, 0xec, 0x1c, - 0xfa, 0xdb, 0xf9, 0xb7, 0x95, 0xd3, 0x42, 0x3d, 0xd5, 0xe8, 0x00, 0xf7, 0x38, 0x72, 0x0c, 0xa4, - 0x6e, 0x8b, 0x49, 0x2c, 0x90, 0x9b, 0x0d, 0xe5, 0xfb, 0xe5, 0x45, 0xdf, 0x42, 0x3e, 0xd5, 0xe8, - 0x10, 0xf7, 0x49, 0xf2, 0x0b, 0x0c, 0x2f, 0xc8, 0xc4, 0x59, 0x15, 0xb6, 0xa9, 0x4c, 0xed, 0xc3, - 0xa6, 0x3f, 0x73, 0xe9, 0x2e, 0x68, 0xdf, 0xab, 0x61, 0xf2, 0x1b, 0xde, 0x6f, 0xad, 0xca, 0x80, - 0x2d, 0xe5, 0xf5, 0xe9, 0x59, 0xaf, 0x2a, 0x9c, 0xe1, 0xd5, 0x89, 0x49, 0x1b, 0x9a, 0x98, 0x45, - 0x36, 0x81, 0xc1, 0xfe, 0x42, 0xf6, 0x95, 0x0e, 0xc3, 0x27, 0xf5, 0xc8, 0x07, 0xe8, 0x04, 0x3c, - 0xf4, 0x83, 0x62, 0xef, 0x16, 0x2d, 0x51, 0xce, 0x2f, 0xe2, 0x34, 0x62, 0x52, 0xed, 0x65, 0xd0, - 0x12, 0xe5, 0xbc, 0xba, 0x11, 0x55, 0x65, 0x83, 0x96, 0x88, 0x10, 0x68, 0x05, 0x0c, 0x03, 0x15, - 0xbe, 0x4f, 0xd5, 0x99, 0x7c, 0x84, 0x5e, 0xc4, 0x25, 0x9b, 0x33, 0xc9, 0xcc, 0xb6, 0xe2, 0x2b, - 0x6c, 0xff, 0x87, 0x7e, 0x7d, 0x96, 0x57, 0xe7, 0x18, 0x41, 0x3b, 0x14, 0x73, 0x7e, 0x51, 0xc6, - 0x28, 0x80, 0x7d, 0xa9, 0x83, 0xf1, 0x68, 0xa1, 0xb7, 0xf1, 0xcd, 0x59, 0xd5, 0xb3, 0xac, 0x57, - 0x00, 0x62, 0x42, 0x37, 0x0a, 0x11, 0x43, 0xe1, 0xab, 0x7a, 0x3d, 0xba, 0x85, 0x93, 0xbf, 0x37, - 0x6b, 0x4b, 0x5f, 0xad, 0x2d, 0xfd, 0x7e, 0x6d, 0xe9, 0xd7, 0x1b, 0x4b, 0x5b, 0x6d, 0x2c, 0xed, - 0x76, 0x63, 0x69, 0x27, 0x3f, 0xfc, 0x50, 0x06, 0xd9, 0xcc, 0xf1, 0xe2, 0xc8, 0xf5, 0xe2, 0x88, - 0xcb, 0xd9, 0x42, 0xee, 0x0e, 0xea, 0xc1, 0xb8, 0x87, 0x5e, 0xd4, 0xac, 0xa3, 0xbe, 0x7d, 0x7f, - 0x08, 0x00, 0x00, 0xff, 0xff, 0x04, 0xbe, 0xb0, 0x90, 0x70, 0x03, 0x00, 0x00, + proto.RegisterType((*Message)(nil), "cometbft.statesync.v1.Message") + proto.RegisterType((*SnapshotsRequest)(nil), "cometbft.statesync.v1.SnapshotsRequest") + proto.RegisterType((*SnapshotsResponse)(nil), "cometbft.statesync.v1.SnapshotsResponse") + proto.RegisterType((*ChunkRequest)(nil), "cometbft.statesync.v1.ChunkRequest") + proto.RegisterType((*ChunkResponse)(nil), "cometbft.statesync.v1.ChunkResponse") +} + +func init() { proto.RegisterFile("cometbft/statesync/v1/types.proto", fileDescriptor_95fd383b29885bb3) } + +var fileDescriptor_95fd383b29885bb3 = []byte{ + // 399 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0xcd, 0x6a, 0xdb, 0x40, + 0x18, 0x94, 0xfc, 0xcf, 0x57, 0xab, 0xd8, 0x4b, 0x5b, 0x44, 0x0f, 0xa2, 0x55, 0x0b, 0xf5, 0x49, + 0xc2, 0x2d, 0xf4, 0x01, 0xdc, 0x8b, 0x29, 0x18, 0xca, 0xb6, 0x14, 0x92, 0x4b, 0x58, 0xcb, 0x6b, + 0x49, 0x04, 0xfd, 0xc4, 0xdf, 0xca, 0xc4, 0x0f, 0x90, 0x53, 0x2e, 0x79, 0xac, 0x1c, 0x7d, 0xcc, + 0x29, 0x04, 0xfb, 0x45, 0x82, 0x56, 0x3f, 0x51, 0x1c, 0x27, 0x21, 0x90, 0xdb, 0xce, 0x30, 0x1e, + 0xcf, 0x8c, 0xf8, 0xe0, 0xb3, 0x13, 0x05, 0x5c, 0x4c, 0xe7, 0xc2, 0x46, 0xc1, 0x04, 0xc7, 0x55, + 0xe8, 0xd8, 0xcb, 0xa1, 0x2d, 0x56, 0x31, 0x47, 0x2b, 0x5e, 0x44, 0x22, 0x22, 0xef, 0x0b, 0x89, + 0x55, 0x4a, 0xac, 0xe5, 0xd0, 0xbc, 0xae, 0x41, 0x7b, 0xc2, 0x11, 0x99, 0xcb, 0xc9, 0x7f, 0xe8, + 0x63, 0xc8, 0x62, 0xf4, 0x22, 0x81, 0x47, 0x0b, 0x7e, 0x92, 0x70, 0x14, 0xba, 0xfa, 0x49, 0x1d, + 0xbc, 0xf9, 0xfe, 0xcd, 0xda, 0xfb, 0x73, 0xeb, 0x6f, 0xa1, 0xa7, 0x99, 0x7c, 0xac, 0xd0, 0x1e, + 0xee, 0x70, 0xe4, 0x00, 0x48, 0xd5, 0x17, 0xe3, 0x28, 0x44, 0xae, 0xd7, 0xa4, 0xf1, 0xe0, 0x79, + 0xe3, 0x4c, 0x3f, 0x56, 0x68, 0x1f, 0x77, 0x49, 0xf2, 0x1b, 0x34, 0xc7, 0x4b, 0xc2, 0xe3, 0x32, + 0x6e, 0x5d, 0xba, 0x7e, 0x79, 0xc4, 0xf5, 0x57, 0xaa, 0xbd, 0x8b, 0xda, 0x75, 0x2a, 0x98, 0x4c, + 0xe0, 0x6d, 0xe1, 0x95, 0x47, 0x6c, 0x48, 0xb3, 0xaf, 0x4f, 0x9b, 0x95, 0xf1, 0x34, 0xa7, 0x4a, + 0x8c, 0x9a, 0x50, 0xc7, 0x24, 0x30, 0x09, 0xf4, 0x76, 0x47, 0x32, 0xcf, 0x55, 0xe8, 0x3f, 0x28, + 0x48, 0x3e, 0x40, 0xcb, 0xe3, 0xbe, 0xeb, 0x65, 0x9b, 0x37, 0x68, 0x8e, 0x52, 0x7e, 0x1e, 0x2d, + 0x02, 0x26, 0xe4, 0x64, 0x1a, 0xcd, 0x51, 0xca, 0xcb, 0x7f, 0x44, 0x59, 0x5a, 0xa3, 0x39, 0x22, + 0x04, 0x1a, 0x1e, 0x43, 0x4f, 0xa6, 0xef, 0x52, 0xf9, 0x26, 0x1f, 0xa1, 0x13, 0x70, 0xc1, 0x66, + 0x4c, 0x30, 0xbd, 0x29, 0xf9, 0x12, 0x9b, 0xff, 0xa0, 0x5b, 0xdd, 0xe5, 0xc5, 0x39, 0xde, 0x41, + 0xd3, 0x0f, 0x67, 0xfc, 0x34, 0x8f, 0x91, 0x01, 0xf3, 0x4c, 0x05, 0xed, 0xde, 0x42, 0xaf, 0xe3, + 0x9b, 0xb2, 0xb2, 0x67, 0x5e, 0x2f, 0x03, 0x44, 0x87, 0x76, 0xe0, 0x23, 0xfa, 0xa1, 0x2b, 0xeb, + 0x75, 0x68, 0x01, 0x47, 0x7f, 0x2e, 0x37, 0x86, 0xba, 0xde, 0x18, 0xea, 0xcd, 0xc6, 0x50, 0x2f, + 0xb6, 0x86, 0xb2, 0xde, 0x1a, 0xca, 0xd5, 0xd6, 0x50, 0x0e, 0x7f, 0xba, 0xbe, 0xf0, 0x92, 0x69, + 0xfa, 0x75, 0xed, 0xf2, 0x7e, 0xca, 0x07, 0x8b, 0x7d, 0x7b, 0xef, 0x55, 0x4d, 0x5b, 0xf2, 0xa0, + 0x7e, 0xdc, 0x06, 0x00, 0x00, 0xff, 0xff, 0x99, 0x49, 0xe4, 0x5a, 0x75, 0x03, 0x00, 0x00, } func (m *Message) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/store/types.pb.go b/api/cometbft/store/v1/types.pb.go similarity index 83% rename from proto/tendermint/store/types.pb.go rename to api/cometbft/store/v1/types.pb.go index e7e553e0e2c..81978c26944 100644 --- a/proto/tendermint/store/types.pb.go +++ b/api/cometbft/store/v1/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/store/types.proto +// source: cometbft/store/v1/types.proto -package store +package v1 import ( fmt "fmt" @@ -22,6 +22,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// BlockStoreState represents the state of the block store. type BlockStoreState struct { Base int64 `protobuf:"varint,1,opt,name=base,proto3" json:"base,omitempty"` Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` @@ -31,7 +32,7 @@ func (m *BlockStoreState) Reset() { *m = BlockStoreState{} } func (m *BlockStoreState) String() string { return proto.CompactTextString(m) } func (*BlockStoreState) ProtoMessage() {} func (*BlockStoreState) Descriptor() ([]byte, []int) { - return fileDescriptor_ff9e53a0a74267f7, []int{0} + return fileDescriptor_39bdcbdd79a94f5f, []int{0} } func (m *BlockStoreState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -75,24 +76,24 @@ func (m *BlockStoreState) GetHeight() int64 { } func init() { - proto.RegisterType((*BlockStoreState)(nil), "tendermint.store.BlockStoreState") + proto.RegisterType((*BlockStoreState)(nil), "cometbft.store.v1.BlockStoreState") } -func init() { proto.RegisterFile("tendermint/store/types.proto", fileDescriptor_ff9e53a0a74267f7) } +func init() { proto.RegisterFile("cometbft/store/v1/types.proto", fileDescriptor_39bdcbdd79a94f5f) } -var fileDescriptor_ff9e53a0a74267f7 = []byte{ - // 171 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x49, 0xcd, 0x4b, - 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x2f, 0x2e, 0xc9, 0x2f, 0x4a, 0xd5, 0x2f, 0xa9, 0x2c, - 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x40, 0xc8, 0xea, 0x81, 0x65, 0x95, - 0x6c, 0xb9, 0xf8, 0x9d, 0x72, 0xf2, 0x93, 0xb3, 0x83, 0x41, 0xbc, 0xe0, 0x92, 0xc4, 0x92, 0x54, - 0x21, 0x21, 0x2e, 0x96, 0xa4, 0xc4, 0xe2, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xe6, 0x20, 0x30, - 0x5b, 0x48, 0x8c, 0x8b, 0x2d, 0x23, 0x35, 0x33, 0x3d, 0xa3, 0x44, 0x82, 0x09, 0x2c, 0x0a, 0xe5, - 0x39, 0xf9, 0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, - 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x71, 0x7a, 0x66, - 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x72, 0x7e, 0x6e, 0x6a, 0x49, 0x52, 0x5a, - 0x09, 0x82, 0x01, 0x76, 0x8e, 0x3e, 0xba, 0x5b, 0x93, 0xd8, 0xc0, 0xe2, 0xc6, 0x80, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xb7, 0x2b, 0x34, 0x2a, 0xc6, 0x00, 0x00, 0x00, +var fileDescriptor_39bdcbdd79a94f5f = []byte{ + // 170 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4d, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x2e, 0xc9, 0x2f, 0x4a, 0xd5, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, + 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x84, 0x49, 0xeb, 0x81, 0xa5, + 0xf5, 0xca, 0x0c, 0x95, 0x6c, 0xb9, 0xf8, 0x9d, 0x72, 0xf2, 0x93, 0xb3, 0x83, 0x41, 0x02, 0xc1, + 0x25, 0x89, 0x25, 0xa9, 0x42, 0x42, 0x5c, 0x2c, 0x49, 0x89, 0xc5, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, + 0x1a, 0xcc, 0x41, 0x60, 0xb6, 0x90, 0x18, 0x17, 0x5b, 0x46, 0x6a, 0x66, 0x7a, 0x46, 0x89, 0x04, + 0x13, 0x58, 0x14, 0xca, 0x73, 0xf2, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, + 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, + 0x28, 0xa3, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0xb8, 0xab, 0xe0, + 0x8c, 0xc4, 0x82, 0x4c, 0x7d, 0x0c, 0xb7, 0x26, 0xb1, 0x81, 0x9d, 0x69, 0x0c, 0x08, 0x00, 0x00, + 0xff, 0xff, 0x25, 0xd4, 0x78, 0x17, 0xc7, 0x00, 0x00, 0x00, } func (m *BlockStoreState) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/types/block.pb.go b/api/cometbft/types/v1/block.pb.go similarity index 83% rename from proto/tendermint/types/block.pb.go rename to api/cometbft/types/v1/block.pb.go index 3b3e3811ffc..311eeaafd37 100644 --- a/proto/tendermint/types/block.pb.go +++ b/api/cometbft/types/v1/block.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/types/block.proto +// source: cometbft/types/v1/block.proto -package types +package v1 import ( fmt "fmt" @@ -23,6 +23,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// Block defines the structure of a block in the CometBFT blockchain. type Block struct { Header Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header"` Data Data `protobuf:"bytes,2,opt,name=data,proto3" json:"data"` @@ -34,7 +35,7 @@ func (m *Block) Reset() { *m = Block{} } func (m *Block) String() string { return proto.CompactTextString(m) } func (*Block) ProtoMessage() {} func (*Block) Descriptor() ([]byte, []int) { - return fileDescriptor_70840e82f4357ab1, []int{0} + return fileDescriptor_fbda8644c7f5ead0, []int{0} } func (m *Block) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -92,30 +93,30 @@ func (m *Block) GetLastCommit() *Commit { } func init() { - proto.RegisterType((*Block)(nil), "tendermint.types.Block") + proto.RegisterType((*Block)(nil), "cometbft.types.v1.Block") } -func init() { proto.RegisterFile("tendermint/types/block.proto", fileDescriptor_70840e82f4357ab1) } +func init() { proto.RegisterFile("cometbft/types/v1/block.proto", fileDescriptor_fbda8644c7f5ead0) } -var fileDescriptor_70840e82f4357ab1 = []byte{ - // 272 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x49, 0xcd, 0x4b, - 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0xca, 0xc9, - 0x4f, 0xce, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x40, 0xc8, 0xea, 0x81, 0x65, 0xa5, - 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x92, 0xfa, 0x20, 0x16, 0x44, 0x9d, 0x14, 0xa6, 0x29, 0x60, - 0x12, 0x2a, 0x2b, 0x8f, 0x21, 0x9b, 0x5a, 0x96, 0x99, 0x92, 0x9a, 0x97, 0x9c, 0x0a, 0x51, 0xa0, - 0xf4, 0x8e, 0x91, 0x8b, 0xd5, 0x09, 0x64, 0xad, 0x90, 0x19, 0x17, 0x5b, 0x46, 0x6a, 0x62, 0x4a, - 0x6a, 0x91, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, 0x91, 0x84, 0x1e, 0xba, 0x0b, 0xf4, 0x3c, 0xc0, - 0xf2, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33, 0x04, 0x41, 0x55, 0x0b, 0x19, 0x70, 0xb1, 0xa4, 0x24, - 0x96, 0x24, 0x4a, 0x30, 0x81, 0x75, 0x89, 0x61, 0xea, 0x72, 0x49, 0x2c, 0x49, 0x84, 0xea, 0x01, - 0xab, 0x14, 0x72, 0xe0, 0xe2, 0x80, 0xb9, 0x42, 0x82, 0x19, 0xac, 0x4b, 0x0e, 0x53, 0x97, 0x2b, - 0x54, 0x85, 0x4f, 0x66, 0x71, 0x09, 0x54, 0x37, 0x5c, 0x97, 0x90, 0x25, 0x17, 0x77, 0x4e, 0x62, - 0x71, 0x49, 0x7c, 0x72, 0x7e, 0x6e, 0x6e, 0x66, 0x89, 0x04, 0x0b, 0x2e, 0x07, 0x3b, 0x83, 0xe5, - 0x83, 0xb8, 0x40, 0x8a, 0x21, 0x6c, 0x27, 0xdf, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, - 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, - 0x63, 0x88, 0x32, 0x4e, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, - 0xcf, 0x4d, 0x2d, 0x49, 0x4a, 0x2b, 0x41, 0x30, 0x20, 0x01, 0x8f, 0x1e, 0x9c, 0x49, 0x6c, 0x60, - 0x71, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x15, 0xdf, 0xde, 0x0a, 0xcd, 0x01, 0x00, 0x00, +var fileDescriptor_fbda8644c7f5ead0 = []byte{ + // 271 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4d, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0x33, 0xd4, 0x4f, 0xca, + 0xc9, 0x4f, 0xce, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x84, 0x49, 0xeb, 0x81, 0xa5, + 0xf5, 0xca, 0x0c, 0xa5, 0xb0, 0xe8, 0x80, 0xc8, 0x81, 0x75, 0x48, 0x29, 0x60, 0x4a, 0xa7, 0x96, + 0x65, 0xa6, 0xa4, 0xe6, 0x25, 0xa7, 0x42, 0x55, 0x88, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x99, 0xfa, + 0x20, 0x16, 0x44, 0x54, 0xe9, 0x13, 0x23, 0x17, 0xab, 0x13, 0xc8, 0x66, 0x21, 0x73, 0x2e, 0xb6, + 0x8c, 0xd4, 0xc4, 0x94, 0xd4, 0x22, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x49, 0x3d, 0x0c, + 0x47, 0xe8, 0x79, 0x80, 0x15, 0x38, 0xb1, 0x9c, 0xb8, 0x27, 0xcf, 0x10, 0x04, 0x55, 0x2e, 0x64, + 0xc8, 0xc5, 0x92, 0x92, 0x58, 0x92, 0x28, 0xc1, 0x04, 0xd6, 0x26, 0x8e, 0x45, 0x9b, 0x4b, 0x62, + 0x49, 0x22, 0x54, 0x13, 0x58, 0xa9, 0x90, 0x23, 0x17, 0x07, 0xcc, 0x75, 0x12, 0xcc, 0x60, 0x6d, + 0xf2, 0x58, 0xb4, 0xb9, 0x42, 0x95, 0xf8, 0x64, 0x16, 0x97, 0x40, 0xb5, 0xc3, 0xb5, 0x09, 0x59, + 0x71, 0x71, 0xe7, 0x24, 0x16, 0x97, 0xc4, 0x27, 0xe7, 0xe7, 0xe6, 0x66, 0x96, 0x48, 0xb0, 0xe0, + 0x74, 0xb3, 0x33, 0x58, 0x41, 0x10, 0x17, 0x48, 0x35, 0x84, 0xed, 0xe4, 0x73, 0xe2, 0x91, 0x1c, + 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, + 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x46, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x20, 0x63, + 0xf4, 0xe1, 0x21, 0x0a, 0x67, 0x24, 0x16, 0x64, 0xea, 0x63, 0x84, 0x73, 0x12, 0x1b, 0x38, 0x24, + 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x58, 0x78, 0xe4, 0xc7, 0xd4, 0x01, 0x00, 0x00, } func (m *Block) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/types/canonical.pb.go b/api/cometbft/types/v1/canonical.pb.go similarity index 89% rename from proto/tendermint/types/canonical.pb.go rename to api/cometbft/types/v1/canonical.pb.go index 7e776e02d58..99d65dd9240 100644 --- a/proto/tendermint/types/canonical.pb.go +++ b/api/cometbft/types/v1/canonical.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/types/canonical.proto +// source: cometbft/types/v1/canonical.proto -package types +package v1 import ( encoding_binary "encoding/binary" @@ -28,6 +28,8 @@ var _ = time.Kitchen // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// CanonicalBlockID is a canonical representation of a BlockID, which gets +// serialized and signed. type CanonicalBlockID struct { Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` PartSetHeader CanonicalPartSetHeader `protobuf:"bytes,2,opt,name=part_set_header,json=partSetHeader,proto3" json:"part_set_header"` @@ -37,7 +39,7 @@ func (m *CanonicalBlockID) Reset() { *m = CanonicalBlockID{} } func (m *CanonicalBlockID) String() string { return proto.CompactTextString(m) } func (*CanonicalBlockID) ProtoMessage() {} func (*CanonicalBlockID) Descriptor() ([]byte, []int) { - return fileDescriptor_8d1a1a84ff7267ed, []int{0} + return fileDescriptor_bd60568638662265, []int{0} } func (m *CanonicalBlockID) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -80,6 +82,8 @@ func (m *CanonicalBlockID) GetPartSetHeader() CanonicalPartSetHeader { return CanonicalPartSetHeader{} } +// CanonicalPartSetHeader is a canonical representation of a PartSetHeader, +// which gets serialized and signed. type CanonicalPartSetHeader struct { Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` @@ -89,7 +93,7 @@ func (m *CanonicalPartSetHeader) Reset() { *m = CanonicalPartSetHeader{} func (m *CanonicalPartSetHeader) String() string { return proto.CompactTextString(m) } func (*CanonicalPartSetHeader) ProtoMessage() {} func (*CanonicalPartSetHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_8d1a1a84ff7267ed, []int{1} + return fileDescriptor_bd60568638662265, []int{1} } func (m *CanonicalPartSetHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -132,8 +136,10 @@ func (m *CanonicalPartSetHeader) GetHash() []byte { return nil } +// CanonicalProposal is a canonical representation of a Proposal, which gets +// serialized and signed. type CanonicalProposal struct { - Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.types.SignedMsgType" json:"type,omitempty"` + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.types.v1.SignedMsgType" json:"type,omitempty"` Height int64 `protobuf:"fixed64,2,opt,name=height,proto3" json:"height,omitempty"` Round int64 `protobuf:"fixed64,3,opt,name=round,proto3" json:"round,omitempty"` POLRound int64 `protobuf:"varint,4,opt,name=pol_round,json=polRound,proto3" json:"pol_round,omitempty"` @@ -146,7 +152,7 @@ func (m *CanonicalProposal) Reset() { *m = CanonicalProposal{} } func (m *CanonicalProposal) String() string { return proto.CompactTextString(m) } func (*CanonicalProposal) ProtoMessage() {} func (*CanonicalProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_8d1a1a84ff7267ed, []int{2} + return fileDescriptor_bd60568638662265, []int{2} } func (m *CanonicalProposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -224,8 +230,10 @@ func (m *CanonicalProposal) GetChainID() string { return "" } +// CanonicalVote is a canonical representation of a Vote, which gets +// serialized and signed. type CanonicalVote struct { - Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.types.SignedMsgType" json:"type,omitempty"` + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.types.v1.SignedMsgType" json:"type,omitempty"` Height int64 `protobuf:"fixed64,2,opt,name=height,proto3" json:"height,omitempty"` Round int64 `protobuf:"fixed64,3,opt,name=round,proto3" json:"round,omitempty"` BlockID *CanonicalBlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` @@ -237,7 +245,7 @@ func (m *CanonicalVote) Reset() { *m = CanonicalVote{} } func (m *CanonicalVote) String() string { return proto.CompactTextString(m) } func (*CanonicalVote) ProtoMessage() {} func (*CanonicalVote) Descriptor() ([]byte, []int) { - return fileDescriptor_8d1a1a84ff7267ed, []int{3} + return fileDescriptor_bd60568638662265, []int{3} } func (m *CanonicalVote) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -321,7 +329,7 @@ func (m *CanonicalVoteExtension) Reset() { *m = CanonicalVoteExtension{} func (m *CanonicalVoteExtension) String() string { return proto.CompactTextString(m) } func (*CanonicalVoteExtension) ProtoMessage() {} func (*CanonicalVoteExtension) Descriptor() ([]byte, []int) { - return fileDescriptor_8d1a1a84ff7267ed, []int{4} + return fileDescriptor_bd60568638662265, []int{4} } func (m *CanonicalVoteExtension) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -379,50 +387,50 @@ func (m *CanonicalVoteExtension) GetChainId() string { } func init() { - proto.RegisterType((*CanonicalBlockID)(nil), "tendermint.types.CanonicalBlockID") - proto.RegisterType((*CanonicalPartSetHeader)(nil), "tendermint.types.CanonicalPartSetHeader") - proto.RegisterType((*CanonicalProposal)(nil), "tendermint.types.CanonicalProposal") - proto.RegisterType((*CanonicalVote)(nil), "tendermint.types.CanonicalVote") - proto.RegisterType((*CanonicalVoteExtension)(nil), "tendermint.types.CanonicalVoteExtension") -} - -func init() { proto.RegisterFile("tendermint/types/canonical.proto", fileDescriptor_8d1a1a84ff7267ed) } - -var fileDescriptor_8d1a1a84ff7267ed = []byte{ - // 525 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x54, 0xc1, 0x6e, 0x9b, 0x40, - 0x10, 0x35, 0x0e, 0xb6, 0x61, 0x13, 0xb7, 0xee, 0x2a, 0x8a, 0xa8, 0x15, 0x01, 0xe2, 0x50, 0xd1, - 0x0b, 0x48, 0xf1, 0x1f, 0x90, 0x56, 0xaa, 0xab, 0x46, 0x8d, 0x48, 0x94, 0x43, 0x2f, 0xd6, 0x02, - 0x1b, 0x40, 0x05, 0x16, 0xc1, 0x5a, 0x6a, 0x2e, 0xed, 0x2f, 0xe4, 0x3b, 0xfa, 0x25, 0x39, 0xe6, - 0xd8, 0x5e, 0xdc, 0x0a, 0xff, 0x48, 0xb5, 0x0b, 0x06, 0x2b, 0xa9, 0x2c, 0x55, 0xad, 0x7a, 0x41, - 0x33, 0x6f, 0xde, 0xce, 0x3c, 0xbd, 0x61, 0x17, 0xe8, 0x14, 0x67, 0x01, 0x2e, 0xd2, 0x38, 0xa3, - 0x36, 0xbd, 0xc9, 0x71, 0x69, 0xfb, 0x28, 0x23, 0x59, 0xec, 0xa3, 0xc4, 0xca, 0x0b, 0x42, 0x09, - 0x9c, 0x74, 0x0c, 0x8b, 0x33, 0xa6, 0x87, 0x21, 0x09, 0x09, 0x2f, 0xda, 0x2c, 0xaa, 0x79, 0xd3, - 0xe3, 0x47, 0x9d, 0xf8, 0xb7, 0xa9, 0x6a, 0x21, 0x21, 0x61, 0x82, 0x6d, 0x9e, 0x79, 0xcb, 0x6b, - 0x9b, 0xc6, 0x29, 0x2e, 0x29, 0x4a, 0xf3, 0x9a, 0x60, 0x7c, 0x06, 0x93, 0xd3, 0xcd, 0x64, 0x27, - 0x21, 0xfe, 0xc7, 0xf9, 0x2b, 0x08, 0x81, 0x18, 0xa1, 0x32, 0x52, 0x04, 0x5d, 0x30, 0x0f, 0x5c, - 0x1e, 0xc3, 0x2b, 0xf0, 0x34, 0x47, 0x05, 0x5d, 0x94, 0x98, 0x2e, 0x22, 0x8c, 0x02, 0x5c, 0x28, - 0x7d, 0x5d, 0x30, 0xf7, 0x4f, 0x4c, 0xeb, 0xa1, 0x50, 0xab, 0x6d, 0x78, 0x8e, 0x0a, 0x7a, 0x81, - 0xe9, 0x1b, 0xce, 0x77, 0xc4, 0xbb, 0x95, 0xd6, 0x73, 0xc7, 0xf9, 0x36, 0x68, 0x38, 0xe0, 0xe8, - 0xf7, 0x74, 0x78, 0x08, 0x06, 0x94, 0x50, 0x94, 0x70, 0x19, 0x63, 0xb7, 0x4e, 0x5a, 0x6d, 0xfd, - 0x4e, 0x9b, 0xf1, 0xbd, 0x0f, 0x9e, 0x75, 0x4d, 0x0a, 0x92, 0x93, 0x12, 0x25, 0x70, 0x06, 0x44, - 0x26, 0x87, 0x1f, 0x7f, 0x72, 0xa2, 0x3d, 0x96, 0x79, 0x11, 0x87, 0x19, 0x0e, 0xce, 0xca, 0xf0, - 0xf2, 0x26, 0xc7, 0x2e, 0x27, 0xc3, 0x23, 0x30, 0x8c, 0x70, 0x1c, 0x46, 0x94, 0x0f, 0x98, 0xb8, - 0x4d, 0xc6, 0xc4, 0x14, 0x64, 0x99, 0x05, 0xca, 0x1e, 0x87, 0xeb, 0x04, 0xbe, 0x04, 0x72, 0x4e, - 0x92, 0x45, 0x5d, 0x11, 0x75, 0xc1, 0xdc, 0x73, 0x0e, 0xaa, 0x95, 0x26, 0x9d, 0xbf, 0x7f, 0xe7, - 0x32, 0xcc, 0x95, 0x72, 0x92, 0xf0, 0x08, 0xbe, 0x05, 0x92, 0xc7, 0xec, 0x5d, 0xc4, 0x81, 0x32, - 0xe0, 0xc6, 0x19, 0x3b, 0x8c, 0x6b, 0x36, 0xe1, 0xec, 0x57, 0x2b, 0x6d, 0xd4, 0x24, 0xee, 0x88, - 0x37, 0x98, 0x07, 0xd0, 0x01, 0x72, 0xbb, 0x46, 0x65, 0xc8, 0x9b, 0x4d, 0xad, 0x7a, 0xd1, 0xd6, - 0x66, 0xd1, 0xd6, 0xe5, 0x86, 0xe1, 0x48, 0xcc, 0xf7, 0xdb, 0x1f, 0x9a, 0xe0, 0x76, 0xc7, 0xe0, - 0x0b, 0x20, 0xf9, 0x11, 0x8a, 0x33, 0xa6, 0x67, 0xa4, 0x0b, 0xa6, 0x5c, 0xcf, 0x3a, 0x65, 0x18, - 0x9b, 0xc5, 0x8b, 0xf3, 0xc0, 0xf8, 0xda, 0x07, 0xe3, 0x56, 0xd6, 0x15, 0xa1, 0xf8, 0x7f, 0xf8, - 0xba, 0x6d, 0x96, 0xf8, 0x2f, 0xcd, 0x1a, 0xfc, 0xbd, 0x59, 0xc3, 0x1d, 0x66, 0x7d, 0xd9, 0xfa, - 0x99, 0x99, 0x57, 0xaf, 0x3f, 0x51, 0x9c, 0x95, 0x31, 0xc9, 0xe0, 0x31, 0x90, 0xf1, 0x26, 0x69, - 0xee, 0x55, 0x07, 0xfc, 0xa1, 0x3b, 0xcf, 0xb7, 0xd4, 0x30, 0x77, 0xe4, 0x56, 0x80, 0x73, 0x76, - 0x57, 0xa9, 0xc2, 0x7d, 0xa5, 0x0a, 0x3f, 0x2b, 0x55, 0xb8, 0x5d, 0xab, 0xbd, 0xfb, 0xb5, 0xda, - 0xfb, 0xb6, 0x56, 0x7b, 0x1f, 0x66, 0x61, 0x4c, 0xa3, 0xa5, 0x67, 0xf9, 0x24, 0xb5, 0x7d, 0x92, - 0x62, 0xea, 0x5d, 0xd3, 0x2e, 0xa8, 0x5f, 0x95, 0x87, 0x2f, 0x89, 0x37, 0xe4, 0xf8, 0xec, 0x57, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xe6, 0x22, 0x5b, 0x0b, 0xae, 0x04, 0x00, 0x00, + proto.RegisterType((*CanonicalBlockID)(nil), "cometbft.types.v1.CanonicalBlockID") + proto.RegisterType((*CanonicalPartSetHeader)(nil), "cometbft.types.v1.CanonicalPartSetHeader") + proto.RegisterType((*CanonicalProposal)(nil), "cometbft.types.v1.CanonicalProposal") + proto.RegisterType((*CanonicalVote)(nil), "cometbft.types.v1.CanonicalVote") + proto.RegisterType((*CanonicalVoteExtension)(nil), "cometbft.types.v1.CanonicalVoteExtension") +} + +func init() { proto.RegisterFile("cometbft/types/v1/canonical.proto", fileDescriptor_bd60568638662265) } + +var fileDescriptor_bd60568638662265 = []byte{ + // 526 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0xdf, 0x6a, 0xd3, 0x50, + 0x1c, 0xc7, 0x9b, 0x2e, 0x6d, 0x93, 0xb3, 0x55, 0xb7, 0xc3, 0x18, 0xb1, 0x68, 0x12, 0x2b, 0x48, + 0x77, 0x93, 0xb0, 0xea, 0x13, 0x64, 0x0a, 0x16, 0x27, 0x8e, 0x6c, 0x28, 0x78, 0x53, 0x4e, 0x92, + 0xb3, 0x24, 0x98, 0xe6, 0x1c, 0x92, 0xd3, 0xe1, 0xae, 0xf6, 0x0a, 0x7b, 0x10, 0x1f, 0x64, 0x97, + 0xbb, 0x14, 0x84, 0x2a, 0xe9, 0x8b, 0xc8, 0x39, 0x69, 0xd2, 0x42, 0x47, 0x41, 0x94, 0xdd, 0xfd, + 0xfe, 0xff, 0xbe, 0x7c, 0x7e, 0xc9, 0x01, 0xcf, 0x7d, 0x32, 0xc1, 0xcc, 0xbb, 0x60, 0x36, 0xbb, + 0xa2, 0x38, 0xb7, 0x2f, 0x8f, 0x6c, 0x1f, 0xa5, 0x24, 0x8d, 0x7d, 0x94, 0x58, 0x34, 0x23, 0x8c, + 0xc0, 0xbd, 0xaa, 0xc4, 0x12, 0x25, 0xd6, 0xe5, 0x51, 0x6f, 0x3f, 0x24, 0x21, 0x11, 0x59, 0x9b, + 0x5b, 0x65, 0x61, 0xef, 0xd9, 0xfa, 0xac, 0xb2, 0xa3, 0x4c, 0x1b, 0x21, 0x21, 0x61, 0x82, 0x6d, + 0xe1, 0x79, 0xd3, 0x0b, 0x9b, 0xc5, 0x13, 0x9c, 0x33, 0x34, 0xa1, 0x65, 0x41, 0xff, 0x1a, 0xec, + 0x1e, 0x57, 0xbb, 0x9d, 0x84, 0xf8, 0x5f, 0x47, 0x6f, 0x20, 0x04, 0x72, 0x84, 0xf2, 0x48, 0x93, + 0x4c, 0x69, 0xb0, 0xe3, 0x0a, 0x1b, 0x7e, 0x06, 0x8f, 0x29, 0xca, 0xd8, 0x38, 0xc7, 0x6c, 0x1c, + 0x61, 0x14, 0xe0, 0x4c, 0x6b, 0x9a, 0xd2, 0x60, 0x7b, 0x78, 0x68, 0xad, 0x49, 0xb5, 0xea, 0x89, + 0xa7, 0x28, 0x63, 0x67, 0x98, 0xbd, 0x13, 0x0d, 0x8e, 0x7c, 0x3b, 0x33, 0x1a, 0x6e, 0x97, 0xae, + 0x06, 0xfb, 0x0e, 0x38, 0xb8, 0xbf, 0x1c, 0xee, 0x83, 0x16, 0x23, 0x0c, 0x25, 0x42, 0x47, 0xd7, + 0x2d, 0x9d, 0x5a, 0x5c, 0x73, 0x29, 0xae, 0xff, 0xb3, 0x09, 0xf6, 0x96, 0x43, 0x32, 0x42, 0x49, + 0x8e, 0x12, 0xf8, 0x1a, 0xc8, 0x5c, 0x91, 0x68, 0x7f, 0x34, 0x34, 0xef, 0xd1, 0x79, 0x16, 0x87, + 0x29, 0x0e, 0x3e, 0xe4, 0xe1, 0xf9, 0x15, 0xc5, 0xae, 0xa8, 0x86, 0x07, 0xa0, 0x1d, 0xe1, 0x38, + 0x8c, 0x98, 0xd8, 0xb0, 0xeb, 0x2e, 0x3c, 0xae, 0x26, 0x23, 0xd3, 0x34, 0xd0, 0xb6, 0x44, 0xb8, + 0x74, 0xe0, 0x21, 0x50, 0x29, 0x49, 0xc6, 0x65, 0x46, 0x36, 0xa5, 0xc1, 0x96, 0xb3, 0x53, 0xcc, + 0x0c, 0xe5, 0xf4, 0xe3, 0x89, 0xcb, 0x63, 0xae, 0x42, 0x49, 0x22, 0x2c, 0xf8, 0x1e, 0x28, 0x1e, + 0x07, 0x3c, 0x8e, 0x03, 0xad, 0x25, 0xd0, 0xbd, 0xd8, 0x84, 0x6e, 0x71, 0x0c, 0x67, 0xbb, 0x98, + 0x19, 0x9d, 0x85, 0xe3, 0x76, 0xc4, 0x84, 0x51, 0x00, 0x1d, 0xa0, 0xd6, 0x97, 0xd4, 0xda, 0x62, + 0x5a, 0xcf, 0x2a, 0x6f, 0x6d, 0x55, 0xb7, 0xb6, 0xce, 0xab, 0x0a, 0x47, 0xe1, 0xe4, 0x6f, 0x7e, + 0x19, 0x92, 0xbb, 0x6c, 0x83, 0x2f, 0x81, 0xe2, 0x47, 0x28, 0x4e, 0xb9, 0xa0, 0x8e, 0x29, 0x0d, + 0xd4, 0x72, 0xd7, 0x31, 0x8f, 0xf1, 0x5d, 0x22, 0x39, 0x0a, 0xfa, 0xdf, 0x9b, 0xa0, 0x5b, 0xcb, + 0xfa, 0x44, 0x18, 0x7e, 0x10, 0xb2, 0xab, 0xb8, 0xe4, 0xff, 0x8a, 0xab, 0xf5, 0xef, 0xb8, 0xda, + 0x1b, 0x70, 0x5d, 0xaf, 0x7c, 0xd0, 0x9c, 0xd6, 0xdb, 0x6f, 0x0c, 0xa7, 0x79, 0x4c, 0x52, 0xf8, + 0x14, 0xa8, 0xb8, 0x72, 0x16, 0x3f, 0xd7, 0x32, 0xf0, 0x97, 0x78, 0x9e, 0xac, 0xa8, 0xe1, 0x78, + 0xd4, 0x5a, 0x80, 0x73, 0x72, 0x5b, 0xe8, 0xd2, 0x5d, 0xa1, 0x4b, 0xbf, 0x0b, 0x5d, 0xba, 0x99, + 0xeb, 0x8d, 0xbb, 0xb9, 0xde, 0xf8, 0x31, 0xd7, 0x1b, 0x5f, 0x86, 0x61, 0xcc, 0xa2, 0xa9, 0xc7, + 0x39, 0xda, 0xf5, 0xbb, 0x51, 0x1b, 0x88, 0xc6, 0xf6, 0xda, 0x6b, 0xe2, 0xb5, 0x05, 0x9f, 0x57, + 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x35, 0xdb, 0x57, 0x1c, 0xb5, 0x04, 0x00, 0x00, } func (m *CanonicalBlockID) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/types/events.pb.go b/api/cometbft/types/v1/events.pb.go similarity index 83% rename from proto/tendermint/types/events.pb.go rename to api/cometbft/types/v1/events.pb.go index 02607e6d9bc..ceb0b571ed1 100644 --- a/proto/tendermint/types/events.pb.go +++ b/api/cometbft/types/v1/events.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/types/events.proto +// source: cometbft/types/v1/events.proto -package types +package v1 import ( fmt "fmt" @@ -22,6 +22,7 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// EventDataRoundState is emitted with each new round step. type EventDataRoundState struct { Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` @@ -32,7 +33,7 @@ func (m *EventDataRoundState) Reset() { *m = EventDataRoundState{} } func (m *EventDataRoundState) String() string { return proto.CompactTextString(m) } func (*EventDataRoundState) ProtoMessage() {} func (*EventDataRoundState) Descriptor() ([]byte, []int) { - return fileDescriptor_72cfafd446dedf7c, []int{0} + return fileDescriptor_52423bfa52525bbb, []int{0} } func (m *EventDataRoundState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -83,26 +84,26 @@ func (m *EventDataRoundState) GetStep() string { } func init() { - proto.RegisterType((*EventDataRoundState)(nil), "tendermint.types.EventDataRoundState") + proto.RegisterType((*EventDataRoundState)(nil), "cometbft.types.v1.EventDataRoundState") } -func init() { proto.RegisterFile("tendermint/types/events.proto", fileDescriptor_72cfafd446dedf7c) } +func init() { proto.RegisterFile("cometbft/types/v1/events.proto", fileDescriptor_52423bfa52525bbb) } -var fileDescriptor_72cfafd446dedf7c = []byte{ - // 195 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2d, 0x49, 0xcd, 0x4b, - 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x4f, 0x2d, 0x4b, - 0xcd, 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x40, 0x48, 0xeb, 0x81, 0xa5, - 0x95, 0xc2, 0xb9, 0x84, 0x5d, 0x41, 0x2a, 0x5c, 0x12, 0x4b, 0x12, 0x83, 0xf2, 0x4b, 0xf3, 0x52, - 0x82, 0x4b, 0x12, 0x4b, 0x52, 0x85, 0xc4, 0xb8, 0xd8, 0x32, 0x52, 0x33, 0xd3, 0x33, 0x4a, 0x24, - 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0xa0, 0x3c, 0x21, 0x11, 0x2e, 0xd6, 0x22, 0x90, 0x2a, 0x09, - 0x26, 0x05, 0x46, 0x0d, 0xd6, 0x20, 0x08, 0x47, 0x48, 0x88, 0x8b, 0xa5, 0xb8, 0x24, 0xb5, 0x40, - 0x82, 0x59, 0x81, 0x51, 0x83, 0x33, 0x08, 0xcc, 0x76, 0xf2, 0x3d, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, - 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, - 0xc6, 0x63, 0x39, 0x86, 0x28, 0xe3, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, - 0xfd, 0xe4, 0xfc, 0xdc, 0xd4, 0x92, 0xa4, 0xb4, 0x12, 0x04, 0x03, 0xec, 0x50, 0x7d, 0x74, 0x6f, - 0x24, 0xb1, 0x81, 0xc5, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa8, 0xb3, 0x7f, 0x37, 0xe1, - 0x00, 0x00, 0x00, +var fileDescriptor_52423bfa52525bbb = []byte{ + // 194 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0x33, 0xd4, 0x4f, 0x2d, + 0x4b, 0xcd, 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x84, 0xc9, 0xeb, 0x81, + 0xe5, 0xf5, 0xca, 0x0c, 0x95, 0xc2, 0xb9, 0x84, 0x5d, 0x41, 0x4a, 0x5c, 0x12, 0x4b, 0x12, 0x83, + 0xf2, 0x4b, 0xf3, 0x52, 0x82, 0x4b, 0x12, 0x4b, 0x52, 0x85, 0xc4, 0xb8, 0xd8, 0x32, 0x52, 0x33, + 0xd3, 0x33, 0x4a, 0x24, 0x18, 0x15, 0x18, 0x35, 0x98, 0x83, 0xa0, 0x3c, 0x21, 0x11, 0x2e, 0xd6, + 0x22, 0x90, 0x2a, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xd6, 0x20, 0x08, 0x47, 0x48, 0x88, 0x8b, 0xa5, + 0xb8, 0x24, 0xb5, 0x40, 0x82, 0x59, 0x81, 0x51, 0x83, 0x33, 0x08, 0xcc, 0x76, 0xf2, 0x39, 0xf1, + 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, + 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xa3, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, + 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0xb8, 0x83, 0xe1, 0x8c, 0xc4, 0x82, 0x4c, 0x7d, 0x0c, 0x6f, 0x24, + 0xb1, 0x81, 0x3d, 0x60, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x86, 0x40, 0xdc, 0x57, 0xe2, 0x00, + 0x00, 0x00, } func (m *EventDataRoundState) Marshal() (dAtA []byte, err error) { diff --git a/proto/tendermint/types/evidence.pb.go b/api/cometbft/types/v1/evidence.pb.go similarity index 88% rename from proto/tendermint/types/evidence.pb.go rename to api/cometbft/types/v1/evidence.pb.go index 1022d4daf45..cdc9bc82673 100644 --- a/proto/tendermint/types/evidence.pb.go +++ b/api/cometbft/types/v1/evidence.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/types/evidence.proto +// source: cometbft/types/v1/evidence.proto -package types +package v1 import ( fmt "fmt" @@ -27,7 +27,10 @@ var _ = time.Kitchen // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// Evidence is a generic type for wrapping evidence of misbehavior by a validator. type Evidence struct { + // The type of evidence. + // // Types that are valid to be assigned to Sum: // *Evidence_DuplicateVoteEvidence // *Evidence_LightClientAttackEvidence @@ -38,7 +41,7 @@ func (m *Evidence) Reset() { *m = Evidence{} } func (m *Evidence) String() string { return proto.CompactTextString(m) } func (*Evidence) ProtoMessage() {} func (*Evidence) Descriptor() ([]byte, []int) { - return fileDescriptor_6825fabc78e0a168, []int{0} + return fileDescriptor_4c96acf1a4e66b9a, []int{0} } func (m *Evidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -125,7 +128,7 @@ func (m *DuplicateVoteEvidence) Reset() { *m = DuplicateVoteEvidence{} } func (m *DuplicateVoteEvidence) String() string { return proto.CompactTextString(m) } func (*DuplicateVoteEvidence) ProtoMessage() {} func (*DuplicateVoteEvidence) Descriptor() ([]byte, []int) { - return fileDescriptor_6825fabc78e0a168, []int{1} + return fileDescriptor_4c96acf1a4e66b9a, []int{1} } func (m *DuplicateVoteEvidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -202,7 +205,7 @@ func (m *LightClientAttackEvidence) Reset() { *m = LightClientAttackEvid func (m *LightClientAttackEvidence) String() string { return proto.CompactTextString(m) } func (*LightClientAttackEvidence) ProtoMessage() {} func (*LightClientAttackEvidence) Descriptor() ([]byte, []int) { - return fileDescriptor_6825fabc78e0a168, []int{2} + return fileDescriptor_4c96acf1a4e66b9a, []int{2} } func (m *LightClientAttackEvidence) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -266,6 +269,7 @@ func (m *LightClientAttackEvidence) GetTimestamp() time.Time { return time.Time{} } +// EvidenceList is a list of evidence. type EvidenceList struct { Evidence []Evidence `protobuf:"bytes,1,rep,name=evidence,proto3" json:"evidence"` } @@ -274,7 +278,7 @@ func (m *EvidenceList) Reset() { *m = EvidenceList{} } func (m *EvidenceList) String() string { return proto.CompactTextString(m) } func (*EvidenceList) ProtoMessage() {} func (*EvidenceList) Descriptor() ([]byte, []int) { - return fileDescriptor_6825fabc78e0a168, []int{3} + return fileDescriptor_4c96acf1a4e66b9a, []int{3} } func (m *EvidenceList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -311,50 +315,50 @@ func (m *EvidenceList) GetEvidence() []Evidence { } func init() { - proto.RegisterType((*Evidence)(nil), "tendermint.types.Evidence") - proto.RegisterType((*DuplicateVoteEvidence)(nil), "tendermint.types.DuplicateVoteEvidence") - proto.RegisterType((*LightClientAttackEvidence)(nil), "tendermint.types.LightClientAttackEvidence") - proto.RegisterType((*EvidenceList)(nil), "tendermint.types.EvidenceList") + proto.RegisterType((*Evidence)(nil), "cometbft.types.v1.Evidence") + proto.RegisterType((*DuplicateVoteEvidence)(nil), "cometbft.types.v1.DuplicateVoteEvidence") + proto.RegisterType((*LightClientAttackEvidence)(nil), "cometbft.types.v1.LightClientAttackEvidence") + proto.RegisterType((*EvidenceList)(nil), "cometbft.types.v1.EvidenceList") } -func init() { proto.RegisterFile("tendermint/types/evidence.proto", fileDescriptor_6825fabc78e0a168) } +func init() { proto.RegisterFile("cometbft/types/v1/evidence.proto", fileDescriptor_4c96acf1a4e66b9a) } -var fileDescriptor_6825fabc78e0a168 = []byte{ +var fileDescriptor_4c96acf1a4e66b9a = []byte{ // 533 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xcf, 0x6e, 0xd3, 0x40, - 0x10, 0xc6, 0xe3, 0x38, 0xa9, 0xc2, 0xb6, 0x40, 0x58, 0x5a, 0x48, 0x43, 0xe4, 0x44, 0xe1, 0xd0, - 0x48, 0x80, 0x2d, 0xb5, 0x57, 0x2e, 0x35, 0x20, 0x15, 0x29, 0x20, 0x64, 0xa1, 0x1e, 0xb8, 0x58, - 0xeb, 0xcd, 0xc6, 0x59, 0xd5, 0xde, 0x8d, 0xe2, 0x49, 0x50, 0x79, 0x8a, 0x3c, 0x56, 0x2f, 0x48, - 0x3d, 0x72, 0x02, 0x94, 0xf0, 0x20, 0xc8, 0xeb, 0x3f, 0x89, 0xea, 0x98, 0x13, 0x97, 0xc8, 0x99, - 0xf9, 0x7d, 0x3b, 0x33, 0x9f, 0x67, 0x8d, 0xba, 0xc0, 0xc4, 0x88, 0xcd, 0x42, 0x2e, 0xc0, 0x82, - 0xeb, 0x29, 0x8b, 0x2c, 0xb6, 0xe0, 0x23, 0x26, 0x28, 0x33, 0xa7, 0x33, 0x09, 0x12, 0x37, 0x37, - 0x80, 0xa9, 0x80, 0xf6, 0xa1, 0x2f, 0x7d, 0xa9, 0x92, 0x56, 0xfc, 0x94, 0x70, 0xed, 0xae, 0x2f, - 0xa5, 0x1f, 0x30, 0x4b, 0xfd, 0xf3, 0xe6, 0x63, 0x0b, 0x78, 0xc8, 0x22, 0x20, 0xe1, 0x34, 0x05, - 0x3a, 0x85, 0x4a, 0xea, 0x37, 0xcd, 0xf6, 0x0a, 0xd9, 0x05, 0x09, 0xf8, 0x88, 0x80, 0x9c, 0x25, - 0x44, 0xff, 0x8f, 0x86, 0x1a, 0xef, 0xd2, 0xde, 0x30, 0x41, 0x4f, 0x47, 0xf3, 0x69, 0xc0, 0x29, - 0x01, 0xe6, 0x2e, 0x24, 0x30, 0x37, 0x6b, 0xbb, 0xa5, 0xf5, 0xb4, 0xc1, 0xfe, 0xe9, 0x89, 0x79, - 0xb7, 0x6f, 0xf3, 0x6d, 0x26, 0xb8, 0x94, 0xc0, 0xb2, 0x93, 0x2e, 0x2a, 0xce, 0xd1, 0x68, 0x57, - 0x02, 0x0b, 0xd4, 0x09, 0xb8, 0x3f, 0x01, 0x97, 0x06, 0x9c, 0x09, 0x70, 0x09, 0x00, 0xa1, 0x57, - 0x9b, 0x3a, 0x55, 0x55, 0xe7, 0x45, 0xb1, 0xce, 0x30, 0x56, 0xbd, 0x51, 0xa2, 0x73, 0xa5, 0xd9, - 0xaa, 0x75, 0x1c, 0x94, 0x25, 0xed, 0x3a, 0xd2, 0xa3, 0x79, 0xd8, 0x5f, 0x56, 0xd1, 0xd1, 0xce, - 0x4e, 0xf1, 0x2b, 0xb4, 0xa7, 0x26, 0x25, 0xe9, 0x88, 0x4f, 0x8a, 0xa5, 0x63, 0xde, 0xa9, 0xc7, - 0xd4, 0x79, 0x8e, 0x7b, 0x69, 0xa7, 0xff, 0xc4, 0x6d, 0xfc, 0x12, 0x61, 0x90, 0x40, 0x82, 0xd8, - 0x4d, 0x2e, 0x7c, 0x77, 0x2a, 0xbf, 0xb2, 0x59, 0x4b, 0xef, 0x69, 0x03, 0xdd, 0x69, 0xaa, 0xcc, - 0xa5, 0x4a, 0x7c, 0x8a, 0xe3, 0xf8, 0x04, 0x3d, 0xcc, 0xdf, 0x4f, 0x8a, 0xd6, 0x14, 0xfa, 0x20, - 0x0f, 0x27, 0xa0, 0x8d, 0xee, 0xe5, 0x8b, 0xd0, 0xaa, 0xab, 0x46, 0xda, 0x66, 0xb2, 0x2a, 0x66, - 0xb6, 0x2a, 0xe6, 0xe7, 0x8c, 0xb0, 0x1b, 0x37, 0x3f, 0xbb, 0x95, 0xe5, 0xaf, 0xae, 0xe6, 0x6c, - 0x64, 0xfd, 0xef, 0x55, 0x74, 0x5c, 0x6a, 0x2a, 0x7e, 0x8f, 0x1e, 0x51, 0x29, 0xc6, 0x01, 0xa7, - 0xaa, 0x6f, 0x2f, 0x90, 0xf4, 0x2a, 0x75, 0xa8, 0x53, 0xf2, 0x72, 0xec, 0x98, 0x71, 0x9a, 0x5b, - 0x32, 0x15, 0xc1, 0xcf, 0xd1, 0x7d, 0x2a, 0xc3, 0x50, 0x0a, 0x77, 0xc2, 0x62, 0x4e, 0x39, 0xa7, - 0x3b, 0x07, 0x49, 0xf0, 0x42, 0xc5, 0xf0, 0x47, 0x74, 0xe8, 0x5d, 0x7f, 0x23, 0x02, 0xb8, 0x60, - 0x6e, 0x3e, 0x6d, 0xd4, 0xd2, 0x7b, 0xfa, 0x60, 0xff, 0xf4, 0xd9, 0x0e, 0x97, 0x33, 0xc6, 0x79, - 0x9c, 0x0b, 0xf3, 0x58, 0x54, 0x62, 0x7c, 0xad, 0xc4, 0xf8, 0xff, 0xe1, 0xe7, 0x10, 0x1d, 0x64, - 0xee, 0x0d, 0x79, 0x04, 0xf8, 0x35, 0x6a, 0x6c, 0xdd, 0x1e, 0x5d, 0x1d, 0x59, 0x98, 0x22, 0xdf, - 0xd3, 0x5a, 0x7c, 0xa4, 0x93, 0x2b, 0xec, 0x0f, 0x37, 0x2b, 0x43, 0xbb, 0x5d, 0x19, 0xda, 0xef, - 0x95, 0xa1, 0x2d, 0xd7, 0x46, 0xe5, 0x76, 0x6d, 0x54, 0x7e, 0xac, 0x8d, 0xca, 0x97, 0x33, 0x9f, - 0xc3, 0x64, 0xee, 0x99, 0x54, 0x86, 0x16, 0x95, 0x21, 0x03, 0x6f, 0x0c, 0x9b, 0x87, 0xe4, 0x0b, - 0x72, 0xf7, 0xda, 0x7b, 0x7b, 0x2a, 0x7e, 0xf6, 0x37, 0x00, 0x00, 0xff, 0xff, 0xab, 0xbe, 0xb8, - 0x21, 0x99, 0x04, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x86, 0xe3, 0x38, 0xa9, 0xc2, 0xb6, 0x40, 0xbb, 0xb4, 0x6a, 0x1a, 0x5a, 0x27, 0x84, 0x03, + 0x39, 0x54, 0xb6, 0x1a, 0xce, 0x1c, 0x6a, 0x40, 0xaa, 0x50, 0x10, 0xc8, 0x42, 0x3d, 0x70, 0xb1, + 0xd6, 0xce, 0xc6, 0x59, 0xd5, 0xf6, 0x5a, 0xf1, 0x24, 0xa8, 0x3c, 0x45, 0xc5, 0x53, 0xf5, 0x46, + 0x8f, 0x9c, 0x00, 0x25, 0x12, 0xcf, 0x81, 0x76, 0x6d, 0x6f, 0x23, 0xc5, 0xe6, 0xc4, 0x6d, 0x33, + 0xf3, 0xfd, 0x3b, 0x33, 0xff, 0xc4, 0x8b, 0x7a, 0x3e, 0x8f, 0x28, 0x78, 0x13, 0xb0, 0xe0, 0x3a, + 0xa1, 0xa9, 0xb5, 0x38, 0xb3, 0xe8, 0x82, 0x8d, 0x69, 0xec, 0x53, 0x33, 0x99, 0x71, 0xe0, 0x78, + 0xaf, 0x20, 0x4c, 0x49, 0x98, 0x8b, 0xb3, 0xce, 0xc9, 0xa6, 0x28, 0xcb, 0x49, 0x45, 0xe7, 0xd9, + 0x66, 0x7a, 0x41, 0x42, 0x36, 0x26, 0xc0, 0x67, 0x39, 0xb2, 0x1f, 0xf0, 0x80, 0xcb, 0xa3, 0x25, + 0x4e, 0x79, 0xb4, 0x1b, 0x70, 0x1e, 0x84, 0xd4, 0x92, 0xbf, 0xbc, 0xf9, 0xc4, 0x02, 0x16, 0xd1, + 0x14, 0x48, 0x94, 0x64, 0x40, 0xff, 0x8f, 0x86, 0x5a, 0x6f, 0xf3, 0xf6, 0xb0, 0x87, 0x0e, 0xc7, + 0xf3, 0x24, 0x64, 0x3e, 0x01, 0xea, 0x2e, 0x38, 0x50, 0xb7, 0xe8, 0xbc, 0xad, 0xf5, 0xb4, 0xc1, + 0xf6, 0x70, 0x60, 0x6e, 0xb4, 0x6e, 0xbe, 0x29, 0x14, 0x97, 0x1c, 0x68, 0x71, 0xd5, 0x45, 0xcd, + 0x39, 0x18, 0x97, 0x25, 0x30, 0x47, 0xc7, 0x21, 0x0b, 0xa6, 0xe0, 0xfa, 0x21, 0xa3, 0x31, 0xb8, + 0x04, 0x80, 0xf8, 0x57, 0xf7, 0x85, 0xea, 0xb2, 0xd0, 0x69, 0x49, 0xa1, 0x91, 0x90, 0xbd, 0x96, + 0xaa, 0x73, 0x29, 0x5a, 0x2b, 0x76, 0x14, 0x56, 0x25, 0xed, 0x26, 0xd2, 0xd3, 0x79, 0xd4, 0xff, + 0x56, 0x47, 0x07, 0xa5, 0xad, 0x62, 0x13, 0x6d, 0xc9, 0x59, 0x49, 0x3e, 0xe4, 0x61, 0x49, 0x6d, + 0x21, 0x70, 0x9a, 0x02, 0x3b, 0x57, 0xbc, 0x97, 0xf7, 0xfa, 0x6f, 0xde, 0xc6, 0xa7, 0x08, 0x03, + 0x07, 0x12, 0x0a, 0x47, 0x59, 0x1c, 0xb8, 0x09, 0xff, 0x42, 0x67, 0x6d, 0xbd, 0xa7, 0x0d, 0x74, + 0x67, 0x57, 0x66, 0x2e, 0x65, 0xe2, 0xa3, 0x88, 0xe3, 0x17, 0xe8, 0xb1, 0x5a, 0x6d, 0x8e, 0x36, + 0x24, 0xfa, 0x48, 0x85, 0x33, 0xd0, 0x46, 0x0f, 0xd4, 0x32, 0xdb, 0x4d, 0xd9, 0x49, 0xc7, 0xcc, + 0xd6, 0x6d, 0x16, 0xeb, 0x36, 0x3f, 0x15, 0x84, 0xdd, 0xba, 0xfd, 0xd9, 0xad, 0xdd, 0xfc, 0xea, + 0x6a, 0xce, 0xbd, 0xac, 0xff, 0xbd, 0x8e, 0x8e, 0x2a, 0x6d, 0xc5, 0xef, 0xd0, 0x9e, 0xcf, 0xe3, + 0x49, 0xc8, 0x7c, 0xd9, 0xb7, 0x17, 0x72, 0xff, 0x2a, 0xf7, 0xe8, 0xa4, 0x6a, 0x3f, 0xb6, 0x80, + 0x9c, 0xdd, 0x35, 0x9d, 0x8c, 0xe0, 0xe7, 0xe8, 0xa1, 0xcf, 0xa3, 0x88, 0xc7, 0xee, 0x94, 0x0a, + 0x4e, 0x7a, 0xa7, 0x3b, 0x3b, 0x59, 0xf0, 0x42, 0xc6, 0xf0, 0x07, 0xb4, 0xef, 0x5d, 0x7f, 0x25, + 0x31, 0xb0, 0x98, 0xba, 0x6a, 0xdc, 0xb4, 0xad, 0xf7, 0xf4, 0xc1, 0xf6, 0xf0, 0xb8, 0xcc, 0xe7, + 0x02, 0x72, 0x9e, 0x28, 0xa5, 0x8a, 0xa5, 0x15, 0xd6, 0x37, 0x2a, 0xac, 0xff, 0x1f, 0x8e, 0xbe, + 0x47, 0x3b, 0x85, 0x7f, 0x23, 0x96, 0x02, 0x7e, 0x85, 0x5a, 0x6b, 0xdf, 0x90, 0x18, 0xe3, 0x69, + 0xc9, 0x18, 0xea, 0xcf, 0xda, 0x10, 0x77, 0x3a, 0x4a, 0x62, 0x8f, 0x6e, 0x97, 0x86, 0x76, 0xb7, + 0x34, 0xb4, 0xdf, 0x4b, 0x43, 0xbb, 0x59, 0x19, 0xb5, 0xbb, 0x95, 0x51, 0xfb, 0xb1, 0x32, 0x6a, + 0x9f, 0x87, 0x01, 0x83, 0xe9, 0xdc, 0x13, 0x97, 0x59, 0xea, 0x75, 0x50, 0x07, 0x92, 0x30, 0x6b, + 0xe3, 0xcd, 0xf0, 0xb6, 0xe4, 0x14, 0x2f, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x50, 0xcc, 0xfa, + 0x44, 0xa3, 0x04, 0x00, 0x00, } func (m *Evidence) Marshal() (dAtA []byte, err error) { diff --git a/api/cometbft/types/v1/params.pb.go b/api/cometbft/types/v1/params.pb.go new file mode 100644 index 00000000000..245c5261161 --- /dev/null +++ b/api/cometbft/types/v1/params.pb.go @@ -0,0 +1,2733 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/types/v1/params.proto + +package v1 + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + types "github.com/cosmos/gogoproto/types" + _ "github.com/golang/protobuf/ptypes/duration" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ConsensusParams contains consensus critical parameters that determine the +// validity of blocks. +type ConsensusParams struct { + Block *BlockParams `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Evidence *EvidenceParams `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence,omitempty"` + Validator *ValidatorParams `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator,omitempty"` + Version *VersionParams `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + Abci *ABCIParams `protobuf:"bytes,5,opt,name=abci,proto3" json:"abci,omitempty"` // Deprecated: Do not use. + Synchrony *SynchronyParams `protobuf:"bytes,6,opt,name=synchrony,proto3" json:"synchrony,omitempty"` + Feature *FeatureParams `protobuf:"bytes,7,opt,name=feature,proto3" json:"feature,omitempty"` +} + +func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } +func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } +func (*ConsensusParams) ProtoMessage() {} +func (*ConsensusParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{0} +} +func (m *ConsensusParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsensusParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsensusParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsensusParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsensusParams.Merge(m, src) +} +func (m *ConsensusParams) XXX_Size() int { + return m.Size() +} +func (m *ConsensusParams) XXX_DiscardUnknown() { + xxx_messageInfo_ConsensusParams.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsensusParams proto.InternalMessageInfo + +func (m *ConsensusParams) GetBlock() *BlockParams { + if m != nil { + return m.Block + } + return nil +} + +func (m *ConsensusParams) GetEvidence() *EvidenceParams { + if m != nil { + return m.Evidence + } + return nil +} + +func (m *ConsensusParams) GetValidator() *ValidatorParams { + if m != nil { + return m.Validator + } + return nil +} + +func (m *ConsensusParams) GetVersion() *VersionParams { + if m != nil { + return m.Version + } + return nil +} + +// Deprecated: Do not use. +func (m *ConsensusParams) GetAbci() *ABCIParams { + if m != nil { + return m.Abci + } + return nil +} + +func (m *ConsensusParams) GetSynchrony() *SynchronyParams { + if m != nil { + return m.Synchrony + } + return nil +} + +func (m *ConsensusParams) GetFeature() *FeatureParams { + if m != nil { + return m.Feature + } + return nil +} + +// BlockParams define limits on the block size and gas. +type BlockParams struct { + // Maximum size of a block, in bytes. + // + // Must be greater or equal to -1 and cannot be greater than the hard-coded + // maximum block size, which is 100MB. + // + // If set to -1, the limit is the hard-coded maximum block size. + MaxBytes int64 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` + // Maximum gas wanted by transactions included in a block. + // + // Must be greater or equal to -1. If set to -1, no limit is enforced. + MaxGas int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` +} + +func (m *BlockParams) Reset() { *m = BlockParams{} } +func (m *BlockParams) String() string { return proto.CompactTextString(m) } +func (*BlockParams) ProtoMessage() {} +func (*BlockParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{1} +} +func (m *BlockParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockParams.Merge(m, src) +} +func (m *BlockParams) XXX_Size() int { + return m.Size() +} +func (m *BlockParams) XXX_DiscardUnknown() { + xxx_messageInfo_BlockParams.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockParams proto.InternalMessageInfo + +func (m *BlockParams) GetMaxBytes() int64 { + if m != nil { + return m.MaxBytes + } + return 0 +} + +func (m *BlockParams) GetMaxGas() int64 { + if m != nil { + return m.MaxGas + } + return 0 +} + +// EvidenceParams determine the validity of evidences of Byzantine behavior. +type EvidenceParams struct { + // Maximum age of evidence, in blocks. + // + // The recommended formula for calculating it is max_age_duration / {average + // block time}. + MaxAgeNumBlocks int64 `protobuf:"varint,1,opt,name=max_age_num_blocks,json=maxAgeNumBlocks,proto3" json:"max_age_num_blocks,omitempty"` + // Maximum age of evidence, in time. + // + // The recommended value of is should correspond to the application's + // "unbonding period" or other similar mechanism for handling + // Nothing-At-Stake attacks. + // See: https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed. + MaxAgeDuration time.Duration `protobuf:"bytes,2,opt,name=max_age_duration,json=maxAgeDuration,proto3,stdduration" json:"max_age_duration"` + // Maximum size in bytes of evidence allowed to be included in a block. + // + // It should fall comfortably under the maximum size of a block. + MaxBytes int64 `protobuf:"varint,3,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` +} + +func (m *EvidenceParams) Reset() { *m = EvidenceParams{} } +func (m *EvidenceParams) String() string { return proto.CompactTextString(m) } +func (*EvidenceParams) ProtoMessage() {} +func (*EvidenceParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{2} +} +func (m *EvidenceParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EvidenceParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EvidenceParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EvidenceParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_EvidenceParams.Merge(m, src) +} +func (m *EvidenceParams) XXX_Size() int { + return m.Size() +} +func (m *EvidenceParams) XXX_DiscardUnknown() { + xxx_messageInfo_EvidenceParams.DiscardUnknown(m) +} + +var xxx_messageInfo_EvidenceParams proto.InternalMessageInfo + +func (m *EvidenceParams) GetMaxAgeNumBlocks() int64 { + if m != nil { + return m.MaxAgeNumBlocks + } + return 0 +} + +func (m *EvidenceParams) GetMaxAgeDuration() time.Duration { + if m != nil { + return m.MaxAgeDuration + } + return 0 +} + +func (m *EvidenceParams) GetMaxBytes() int64 { + if m != nil { + return m.MaxBytes + } + return 0 +} + +// ValidatorParams restrict the public key types validators can use. +// +// NOTE: uses ABCI public keys naming, not Amino names. +type ValidatorParams struct { + PubKeyTypes []string `protobuf:"bytes,1,rep,name=pub_key_types,json=pubKeyTypes,proto3" json:"pub_key_types,omitempty"` +} + +func (m *ValidatorParams) Reset() { *m = ValidatorParams{} } +func (m *ValidatorParams) String() string { return proto.CompactTextString(m) } +func (*ValidatorParams) ProtoMessage() {} +func (*ValidatorParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{3} +} +func (m *ValidatorParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ValidatorParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ValidatorParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ValidatorParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidatorParams.Merge(m, src) +} +func (m *ValidatorParams) XXX_Size() int { + return m.Size() +} +func (m *ValidatorParams) XXX_DiscardUnknown() { + xxx_messageInfo_ValidatorParams.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidatorParams proto.InternalMessageInfo + +func (m *ValidatorParams) GetPubKeyTypes() []string { + if m != nil { + return m.PubKeyTypes + } + return nil +} + +// VersionParams contain the version of specific components of CometBFT. +type VersionParams struct { + // The ABCI application version. + // + // It was named app_version in CometBFT 0.34. + App uint64 `protobuf:"varint,1,opt,name=app,proto3" json:"app,omitempty"` +} + +func (m *VersionParams) Reset() { *m = VersionParams{} } +func (m *VersionParams) String() string { return proto.CompactTextString(m) } +func (*VersionParams) ProtoMessage() {} +func (*VersionParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{4} +} +func (m *VersionParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VersionParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VersionParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *VersionParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_VersionParams.Merge(m, src) +} +func (m *VersionParams) XXX_Size() int { + return m.Size() +} +func (m *VersionParams) XXX_DiscardUnknown() { + xxx_messageInfo_VersionParams.DiscardUnknown(m) +} + +var xxx_messageInfo_VersionParams proto.InternalMessageInfo + +func (m *VersionParams) GetApp() uint64 { + if m != nil { + return m.App + } + return 0 +} + +// HashedParams is a subset of ConsensusParams. +// +// It is hashed into the Header.ConsensusHash. +type HashedParams struct { + BlockMaxBytes int64 `protobuf:"varint,1,opt,name=block_max_bytes,json=blockMaxBytes,proto3" json:"block_max_bytes,omitempty"` + BlockMaxGas int64 `protobuf:"varint,2,opt,name=block_max_gas,json=blockMaxGas,proto3" json:"block_max_gas,omitempty"` +} + +func (m *HashedParams) Reset() { *m = HashedParams{} } +func (m *HashedParams) String() string { return proto.CompactTextString(m) } +func (*HashedParams) ProtoMessage() {} +func (*HashedParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{5} +} +func (m *HashedParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *HashedParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_HashedParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *HashedParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_HashedParams.Merge(m, src) +} +func (m *HashedParams) XXX_Size() int { + return m.Size() +} +func (m *HashedParams) XXX_DiscardUnknown() { + xxx_messageInfo_HashedParams.DiscardUnknown(m) +} + +var xxx_messageInfo_HashedParams proto.InternalMessageInfo + +func (m *HashedParams) GetBlockMaxBytes() int64 { + if m != nil { + return m.BlockMaxBytes + } + return 0 +} + +func (m *HashedParams) GetBlockMaxGas() int64 { + if m != nil { + return m.BlockMaxGas + } + return 0 +} + +// SynchronyParams determine the validity of block timestamps. +// +// These parameters are part of the Proposer-Based Timestamps (PBTS) algorithm. +// For more information on the relationship of the synchrony parameters to +// block timestamps validity, refer to the PBTS specification: +// https://github.com/tendermint/spec/blob/master/spec/consensus/proposer-based-timestamp/README.md +type SynchronyParams struct { + // Bound for how skewed a proposer's clock may be from any validator on the + // network while still producing valid proposals. + Precision *time.Duration `protobuf:"bytes,1,opt,name=precision,proto3,stdduration" json:"precision,omitempty"` + // Bound for how long a proposal message may take to reach all validators on + // a network and still be considered valid. + MessageDelay *time.Duration `protobuf:"bytes,2,opt,name=message_delay,json=messageDelay,proto3,stdduration" json:"message_delay,omitempty"` +} + +func (m *SynchronyParams) Reset() { *m = SynchronyParams{} } +func (m *SynchronyParams) String() string { return proto.CompactTextString(m) } +func (*SynchronyParams) ProtoMessage() {} +func (*SynchronyParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{6} +} +func (m *SynchronyParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SynchronyParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SynchronyParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SynchronyParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_SynchronyParams.Merge(m, src) +} +func (m *SynchronyParams) XXX_Size() int { + return m.Size() +} +func (m *SynchronyParams) XXX_DiscardUnknown() { + xxx_messageInfo_SynchronyParams.DiscardUnknown(m) +} + +var xxx_messageInfo_SynchronyParams proto.InternalMessageInfo + +func (m *SynchronyParams) GetPrecision() *time.Duration { + if m != nil { + return m.Precision + } + return nil +} + +func (m *SynchronyParams) GetMessageDelay() *time.Duration { + if m != nil { + return m.MessageDelay + } + return nil +} + +// FeatureParams configure the height from which features of CometBFT are enabled. +type FeatureParams struct { + // First height during which vote extensions will be enabled. + // + // During the specified height, and for all subsequent heights, precommit + // messages that do not contain valid extension data will be considered + // invalid. Prior to this height, or when this height is set to 0, vote + // extensions will not be used or accepted by validators on the network. + // + // Once enabled, vote extensions will be created by the application in + // ExtendVote, validated by the application in VerifyVoteExtension, and + // used by the application in PrepareProposal, when proposing the next block. + // + // Cannot be set to heights lower or equal to the current blockchain height. + VoteExtensionsEnableHeight *types.Int64Value `protobuf:"bytes,1,opt,name=vote_extensions_enable_height,json=voteExtensionsEnableHeight,proto3" json:"vote_extensions_enable_height,omitempty"` + // Height at which Proposer-Based Timestamps (PBTS) will be enabled. + // + // From the specified height, and for all subsequent heights, the PBTS + // algorithm will be used to produce and validate block timestamps. Prior to + // this height, or when this height is set to 0, the legacy BFT Time + // algorithm is used to produce and validate timestamps. + // + // Cannot be set to heights lower or equal to the current blockchain height. + PbtsEnableHeight *types.Int64Value `protobuf:"bytes,2,opt,name=pbts_enable_height,json=pbtsEnableHeight,proto3" json:"pbts_enable_height,omitempty"` +} + +func (m *FeatureParams) Reset() { *m = FeatureParams{} } +func (m *FeatureParams) String() string { return proto.CompactTextString(m) } +func (*FeatureParams) ProtoMessage() {} +func (*FeatureParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{7} +} +func (m *FeatureParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FeatureParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FeatureParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *FeatureParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_FeatureParams.Merge(m, src) +} +func (m *FeatureParams) XXX_Size() int { + return m.Size() +} +func (m *FeatureParams) XXX_DiscardUnknown() { + xxx_messageInfo_FeatureParams.DiscardUnknown(m) +} + +var xxx_messageInfo_FeatureParams proto.InternalMessageInfo + +func (m *FeatureParams) GetVoteExtensionsEnableHeight() *types.Int64Value { + if m != nil { + return m.VoteExtensionsEnableHeight + } + return nil +} + +func (m *FeatureParams) GetPbtsEnableHeight() *types.Int64Value { + if m != nil { + return m.PbtsEnableHeight + } + return nil +} + +// ABCIParams is deprecated and its contents moved to FeatureParams +// +// Deprecated: Do not use. +type ABCIParams struct { + // vote_extensions_enable_height has been deprecated. + // Instead, use FeatureParams.vote_extensions_enable_height. + VoteExtensionsEnableHeight int64 `protobuf:"varint,1,opt,name=vote_extensions_enable_height,json=voteExtensionsEnableHeight,proto3" json:"vote_extensions_enable_height,omitempty"` +} + +func (m *ABCIParams) Reset() { *m = ABCIParams{} } +func (m *ABCIParams) String() string { return proto.CompactTextString(m) } +func (*ABCIParams) ProtoMessage() {} +func (*ABCIParams) Descriptor() ([]byte, []int) { + return fileDescriptor_8c2f6d19461b2fe7, []int{8} +} +func (m *ABCIParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ABCIParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ABCIParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ABCIParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_ABCIParams.Merge(m, src) +} +func (m *ABCIParams) XXX_Size() int { + return m.Size() +} +func (m *ABCIParams) XXX_DiscardUnknown() { + xxx_messageInfo_ABCIParams.DiscardUnknown(m) +} + +var xxx_messageInfo_ABCIParams proto.InternalMessageInfo + +func (m *ABCIParams) GetVoteExtensionsEnableHeight() int64 { + if m != nil { + return m.VoteExtensionsEnableHeight + } + return 0 +} + +func init() { + proto.RegisterType((*ConsensusParams)(nil), "cometbft.types.v1.ConsensusParams") + proto.RegisterType((*BlockParams)(nil), "cometbft.types.v1.BlockParams") + proto.RegisterType((*EvidenceParams)(nil), "cometbft.types.v1.EvidenceParams") + proto.RegisterType((*ValidatorParams)(nil), "cometbft.types.v1.ValidatorParams") + proto.RegisterType((*VersionParams)(nil), "cometbft.types.v1.VersionParams") + proto.RegisterType((*HashedParams)(nil), "cometbft.types.v1.HashedParams") + proto.RegisterType((*SynchronyParams)(nil), "cometbft.types.v1.SynchronyParams") + proto.RegisterType((*FeatureParams)(nil), "cometbft.types.v1.FeatureParams") + proto.RegisterType((*ABCIParams)(nil), "cometbft.types.v1.ABCIParams") +} + +func init() { proto.RegisterFile("cometbft/types/v1/params.proto", fileDescriptor_8c2f6d19461b2fe7) } + +var fileDescriptor_8c2f6d19461b2fe7 = []byte{ + // 729 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0xbf, 0x4e, 0xdb, 0x50, + 0x14, 0xc6, 0x73, 0xe3, 0x00, 0xc9, 0x09, 0x21, 0xe9, 0x55, 0xa5, 0xba, 0x20, 0x1c, 0xea, 0xa1, + 0x42, 0x42, 0xb2, 0x05, 0xa5, 0x1d, 0x90, 0x50, 0x4b, 0x80, 0x02, 0xad, 0x68, 0x91, 0xa9, 0x18, + 0x58, 0xac, 0xeb, 0xe4, 0xe2, 0x58, 0xc4, 0x7f, 0xe4, 0x6b, 0xa7, 0xc9, 0x5b, 0x74, 0xaa, 0x3a, + 0x32, 0xb6, 0x6f, 0xd0, 0xbe, 0x40, 0xc5, 0xc8, 0xd8, 0x89, 0x56, 0x61, 0xe9, 0x63, 0x54, 0xbe, + 0xb6, 0x13, 0x12, 0x42, 0x61, 0xb3, 0x7d, 0xbe, 0xdf, 0xe7, 0xef, 0x9e, 0x73, 0x6c, 0x90, 0xea, + 0xae, 0x4d, 0x03, 0xe3, 0x24, 0x50, 0x83, 0xae, 0x47, 0x99, 0xda, 0x5e, 0x56, 0x3d, 0xe2, 0x13, + 0x9b, 0x29, 0x9e, 0xef, 0x06, 0x2e, 0x7e, 0x90, 0xd6, 0x15, 0x5e, 0x57, 0xda, 0xcb, 0xb3, 0x0f, + 0x4d, 0xd7, 0x74, 0x79, 0x55, 0x8d, 0xae, 0x62, 0xe1, 0xac, 0x64, 0xba, 0xae, 0xd9, 0xa2, 0x2a, + 0xbf, 0x33, 0xc2, 0x13, 0xb5, 0x11, 0xfa, 0x24, 0xb0, 0x5c, 0xe7, 0xb6, 0xfa, 0x47, 0x9f, 0x78, + 0x1e, 0xf5, 0x93, 0x17, 0xc9, 0x3f, 0x04, 0x28, 0x6f, 0xba, 0x0e, 0xa3, 0x0e, 0x0b, 0xd9, 0x01, + 0x8f, 0x80, 0x57, 0x61, 0xc2, 0x68, 0xb9, 0xf5, 0x53, 0x11, 0x2d, 0xa0, 0xc5, 0xe2, 0x8a, 0xa4, + 0xdc, 0x08, 0xa3, 0xd4, 0xa2, 0x7a, 0x2c, 0xd7, 0x62, 0x31, 0x5e, 0x87, 0x3c, 0x6d, 0x5b, 0x0d, + 0xea, 0xd4, 0xa9, 0x98, 0xe5, 0xe0, 0x93, 0x31, 0xe0, 0x76, 0x22, 0x49, 0xd8, 0x3e, 0x82, 0x5f, + 0x41, 0xa1, 0x4d, 0x5a, 0x56, 0x83, 0x04, 0xae, 0x2f, 0x0a, 0x9c, 0x97, 0xc7, 0xf0, 0x47, 0xa9, + 0x26, 0x31, 0x18, 0x40, 0x78, 0x0d, 0xa6, 0xda, 0xd4, 0x67, 0x96, 0xeb, 0x88, 0x39, 0xce, 0x2f, + 0x8c, 0xe3, 0x63, 0x45, 0x42, 0xa7, 0x00, 0x7e, 0x0e, 0x39, 0x62, 0xd4, 0x2d, 0x71, 0x82, 0x83, + 0xf3, 0x63, 0xc0, 0x8d, 0xda, 0xe6, 0x5e, 0x4c, 0xd5, 0xb2, 0x22, 0xd2, 0xb8, 0x3c, 0x0a, 0xcd, + 0xba, 0x4e, 0xbd, 0xe9, 0xbb, 0x4e, 0x57, 0x9c, 0xbc, 0x35, 0xf4, 0x61, 0xaa, 0x49, 0x43, 0xf7, + 0xa1, 0x28, 0xf4, 0x09, 0x25, 0x41, 0xe8, 0x53, 0x71, 0xea, 0xd6, 0xd0, 0xaf, 0x63, 0x45, 0x1a, + 0x3a, 0x01, 0xe4, 0x3d, 0x28, 0x5e, 0x9b, 0x03, 0x9e, 0x83, 0x82, 0x4d, 0x3a, 0xba, 0xd1, 0x0d, + 0x28, 0xe3, 0xa3, 0x13, 0xb4, 0xbc, 0x4d, 0x3a, 0xb5, 0xe8, 0x1e, 0x3f, 0x82, 0xa9, 0xa8, 0x68, + 0x12, 0xc6, 0x87, 0x23, 0x68, 0x93, 0x36, 0xe9, 0xec, 0x10, 0xf6, 0x26, 0x97, 0x17, 0x2a, 0x39, + 0xf9, 0x1b, 0x82, 0x99, 0xe1, 0xd1, 0xe0, 0x25, 0xc0, 0x11, 0x41, 0x4c, 0xaa, 0x3b, 0xa1, 0xad, + 0xf3, 0x21, 0xa7, 0xbe, 0x65, 0x9b, 0x74, 0x36, 0x4c, 0xfa, 0x2e, 0xb4, 0x79, 0x00, 0x86, 0xf7, + 0xa1, 0x92, 0x8a, 0xd3, 0x05, 0x4c, 0x96, 0xe0, 0xb1, 0x12, 0x6f, 0xa0, 0x92, 0x6e, 0xa0, 0xb2, + 0x95, 0x08, 0x6a, 0xf9, 0xf3, 0xcb, 0x6a, 0xe6, 0xcb, 0xef, 0x2a, 0xd2, 0x66, 0x62, 0xbf, 0xb4, + 0x32, 0x7c, 0x14, 0x61, 0xf8, 0x28, 0xf2, 0x4b, 0x28, 0x8f, 0x6c, 0x01, 0x96, 0xa1, 0xe4, 0x85, + 0x86, 0x7e, 0x4a, 0xbb, 0x3a, 0x6f, 0x9a, 0x88, 0x16, 0x84, 0xc5, 0x82, 0x56, 0xf4, 0x42, 0xe3, + 0x2d, 0xed, 0x7e, 0x88, 0x1e, 0xad, 0xe5, 0xbf, 0x9f, 0x55, 0xd1, 0xdf, 0xb3, 0x2a, 0x92, 0x97, + 0xa0, 0x34, 0xb4, 0x06, 0xb8, 0x02, 0x02, 0xf1, 0x3c, 0x7e, 0xb6, 0x9c, 0x16, 0x5d, 0x5e, 0x13, + 0x1f, 0xc3, 0xf4, 0x2e, 0x61, 0x4d, 0xda, 0x48, 0xb4, 0x4f, 0xa1, 0xcc, 0x5b, 0xa1, 0x8f, 0xf6, + 0xba, 0xc4, 0x1f, 0xef, 0xa7, 0x0d, 0x97, 0xa1, 0x34, 0xd0, 0x0d, 0xda, 0x5e, 0x4c, 0x55, 0x3b, + 0x84, 0xc9, 0x9f, 0x11, 0x94, 0x47, 0x76, 0x03, 0xaf, 0x43, 0xc1, 0xf3, 0x69, 0xdd, 0xe2, 0x7b, + 0x8c, 0xee, 0x6a, 0x61, 0x8e, 0xb7, 0x6f, 0x40, 0xe0, 0x2d, 0x28, 0xd9, 0x94, 0x31, 0x3e, 0x08, + 0xda, 0x22, 0xdd, 0xbb, 0xa7, 0x10, 0x5b, 0x4c, 0x27, 0xd4, 0x56, 0x04, 0xc9, 0x3f, 0x11, 0x94, + 0x86, 0x96, 0x0e, 0x37, 0x60, 0xbe, 0xed, 0x06, 0x54, 0xa7, 0x9d, 0x80, 0x3a, 0xd1, 0x9b, 0x98, + 0x4e, 0x1d, 0x62, 0xb4, 0xa8, 0xde, 0xa4, 0x96, 0xd9, 0x0c, 0x92, 0xa8, 0x73, 0x37, 0xde, 0xb3, + 0xe7, 0x04, 0x2f, 0x56, 0x8f, 0x48, 0x2b, 0xa4, 0xb5, 0xdc, 0xf9, 0x65, 0x15, 0x69, 0xb3, 0x91, + 0xcf, 0x76, 0xdf, 0x66, 0x9b, 0xbb, 0xec, 0x72, 0x13, 0xfc, 0x1e, 0xb0, 0x67, 0x04, 0xa3, 0xd6, + 0xd9, 0xfb, 0x5a, 0x57, 0x22, 0xf8, 0xba, 0xa1, 0x7c, 0x08, 0x30, 0xf8, 0x70, 0xf1, 0xc6, 0x7d, + 0x0e, 0x21, 0xfc, 0x2f, 0xe1, 0x5a, 0x56, 0x44, 0xb5, 0x83, 0xaf, 0x3d, 0x09, 0x9d, 0xf7, 0x24, + 0x74, 0xd1, 0x93, 0xd0, 0x9f, 0x9e, 0x84, 0x3e, 0x5d, 0x49, 0x99, 0x8b, 0x2b, 0x29, 0xf3, 0xeb, + 0x4a, 0xca, 0x1c, 0xaf, 0x98, 0x56, 0xd0, 0x0c, 0x8d, 0xe8, 0x33, 0x56, 0xfb, 0x7f, 0xf9, 0xfe, + 0x05, 0xf1, 0x2c, 0xf5, 0xc6, 0xbf, 0xdf, 0x98, 0xe4, 0x67, 0x7a, 0xf6, 0x2f, 0x00, 0x00, 0xff, + 0xff, 0xd6, 0x46, 0x5b, 0x10, 0x17, 0x06, 0x00, 0x00, +} + +func (this *ConsensusParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ConsensusParams) + if !ok { + that2, ok := that.(ConsensusParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Block.Equal(that1.Block) { + return false + } + if !this.Evidence.Equal(that1.Evidence) { + return false + } + if !this.Validator.Equal(that1.Validator) { + return false + } + if !this.Version.Equal(that1.Version) { + return false + } + if !this.Abci.Equal(that1.Abci) { + return false + } + if !this.Synchrony.Equal(that1.Synchrony) { + return false + } + if !this.Feature.Equal(that1.Feature) { + return false + } + return true +} +func (this *BlockParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*BlockParams) + if !ok { + that2, ok := that.(BlockParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MaxBytes != that1.MaxBytes { + return false + } + if this.MaxGas != that1.MaxGas { + return false + } + return true +} +func (this *EvidenceParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*EvidenceParams) + if !ok { + that2, ok := that.(EvidenceParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MaxAgeNumBlocks != that1.MaxAgeNumBlocks { + return false + } + if this.MaxAgeDuration != that1.MaxAgeDuration { + return false + } + if this.MaxBytes != that1.MaxBytes { + return false + } + return true +} +func (this *ValidatorParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ValidatorParams) + if !ok { + that2, ok := that.(ValidatorParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.PubKeyTypes) != len(that1.PubKeyTypes) { + return false + } + for i := range this.PubKeyTypes { + if this.PubKeyTypes[i] != that1.PubKeyTypes[i] { + return false + } + } + return true +} +func (this *VersionParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*VersionParams) + if !ok { + that2, ok := that.(VersionParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.App != that1.App { + return false + } + return true +} +func (this *HashedParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*HashedParams) + if !ok { + that2, ok := that.(HashedParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.BlockMaxBytes != that1.BlockMaxBytes { + return false + } + if this.BlockMaxGas != that1.BlockMaxGas { + return false + } + return true +} +func (this *SynchronyParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*SynchronyParams) + if !ok { + that2, ok := that.(SynchronyParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Precision != nil && that1.Precision != nil { + if *this.Precision != *that1.Precision { + return false + } + } else if this.Precision != nil { + return false + } else if that1.Precision != nil { + return false + } + if this.MessageDelay != nil && that1.MessageDelay != nil { + if *this.MessageDelay != *that1.MessageDelay { + return false + } + } else if this.MessageDelay != nil { + return false + } else if that1.MessageDelay != nil { + return false + } + return true +} +func (this *FeatureParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*FeatureParams) + if !ok { + that2, ok := that.(FeatureParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.VoteExtensionsEnableHeight.Equal(that1.VoteExtensionsEnableHeight) { + return false + } + if !this.PbtsEnableHeight.Equal(that1.PbtsEnableHeight) { + return false + } + return true +} +func (this *ABCIParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ABCIParams) + if !ok { + that2, ok := that.(ABCIParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.VoteExtensionsEnableHeight != that1.VoteExtensionsEnableHeight { + return false + } + return true +} +func (m *ConsensusParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsensusParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsensusParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Feature != nil { + { + size, err := m.Feature.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + if m.Synchrony != nil { + { + size, err := m.Synchrony.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + if m.Abci != nil { + { + size, err := m.Abci.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.Version != nil { + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.Validator != nil { + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Evidence != nil { + { + size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Block != nil { + { + size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *BlockParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BlockParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MaxGas != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.MaxGas)) + i-- + dAtA[i] = 0x10 + } + if m.MaxBytes != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.MaxBytes)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EvidenceParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EvidenceParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EvidenceParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MaxBytes != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.MaxBytes)) + i-- + dAtA[i] = 0x18 + } + n8, err8 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.MaxAgeDuration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.MaxAgeDuration):]) + if err8 != nil { + return 0, err8 + } + i -= n8 + i = encodeVarintParams(dAtA, i, uint64(n8)) + i-- + dAtA[i] = 0x12 + if m.MaxAgeNumBlocks != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.MaxAgeNumBlocks)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ValidatorParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ValidatorParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.PubKeyTypes) > 0 { + for iNdEx := len(m.PubKeyTypes) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.PubKeyTypes[iNdEx]) + copy(dAtA[i:], m.PubKeyTypes[iNdEx]) + i = encodeVarintParams(dAtA, i, uint64(len(m.PubKeyTypes[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *VersionParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VersionParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VersionParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.App != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.App)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *HashedParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *HashedParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *HashedParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BlockMaxGas != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.BlockMaxGas)) + i-- + dAtA[i] = 0x10 + } + if m.BlockMaxBytes != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.BlockMaxBytes)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SynchronyParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SynchronyParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SynchronyParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MessageDelay != nil { + n9, err9 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(*m.MessageDelay, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(*m.MessageDelay):]) + if err9 != nil { + return 0, err9 + } + i -= n9 + i = encodeVarintParams(dAtA, i, uint64(n9)) + i-- + dAtA[i] = 0x12 + } + if m.Precision != nil { + n10, err10 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(*m.Precision, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(*m.Precision):]) + if err10 != nil { + return 0, err10 + } + i -= n10 + i = encodeVarintParams(dAtA, i, uint64(n10)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *FeatureParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *FeatureParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FeatureParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PbtsEnableHeight != nil { + { + size, err := m.PbtsEnableHeight.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.VoteExtensionsEnableHeight != nil { + { + size, err := m.VoteExtensionsEnableHeight.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ABCIParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ABCIParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ABCIParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.VoteExtensionsEnableHeight != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.VoteExtensionsEnableHeight)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintParams(dAtA []byte, offset int, v uint64) int { + offset -= sovParams(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func NewPopulatedValidatorParams(r randyParams, easy bool) *ValidatorParams { + this := &ValidatorParams{} + v1 := r.Intn(10) + this.PubKeyTypes = make([]string, v1) + for i := 0; i < v1; i++ { + this.PubKeyTypes[i] = string(randStringParams(r)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedVersionParams(r randyParams, easy bool) *VersionParams { + this := &VersionParams{} + this.App = uint64(uint64(r.Uint32())) + if !easy && r.Intn(10) != 0 { + } + return this +} + +type randyParams interface { + Float32() float32 + Float64() float64 + Int63() int64 + Int31() int32 + Uint32() uint32 + Intn(n int) int +} + +func randUTF8RuneParams(r randyParams) rune { + ru := r.Intn(62) + if ru < 10 { + return rune(ru + 48) + } else if ru < 36 { + return rune(ru + 55) + } + return rune(ru + 61) +} +func randStringParams(r randyParams) string { + v2 := r.Intn(100) + tmps := make([]rune, v2) + for i := 0; i < v2; i++ { + tmps[i] = randUTF8RuneParams(r) + } + return string(tmps) +} +func randUnrecognizedParams(r randyParams, maxFieldNumber int) (dAtA []byte) { + l := r.Intn(5) + for i := 0; i < l; i++ { + wire := r.Intn(4) + if wire == 3 { + wire = 5 + } + fieldNumber := maxFieldNumber + r.Intn(100) + dAtA = randFieldParams(dAtA, r, fieldNumber, wire) + } + return dAtA +} +func randFieldParams(dAtA []byte, r randyParams, fieldNumber int, wire int) []byte { + key := uint32(fieldNumber)<<3 | uint32(wire) + switch wire { + case 0: + dAtA = encodeVarintPopulateParams(dAtA, uint64(key)) + v3 := r.Int63() + if r.Intn(2) == 0 { + v3 *= -1 + } + dAtA = encodeVarintPopulateParams(dAtA, uint64(v3)) + case 1: + dAtA = encodeVarintPopulateParams(dAtA, uint64(key)) + dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) + case 2: + dAtA = encodeVarintPopulateParams(dAtA, uint64(key)) + ll := r.Intn(100) + dAtA = encodeVarintPopulateParams(dAtA, uint64(ll)) + for j := 0; j < ll; j++ { + dAtA = append(dAtA, byte(r.Intn(256))) + } + default: + dAtA = encodeVarintPopulateParams(dAtA, uint64(key)) + dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) + } + return dAtA +} +func encodeVarintPopulateParams(dAtA []byte, v uint64) []byte { + for v >= 1<<7 { + dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80)) + v >>= 7 + } + dAtA = append(dAtA, uint8(v)) + return dAtA +} +func (m *ConsensusParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Block != nil { + l = m.Block.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Evidence != nil { + l = m.Evidence.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Validator != nil { + l = m.Validator.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Version != nil { + l = m.Version.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Abci != nil { + l = m.Abci.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Synchrony != nil { + l = m.Synchrony.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Feature != nil { + l = m.Feature.Size() + n += 1 + l + sovParams(uint64(l)) + } + return n +} + +func (m *BlockParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxBytes != 0 { + n += 1 + sovParams(uint64(m.MaxBytes)) + } + if m.MaxGas != 0 { + n += 1 + sovParams(uint64(m.MaxGas)) + } + return n +} + +func (m *EvidenceParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxAgeNumBlocks != 0 { + n += 1 + sovParams(uint64(m.MaxAgeNumBlocks)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.MaxAgeDuration) + n += 1 + l + sovParams(uint64(l)) + if m.MaxBytes != 0 { + n += 1 + sovParams(uint64(m.MaxBytes)) + } + return n +} + +func (m *ValidatorParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.PubKeyTypes) > 0 { + for _, s := range m.PubKeyTypes { + l = len(s) + n += 1 + l + sovParams(uint64(l)) + } + } + return n +} + +func (m *VersionParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.App != 0 { + n += 1 + sovParams(uint64(m.App)) + } + return n +} + +func (m *HashedParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BlockMaxBytes != 0 { + n += 1 + sovParams(uint64(m.BlockMaxBytes)) + } + if m.BlockMaxGas != 0 { + n += 1 + sovParams(uint64(m.BlockMaxGas)) + } + return n +} + +func (m *SynchronyParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Precision != nil { + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(*m.Precision) + n += 1 + l + sovParams(uint64(l)) + } + if m.MessageDelay != nil { + l = github_com_cosmos_gogoproto_types.SizeOfStdDuration(*m.MessageDelay) + n += 1 + l + sovParams(uint64(l)) + } + return n +} + +func (m *FeatureParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.VoteExtensionsEnableHeight != nil { + l = m.VoteExtensionsEnableHeight.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.PbtsEnableHeight != nil { + l = m.PbtsEnableHeight.Size() + n += 1 + l + sovParams(uint64(l)) + } + return n +} + +func (m *ABCIParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.VoteExtensionsEnableHeight != 0 { + n += 1 + sovParams(uint64(m.VoteExtensionsEnableHeight)) + } + return n +} + +func sovParams(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozParams(x uint64) (n int) { + return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ConsensusParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsensusParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Block == nil { + m.Block = &BlockParams{} + } + if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Evidence == nil { + m.Evidence = &EvidenceParams{} + } + if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Validator == nil { + m.Validator = &ValidatorParams{} + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Version == nil { + m.Version = &VersionParams{} + } + if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Abci", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Abci == nil { + m.Abci = &ABCIParams{} + } + if err := m.Abci.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Synchrony", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Synchrony == nil { + m.Synchrony = &SynchronyParams{} + } + if err := m.Synchrony.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Feature", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Feature == nil { + m.Feature = &FeatureParams{} + } + if err := m.Feature.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxBytes", wireType) + } + m.MaxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxGas", wireType) + } + m.MaxGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxGas |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EvidenceParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EvidenceParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EvidenceParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxAgeNumBlocks", wireType) + } + m.MaxAgeNumBlocks = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxAgeNumBlocks |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxAgeDuration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(&m.MaxAgeDuration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxBytes", wireType) + } + m.MaxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ValidatorParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ValidatorParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKeyTypes", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PubKeyTypes = append(m.PubKeyTypes, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VersionParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VersionParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VersionParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field App", wireType) + } + m.App = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.App |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *HashedParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: HashedParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: HashedParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockMaxBytes", wireType) + } + m.BlockMaxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockMaxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockMaxGas", wireType) + } + m.BlockMaxGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockMaxGas |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SynchronyParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SynchronyParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SynchronyParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Precision", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Precision == nil { + m.Precision = new(time.Duration) + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(m.Precision, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MessageDelay", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MessageDelay == nil { + m.MessageDelay = new(time.Duration) + } + if err := github_com_cosmos_gogoproto_types.StdDurationUnmarshal(m.MessageDelay, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *FeatureParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: FeatureParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FeatureParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtensionsEnableHeight", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.VoteExtensionsEnableHeight == nil { + m.VoteExtensionsEnableHeight = &types.Int64Value{} + } + if err := m.VoteExtensionsEnableHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PbtsEnableHeight", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PbtsEnableHeight == nil { + m.PbtsEnableHeight = &types.Int64Value{} + } + if err := m.PbtsEnableHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ABCIParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ABCIParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ABCIParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteExtensionsEnableHeight", wireType) + } + m.VoteExtensionsEnableHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VoteExtensionsEnableHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipParams(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthParams + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupParams + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthParams + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowParams = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/tendermint/types/types.pb.go b/api/cometbft/types/v1/types.pb.go similarity index 90% rename from proto/tendermint/types/types.pb.go rename to api/cometbft/types/v1/types.pb.go index 2b2c819b4f4..b9fef6df44a 100644 --- a/proto/tendermint/types/types.pb.go +++ b/api/cometbft/types/v1/types.pb.go @@ -1,12 +1,12 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/types/types.proto +// source: cometbft/types/v1/types.proto -package types +package v1 import ( fmt "fmt" - crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" - version "github.com/cometbft/cometbft/proto/tendermint/version" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + v11 "github.com/cometbft/cometbft/api/cometbft/version/v1" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" _ "github.com/cosmos/gogoproto/types" @@ -33,11 +33,13 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type SignedMsgType int32 const ( + // Unknown UnknownType SignedMsgType = 0 - // Votes - PrevoteType SignedMsgType = 1 + // Prevote + PrevoteType SignedMsgType = 1 + // Precommit PrecommitType SignedMsgType = 2 - // Proposals + // Proposal ProposalType SignedMsgType = 32 ) @@ -60,10 +62,10 @@ func (x SignedMsgType) String() string { } func (SignedMsgType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{0} + return fileDescriptor_8ea20b664d765b5f, []int{0} } -// PartsetHeader +// Header of the parts set for a block. type PartSetHeader struct { Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` @@ -73,7 +75,7 @@ func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } func (*PartSetHeader) ProtoMessage() {} func (*PartSetHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{0} + return fileDescriptor_8ea20b664d765b5f, []int{0} } func (m *PartSetHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -116,17 +118,18 @@ func (m *PartSetHeader) GetHash() []byte { return nil } +// Part of the block. type Part struct { - Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` - Bytes []byte `protobuf:"bytes,2,opt,name=bytes,proto3" json:"bytes,omitempty"` - Proof crypto.Proof `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof"` + Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Bytes []byte `protobuf:"bytes,2,opt,name=bytes,proto3" json:"bytes,omitempty"` + Proof v1.Proof `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof"` } func (m *Part) Reset() { *m = Part{} } func (m *Part) String() string { return proto.CompactTextString(m) } func (*Part) ProtoMessage() {} func (*Part) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{1} + return fileDescriptor_8ea20b664d765b5f, []int{1} } func (m *Part) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -169,14 +172,14 @@ func (m *Part) GetBytes() []byte { return nil } -func (m *Part) GetProof() crypto.Proof { +func (m *Part) GetProof() v1.Proof { if m != nil { return m.Proof } - return crypto.Proof{} + return v1.Proof{} } -// BlockID +// BlockID defines the unique ID of a block as its hash and its `PartSetHeader`. type BlockID struct { Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` PartSetHeader PartSetHeader `protobuf:"bytes,2,opt,name=part_set_header,json=partSetHeader,proto3" json:"part_set_header"` @@ -186,7 +189,7 @@ func (m *BlockID) Reset() { *m = BlockID{} } func (m *BlockID) String() string { return proto.CompactTextString(m) } func (*BlockID) ProtoMessage() {} func (*BlockID) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{2} + return fileDescriptor_8ea20b664d765b5f, []int{2} } func (m *BlockID) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -232,10 +235,10 @@ func (m *BlockID) GetPartSetHeader() PartSetHeader { // Header defines the structure of a block header. type Header struct { // basic block info - Version version.Consensus `protobuf:"bytes,1,opt,name=version,proto3" json:"version"` - ChainID string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` - Time time.Time `protobuf:"bytes,4,opt,name=time,proto3,stdtime" json:"time"` + Version v11.Consensus `protobuf:"bytes,1,opt,name=version,proto3" json:"version"` + ChainID string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,4,opt,name=time,proto3,stdtime" json:"time"` // prev block info LastBlockId BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId,proto3" json:"last_block_id"` // hashes of block data @@ -256,7 +259,7 @@ func (m *Header) Reset() { *m = Header{} } func (m *Header) String() string { return proto.CompactTextString(m) } func (*Header) ProtoMessage() {} func (*Header) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{3} + return fileDescriptor_8ea20b664d765b5f, []int{3} } func (m *Header) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -285,11 +288,11 @@ func (m *Header) XXX_DiscardUnknown() { var xxx_messageInfo_Header proto.InternalMessageInfo -func (m *Header) GetVersion() version.Consensus { +func (m *Header) GetVersion() v11.Consensus { if m != nil { return m.Version } - return version.Consensus{} + return v11.Consensus{} } func (m *Header) GetChainID() string { @@ -395,7 +398,7 @@ func (m *Data) Reset() { *m = Data{} } func (m *Data) String() string { return proto.CompactTextString(m) } func (*Data) ProtoMessage() {} func (*Data) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{4} + return fileDescriptor_8ea20b664d765b5f, []int{4} } func (m *Data) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -434,7 +437,7 @@ func (m *Data) GetTxs() [][]byte { // Vote represents a prevote or precommit vote from validators for // consensus. type Vote struct { - Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.types.SignedMsgType" json:"type,omitempty"` + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.types.v1.SignedMsgType" json:"type,omitempty"` Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` Round int32 `protobuf:"varint,3,opt,name=round,proto3" json:"round,omitempty"` BlockID BlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id"` @@ -457,7 +460,7 @@ func (m *Vote) Reset() { *m = Vote{} } func (m *Vote) String() string { return proto.CompactTextString(m) } func (*Vote) ProtoMessage() {} func (*Vote) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{5} + return fileDescriptor_8ea20b664d765b5f, []int{5} } func (m *Vote) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -568,7 +571,7 @@ func (m *Commit) Reset() { *m = Commit{} } func (m *Commit) String() string { return proto.CompactTextString(m) } func (*Commit) ProtoMessage() {} func (*Commit) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{6} + return fileDescriptor_8ea20b664d765b5f, []int{6} } func (m *Commit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -627,7 +630,7 @@ func (m *Commit) GetSignatures() []CommitSig { // CommitSig is a part of the Vote included in a Commit. type CommitSig struct { - BlockIdFlag BlockIDFlag `protobuf:"varint,1,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=tendermint.types.BlockIDFlag" json:"block_id_flag,omitempty"` + BlockIdFlag BlockIDFlag `protobuf:"varint,1,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=cometbft.types.v1.BlockIDFlag" json:"block_id_flag,omitempty"` ValidatorAddress []byte `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` Timestamp time.Time `protobuf:"bytes,3,opt,name=timestamp,proto3,stdtime" json:"timestamp"` Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` @@ -637,7 +640,7 @@ func (m *CommitSig) Reset() { *m = CommitSig{} } func (m *CommitSig) String() string { return proto.CompactTextString(m) } func (*CommitSig) ProtoMessage() {} func (*CommitSig) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{7} + return fileDescriptor_8ea20b664d765b5f, []int{7} } func (m *CommitSig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -694,6 +697,7 @@ func (m *CommitSig) GetSignature() []byte { return nil } +// ExtendedCommit is a Commit with ExtendedCommitSig. type ExtendedCommit struct { Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` @@ -705,7 +709,7 @@ func (m *ExtendedCommit) Reset() { *m = ExtendedCommit{} } func (m *ExtendedCommit) String() string { return proto.CompactTextString(m) } func (*ExtendedCommit) ProtoMessage() {} func (*ExtendedCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{8} + return fileDescriptor_8ea20b664d765b5f, []int{8} } func (m *ExtendedCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -766,7 +770,7 @@ func (m *ExtendedCommit) GetExtendedSignatures() []ExtendedCommitSig { // extension-related fields. We use two signatures to ensure backwards compatibility. // That is the digest of the original signature is still the same in prior versions type ExtendedCommitSig struct { - BlockIdFlag BlockIDFlag `protobuf:"varint,1,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=tendermint.types.BlockIDFlag" json:"block_id_flag,omitempty"` + BlockIdFlag BlockIDFlag `protobuf:"varint,1,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=cometbft.types.v1.BlockIDFlag" json:"block_id_flag,omitempty"` ValidatorAddress []byte `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` Timestamp time.Time `protobuf:"bytes,3,opt,name=timestamp,proto3,stdtime" json:"timestamp"` Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` @@ -780,7 +784,7 @@ func (m *ExtendedCommitSig) Reset() { *m = ExtendedCommitSig{} } func (m *ExtendedCommitSig) String() string { return proto.CompactTextString(m) } func (*ExtendedCommitSig) ProtoMessage() {} func (*ExtendedCommitSig) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{9} + return fileDescriptor_8ea20b664d765b5f, []int{9} } func (m *ExtendedCommitSig) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -851,8 +855,9 @@ func (m *ExtendedCommitSig) GetExtensionSignature() []byte { return nil } +// Block proposal. type Proposal struct { - Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=tendermint.types.SignedMsgType" json:"type,omitempty"` + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.types.v1.SignedMsgType" json:"type,omitempty"` Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` Round int32 `protobuf:"varint,3,opt,name=round,proto3" json:"round,omitempty"` PolRound int32 `protobuf:"varint,4,opt,name=pol_round,json=polRound,proto3" json:"pol_round,omitempty"` @@ -865,7 +870,7 @@ func (m *Proposal) Reset() { *m = Proposal{} } func (m *Proposal) String() string { return proto.CompactTextString(m) } func (*Proposal) ProtoMessage() {} func (*Proposal) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{10} + return fileDescriptor_8ea20b664d765b5f, []int{10} } func (m *Proposal) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -943,6 +948,7 @@ func (m *Proposal) GetSignature() []byte { return nil } +// SignedHeader contains a Header(H) and Commit(H+1) with signatures of validators who signed it. type SignedHeader struct { Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` Commit *Commit `protobuf:"bytes,2,opt,name=commit,proto3" json:"commit,omitempty"` @@ -952,7 +958,7 @@ func (m *SignedHeader) Reset() { *m = SignedHeader{} } func (m *SignedHeader) String() string { return proto.CompactTextString(m) } func (*SignedHeader) ProtoMessage() {} func (*SignedHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{11} + return fileDescriptor_8ea20b664d765b5f, []int{11} } func (m *SignedHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -995,6 +1001,7 @@ func (m *SignedHeader) GetCommit() *Commit { return nil } +// LightBlock is a combination of SignedHeader and ValidatorSet. It is used by light clients. type LightBlock struct { SignedHeader *SignedHeader `protobuf:"bytes,1,opt,name=signed_header,json=signedHeader,proto3" json:"signed_header,omitempty"` ValidatorSet *ValidatorSet `protobuf:"bytes,2,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty"` @@ -1004,7 +1011,7 @@ func (m *LightBlock) Reset() { *m = LightBlock{} } func (m *LightBlock) String() string { return proto.CompactTextString(m) } func (*LightBlock) ProtoMessage() {} func (*LightBlock) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{12} + return fileDescriptor_8ea20b664d765b5f, []int{12} } func (m *LightBlock) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1047,6 +1054,7 @@ func (m *LightBlock) GetValidatorSet() *ValidatorSet { return nil } +// BlockMeta contains meta information about a block. type BlockMeta struct { BlockID BlockID `protobuf:"bytes,1,opt,name=block_id,json=blockId,proto3" json:"block_id"` BlockSize int64 `protobuf:"varint,2,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"` @@ -1058,7 +1066,7 @@ func (m *BlockMeta) Reset() { *m = BlockMeta{} } func (m *BlockMeta) String() string { return proto.CompactTextString(m) } func (*BlockMeta) ProtoMessage() {} func (*BlockMeta) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{13} + return fileDescriptor_8ea20b664d765b5f, []int{13} } func (m *BlockMeta) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1117,16 +1125,16 @@ func (m *BlockMeta) GetNumTxs() int64 { // TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree. type TxProof struct { - RootHash []byte `protobuf:"bytes,1,opt,name=root_hash,json=rootHash,proto3" json:"root_hash,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Proof *crypto.Proof `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof,omitempty"` + RootHash []byte `protobuf:"bytes,1,opt,name=root_hash,json=rootHash,proto3" json:"root_hash,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Proof *v1.Proof `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof,omitempty"` } func (m *TxProof) Reset() { *m = TxProof{} } func (m *TxProof) String() string { return proto.CompactTextString(m) } func (*TxProof) ProtoMessage() {} func (*TxProof) Descriptor() ([]byte, []int) { - return fileDescriptor_d3a6e55e2345de56, []int{14} + return fileDescriptor_8ea20b664d765b5f, []int{14} } func (m *TxProof) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1169,7 +1177,7 @@ func (m *TxProof) GetData() []byte { return nil } -func (m *TxProof) GetProof() *crypto.Proof { +func (m *TxProof) GetProof() *v1.Proof { if m != nil { return m.Proof } @@ -1177,110 +1185,111 @@ func (m *TxProof) GetProof() *crypto.Proof { } func init() { - proto.RegisterEnum("tendermint.types.SignedMsgType", SignedMsgType_name, SignedMsgType_value) - proto.RegisterType((*PartSetHeader)(nil), "tendermint.types.PartSetHeader") - proto.RegisterType((*Part)(nil), "tendermint.types.Part") - proto.RegisterType((*BlockID)(nil), "tendermint.types.BlockID") - proto.RegisterType((*Header)(nil), "tendermint.types.Header") - proto.RegisterType((*Data)(nil), "tendermint.types.Data") - proto.RegisterType((*Vote)(nil), "tendermint.types.Vote") - proto.RegisterType((*Commit)(nil), "tendermint.types.Commit") - proto.RegisterType((*CommitSig)(nil), "tendermint.types.CommitSig") - proto.RegisterType((*ExtendedCommit)(nil), "tendermint.types.ExtendedCommit") - proto.RegisterType((*ExtendedCommitSig)(nil), "tendermint.types.ExtendedCommitSig") - proto.RegisterType((*Proposal)(nil), "tendermint.types.Proposal") - proto.RegisterType((*SignedHeader)(nil), "tendermint.types.SignedHeader") - proto.RegisterType((*LightBlock)(nil), "tendermint.types.LightBlock") - proto.RegisterType((*BlockMeta)(nil), "tendermint.types.BlockMeta") - proto.RegisterType((*TxProof)(nil), "tendermint.types.TxProof") -} - -func init() { proto.RegisterFile("tendermint/types/types.proto", fileDescriptor_d3a6e55e2345de56) } - -var fileDescriptor_d3a6e55e2345de56 = []byte{ - // 1310 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x57, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xce, 0xda, 0xeb, 0x5f, 0xcf, 0x76, 0xe2, 0x2c, 0x11, 0x75, 0xdd, 0xc6, 0xb1, 0x5c, 0x01, - 0xa1, 0xa0, 0x4d, 0x95, 0x22, 0x04, 0x07, 0x0e, 0xf9, 0x45, 0x1b, 0x51, 0x27, 0xd6, 0xda, 0x2d, - 0xa2, 0x97, 0xd5, 0xda, 0x3b, 0xb1, 0x97, 0xda, 0x3b, 0xab, 0xdd, 0x71, 0x70, 0xfa, 0x17, 0xa0, - 0x9e, 0x7a, 0xe2, 0xd6, 0x13, 0x1c, 0xb8, 0x83, 0xc4, 0x15, 0x71, 0xea, 0xb1, 0x37, 0xb8, 0x50, - 0x20, 0x95, 0xf8, 0x3b, 0xd0, 0xbc, 0x99, 0xdd, 0xb5, 0xe3, 0x18, 0xaa, 0xa8, 0x02, 0x89, 0x8b, - 0xb5, 0xf3, 0xde, 0xf7, 0xde, 0xbc, 0x79, 0xdf, 0x37, 0xa3, 0x67, 0xb8, 0xca, 0x88, 0x6b, 0x13, - 0x7f, 0xe8, 0xb8, 0x6c, 0x83, 0x9d, 0x78, 0x24, 0x10, 0xbf, 0xba, 0xe7, 0x53, 0x46, 0xb5, 0x52, - 0xec, 0xd5, 0xd1, 0x5e, 0x59, 0xe9, 0xd1, 0x1e, 0x45, 0xe7, 0x06, 0xff, 0x12, 0xb8, 0xca, 0x5a, - 0x8f, 0xd2, 0xde, 0x80, 0x6c, 0xe0, 0xaa, 0x33, 0x3a, 0xda, 0x60, 0xce, 0x90, 0x04, 0xcc, 0x1a, - 0x7a, 0x12, 0xb0, 0x3a, 0xb1, 0x4d, 0xd7, 0x3f, 0xf1, 0x18, 0xe5, 0x58, 0x7a, 0x24, 0xdd, 0xd5, - 0x09, 0xf7, 0x31, 0xf1, 0x03, 0x87, 0xba, 0x93, 0x75, 0x54, 0x6a, 0x33, 0x55, 0x1e, 0x5b, 0x03, - 0xc7, 0xb6, 0x18, 0xf5, 0x05, 0xa2, 0xfe, 0x21, 0x14, 0x9b, 0x96, 0xcf, 0x5a, 0x84, 0xdd, 0x26, - 0x96, 0x4d, 0x7c, 0x6d, 0x05, 0x52, 0x8c, 0x32, 0x6b, 0x50, 0x56, 0x6a, 0xca, 0x7a, 0xd1, 0x10, - 0x0b, 0x4d, 0x03, 0xb5, 0x6f, 0x05, 0xfd, 0x72, 0xa2, 0xa6, 0xac, 0x17, 0x0c, 0xfc, 0xae, 0xf7, - 0x41, 0xe5, 0xa1, 0x3c, 0xc2, 0x71, 0x6d, 0x32, 0x0e, 0x23, 0x70, 0xc1, 0xad, 0x9d, 0x13, 0x46, - 0x02, 0x19, 0x22, 0x16, 0xda, 0x7b, 0x90, 0xc2, 0xfa, 0xcb, 0xc9, 0x9a, 0xb2, 0x9e, 0xdf, 0x2c, - 0xeb, 0x13, 0x8d, 0x12, 0xe7, 0xd3, 0x9b, 0xdc, 0xbf, 0xad, 0x3e, 0x7d, 0xbe, 0xb6, 0x60, 0x08, - 0x70, 0x7d, 0x00, 0x99, 0xed, 0x01, 0xed, 0x3e, 0xd8, 0xdf, 0x8d, 0x0a, 0x51, 0xe2, 0x42, 0xb4, - 0x06, 0x2c, 0x79, 0x96, 0xcf, 0xcc, 0x80, 0x30, 0xb3, 0x8f, 0xa7, 0xc0, 0x4d, 0xf3, 0x9b, 0x6b, - 0xfa, 0x59, 0x1e, 0xf4, 0xa9, 0xc3, 0xca, 0x5d, 0x8a, 0xde, 0xa4, 0xb1, 0xfe, 0xa7, 0x0a, 0x69, - 0xd9, 0x8c, 0x8f, 0x20, 0x23, 0xdb, 0x8a, 0x1b, 0xe6, 0x37, 0x57, 0x27, 0x33, 0x4a, 0x97, 0xbe, - 0x43, 0xdd, 0x80, 0xb8, 0xc1, 0x28, 0x90, 0xf9, 0xc2, 0x18, 0xed, 0x4d, 0xc8, 0x76, 0xfb, 0x96, - 0xe3, 0x9a, 0x8e, 0x8d, 0x15, 0xe5, 0xb6, 0xf3, 0xa7, 0xcf, 0xd7, 0x32, 0x3b, 0xdc, 0xb6, 0xbf, - 0x6b, 0x64, 0xd0, 0xb9, 0x6f, 0x6b, 0xaf, 0x43, 0xba, 0x4f, 0x9c, 0x5e, 0x9f, 0x61, 0x5b, 0x92, - 0x86, 0x5c, 0x69, 0x1f, 0x80, 0xca, 0x05, 0x51, 0x56, 0x71, 0xef, 0x8a, 0x2e, 0xd4, 0xa2, 0x87, - 0x6a, 0xd1, 0xdb, 0xa1, 0x5a, 0xb6, 0xb3, 0x7c, 0xe3, 0xc7, 0xbf, 0xad, 0x29, 0x06, 0x46, 0x68, - 0x3b, 0x50, 0x1c, 0x58, 0x01, 0x33, 0x3b, 0xbc, 0x6d, 0x7c, 0xfb, 0x14, 0xa6, 0xb8, 0x3c, 0xdb, - 0x10, 0xd9, 0x58, 0x59, 0x7a, 0x9e, 0x47, 0x09, 0x93, 0xad, 0xad, 0x43, 0x09, 0x93, 0x74, 0xe9, - 0x70, 0xe8, 0x30, 0x13, 0xfb, 0x9e, 0xc6, 0xbe, 0x2f, 0x72, 0xfb, 0x0e, 0x9a, 0x6f, 0x73, 0x06, - 0xae, 0x40, 0xce, 0xb6, 0x98, 0x25, 0x20, 0x19, 0x84, 0x64, 0xb9, 0x01, 0x9d, 0x6f, 0xc1, 0x52, - 0xa4, 0xba, 0x40, 0x40, 0xb2, 0x22, 0x4b, 0x6c, 0x46, 0xe0, 0x0d, 0x58, 0x71, 0xc9, 0x98, 0x99, - 0x67, 0xd1, 0x39, 0x44, 0x6b, 0xdc, 0x77, 0x6f, 0x3a, 0xe2, 0x0d, 0x58, 0xec, 0x86, 0xcd, 0x17, - 0x58, 0x40, 0x6c, 0x31, 0xb2, 0x22, 0xec, 0x32, 0x64, 0x2d, 0xcf, 0x13, 0x80, 0x3c, 0x02, 0x32, - 0x96, 0xe7, 0xa1, 0xeb, 0x3a, 0x2c, 0xe3, 0x19, 0x7d, 0x12, 0x8c, 0x06, 0x4c, 0x26, 0x29, 0x20, - 0x66, 0x89, 0x3b, 0x0c, 0x61, 0x47, 0xec, 0x35, 0x28, 0x92, 0x63, 0xc7, 0x26, 0x6e, 0x97, 0x08, - 0x5c, 0x11, 0x71, 0x85, 0xd0, 0x88, 0xa0, 0xb7, 0xa1, 0xe4, 0xf9, 0xd4, 0xa3, 0x01, 0xf1, 0x4d, - 0xcb, 0xb6, 0x7d, 0x12, 0x04, 0xe5, 0x45, 0x91, 0x2f, 0xb4, 0x6f, 0x09, 0x73, 0xbd, 0x0c, 0xea, - 0xae, 0xc5, 0x2c, 0xad, 0x04, 0x49, 0x36, 0x0e, 0xca, 0x4a, 0x2d, 0xb9, 0x5e, 0x30, 0xf8, 0x67, - 0xfd, 0x87, 0x24, 0xa8, 0xf7, 0x28, 0x23, 0xda, 0x4d, 0x50, 0x39, 0x4d, 0xa8, 0xbe, 0xc5, 0xf3, - 0xf4, 0xdc, 0x72, 0x7a, 0x2e, 0xb1, 0x1b, 0x41, 0xaf, 0x7d, 0xe2, 0x11, 0x03, 0xc1, 0x13, 0x72, - 0x4a, 0x4c, 0xc9, 0x69, 0x05, 0x52, 0x3e, 0x1d, 0xb9, 0x36, 0xaa, 0x2c, 0x65, 0x88, 0x85, 0xb6, - 0x07, 0xd9, 0x48, 0x25, 0xea, 0x3f, 0xa9, 0x64, 0x89, 0xab, 0x84, 0x6b, 0x58, 0x1a, 0x8c, 0x4c, - 0x47, 0x8a, 0x65, 0x1b, 0x72, 0xd1, 0xe3, 0x25, 0xd5, 0xf6, 0x72, 0x82, 0x8d, 0xc3, 0xb4, 0x77, - 0x60, 0x39, 0xe2, 0x3e, 0x6a, 0x9e, 0x50, 0x5c, 0x29, 0x72, 0xc8, 0xee, 0x4d, 0xc9, 0xca, 0x14, - 0x0f, 0x50, 0x06, 0xcf, 0x15, 0xcb, 0x6a, 0x1f, 0x5f, 0xa2, 0xab, 0x90, 0x0b, 0x9c, 0x9e, 0x6b, - 0xb1, 0x91, 0x4f, 0xa4, 0xf2, 0x62, 0x03, 0xf7, 0x92, 0x31, 0x23, 0x2e, 0x5e, 0x72, 0xa1, 0xb4, - 0xd8, 0xa0, 0x6d, 0xc0, 0x6b, 0xd1, 0xc2, 0x8c, 0xb3, 0x08, 0x95, 0x69, 0x91, 0xab, 0x15, 0x7a, - 0xea, 0x3f, 0x2a, 0x90, 0x16, 0x17, 0x63, 0x82, 0x06, 0xe5, 0x7c, 0x1a, 0x12, 0xf3, 0x68, 0x48, - 0x5e, 0x9c, 0x86, 0x2d, 0x80, 0xa8, 0xcc, 0xa0, 0xac, 0xd6, 0x92, 0xeb, 0xf9, 0xcd, 0x2b, 0xb3, - 0x89, 0x44, 0x89, 0x2d, 0xa7, 0x27, 0xef, 0xfd, 0x44, 0x50, 0xfd, 0x57, 0x05, 0x72, 0x91, 0x5f, - 0xdb, 0x82, 0x62, 0x58, 0x97, 0x79, 0x34, 0xb0, 0x7a, 0x52, 0x8a, 0xab, 0x73, 0x8b, 0xfb, 0x78, - 0x60, 0xf5, 0x8c, 0xbc, 0xac, 0x87, 0x2f, 0xce, 0xa7, 0x35, 0x31, 0x87, 0xd6, 0x29, 0x1d, 0x25, - 0x2f, 0xa6, 0xa3, 0x29, 0xc6, 0xd5, 0x33, 0x8c, 0xd7, 0xff, 0x50, 0x60, 0x71, 0x6f, 0x8c, 0xe5, - 0xdb, 0xff, 0x25, 0x55, 0xf7, 0xa5, 0xb6, 0x6c, 0x62, 0x9b, 0x33, 0x9c, 0x5d, 0x9b, 0xcd, 0x38, - 0x5d, 0x73, 0xcc, 0x9d, 0x16, 0x66, 0x69, 0xc5, 0x1c, 0x7e, 0x9f, 0x80, 0xe5, 0x19, 0xfc, 0xff, - 0x8f, 0xcb, 0xe9, 0xdb, 0x9b, 0x7a, 0xc9, 0xdb, 0x9b, 0x9e, 0x7b, 0x7b, 0xbf, 0x4b, 0x40, 0xb6, - 0x89, 0xaf, 0xb4, 0x35, 0xf8, 0x37, 0xde, 0xde, 0x2b, 0x90, 0xf3, 0xe8, 0xc0, 0x14, 0x1e, 0x15, - 0x3d, 0x59, 0x8f, 0x0e, 0x8c, 0x19, 0x99, 0xa5, 0x5e, 0xd1, 0xc3, 0x9c, 0x7e, 0x05, 0x24, 0x64, - 0xce, 0x5e, 0x28, 0x1f, 0x0a, 0xa2, 0x15, 0x72, 0x6a, 0xba, 0xc1, 0x7b, 0x80, 0x63, 0x98, 0x32, - 0x3b, 0xe5, 0x89, 0xb2, 0x05, 0xd2, 0x90, 0x38, 0x1e, 0x21, 0x86, 0x0c, 0x39, 0xb8, 0x95, 0xe7, - 0xbd, 0x58, 0x86, 0xc4, 0xd5, 0xbf, 0x52, 0x00, 0xee, 0xf0, 0xce, 0xe2, 0x79, 0xf9, 0xbc, 0x13, - 0x60, 0x09, 0xe6, 0xd4, 0xce, 0xd5, 0x79, 0xa4, 0xc9, 0xfd, 0x0b, 0xc1, 0x64, 0xdd, 0x3b, 0x50, - 0x8c, 0xb5, 0x1d, 0x90, 0xb0, 0x98, 0x73, 0x92, 0x44, 0x63, 0x48, 0x8b, 0x30, 0xa3, 0x70, 0x3c, - 0xb1, 0xaa, 0xff, 0xa4, 0x40, 0x0e, 0x6b, 0x6a, 0x10, 0x66, 0x4d, 0x71, 0xa8, 0x5c, 0x9c, 0xc3, - 0x55, 0x00, 0x91, 0x26, 0x70, 0x1e, 0x12, 0xa9, 0xac, 0x1c, 0x5a, 0x5a, 0xce, 0x43, 0xa2, 0xbd, - 0x1f, 0x35, 0x3c, 0xf9, 0xf7, 0x0d, 0x97, 0x2f, 0x46, 0xd8, 0xf6, 0x4b, 0x90, 0x71, 0x47, 0x43, - 0x93, 0x0f, 0x1f, 0xaa, 0x50, 0xab, 0x3b, 0x1a, 0xb6, 0xc7, 0x41, 0xfd, 0x73, 0xc8, 0xb4, 0xc7, - 0x38, 0x88, 0x73, 0x89, 0xfa, 0x94, 0xca, 0xe9, 0x4f, 0x4c, 0xdd, 0x59, 0x6e, 0xc0, 0x61, 0x47, - 0x03, 0x95, 0x8f, 0x79, 0xe1, 0xdf, 0x02, 0xfe, 0xad, 0xe9, 0x2f, 0x39, 0xe2, 0xcb, 0xe1, 0xfe, - 0xfa, 0xcf, 0x0a, 0x14, 0xa7, 0x6e, 0x92, 0xf6, 0x2e, 0x5c, 0x6a, 0xed, 0xdf, 0x3a, 0xd8, 0xdb, - 0x35, 0x1b, 0xad, 0x5b, 0x66, 0xfb, 0xb3, 0xe6, 0x9e, 0x79, 0xf7, 0xe0, 0x93, 0x83, 0xc3, 0x4f, - 0x0f, 0x4a, 0x0b, 0x95, 0xa5, 0x47, 0x4f, 0x6a, 0xf9, 0xbb, 0xee, 0x03, 0x97, 0x7e, 0xe1, 0xce, - 0x43, 0x37, 0x8d, 0xbd, 0x7b, 0x87, 0xed, 0xbd, 0x92, 0x22, 0xd0, 0x4d, 0x9f, 0x1c, 0x53, 0x46, - 0x10, 0x7d, 0x03, 0x2e, 0x9f, 0x83, 0xde, 0x39, 0x6c, 0x34, 0xf6, 0xdb, 0xa5, 0x44, 0x65, 0xf9, - 0xd1, 0x93, 0x5a, 0xb1, 0xe9, 0x13, 0xa1, 0x32, 0x8c, 0xd0, 0xa1, 0x3c, 0x1b, 0x71, 0xd8, 0x3c, - 0x6c, 0x6d, 0xdd, 0x29, 0xd5, 0x2a, 0xa5, 0x47, 0x4f, 0x6a, 0x85, 0xf0, 0xc9, 0xe0, 0xf8, 0x4a, - 0xf6, 0xcb, 0xaf, 0xab, 0x0b, 0xdf, 0x7e, 0x53, 0x55, 0xb6, 0x1b, 0x4f, 0x4f, 0xab, 0xca, 0xb3, - 0xd3, 0xaa, 0xf2, 0xfb, 0x69, 0x55, 0x79, 0xfc, 0xa2, 0xba, 0xf0, 0xec, 0x45, 0x75, 0xe1, 0x97, - 0x17, 0xd5, 0x85, 0xfb, 0x37, 0x7b, 0x0e, 0xeb, 0x8f, 0x3a, 0x7a, 0x97, 0x0e, 0x37, 0xba, 0x74, - 0x48, 0x58, 0xe7, 0x88, 0xc5, 0x1f, 0xe2, 0x6f, 0xe2, 0xd9, 0xbf, 0x6e, 0x9d, 0x34, 0xda, 0x6f, - 0xfe, 0x15, 0x00, 0x00, 0xff, 0xff, 0x8c, 0xb6, 0xa1, 0x4e, 0x7b, 0x0e, 0x00, 0x00, + proto.RegisterEnum("cometbft.types.v1.SignedMsgType", SignedMsgType_name, SignedMsgType_value) + proto.RegisterType((*PartSetHeader)(nil), "cometbft.types.v1.PartSetHeader") + proto.RegisterType((*Part)(nil), "cometbft.types.v1.Part") + proto.RegisterType((*BlockID)(nil), "cometbft.types.v1.BlockID") + proto.RegisterType((*Header)(nil), "cometbft.types.v1.Header") + proto.RegisterType((*Data)(nil), "cometbft.types.v1.Data") + proto.RegisterType((*Vote)(nil), "cometbft.types.v1.Vote") + proto.RegisterType((*Commit)(nil), "cometbft.types.v1.Commit") + proto.RegisterType((*CommitSig)(nil), "cometbft.types.v1.CommitSig") + proto.RegisterType((*ExtendedCommit)(nil), "cometbft.types.v1.ExtendedCommit") + proto.RegisterType((*ExtendedCommitSig)(nil), "cometbft.types.v1.ExtendedCommitSig") + proto.RegisterType((*Proposal)(nil), "cometbft.types.v1.Proposal") + proto.RegisterType((*SignedHeader)(nil), "cometbft.types.v1.SignedHeader") + proto.RegisterType((*LightBlock)(nil), "cometbft.types.v1.LightBlock") + proto.RegisterType((*BlockMeta)(nil), "cometbft.types.v1.BlockMeta") + proto.RegisterType((*TxProof)(nil), "cometbft.types.v1.TxProof") +} + +func init() { proto.RegisterFile("cometbft/types/v1/types.proto", fileDescriptor_8ea20b664d765b5f) } + +var fileDescriptor_8ea20b664d765b5f = []byte{ + // 1314 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x57, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xda, 0xeb, 0x7f, 0xcf, 0x76, 0xe2, 0x2c, 0x11, 0x75, 0xdc, 0xd6, 0x31, 0xe6, 0x5f, + 0x28, 0xc8, 0x6e, 0x02, 0x08, 0xb8, 0x20, 0xd5, 0x49, 0xda, 0x46, 0x34, 0x89, 0xb5, 0x76, 0x8b, + 0x80, 0xc3, 0x6a, 0xed, 0x9d, 0xd8, 0xab, 0xda, 0x3b, 0xab, 0xdd, 0xb1, 0x49, 0xfa, 0x09, 0x50, + 0x4f, 0x3d, 0x72, 0xe9, 0x09, 0x0e, 0x7c, 0x81, 0x1e, 0xb8, 0x22, 0x0e, 0x3d, 0xf6, 0x06, 0xa7, + 0x82, 0x92, 0x0b, 0x1f, 0x03, 0xcd, 0x9b, 0xd9, 0xdd, 0x38, 0xb6, 0xd5, 0x88, 0x56, 0x20, 0x71, + 0x9b, 0x79, 0xef, 0xf7, 0xde, 0xbc, 0x7d, 0xbf, 0xdf, 0x8c, 0xde, 0xc2, 0xd5, 0x2e, 0x1d, 0x12, + 0xd6, 0x39, 0x64, 0x75, 0x76, 0xec, 0x12, 0xbf, 0x3e, 0xde, 0x10, 0x8b, 0x9a, 0xeb, 0x51, 0x46, + 0xb5, 0xe5, 0xc0, 0x5d, 0x13, 0xd6, 0xf1, 0x46, 0xa9, 0x1c, 0x46, 0x74, 0xbd, 0x63, 0x97, 0x51, + 0x1e, 0xe2, 0x7a, 0x94, 0x1e, 0x8a, 0x90, 0xd2, 0x1b, 0xd3, 0x19, 0xc7, 0xe6, 0xc0, 0xb6, 0x4c, + 0x46, 0x3d, 0x09, 0x59, 0x0b, 0x21, 0x63, 0xe2, 0xf9, 0x36, 0x75, 0xce, 0x1d, 0x5b, 0x5a, 0xe9, + 0xd1, 0x1e, 0xc5, 0x65, 0x9d, 0xaf, 0x82, 0xb0, 0x1e, 0xa5, 0xbd, 0x01, 0xa9, 0xe3, 0xae, 0x33, + 0x3a, 0xac, 0x33, 0x7b, 0x48, 0x7c, 0x66, 0x0e, 0x5d, 0x01, 0xa8, 0x7e, 0x06, 0xf9, 0xa6, 0xe9, + 0xb1, 0x16, 0x61, 0xb7, 0x89, 0x69, 0x11, 0x4f, 0x5b, 0x81, 0x04, 0xa3, 0xcc, 0x1c, 0x14, 0x95, + 0x8a, 0xb2, 0x9e, 0xd7, 0xc5, 0x46, 0xd3, 0x40, 0xed, 0x9b, 0x7e, 0xbf, 0x18, 0xab, 0x28, 0xeb, + 0x39, 0x1d, 0xd7, 0x55, 0x1b, 0x54, 0x1e, 0xca, 0x23, 0x6c, 0xc7, 0x22, 0x47, 0x41, 0x04, 0x6e, + 0xb8, 0xb5, 0x73, 0xcc, 0x88, 0x2f, 0x43, 0xc4, 0x46, 0xfb, 0x18, 0x12, 0xf8, 0xe1, 0xc5, 0x78, + 0x45, 0x59, 0xcf, 0x6e, 0xae, 0xd6, 0xc2, 0x66, 0x89, 0xce, 0xd4, 0xc6, 0x1b, 0xb5, 0x26, 0x07, + 0x34, 0xd4, 0xa7, 0xcf, 0xd7, 0x16, 0x74, 0x81, 0xae, 0x0e, 0x21, 0xd5, 0x18, 0xd0, 0xee, 0xfd, + 0xdd, 0xed, 0xb0, 0x12, 0x25, 0xaa, 0x44, 0xdb, 0x87, 0x25, 0xd7, 0xf4, 0x98, 0xe1, 0x13, 0x66, + 0xf4, 0xf1, 0x33, 0xf0, 0xd4, 0xec, 0x66, 0xa5, 0x36, 0x45, 0x46, 0x6d, 0xe2, 0x73, 0xe5, 0x31, + 0x79, 0xf7, 0xac, 0xb1, 0xfa, 0x97, 0x0a, 0x49, 0xd9, 0x8e, 0xcf, 0x21, 0x25, 0x1b, 0x8e, 0x27, + 0x66, 0x37, 0xcb, 0x51, 0x4a, 0xe9, 0xe0, 0x49, 0xb7, 0xa8, 0xe3, 0x13, 0xc7, 0x1f, 0xf9, 0x32, + 0x61, 0x10, 0xa4, 0xbd, 0x03, 0xe9, 0x6e, 0xdf, 0xb4, 0x1d, 0xc3, 0xb6, 0xb0, 0xa6, 0x4c, 0x23, + 0x7b, 0xf2, 0x7c, 0x2d, 0xb5, 0xc5, 0x6d, 0xbb, 0xdb, 0x7a, 0x0a, 0x9d, 0xbb, 0x96, 0xf6, 0x3a, + 0x24, 0xfb, 0xc4, 0xee, 0xf5, 0x19, 0x76, 0x26, 0xae, 0xcb, 0x9d, 0xf6, 0x29, 0xa8, 0x9c, 0xb2, + 0xa2, 0x8a, 0x87, 0x97, 0x6a, 0x82, 0xcf, 0x5a, 0xc0, 0x67, 0xad, 0x1d, 0xf0, 0xd9, 0x48, 0xf3, + 0x83, 0x1f, 0xfd, 0xb1, 0xa6, 0xe8, 0x18, 0xa1, 0x6d, 0x43, 0x7e, 0x60, 0xfa, 0xcc, 0xe8, 0xf0, + 0xc6, 0xf1, 0xe3, 0x13, 0x32, 0xc5, 0x74, 0x4b, 0x64, 0x6f, 0x65, 0xed, 0x59, 0x1e, 0x26, 0x4c, + 0x96, 0xb6, 0x0e, 0x05, 0xcc, 0xd2, 0xa5, 0xc3, 0xa1, 0xcd, 0x0c, 0x6c, 0x7d, 0x12, 0x5b, 0xbf, + 0xc8, 0xed, 0x5b, 0x68, 0xbe, 0xcd, 0x49, 0xb8, 0x0c, 0x19, 0xcb, 0x64, 0xa6, 0x80, 0xa4, 0x10, + 0x92, 0xe6, 0x06, 0x74, 0xbe, 0x0b, 0x4b, 0xa1, 0xa2, 0x7d, 0x01, 0x49, 0x8b, 0x2c, 0x91, 0x19, + 0x81, 0xd7, 0x61, 0xc5, 0x21, 0x47, 0xcc, 0x38, 0x8f, 0xce, 0x20, 0x5a, 0xe3, 0xbe, 0x7b, 0x93, + 0x11, 0x6f, 0xc3, 0x62, 0x37, 0xe8, 0xbe, 0xc0, 0x02, 0x62, 0xf3, 0xa1, 0x15, 0x61, 0xab, 0x90, + 0x36, 0x5d, 0x57, 0x00, 0xb2, 0x08, 0x48, 0x99, 0xae, 0x8b, 0xae, 0x6b, 0xb0, 0x8c, 0xdf, 0xe8, + 0x11, 0x7f, 0x34, 0x60, 0x32, 0x49, 0x0e, 0x31, 0x4b, 0xdc, 0xa1, 0x0b, 0x3b, 0x62, 0xdf, 0x84, + 0x3c, 0x19, 0xdb, 0x16, 0x71, 0xba, 0x44, 0xe0, 0xf2, 0x88, 0xcb, 0x05, 0x46, 0x04, 0xbd, 0x07, + 0x05, 0xd7, 0xa3, 0x2e, 0xf5, 0x89, 0x67, 0x98, 0x96, 0xe5, 0x11, 0xdf, 0x2f, 0x2e, 0x8a, 0x7c, + 0x81, 0xfd, 0x86, 0x30, 0x57, 0x8b, 0xa0, 0x6e, 0x9b, 0xcc, 0xd4, 0x0a, 0x10, 0x67, 0x47, 0x7e, + 0x51, 0xa9, 0xc4, 0xd7, 0x73, 0x3a, 0x5f, 0x56, 0x7f, 0x8e, 0x83, 0x7a, 0x8f, 0x32, 0xa2, 0x7d, + 0x04, 0x2a, 0x67, 0x0a, 0xf5, 0xb7, 0x38, 0x53, 0xd2, 0x2d, 0xbb, 0xe7, 0x10, 0x6b, 0xcf, 0xef, + 0xb5, 0x8f, 0x5d, 0xa2, 0x23, 0xfa, 0x8c, 0xa0, 0x62, 0x13, 0x82, 0x5a, 0x81, 0x84, 0x47, 0x47, + 0x8e, 0x85, 0x3a, 0x4b, 0xe8, 0x62, 0xa3, 0xdd, 0x84, 0x74, 0xa8, 0x13, 0xf5, 0x85, 0x3a, 0x59, + 0xe2, 0x3a, 0xe1, 0x32, 0x96, 0x06, 0x3d, 0xd5, 0x91, 0x72, 0x69, 0x40, 0x26, 0x7c, 0x61, 0x42, + 0xc1, 0x5d, 0x44, 0xb3, 0x51, 0x98, 0xf6, 0x3e, 0x2c, 0x87, 0xec, 0x87, 0xed, 0x13, 0x9a, 0x2b, + 0x84, 0x0e, 0xd9, 0xbf, 0x09, 0x61, 0x19, 0xe2, 0x19, 0x4a, 0xe1, 0x87, 0x45, 0xc2, 0xda, 0xc5, + 0xf7, 0xe8, 0x0a, 0x64, 0x7c, 0xbb, 0xe7, 0x98, 0x6c, 0xe4, 0x11, 0xa9, 0xbd, 0xc8, 0xc0, 0xbd, + 0xe4, 0x88, 0x11, 0x07, 0x2f, 0xba, 0xd0, 0x5a, 0x64, 0xd0, 0xea, 0xf0, 0x5a, 0xb8, 0x31, 0xa2, + 0x2c, 0x42, 0x67, 0x5a, 0xe8, 0x6a, 0x05, 0x9e, 0xea, 0x2f, 0x0a, 0x24, 0xc5, 0xd5, 0x38, 0xc3, + 0x83, 0x32, 0x9b, 0x87, 0xd8, 0x3c, 0x1e, 0xe2, 0x2f, 0xc5, 0x03, 0x84, 0x75, 0xfa, 0x45, 0xb5, + 0x12, 0x5f, 0xcf, 0x6e, 0x5e, 0x99, 0x91, 0x49, 0x14, 0xd9, 0xb2, 0x7b, 0xf2, 0xee, 0x9f, 0x89, + 0xaa, 0x3e, 0x57, 0x20, 0x13, 0xfa, 0xb5, 0x06, 0xe4, 0x83, 0xca, 0x8c, 0xc3, 0x81, 0xd9, 0x93, + 0x72, 0x2c, 0xcf, 0x2f, 0xef, 0xe6, 0xc0, 0xec, 0xe9, 0x59, 0x59, 0x11, 0xdf, 0xcc, 0x66, 0x36, + 0x36, 0x87, 0xd9, 0x09, 0x29, 0xc5, 0xff, 0x99, 0x94, 0x26, 0x48, 0x57, 0xcf, 0x91, 0x5e, 0x3d, + 0x55, 0x60, 0x71, 0x87, 0x93, 0x67, 0x11, 0xeb, 0x3f, 0x65, 0xeb, 0x1b, 0xa9, 0x2f, 0x8b, 0x58, + 0xc6, 0x14, 0x6d, 0x6f, 0xcd, 0x48, 0x39, 0x59, 0x75, 0x44, 0x9f, 0x16, 0xa4, 0x69, 0x45, 0x34, + 0x3e, 0x89, 0xc1, 0xf2, 0x14, 0xfe, 0x7f, 0x48, 0xe7, 0xe4, 0x1d, 0x4e, 0x5c, 0xf0, 0x0e, 0x27, + 0xe7, 0xde, 0xe1, 0x27, 0x31, 0x48, 0x37, 0xf1, 0xb5, 0x36, 0x07, 0xff, 0xca, 0x1b, 0x7c, 0x19, + 0x32, 0x2e, 0x1d, 0x18, 0xc2, 0xa3, 0xa2, 0x27, 0xed, 0xd2, 0x81, 0x3e, 0x25, 0xb5, 0xc4, 0xab, + 0x7a, 0xa0, 0x93, 0xaf, 0x80, 0x86, 0xd4, 0xf9, 0x5b, 0xc5, 0x20, 0x27, 0x7a, 0x21, 0x27, 0xa8, + 0x0d, 0xde, 0x04, 0x9c, 0xc9, 0x94, 0xf3, 0x33, 0x5f, 0x58, 0xb7, 0x80, 0xea, 0x12, 0xc8, 0x43, + 0xc4, 0xbc, 0x21, 0xc7, 0xb8, 0xd5, 0xb9, 0x2f, 0x97, 0x2e, 0x81, 0xd5, 0xef, 0x15, 0x80, 0x3b, + 0xbc, 0xb9, 0xf8, 0xc5, 0x7c, 0xf8, 0xf1, 0xb1, 0x08, 0x63, 0xe2, 0xec, 0xb5, 0xb9, 0xc4, 0xc9, + 0x0a, 0x72, 0xfe, 0xd9, 0xd2, 0xb7, 0x21, 0x1f, 0x09, 0xdc, 0x27, 0x41, 0x39, 0xb3, 0xb2, 0x84, + 0x43, 0x49, 0x8b, 0x30, 0x3d, 0x37, 0x3e, 0xb3, 0xab, 0xfe, 0xaa, 0x40, 0x06, 0xab, 0xda, 0x23, + 0xcc, 0x9c, 0x20, 0x52, 0x79, 0x09, 0x22, 0xaf, 0x02, 0x88, 0x3c, 0xbe, 0xfd, 0x80, 0x48, 0x7d, + 0x65, 0xd0, 0xd2, 0xb2, 0x1f, 0x10, 0xed, 0x93, 0xb0, 0xeb, 0xf1, 0x17, 0x74, 0x5d, 0x3e, 0x1d, + 0x41, 0xef, 0x2f, 0x41, 0xca, 0x19, 0x0d, 0x0d, 0x3e, 0x8c, 0xa8, 0x42, 0xb4, 0xce, 0x68, 0xd8, + 0x3e, 0xf2, 0xab, 0xf7, 0x21, 0xd5, 0x3e, 0xc2, 0xd9, 0x9c, 0x2b, 0xd5, 0xa3, 0x54, 0x4e, 0x83, + 0x62, 0x10, 0x4f, 0x73, 0x03, 0x0e, 0x3f, 0x1a, 0xa8, 0x7c, 0xec, 0x0b, 0x7e, 0x15, 0xf8, 0x5a, + 0xab, 0x5f, 0x74, 0xec, 0x97, 0x03, 0xff, 0xb5, 0xdf, 0x14, 0xc8, 0x4f, 0xdc, 0x28, 0xed, 0x03, + 0xb8, 0xd4, 0xda, 0xbd, 0xb5, 0xbf, 0xb3, 0x6d, 0xec, 0xb5, 0x6e, 0x19, 0xed, 0xaf, 0x9a, 0x3b, + 0xc6, 0xdd, 0xfd, 0x2f, 0xf6, 0x0f, 0xbe, 0xdc, 0x2f, 0x2c, 0x94, 0x96, 0x1e, 0x3e, 0xae, 0x64, + 0xef, 0x3a, 0xf7, 0x1d, 0xfa, 0xad, 0x33, 0x0f, 0xdd, 0xd4, 0x77, 0xee, 0x1d, 0xb4, 0x77, 0x0a, + 0x8a, 0x40, 0x37, 0x3d, 0x32, 0xa6, 0x8c, 0x20, 0xfa, 0x3a, 0xac, 0xce, 0x40, 0x6f, 0x1d, 0xec, + 0xed, 0xed, 0xb6, 0x0b, 0xb1, 0xd2, 0xf2, 0xc3, 0xc7, 0x95, 0x7c, 0xd3, 0x23, 0x42, 0x6a, 0x18, + 0x51, 0x83, 0xe2, 0x74, 0xc4, 0x41, 0xf3, 0xa0, 0x75, 0xe3, 0x4e, 0xa1, 0x52, 0x2a, 0x3c, 0x7c, + 0x5c, 0xc9, 0x05, 0x6f, 0x07, 0xc7, 0x97, 0xd2, 0xdf, 0xfd, 0x50, 0x5e, 0xf8, 0xe9, 0xc7, 0xb2, + 0xd2, 0xb8, 0xf3, 0xf4, 0xa4, 0xac, 0x3c, 0x3b, 0x29, 0x2b, 0x7f, 0x9e, 0x94, 0x95, 0x47, 0xa7, + 0xe5, 0x85, 0x67, 0xa7, 0xe5, 0x85, 0xdf, 0x4f, 0xcb, 0x0b, 0x5f, 0x6f, 0xf6, 0x6c, 0xd6, 0x1f, + 0x75, 0x78, 0x6f, 0xea, 0xd1, 0x0f, 0x63, 0xb0, 0x30, 0x5d, 0xbb, 0x3e, 0xf5, 0x9b, 0xd8, 0x49, + 0xe2, 0x9d, 0xfd, 0xf0, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdf, 0x98, 0x74, 0x84, 0x94, 0x0e, + 0x00, 0x00, } func (m *PartSetHeader) Marshal() (dAtA []byte, err error) { @@ -5264,7 +5273,7 @@ func (m *TxProof) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Proof == nil { - m.Proof = &crypto.Proof{} + m.Proof = &v1.Proof{} } if err := m.Proof.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err diff --git a/proto/tendermint/types/validator.pb.go b/api/cometbft/types/v1/validator.pb.go similarity index 79% rename from proto/tendermint/types/validator.pb.go rename to api/cometbft/types/v1/validator.pb.go index 45faec7e6ea..69dc036cd8b 100644 --- a/proto/tendermint/types/validator.pb.go +++ b/api/cometbft/types/v1/validator.pb.go @@ -1,11 +1,11 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/types/validator.proto +// source: cometbft/types/v1/validator.proto -package types +package v1 import ( fmt "fmt" - crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" io "io" @@ -28,10 +28,14 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type BlockIDFlag int32 const ( + // Indicates an error condition BlockIDFlagUnknown BlockIDFlag = 0 - BlockIDFlagAbsent BlockIDFlag = 1 - BlockIDFlagCommit BlockIDFlag = 2 - BlockIDFlagNil BlockIDFlag = 3 + // The vote was not received + BlockIDFlagAbsent BlockIDFlag = 1 + // Voted for the block that received the majority + BlockIDFlagCommit BlockIDFlag = 2 + // Voted for nil + BlockIDFlagNil BlockIDFlag = 3 ) var BlockIDFlag_name = map[int32]string{ @@ -53,9 +57,10 @@ func (x BlockIDFlag) String() string { } func (BlockIDFlag) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_4e92274df03d3088, []int{0} + return fileDescriptor_20d37f2fd54e559e, []int{0} } +// ValidatorSet defines a set of validators. type ValidatorSet struct { Validators []*Validator `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"` Proposer *Validator `protobuf:"bytes,2,opt,name=proposer,proto3" json:"proposer,omitempty"` @@ -66,7 +71,7 @@ func (m *ValidatorSet) Reset() { *m = ValidatorSet{} } func (m *ValidatorSet) String() string { return proto.CompactTextString(m) } func (*ValidatorSet) ProtoMessage() {} func (*ValidatorSet) Descriptor() ([]byte, []int) { - return fileDescriptor_4e92274df03d3088, []int{0} + return fileDescriptor_20d37f2fd54e559e, []int{0} } func (m *ValidatorSet) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -116,18 +121,19 @@ func (m *ValidatorSet) GetTotalVotingPower() int64 { return 0 } +// Validator represents a node participating in the consensus protocol. type Validator struct { - Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - PubKey crypto.PublicKey `protobuf:"bytes,2,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` - VotingPower int64 `protobuf:"varint,3,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` - ProposerPriority int64 `protobuf:"varint,4,opt,name=proposer_priority,json=proposerPriority,proto3" json:"proposer_priority,omitempty"` + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + PubKey v1.PublicKey `protobuf:"bytes,2,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + VotingPower int64 `protobuf:"varint,3,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` + ProposerPriority int64 `protobuf:"varint,4,opt,name=proposer_priority,json=proposerPriority,proto3" json:"proposer_priority,omitempty"` } func (m *Validator) Reset() { *m = Validator{} } func (m *Validator) String() string { return proto.CompactTextString(m) } func (*Validator) ProtoMessage() {} func (*Validator) Descriptor() ([]byte, []int) { - return fileDescriptor_4e92274df03d3088, []int{1} + return fileDescriptor_20d37f2fd54e559e, []int{1} } func (m *Validator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -163,11 +169,11 @@ func (m *Validator) GetAddress() []byte { return nil } -func (m *Validator) GetPubKey() crypto.PublicKey { +func (m *Validator) GetPubKey() v1.PublicKey { if m != nil { return m.PubKey } - return crypto.PublicKey{} + return v1.PublicKey{} } func (m *Validator) GetVotingPower() int64 { @@ -184,16 +190,19 @@ func (m *Validator) GetProposerPriority() int64 { return 0 } +// SimpleValidator is a Validator, which is serialized and hashed in consensus. +// Address is removed because it's redundant with the pubkey. +// Proposer priority is removed because it changes every round. type SimpleValidator struct { - PubKey *crypto.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` - VotingPower int64 `protobuf:"varint,2,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` + PubKey *v1.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` + VotingPower int64 `protobuf:"varint,2,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` } func (m *SimpleValidator) Reset() { *m = SimpleValidator{} } func (m *SimpleValidator) String() string { return proto.CompactTextString(m) } func (*SimpleValidator) ProtoMessage() {} func (*SimpleValidator) Descriptor() ([]byte, []int) { - return fileDescriptor_4e92274df03d3088, []int{2} + return fileDescriptor_20d37f2fd54e559e, []int{2} } func (m *SimpleValidator) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -222,7 +231,7 @@ func (m *SimpleValidator) XXX_DiscardUnknown() { var xxx_messageInfo_SimpleValidator proto.InternalMessageInfo -func (m *SimpleValidator) GetPubKey() *crypto.PublicKey { +func (m *SimpleValidator) GetPubKey() *v1.PublicKey { if m != nil { return m.PubKey } @@ -237,48 +246,48 @@ func (m *SimpleValidator) GetVotingPower() int64 { } func init() { - proto.RegisterEnum("tendermint.types.BlockIDFlag", BlockIDFlag_name, BlockIDFlag_value) - proto.RegisterType((*ValidatorSet)(nil), "tendermint.types.ValidatorSet") - proto.RegisterType((*Validator)(nil), "tendermint.types.Validator") - proto.RegisterType((*SimpleValidator)(nil), "tendermint.types.SimpleValidator") -} - -func init() { proto.RegisterFile("tendermint/types/validator.proto", fileDescriptor_4e92274df03d3088) } - -var fileDescriptor_4e92274df03d3088 = []byte{ - // 502 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xcd, 0x6e, 0xd3, 0x40, - 0x14, 0x85, 0x3d, 0x4d, 0xd5, 0x96, 0x49, 0x04, 0xce, 0xa8, 0x45, 0x91, 0xa9, 0x8c, 0xe9, 0x2a, - 0xfc, 0xc8, 0x16, 0x54, 0x88, 0x45, 0x57, 0x49, 0x4a, 0x51, 0x94, 0xc4, 0x89, 0x92, 0xb6, 0x48, - 0x6c, 0xac, 0x38, 0x19, 0xcc, 0xc8, 0x3f, 0x33, 0x1a, 0x4f, 0x52, 0xf9, 0x0d, 0x50, 0x56, 0xbc, - 0x40, 0x56, 0xb0, 0x60, 0xcd, 0x53, 0x74, 0xd9, 0x1d, 0xac, 0x10, 0x4a, 0x5e, 0x04, 0xc5, 0x6e, - 0x62, 0xb7, 0x01, 0x75, 0x77, 0x7d, 0xcf, 0x39, 0xf7, 0x7e, 0x1e, 0xe9, 0x42, 0x4d, 0xe0, 0x60, - 0x88, 0xb9, 0x4f, 0x02, 0x61, 0x88, 0x88, 0xe1, 0xd0, 0x18, 0xf7, 0x3d, 0x32, 0xec, 0x0b, 0xca, - 0x75, 0xc6, 0xa9, 0xa0, 0x48, 0x4e, 0x1d, 0x7a, 0xec, 0x50, 0x76, 0x1d, 0xea, 0xd0, 0x58, 0x34, - 0x16, 0x55, 0xe2, 0x53, 0xf6, 0x33, 0x93, 0x06, 0x3c, 0x62, 0x82, 0x1a, 0x2e, 0x8e, 0xc2, 0x44, - 0x3d, 0xf8, 0x01, 0x60, 0xe1, 0x7c, 0x39, 0xb9, 0x87, 0x05, 0x3a, 0x82, 0x70, 0xb5, 0x29, 0x2c, - 0x01, 0x2d, 0x57, 0xce, 0xbf, 0x7a, 0xa4, 0xdf, 0xde, 0xa5, 0xaf, 0x32, 0xdd, 0x8c, 0x1d, 0xbd, - 0x81, 0x3b, 0x8c, 0x53, 0x46, 0x43, 0xcc, 0x4b, 0x1b, 0x1a, 0xb8, 0x2b, 0xba, 0x32, 0xa3, 0x17, - 0x10, 0x09, 0x2a, 0xfa, 0x9e, 0x35, 0xa6, 0x82, 0x04, 0x8e, 0xc5, 0xe8, 0x05, 0xe6, 0xa5, 0x9c, - 0x06, 0xca, 0xb9, 0xae, 0x1c, 0x2b, 0xe7, 0xb1, 0xd0, 0x59, 0xf4, 0x17, 0xd0, 0xf7, 0x56, 0x53, - 0x50, 0x09, 0x6e, 0xf7, 0x87, 0x43, 0x8e, 0xc3, 0x05, 0x2e, 0x28, 0x17, 0xba, 0xcb, 0x4f, 0x74, - 0x04, 0xb7, 0xd9, 0xc8, 0xb6, 0x5c, 0x1c, 0x5d, 0xd3, 0xec, 0x67, 0x69, 0x92, 0xc7, 0xd0, 0x3b, - 0x23, 0xdb, 0x23, 0x83, 0x06, 0x8e, 0xaa, 0x9b, 0x97, 0xbf, 0x1f, 0x4b, 0xdd, 0x2d, 0x36, 0xb2, - 0x1b, 0x38, 0x42, 0x4f, 0x60, 0xe1, 0x1f, 0x30, 0xf9, 0x71, 0xca, 0x81, 0x9e, 0xc3, 0xe2, 0xf2, - 0x0f, 0x2c, 0xc6, 0x09, 0xe5, 0x44, 0x44, 0xa5, 0xcd, 0x04, 0x7a, 0x29, 0x74, 0xae, 0xfb, 0x07, - 0x2e, 0x7c, 0xd0, 0x23, 0x3e, 0xf3, 0x70, 0x4a, 0xfe, 0x3a, 0xe5, 0x03, 0x77, 0xf3, 0xfd, 0x97, - 0x6c, 0x63, 0x8d, 0xec, 0xd9, 0x4f, 0x00, 0xf3, 0x55, 0x8f, 0x0e, 0xdc, 0xfa, 0xf1, 0x89, 0xd7, - 0x77, 0xd0, 0x4b, 0xb8, 0x57, 0x6d, 0xb6, 0x6b, 0x0d, 0xab, 0x7e, 0x6c, 0x9d, 0x34, 0x2b, 0xef, - 0xac, 0x33, 0xb3, 0x61, 0xb6, 0xdf, 0x9b, 0xb2, 0xa4, 0x3c, 0x9c, 0x4c, 0x35, 0x94, 0xf1, 0x9e, - 0x05, 0x6e, 0x40, 0x2f, 0x02, 0x64, 0xc0, 0xdd, 0x9b, 0x91, 0x4a, 0xb5, 0xf7, 0xd6, 0x3c, 0x95, - 0x81, 0xb2, 0x37, 0x99, 0x6a, 0xc5, 0x4c, 0xa2, 0x62, 0x87, 0x38, 0x10, 0xeb, 0x81, 0x5a, 0xbb, - 0xd5, 0xaa, 0x9f, 0xca, 0x1b, 0x6b, 0x81, 0x1a, 0xf5, 0x7d, 0x22, 0xd0, 0x53, 0x58, 0xbc, 0x19, - 0x30, 0xeb, 0x4d, 0x39, 0xa7, 0xa0, 0xc9, 0x54, 0xbb, 0x9f, 0x71, 0x9b, 0xc4, 0x53, 0x76, 0x3e, - 0x7f, 0x55, 0xa5, 0xef, 0xdf, 0x54, 0x50, 0x6d, 0x5d, 0xce, 0x54, 0x70, 0x35, 0x53, 0xc1, 0x9f, - 0x99, 0x0a, 0xbe, 0xcc, 0x55, 0xe9, 0x6a, 0xae, 0x4a, 0xbf, 0xe6, 0xaa, 0xf4, 0xe1, 0xd0, 0x21, - 0xe2, 0xd3, 0xc8, 0xd6, 0x07, 0xd4, 0x37, 0x06, 0xd4, 0xc7, 0xc2, 0xfe, 0x28, 0xd2, 0x22, 0xb9, - 0x8b, 0xdb, 0x57, 0x65, 0x6f, 0xc5, 0xfd, 0xc3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbb, 0x8c, - 0xe3, 0x20, 0x70, 0x03, 0x00, 0x00, + proto.RegisterEnum("cometbft.types.v1.BlockIDFlag", BlockIDFlag_name, BlockIDFlag_value) + proto.RegisterType((*ValidatorSet)(nil), "cometbft.types.v1.ValidatorSet") + proto.RegisterType((*Validator)(nil), "cometbft.types.v1.Validator") + proto.RegisterType((*SimpleValidator)(nil), "cometbft.types.v1.SimpleValidator") +} + +func init() { proto.RegisterFile("cometbft/types/v1/validator.proto", fileDescriptor_20d37f2fd54e559e) } + +var fileDescriptor_20d37f2fd54e559e = []byte{ + // 507 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x4d, 0x6f, 0xda, 0x3e, + 0x1c, 0xc7, 0x63, 0xa8, 0xda, 0xfe, 0x0d, 0xfa, 0x0f, 0xac, 0x76, 0x42, 0xd1, 0x9a, 0xa5, 0x9c, + 0xd8, 0x83, 0x88, 0xe8, 0xa4, 0x69, 0x87, 0x5e, 0x08, 0x5d, 0x27, 0x04, 0x0d, 0x08, 0xda, 0x4e, + 0xda, 0x25, 0x4a, 0xc0, 0xcb, 0x2c, 0x42, 0x6c, 0x25, 0x26, 0x55, 0xde, 0xc1, 0xc4, 0x69, 0x6f, + 0x80, 0xd3, 0x76, 0xd8, 0x7d, 0x7b, 0x11, 0x3d, 0xf6, 0xb6, 0x9d, 0xa6, 0x09, 0xde, 0xc8, 0x94, + 0xd0, 0x24, 0x54, 0xd9, 0xb4, 0xdd, 0x1c, 0x7f, 0x1f, 0xfc, 0x89, 0xe5, 0x1f, 0x3c, 0x1c, 0xd1, + 0x29, 0xe6, 0xe6, 0x5b, 0xae, 0xf0, 0x80, 0x61, 0x4f, 0xf1, 0x1b, 0x8a, 0x6f, 0xd8, 0x64, 0x6c, + 0x70, 0xea, 0xd6, 0x99, 0x4b, 0x39, 0x45, 0xe5, 0xd8, 0x52, 0x8f, 0x2c, 0x75, 0xbf, 0x21, 0xee, + 0x59, 0xd4, 0xa2, 0x91, 0xaa, 0x84, 0xab, 0xb5, 0x51, 0x3c, 0x48, 0xba, 0x46, 0x6e, 0xc0, 0x38, + 0x0d, 0xcb, 0x26, 0x38, 0xf0, 0xd6, 0x72, 0xf5, 0x2b, 0x80, 0xc5, 0xcb, 0xb8, 0x7b, 0x88, 0x39, + 0x3a, 0x86, 0x30, 0x39, 0xcb, 0xab, 0x00, 0x39, 0x5f, 0x2b, 0x1c, 0x3d, 0xa8, 0x67, 0x4e, 0xab, + 0x27, 0xa1, 0xc1, 0x86, 0x1f, 0xbd, 0x80, 0xbb, 0xcc, 0xa5, 0x8c, 0x7a, 0xd8, 0xad, 0xe4, 0x64, + 0xf0, 0xd7, 0x6c, 0xe2, 0x46, 0x4f, 0x21, 0xe2, 0x94, 0x1b, 0xb6, 0xee, 0x53, 0x4e, 0x1c, 0x4b, + 0x67, 0xf4, 0x0a, 0xbb, 0x95, 0xbc, 0x0c, 0x6a, 0xf9, 0x41, 0x29, 0x52, 0x2e, 0x23, 0xa1, 0x1f, + 0xee, 0x57, 0xbf, 0x00, 0xf8, 0x5f, 0xd2, 0x82, 0x2a, 0x70, 0xc7, 0x18, 0x8f, 0x5d, 0xec, 0x85, + 0xc0, 0xa0, 0x56, 0x1c, 0xc4, 0x9f, 0xe8, 0x18, 0xee, 0xb0, 0x99, 0xa9, 0x4f, 0x70, 0x70, 0x8b, + 0x73, 0x90, 0xe2, 0xac, 0xef, 0x23, 0xe4, 0xe9, 0xcf, 0x4c, 0x9b, 0x8c, 0x3a, 0x38, 0x50, 0xb7, + 0xae, 0x7f, 0x3c, 0x14, 0x06, 0xdb, 0x6c, 0x66, 0x76, 0x70, 0x80, 0x0e, 0x61, 0xf1, 0x37, 0x34, + 0x05, 0x3f, 0x05, 0x41, 0x4f, 0x60, 0x39, 0xfe, 0x05, 0x9d, 0xb9, 0x84, 0xba, 0x84, 0x07, 0x95, + 0xad, 0x35, 0x75, 0x2c, 0xf4, 0x6f, 0xf7, 0xab, 0x36, 0xbc, 0x37, 0x24, 0x53, 0x66, 0xe3, 0x14, + 0xfd, 0x79, 0x0a, 0x08, 0xfe, 0x01, 0xf0, 0x8f, 0x68, 0xb9, 0x0c, 0xda, 0xe3, 0x6f, 0x00, 0x16, + 0x54, 0x9b, 0x8e, 0x26, 0xed, 0x93, 0x53, 0xdb, 0xb0, 0x50, 0x03, 0xee, 0xab, 0xdd, 0x5e, 0xab, + 0xa3, 0xb7, 0x4f, 0xf4, 0xd3, 0x6e, 0xf3, 0x95, 0x7e, 0xa1, 0x75, 0xb4, 0xde, 0x6b, 0xad, 0x24, + 0x88, 0xf7, 0xe7, 0x0b, 0x19, 0x6d, 0x78, 0x2f, 0x9c, 0x89, 0x43, 0xaf, 0x1c, 0xa4, 0xc0, 0xbd, + 0xbb, 0x91, 0xa6, 0x3a, 0x7c, 0xa9, 0x9d, 0x97, 0x80, 0xb8, 0x3f, 0x5f, 0xc8, 0xe5, 0x8d, 0x44, + 0xd3, 0xf4, 0xb0, 0xc3, 0xb3, 0x81, 0x56, 0xef, 0xec, 0xac, 0x7d, 0x5e, 0xca, 0x65, 0x02, 0x2d, + 0x3a, 0x9d, 0x12, 0x8e, 0x1e, 0xc1, 0xf2, 0xdd, 0x80, 0xd6, 0xee, 0x96, 0xf2, 0x22, 0x9a, 0x2f, + 0xe4, 0xff, 0x37, 0xdc, 0x1a, 0xb1, 0xc5, 0xdd, 0xf7, 0x1f, 0x25, 0xe1, 0xf3, 0x27, 0x09, 0xa8, + 0xdd, 0xeb, 0xa5, 0x04, 0x6e, 0x96, 0x12, 0xf8, 0xb9, 0x94, 0xc0, 0x87, 0x95, 0x24, 0xdc, 0xac, + 0x24, 0xe1, 0xfb, 0x4a, 0x12, 0xde, 0x1c, 0x59, 0x84, 0xbf, 0x9b, 0x99, 0xe1, 0x1d, 0x2a, 0xe9, + 0xc3, 0x8f, 0x17, 0x06, 0x23, 0x4a, 0x66, 0xb4, 0xcc, 0xed, 0x68, 0x12, 0x9e, 0xfd, 0x0a, 0x00, + 0x00, 0xff, 0xff, 0x2e, 0xe8, 0xdc, 0x7e, 0x76, 0x03, 0x00, 0x00, } func (m *ValidatorSet) Marshal() (dAtA []byte, err error) { @@ -854,7 +863,7 @@ func (m *SimpleValidator) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.PubKey == nil { - m.PubKey = &crypto.PublicKey{} + m.PubKey = &v1.PublicKey{} } if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err diff --git a/api/cometbft/types/v1beta1/block.pb.go b/api/cometbft/types/v1beta1/block.pb.go new file mode 100644 index 00000000000..0a4c6780deb --- /dev/null +++ b/api/cometbft/types/v1beta1/block.pb.go @@ -0,0 +1,494 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/types/v1beta1/block.proto + +package v1beta1 + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Block defines the structure of a block in the CometBFT blockchain. +type Block struct { + Header Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header"` + Data Data `protobuf:"bytes,2,opt,name=data,proto3" json:"data"` + Evidence EvidenceList `protobuf:"bytes,3,opt,name=evidence,proto3" json:"evidence"` + LastCommit *Commit `protobuf:"bytes,4,opt,name=last_commit,json=lastCommit,proto3" json:"last_commit,omitempty"` +} + +func (m *Block) Reset() { *m = Block{} } +func (m *Block) String() string { return proto.CompactTextString(m) } +func (*Block) ProtoMessage() {} +func (*Block) Descriptor() ([]byte, []int) { + return fileDescriptor_9a94804f701ae91c, []int{0} +} +func (m *Block) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Block) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Block.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Block) XXX_Merge(src proto.Message) { + xxx_messageInfo_Block.Merge(m, src) +} +func (m *Block) XXX_Size() int { + return m.Size() +} +func (m *Block) XXX_DiscardUnknown() { + xxx_messageInfo_Block.DiscardUnknown(m) +} + +var xxx_messageInfo_Block proto.InternalMessageInfo + +func (m *Block) GetHeader() Header { + if m != nil { + return m.Header + } + return Header{} +} + +func (m *Block) GetData() Data { + if m != nil { + return m.Data + } + return Data{} +} + +func (m *Block) GetEvidence() EvidenceList { + if m != nil { + return m.Evidence + } + return EvidenceList{} +} + +func (m *Block) GetLastCommit() *Commit { + if m != nil { + return m.LastCommit + } + return nil +} + +func init() { + proto.RegisterType((*Block)(nil), "cometbft.types.v1beta1.Block") +} + +func init() { + proto.RegisterFile("cometbft/types/v1beta1/block.proto", fileDescriptor_9a94804f701ae91c) +} + +var fileDescriptor_9a94804f701ae91c = []byte{ + // 277 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4a, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, + 0x49, 0x34, 0xd4, 0x4f, 0xca, 0xc9, 0x4f, 0xce, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, + 0x83, 0xa9, 0xd1, 0x03, 0xab, 0xd1, 0x83, 0xaa, 0x91, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x2b, + 0xd1, 0x07, 0xb1, 0x20, 0xaa, 0xa5, 0x70, 0x99, 0x08, 0xd1, 0x0b, 0x51, 0xa3, 0x8a, 0x43, 0x4d, + 0x6a, 0x59, 0x66, 0x4a, 0x6a, 0x5e, 0x72, 0x2a, 0x44, 0x99, 0x52, 0x1b, 0x13, 0x17, 0xab, 0x13, + 0xc8, 0x21, 0x42, 0x36, 0x5c, 0x6c, 0x19, 0xa9, 0x89, 0x29, 0xa9, 0x45, 0x12, 0x8c, 0x0a, 0x8c, + 0x1a, 0xdc, 0x46, 0x72, 0x7a, 0xd8, 0xdd, 0xa4, 0xe7, 0x01, 0x56, 0xe5, 0xc4, 0x72, 0xe2, 0x9e, + 0x3c, 0x43, 0x10, 0x54, 0x8f, 0x90, 0x19, 0x17, 0x4b, 0x4a, 0x62, 0x49, 0xa2, 0x04, 0x13, 0x58, + 0xaf, 0x0c, 0x2e, 0xbd, 0x2e, 0x89, 0x25, 0x89, 0x50, 0x9d, 0x60, 0xf5, 0x42, 0x6e, 0x5c, 0x1c, + 0x30, 0x17, 0x49, 0x30, 0x83, 0xf5, 0xaa, 0xe0, 0xd2, 0xeb, 0x0a, 0x55, 0xe7, 0x93, 0x59, 0x5c, + 0x02, 0x35, 0x03, 0xae, 0x57, 0xc8, 0x9e, 0x8b, 0x3b, 0x27, 0xb1, 0xb8, 0x24, 0x3e, 0x39, 0x3f, + 0x37, 0x37, 0xb3, 0x44, 0x82, 0x05, 0xbf, 0x17, 0x9c, 0xc1, 0xaa, 0x82, 0xb8, 0x40, 0x5a, 0x20, + 0x6c, 0xa7, 0xc0, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, + 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x4f, 0xcf, + 0x2c, 0xc9, 0x28, 0x4d, 0x02, 0x99, 0xa5, 0x0f, 0x0f, 0x54, 0x38, 0x23, 0xb1, 0x20, 0x53, 0x1f, + 0x7b, 0x50, 0x27, 0xb1, 0x81, 0x83, 0xd8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xf3, 0x24, 0x27, + 0xcb, 0x01, 0x02, 0x00, 0x00, +} + +func (m *Block) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Block) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Block) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.LastCommit != nil { + { + size, err := m.LastCommit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + { + size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.Data.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.Header.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBlock(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintBlock(dAtA []byte, offset int, v uint64) int { + offset -= sovBlock(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Block) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Header.Size() + n += 1 + l + sovBlock(uint64(l)) + l = m.Data.Size() + n += 1 + l + sovBlock(uint64(l)) + l = m.Evidence.Size() + n += 1 + l + sovBlock(uint64(l)) + if m.LastCommit != nil { + l = m.LastCommit.Size() + n += 1 + l + sovBlock(uint64(l)) + } + return n +} + +func sovBlock(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozBlock(x uint64) (n int) { + return sovBlock(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Block) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Block: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Block: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Data.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastCommit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBlock + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBlock + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBlock + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LastCommit == nil { + m.LastCommit = &Commit{} + } + if err := m.LastCommit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBlock(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBlock + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipBlock(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlock + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlock + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowBlock + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthBlock + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupBlock + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthBlock + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthBlock = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowBlock = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupBlock = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/types/v1beta1/canonical.pb.go b/api/cometbft/types/v1beta1/canonical.pb.go new file mode 100644 index 00000000000..2e03ff7d4a0 --- /dev/null +++ b/api/cometbft/types/v1beta1/canonical.pb.go @@ -0,0 +1,1389 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/types/v1beta1/canonical.proto + +package v1beta1 + +import ( + encoding_binary "encoding/binary" + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// CanonicalBlockID is a canonical representation of a BlockID, which gets +// serialized and signed. +type CanonicalBlockID struct { + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + PartSetHeader CanonicalPartSetHeader `protobuf:"bytes,2,opt,name=part_set_header,json=partSetHeader,proto3" json:"part_set_header"` +} + +func (m *CanonicalBlockID) Reset() { *m = CanonicalBlockID{} } +func (m *CanonicalBlockID) String() string { return proto.CompactTextString(m) } +func (*CanonicalBlockID) ProtoMessage() {} +func (*CanonicalBlockID) Descriptor() ([]byte, []int) { + return fileDescriptor_476991b7998505b4, []int{0} +} +func (m *CanonicalBlockID) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CanonicalBlockID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CanonicalBlockID.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CanonicalBlockID) XXX_Merge(src proto.Message) { + xxx_messageInfo_CanonicalBlockID.Merge(m, src) +} +func (m *CanonicalBlockID) XXX_Size() int { + return m.Size() +} +func (m *CanonicalBlockID) XXX_DiscardUnknown() { + xxx_messageInfo_CanonicalBlockID.DiscardUnknown(m) +} + +var xxx_messageInfo_CanonicalBlockID proto.InternalMessageInfo + +func (m *CanonicalBlockID) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *CanonicalBlockID) GetPartSetHeader() CanonicalPartSetHeader { + if m != nil { + return m.PartSetHeader + } + return CanonicalPartSetHeader{} +} + +// CanonicalPartSetHeader is a canonical representation of a PartSetHeader, +// which gets serialized and signed. +type CanonicalPartSetHeader struct { + Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` +} + +func (m *CanonicalPartSetHeader) Reset() { *m = CanonicalPartSetHeader{} } +func (m *CanonicalPartSetHeader) String() string { return proto.CompactTextString(m) } +func (*CanonicalPartSetHeader) ProtoMessage() {} +func (*CanonicalPartSetHeader) Descriptor() ([]byte, []int) { + return fileDescriptor_476991b7998505b4, []int{1} +} +func (m *CanonicalPartSetHeader) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CanonicalPartSetHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CanonicalPartSetHeader.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CanonicalPartSetHeader) XXX_Merge(src proto.Message) { + xxx_messageInfo_CanonicalPartSetHeader.Merge(m, src) +} +func (m *CanonicalPartSetHeader) XXX_Size() int { + return m.Size() +} +func (m *CanonicalPartSetHeader) XXX_DiscardUnknown() { + xxx_messageInfo_CanonicalPartSetHeader.DiscardUnknown(m) +} + +var xxx_messageInfo_CanonicalPartSetHeader proto.InternalMessageInfo + +func (m *CanonicalPartSetHeader) GetTotal() uint32 { + if m != nil { + return m.Total + } + return 0 +} + +func (m *CanonicalPartSetHeader) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +// CanonicalProposal is a canonical representation of a Proposal, which gets +// serialized and signed. +type CanonicalProposal struct { + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.types.v1beta1.SignedMsgType" json:"type,omitempty"` + Height int64 `protobuf:"fixed64,2,opt,name=height,proto3" json:"height,omitempty"` + Round int64 `protobuf:"fixed64,3,opt,name=round,proto3" json:"round,omitempty"` + POLRound int64 `protobuf:"varint,4,opt,name=pol_round,json=polRound,proto3" json:"pol_round,omitempty"` + BlockID *CanonicalBlockID `protobuf:"bytes,5,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` + Timestamp time.Time `protobuf:"bytes,6,opt,name=timestamp,proto3,stdtime" json:"timestamp"` + ChainID string `protobuf:"bytes,7,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *CanonicalProposal) Reset() { *m = CanonicalProposal{} } +func (m *CanonicalProposal) String() string { return proto.CompactTextString(m) } +func (*CanonicalProposal) ProtoMessage() {} +func (*CanonicalProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_476991b7998505b4, []int{2} +} +func (m *CanonicalProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CanonicalProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CanonicalProposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CanonicalProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_CanonicalProposal.Merge(m, src) +} +func (m *CanonicalProposal) XXX_Size() int { + return m.Size() +} +func (m *CanonicalProposal) XXX_DiscardUnknown() { + xxx_messageInfo_CanonicalProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_CanonicalProposal proto.InternalMessageInfo + +func (m *CanonicalProposal) GetType() SignedMsgType { + if m != nil { + return m.Type + } + return UnknownType +} + +func (m *CanonicalProposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *CanonicalProposal) GetRound() int64 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *CanonicalProposal) GetPOLRound() int64 { + if m != nil { + return m.POLRound + } + return 0 +} + +func (m *CanonicalProposal) GetBlockID() *CanonicalBlockID { + if m != nil { + return m.BlockID + } + return nil +} + +func (m *CanonicalProposal) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +func (m *CanonicalProposal) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +// CanonicalVote is a canonical representation of a Vote, which gets +// serialized and signed. +type CanonicalVote struct { + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.types.v1beta1.SignedMsgType" json:"type,omitempty"` + Height int64 `protobuf:"fixed64,2,opt,name=height,proto3" json:"height,omitempty"` + Round int64 `protobuf:"fixed64,3,opt,name=round,proto3" json:"round,omitempty"` + BlockID *CanonicalBlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id,omitempty"` + Timestamp time.Time `protobuf:"bytes,5,opt,name=timestamp,proto3,stdtime" json:"timestamp"` + ChainID string `protobuf:"bytes,6,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (m *CanonicalVote) Reset() { *m = CanonicalVote{} } +func (m *CanonicalVote) String() string { return proto.CompactTextString(m) } +func (*CanonicalVote) ProtoMessage() {} +func (*CanonicalVote) Descriptor() ([]byte, []int) { + return fileDescriptor_476991b7998505b4, []int{3} +} +func (m *CanonicalVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CanonicalVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CanonicalVote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CanonicalVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_CanonicalVote.Merge(m, src) +} +func (m *CanonicalVote) XXX_Size() int { + return m.Size() +} +func (m *CanonicalVote) XXX_DiscardUnknown() { + xxx_messageInfo_CanonicalVote.DiscardUnknown(m) +} + +var xxx_messageInfo_CanonicalVote proto.InternalMessageInfo + +func (m *CanonicalVote) GetType() SignedMsgType { + if m != nil { + return m.Type + } + return UnknownType +} + +func (m *CanonicalVote) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *CanonicalVote) GetRound() int64 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *CanonicalVote) GetBlockID() *CanonicalBlockID { + if m != nil { + return m.BlockID + } + return nil +} + +func (m *CanonicalVote) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +func (m *CanonicalVote) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +func init() { + proto.RegisterType((*CanonicalBlockID)(nil), "cometbft.types.v1beta1.CanonicalBlockID") + proto.RegisterType((*CanonicalPartSetHeader)(nil), "cometbft.types.v1beta1.CanonicalPartSetHeader") + proto.RegisterType((*CanonicalProposal)(nil), "cometbft.types.v1beta1.CanonicalProposal") + proto.RegisterType((*CanonicalVote)(nil), "cometbft.types.v1beta1.CanonicalVote") +} + +func init() { + proto.RegisterFile("cometbft/types/v1beta1/canonical.proto", fileDescriptor_476991b7998505b4) +} + +var fileDescriptor_476991b7998505b4 = []byte{ + // 498 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x93, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x86, 0xb3, 0xa9, 0x93, 0x38, 0xdb, 0x06, 0xca, 0xaa, 0x8a, 0xac, 0x1c, 0xec, 0xc8, 0x12, + 0x95, 0xb9, 0xd8, 0x6a, 0x39, 0x20, 0xae, 0x2e, 0x07, 0x22, 0x81, 0x08, 0x6e, 0xc5, 0x01, 0x21, + 0x45, 0x6b, 0x7b, 0x6b, 0x5b, 0x38, 0xde, 0x95, 0xbd, 0x41, 0xea, 0x9d, 0x07, 0xe8, 0xd3, 0xf0, + 0x0c, 0x3d, 0xf6, 0xc8, 0x29, 0x20, 0x47, 0xbc, 0x07, 0xda, 0xdd, 0xc4, 0xe9, 0x21, 0x11, 0x07, + 0x10, 0xb7, 0x99, 0xf1, 0x3f, 0x33, 0x9f, 0xff, 0xd1, 0xc2, 0xd3, 0x88, 0xce, 0x09, 0x0f, 0xaf, + 0xb9, 0xc7, 0x6f, 0x18, 0xa9, 0xbc, 0x2f, 0x67, 0x21, 0xe1, 0xf8, 0xcc, 0x8b, 0x70, 0x41, 0x8b, + 0x2c, 0xc2, 0xb9, 0xcb, 0x4a, 0xca, 0x29, 0x1a, 0x6e, 0x74, 0xae, 0xd4, 0xb9, 0x6b, 0xdd, 0xe8, + 0x24, 0xa1, 0x09, 0x95, 0x12, 0x4f, 0x44, 0x4a, 0x3d, 0xb2, 0xf7, 0x4c, 0x55, 0xbd, 0x4a, 0x63, + 0x25, 0x94, 0x26, 0x39, 0xf1, 0x64, 0x16, 0x2e, 0xae, 0x3d, 0x9e, 0xcd, 0x49, 0xc5, 0xf1, 0x9c, + 0x29, 0x81, 0xfd, 0x15, 0xc0, 0xe3, 0x8b, 0x0d, 0x86, 0x9f, 0xd3, 0xe8, 0xf3, 0xe4, 0x15, 0x42, + 0x50, 0x4b, 0x71, 0x95, 0x1a, 0x60, 0x0c, 0x9c, 0xa3, 0x40, 0xc6, 0xe8, 0x13, 0x7c, 0xcc, 0x70, + 0xc9, 0x67, 0x15, 0xe1, 0xb3, 0x94, 0xe0, 0x98, 0x94, 0x46, 0x7b, 0x0c, 0x9c, 0xc3, 0x73, 0xd7, + 0xdd, 0x4d, 0xed, 0x36, 0x63, 0xa7, 0xb8, 0xe4, 0x97, 0x84, 0xbf, 0x96, 0x5d, 0xbe, 0x76, 0xb7, + 0xb4, 0x5a, 0xc1, 0x80, 0x3d, 0x2c, 0xda, 0x3e, 0x1c, 0xee, 0x96, 0xa3, 0x13, 0xd8, 0xe1, 0x94, + 0xe3, 0x5c, 0xc2, 0x0c, 0x02, 0x95, 0x34, 0x84, 0xed, 0x2d, 0xa1, 0xfd, 0xab, 0x0d, 0x9f, 0x6c, + 0x87, 0x94, 0x94, 0xd1, 0x0a, 0xe7, 0xe8, 0x25, 0xd4, 0x04, 0x96, 0x6c, 0x7f, 0x74, 0xfe, 0x74, + 0x1f, 0xec, 0x65, 0x96, 0x14, 0x24, 0x7e, 0x5b, 0x25, 0x57, 0x37, 0x8c, 0x04, 0xb2, 0x05, 0x0d, + 0x61, 0x37, 0x25, 0x59, 0x92, 0x72, 0xb9, 0xe6, 0x38, 0x58, 0x67, 0x02, 0xa9, 0xa4, 0x8b, 0x22, + 0x36, 0x0e, 0x64, 0x59, 0x25, 0xe8, 0x19, 0xec, 0x33, 0x9a, 0xcf, 0xd4, 0x17, 0x6d, 0x0c, 0x9c, + 0x03, 0xff, 0xa8, 0x5e, 0x5a, 0xfa, 0xf4, 0xdd, 0x9b, 0x40, 0xd4, 0x02, 0x9d, 0xd1, 0x5c, 0x46, + 0x68, 0x0a, 0xf5, 0x50, 0x58, 0x3d, 0xcb, 0x62, 0xa3, 0x23, 0x4d, 0x74, 0xfe, 0x68, 0xe2, 0xfa, + 0x36, 0xfe, 0x61, 0xbd, 0xb4, 0x7a, 0xeb, 0x24, 0xe8, 0xc9, 0x31, 0x93, 0x18, 0xf9, 0xb0, 0xdf, + 0x5c, 0xd6, 0xe8, 0xca, 0x91, 0x23, 0x57, 0xdd, 0xde, 0xdd, 0xdc, 0xde, 0xbd, 0xda, 0x28, 0x7c, + 0x5d, 0xdc, 0xe0, 0xf6, 0x87, 0x05, 0x82, 0x6d, 0x1b, 0x3a, 0x85, 0x7a, 0x94, 0xe2, 0xac, 0x10, + 0x54, 0xbd, 0x31, 0x70, 0xfa, 0x6a, 0xd7, 0x85, 0xa8, 0x89, 0x5d, 0xf2, 0xe3, 0x24, 0xb6, 0xbf, + 0xb5, 0xe1, 0xa0, 0xc1, 0xfa, 0x40, 0x39, 0xf9, 0x7f, 0x1e, 0x3f, 0x34, 0x4e, 0xfb, 0xf7, 0xc6, + 0x75, 0xfe, 0xde, 0xb8, 0xee, 0x7e, 0xe3, 0xfc, 0xf7, 0x77, 0xb5, 0x09, 0xee, 0x6b, 0x13, 0xfc, + 0xac, 0x4d, 0x70, 0xbb, 0x32, 0x5b, 0xf7, 0x2b, 0xb3, 0xf5, 0x7d, 0x65, 0xb6, 0x3e, 0xbe, 0x48, + 0x32, 0x9e, 0x2e, 0x42, 0xf1, 0x2f, 0x5e, 0xf3, 0xaa, 0x9b, 0x00, 0xb3, 0xcc, 0xdb, 0xfd, 0xd6, + 0xc3, 0xae, 0x64, 0x7c, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x10, 0x33, 0xb1, 0x97, 0x62, 0x04, + 0x00, 0x00, +} + +func (m *CanonicalBlockID) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CanonicalBlockID) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CanonicalBlockID) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.PartSetHeader.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCanonical(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintCanonical(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CanonicalPartSetHeader) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CanonicalPartSetHeader) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CanonicalPartSetHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintCanonical(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0x12 + } + if m.Total != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Total)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *CanonicalProposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CanonicalProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CanonicalProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainID) > 0 { + i -= len(m.ChainID) + copy(dAtA[i:], m.ChainID) + i = encodeVarintCanonical(dAtA, i, uint64(len(m.ChainID))) + i-- + dAtA[i] = 0x3a + } + n2, err2 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintCanonical(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0x32 + if m.BlockID != nil { + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCanonical(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if m.POLRound != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.POLRound)) + i-- + dAtA[i] = 0x20 + } + if m.Round != 0 { + i -= 8 + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(m.Round)) + i-- + dAtA[i] = 0x19 + } + if m.Height != 0 { + i -= 8 + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(m.Height)) + i-- + dAtA[i] = 0x11 + } + if m.Type != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *CanonicalVote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CanonicalVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CanonicalVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ChainID) > 0 { + i -= len(m.ChainID) + copy(dAtA[i:], m.ChainID) + i = encodeVarintCanonical(dAtA, i, uint64(len(m.ChainID))) + i-- + dAtA[i] = 0x32 + } + n4, err4 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) + if err4 != nil { + return 0, err4 + } + i -= n4 + i = encodeVarintCanonical(dAtA, i, uint64(n4)) + i-- + dAtA[i] = 0x2a + if m.BlockID != nil { + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCanonical(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.Round != 0 { + i -= 8 + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(m.Round)) + i-- + dAtA[i] = 0x19 + } + if m.Height != 0 { + i -= 8 + encoding_binary.LittleEndian.PutUint64(dAtA[i:], uint64(m.Height)) + i-- + dAtA[i] = 0x11 + } + if m.Type != 0 { + i = encodeVarintCanonical(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintCanonical(dAtA []byte, offset int, v uint64) int { + offset -= sovCanonical(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *CanonicalBlockID) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovCanonical(uint64(l)) + } + l = m.PartSetHeader.Size() + n += 1 + l + sovCanonical(uint64(l)) + return n +} + +func (m *CanonicalPartSetHeader) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Total != 0 { + n += 1 + sovCanonical(uint64(m.Total)) + } + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovCanonical(uint64(l)) + } + return n +} + +func (m *CanonicalProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovCanonical(uint64(m.Type)) + } + if m.Height != 0 { + n += 9 + } + if m.Round != 0 { + n += 9 + } + if m.POLRound != 0 { + n += 1 + sovCanonical(uint64(m.POLRound)) + } + if m.BlockID != nil { + l = m.BlockID.Size() + n += 1 + l + sovCanonical(uint64(l)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovCanonical(uint64(l)) + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovCanonical(uint64(l)) + } + return n +} + +func (m *CanonicalVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovCanonical(uint64(m.Type)) + } + if m.Height != 0 { + n += 9 + } + if m.Round != 0 { + n += 9 + } + if m.BlockID != nil { + l = m.BlockID.Size() + n += 1 + l + sovCanonical(uint64(l)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovCanonical(uint64(l)) + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovCanonical(uint64(l)) + } + return n +} + +func sovCanonical(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozCanonical(x uint64) (n int) { + return sovCanonical(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *CanonicalBlockID) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CanonicalBlockID: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CanonicalBlockID: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PartSetHeader", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PartSetHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCanonical(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CanonicalPartSetHeader) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CanonicalPartSetHeader: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CanonicalPartSetHeader: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) + } + m.Total = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Total |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCanonical(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CanonicalProposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CanonicalProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CanonicalProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + m.Height = int64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + case 3: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + m.Round = int64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field POLRound", wireType) + } + m.POLRound = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.POLRound |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BlockID == nil { + m.BlockID = &CanonicalBlockID{} + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCanonical(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CanonicalVote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CanonicalVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CanonicalVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + m.Height = int64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + case 3: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + m.Round = int64(encoding_binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BlockID == nil { + m.BlockID = &CanonicalBlockID{} + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCanonical + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthCanonical + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCanonical + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCanonical(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCanonical + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipCanonical(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCanonical + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCanonical + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCanonical + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthCanonical + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupCanonical + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthCanonical + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthCanonical = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowCanonical = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupCanonical = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/types/v1beta1/events.pb.go b/api/cometbft/types/v1beta1/events.pb.go new file mode 100644 index 00000000000..592072b9d27 --- /dev/null +++ b/api/cometbft/types/v1beta1/events.pb.go @@ -0,0 +1,390 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/types/v1beta1/events.proto + +package v1beta1 + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// EventDataRoundState is emitted with each new round step. +type EventDataRoundState struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + Step string `protobuf:"bytes,3,opt,name=step,proto3" json:"step,omitempty"` +} + +func (m *EventDataRoundState) Reset() { *m = EventDataRoundState{} } +func (m *EventDataRoundState) String() string { return proto.CompactTextString(m) } +func (*EventDataRoundState) ProtoMessage() {} +func (*EventDataRoundState) Descriptor() ([]byte, []int) { + return fileDescriptor_659f129cf60555df, []int{0} +} +func (m *EventDataRoundState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventDataRoundState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventDataRoundState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EventDataRoundState) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventDataRoundState.Merge(m, src) +} +func (m *EventDataRoundState) XXX_Size() int { + return m.Size() +} +func (m *EventDataRoundState) XXX_DiscardUnknown() { + xxx_messageInfo_EventDataRoundState.DiscardUnknown(m) +} + +var xxx_messageInfo_EventDataRoundState proto.InternalMessageInfo + +func (m *EventDataRoundState) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *EventDataRoundState) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *EventDataRoundState) GetStep() string { + if m != nil { + return m.Step + } + return "" +} + +func init() { + proto.RegisterType((*EventDataRoundState)(nil), "cometbft.types.v1beta1.EventDataRoundState") +} + +func init() { + proto.RegisterFile("cometbft/types/v1beta1/events.proto", fileDescriptor_659f129cf60555df) +} + +var fileDescriptor_659f129cf60555df = []byte{ + // 200 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4e, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, + 0x49, 0x34, 0xd4, 0x4f, 0x2d, 0x4b, 0xcd, 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, + 0x12, 0x83, 0x29, 0xd2, 0x03, 0x2b, 0xd2, 0x83, 0x2a, 0x52, 0x0a, 0xe7, 0x12, 0x76, 0x05, 0xa9, + 0x73, 0x49, 0x2c, 0x49, 0x0c, 0xca, 0x2f, 0xcd, 0x4b, 0x09, 0x2e, 0x49, 0x2c, 0x49, 0x15, 0x12, + 0xe3, 0x62, 0xcb, 0x48, 0xcd, 0x4c, 0xcf, 0x28, 0x91, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x82, + 0xf2, 0x84, 0x44, 0xb8, 0x58, 0x8b, 0x40, 0xaa, 0x24, 0x98, 0x14, 0x18, 0x35, 0x58, 0x83, 0x20, + 0x1c, 0x21, 0x21, 0x2e, 0x96, 0xe2, 0x92, 0xd4, 0x02, 0x09, 0x66, 0x05, 0x46, 0x0d, 0xce, 0x20, + 0x30, 0xdb, 0x29, 0xf0, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, + 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xcc, 0xd3, + 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xe1, 0x4e, 0x87, 0x33, 0x12, 0x0b, + 0x32, 0xf5, 0xb1, 0x7b, 0x28, 0x89, 0x0d, 0xec, 0x15, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x75, 0x89, 0x8f, 0x3b, 0xf1, 0x00, 0x00, 0x00, +} + +func (m *EventDataRoundState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventDataRoundState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventDataRoundState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Step) > 0 { + i -= len(m.Step) + copy(dAtA[i:], m.Step) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Step))) + i-- + dAtA[i] = 0x1a + } + if m.Round != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintEvents(dAtA []byte, offset int, v uint64) int { + offset -= sovEvents(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *EventDataRoundState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovEvents(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovEvents(uint64(m.Round)) + } + l = len(m.Step) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func sovEvents(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozEvents(x uint64) (n int) { + return sovEvents(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *EventDataRoundState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventDataRoundState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventDataRoundState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Step", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Step = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipEvents(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvents + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvents + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvents + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthEvents + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupEvents + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthEvents + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthEvents = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowEvents = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupEvents = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/types/v1beta1/evidence.pb.go b/api/cometbft/types/v1beta1/evidence.pb.go new file mode 100644 index 00000000000..41dd8b843f7 --- /dev/null +++ b/api/cometbft/types/v1beta1/evidence.pb.go @@ -0,0 +1,1400 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/types/v1beta1/evidence.proto + +package v1beta1 + +import ( + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Evidence is a generic type for wrapping evidence of misbehavior by a validator. +type Evidence struct { + // The type of evidence. + // + // Types that are valid to be assigned to Sum: + // *Evidence_DuplicateVoteEvidence + // *Evidence_LightClientAttackEvidence + Sum isEvidence_Sum `protobuf_oneof:"sum"` +} + +func (m *Evidence) Reset() { *m = Evidence{} } +func (m *Evidence) String() string { return proto.CompactTextString(m) } +func (*Evidence) ProtoMessage() {} +func (*Evidence) Descriptor() ([]byte, []int) { + return fileDescriptor_ab3b8db02b56853b, []int{0} +} +func (m *Evidence) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Evidence.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Evidence) XXX_Merge(src proto.Message) { + xxx_messageInfo_Evidence.Merge(m, src) +} +func (m *Evidence) XXX_Size() int { + return m.Size() +} +func (m *Evidence) XXX_DiscardUnknown() { + xxx_messageInfo_Evidence.DiscardUnknown(m) +} + +var xxx_messageInfo_Evidence proto.InternalMessageInfo + +type isEvidence_Sum interface { + isEvidence_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Evidence_DuplicateVoteEvidence struct { + DuplicateVoteEvidence *DuplicateVoteEvidence `protobuf:"bytes,1,opt,name=duplicate_vote_evidence,json=duplicateVoteEvidence,proto3,oneof" json:"duplicate_vote_evidence,omitempty"` +} +type Evidence_LightClientAttackEvidence struct { + LightClientAttackEvidence *LightClientAttackEvidence `protobuf:"bytes,2,opt,name=light_client_attack_evidence,json=lightClientAttackEvidence,proto3,oneof" json:"light_client_attack_evidence,omitempty"` +} + +func (*Evidence_DuplicateVoteEvidence) isEvidence_Sum() {} +func (*Evidence_LightClientAttackEvidence) isEvidence_Sum() {} + +func (m *Evidence) GetSum() isEvidence_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Evidence) GetDuplicateVoteEvidence() *DuplicateVoteEvidence { + if x, ok := m.GetSum().(*Evidence_DuplicateVoteEvidence); ok { + return x.DuplicateVoteEvidence + } + return nil +} + +func (m *Evidence) GetLightClientAttackEvidence() *LightClientAttackEvidence { + if x, ok := m.GetSum().(*Evidence_LightClientAttackEvidence); ok { + return x.LightClientAttackEvidence + } + return nil +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Evidence) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Evidence_DuplicateVoteEvidence)(nil), + (*Evidence_LightClientAttackEvidence)(nil), + } +} + +// DuplicateVoteEvidence contains evidence of a validator signed two conflicting votes. +type DuplicateVoteEvidence struct { + VoteA *Vote `protobuf:"bytes,1,opt,name=vote_a,json=voteA,proto3" json:"vote_a,omitempty"` + VoteB *Vote `protobuf:"bytes,2,opt,name=vote_b,json=voteB,proto3" json:"vote_b,omitempty"` + TotalVotingPower int64 `protobuf:"varint,3,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` + ValidatorPower int64 `protobuf:"varint,4,opt,name=validator_power,json=validatorPower,proto3" json:"validator_power,omitempty"` + Timestamp time.Time `protobuf:"bytes,5,opt,name=timestamp,proto3,stdtime" json:"timestamp"` +} + +func (m *DuplicateVoteEvidence) Reset() { *m = DuplicateVoteEvidence{} } +func (m *DuplicateVoteEvidence) String() string { return proto.CompactTextString(m) } +func (*DuplicateVoteEvidence) ProtoMessage() {} +func (*DuplicateVoteEvidence) Descriptor() ([]byte, []int) { + return fileDescriptor_ab3b8db02b56853b, []int{1} +} +func (m *DuplicateVoteEvidence) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DuplicateVoteEvidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DuplicateVoteEvidence.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DuplicateVoteEvidence) XXX_Merge(src proto.Message) { + xxx_messageInfo_DuplicateVoteEvidence.Merge(m, src) +} +func (m *DuplicateVoteEvidence) XXX_Size() int { + return m.Size() +} +func (m *DuplicateVoteEvidence) XXX_DiscardUnknown() { + xxx_messageInfo_DuplicateVoteEvidence.DiscardUnknown(m) +} + +var xxx_messageInfo_DuplicateVoteEvidence proto.InternalMessageInfo + +func (m *DuplicateVoteEvidence) GetVoteA() *Vote { + if m != nil { + return m.VoteA + } + return nil +} + +func (m *DuplicateVoteEvidence) GetVoteB() *Vote { + if m != nil { + return m.VoteB + } + return nil +} + +func (m *DuplicateVoteEvidence) GetTotalVotingPower() int64 { + if m != nil { + return m.TotalVotingPower + } + return 0 +} + +func (m *DuplicateVoteEvidence) GetValidatorPower() int64 { + if m != nil { + return m.ValidatorPower + } + return 0 +} + +func (m *DuplicateVoteEvidence) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +// LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client. +type LightClientAttackEvidence struct { + ConflictingBlock *LightBlock `protobuf:"bytes,1,opt,name=conflicting_block,json=conflictingBlock,proto3" json:"conflicting_block,omitempty"` + CommonHeight int64 `protobuf:"varint,2,opt,name=common_height,json=commonHeight,proto3" json:"common_height,omitempty"` + ByzantineValidators []*Validator `protobuf:"bytes,3,rep,name=byzantine_validators,json=byzantineValidators,proto3" json:"byzantine_validators,omitempty"` + TotalVotingPower int64 `protobuf:"varint,4,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` + Timestamp time.Time `protobuf:"bytes,5,opt,name=timestamp,proto3,stdtime" json:"timestamp"` +} + +func (m *LightClientAttackEvidence) Reset() { *m = LightClientAttackEvidence{} } +func (m *LightClientAttackEvidence) String() string { return proto.CompactTextString(m) } +func (*LightClientAttackEvidence) ProtoMessage() {} +func (*LightClientAttackEvidence) Descriptor() ([]byte, []int) { + return fileDescriptor_ab3b8db02b56853b, []int{2} +} +func (m *LightClientAttackEvidence) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LightClientAttackEvidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LightClientAttackEvidence.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LightClientAttackEvidence) XXX_Merge(src proto.Message) { + xxx_messageInfo_LightClientAttackEvidence.Merge(m, src) +} +func (m *LightClientAttackEvidence) XXX_Size() int { + return m.Size() +} +func (m *LightClientAttackEvidence) XXX_DiscardUnknown() { + xxx_messageInfo_LightClientAttackEvidence.DiscardUnknown(m) +} + +var xxx_messageInfo_LightClientAttackEvidence proto.InternalMessageInfo + +func (m *LightClientAttackEvidence) GetConflictingBlock() *LightBlock { + if m != nil { + return m.ConflictingBlock + } + return nil +} + +func (m *LightClientAttackEvidence) GetCommonHeight() int64 { + if m != nil { + return m.CommonHeight + } + return 0 +} + +func (m *LightClientAttackEvidence) GetByzantineValidators() []*Validator { + if m != nil { + return m.ByzantineValidators + } + return nil +} + +func (m *LightClientAttackEvidence) GetTotalVotingPower() int64 { + if m != nil { + return m.TotalVotingPower + } + return 0 +} + +func (m *LightClientAttackEvidence) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +// EvidenceList is a list of evidence. +type EvidenceList struct { + Evidence []Evidence `protobuf:"bytes,1,rep,name=evidence,proto3" json:"evidence"` +} + +func (m *EvidenceList) Reset() { *m = EvidenceList{} } +func (m *EvidenceList) String() string { return proto.CompactTextString(m) } +func (*EvidenceList) ProtoMessage() {} +func (*EvidenceList) Descriptor() ([]byte, []int) { + return fileDescriptor_ab3b8db02b56853b, []int{3} +} +func (m *EvidenceList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EvidenceList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EvidenceList.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *EvidenceList) XXX_Merge(src proto.Message) { + xxx_messageInfo_EvidenceList.Merge(m, src) +} +func (m *EvidenceList) XXX_Size() int { + return m.Size() +} +func (m *EvidenceList) XXX_DiscardUnknown() { + xxx_messageInfo_EvidenceList.DiscardUnknown(m) +} + +var xxx_messageInfo_EvidenceList proto.InternalMessageInfo + +func (m *EvidenceList) GetEvidence() []Evidence { + if m != nil { + return m.Evidence + } + return nil +} + +func init() { + proto.RegisterType((*Evidence)(nil), "cometbft.types.v1beta1.Evidence") + proto.RegisterType((*DuplicateVoteEvidence)(nil), "cometbft.types.v1beta1.DuplicateVoteEvidence") + proto.RegisterType((*LightClientAttackEvidence)(nil), "cometbft.types.v1beta1.LightClientAttackEvidence") + proto.RegisterType((*EvidenceList)(nil), "cometbft.types.v1beta1.EvidenceList") +} + +func init() { + proto.RegisterFile("cometbft/types/v1beta1/evidence.proto", fileDescriptor_ab3b8db02b56853b) +} + +var fileDescriptor_ab3b8db02b56853b = []byte{ + // 540 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x86, 0xe3, 0x3a, 0xa9, 0xc2, 0xb6, 0x40, 0x59, 0x5a, 0x48, 0xa3, 0xca, 0x09, 0x46, 0x40, + 0x0e, 0x60, 0x2b, 0xed, 0x81, 0x73, 0x0d, 0x48, 0x3d, 0x54, 0x02, 0xac, 0xaa, 0x07, 0x2e, 0xd6, + 0xda, 0xd9, 0x38, 0xab, 0xda, 0x5e, 0x2b, 0x9e, 0x04, 0x95, 0xa7, 0xe8, 0x03, 0xf0, 0x40, 0x3d, + 0xf6, 0x08, 0x17, 0x40, 0xc9, 0x0b, 0xf0, 0x08, 0x68, 0xd7, 0xf6, 0x36, 0x87, 0x2c, 0xe2, 0xc0, + 0xcd, 0x99, 0xfd, 0xfe, 0x9d, 0xf9, 0x67, 0x26, 0x8b, 0x9e, 0x45, 0x3c, 0xa5, 0x10, 0x8e, 0xc1, + 0x85, 0xcb, 0x9c, 0x16, 0xee, 0x7c, 0x18, 0x52, 0x20, 0x43, 0x97, 0xce, 0xd9, 0x88, 0x66, 0x11, + 0x75, 0xf2, 0x29, 0x07, 0x8e, 0x1f, 0xd5, 0x98, 0x23, 0x31, 0xa7, 0xc2, 0xba, 0xbb, 0x31, 0x8f, + 0xb9, 0x44, 0x5c, 0xf1, 0x55, 0xd2, 0xdd, 0x5e, 0xcc, 0x79, 0x9c, 0x50, 0x57, 0xfe, 0x0a, 0x67, + 0x63, 0x17, 0x58, 0x4a, 0x0b, 0x20, 0x69, 0x5e, 0x01, 0xb6, 0x26, 0x6b, 0x79, 0x79, 0xc9, 0x3c, + 0xd7, 0x30, 0x73, 0x92, 0xb0, 0x11, 0x01, 0x3e, 0x2d, 0x39, 0xfb, 0xb7, 0x81, 0xda, 0xef, 0xaa, + 0x6a, 0x71, 0x8c, 0x1e, 0x8f, 0x66, 0x79, 0xc2, 0x22, 0x02, 0x34, 0x98, 0x73, 0xa0, 0x41, 0x6d, + 0xa4, 0x63, 0xf4, 0x8d, 0xc1, 0xd6, 0xe1, 0x2b, 0x67, 0xbd, 0x13, 0xe7, 0x6d, 0x2d, 0x3b, 0xe7, + 0x40, 0xeb, 0xfb, 0x4e, 0x1a, 0xfe, 0xde, 0x68, 0xdd, 0x01, 0x06, 0x74, 0x90, 0xb0, 0x78, 0x02, + 0x41, 0x94, 0x30, 0x9a, 0x41, 0x40, 0x00, 0x48, 0x74, 0x71, 0x9b, 0x6d, 0x43, 0x66, 0x1b, 0xea, + 0xb2, 0x9d, 0x0a, 0xed, 0x1b, 0x29, 0x3d, 0x96, 0xca, 0x95, 0x8c, 0xfb, 0x89, 0xee, 0xd0, 0x6b, + 0x21, 0xb3, 0x98, 0xa5, 0xf6, 0xd7, 0x0d, 0xb4, 0xb7, 0xb6, 0x5e, 0x7c, 0x84, 0x36, 0xa5, 0x6b, + 0x52, 0xd9, 0x3d, 0xd0, 0x15, 0x20, 0x54, 0x7e, 0x4b, 0xb0, 0xc7, 0x4a, 0x14, 0x56, 0x55, 0xff, + 0x83, 0xc8, 0xc3, 0x2f, 0x11, 0x06, 0x0e, 0x24, 0x11, 0x5d, 0x66, 0x59, 0x1c, 0xe4, 0xfc, 0x33, + 0x9d, 0x76, 0xcc, 0xbe, 0x31, 0x30, 0xfd, 0x1d, 0x79, 0x72, 0x2e, 0x0f, 0x3e, 0x88, 0x38, 0x7e, + 0x81, 0xee, 0xab, 0xb9, 0x55, 0x68, 0x53, 0xa2, 0xf7, 0x54, 0xb8, 0x04, 0x3d, 0x74, 0x47, 0x2d, + 0x4b, 0xa7, 0x25, 0xcb, 0xe9, 0x3a, 0xe5, 0x3a, 0x39, 0xf5, 0x3a, 0x39, 0x67, 0x35, 0xe1, 0xb5, + 0xaf, 0x7f, 0xf4, 0x1a, 0x57, 0x3f, 0x7b, 0x86, 0x7f, 0x2b, 0xb3, 0xbf, 0x6f, 0xa0, 0x7d, 0x6d, + 0x83, 0xf1, 0x7b, 0xf4, 0x20, 0xe2, 0xd9, 0x38, 0x61, 0x91, 0xac, 0x3b, 0x4c, 0x78, 0x74, 0x51, + 0x75, 0xcb, 0xfe, 0xeb, 0xb8, 0x3c, 0x41, 0xfa, 0x3b, 0x2b, 0x62, 0x19, 0xc1, 0x4f, 0xd1, 0xdd, + 0x88, 0xa7, 0x29, 0xcf, 0x82, 0x09, 0x15, 0x9c, 0xec, 0xa2, 0xe9, 0x6f, 0x97, 0xc1, 0x13, 0x19, + 0xc3, 0x67, 0x68, 0x37, 0xbc, 0xfc, 0x42, 0x32, 0x60, 0x19, 0x0d, 0x94, 0xe7, 0xa2, 0x63, 0xf6, + 0xcd, 0xc1, 0xd6, 0xe1, 0x13, 0x6d, 0xc7, 0x6b, 0xd2, 0x7f, 0xa8, 0xe4, 0x2a, 0x56, 0x68, 0x86, + 0xd0, 0xd4, 0x0c, 0xe1, 0x7f, 0xf4, 0xd6, 0x47, 0xdb, 0x75, 0x27, 0x4f, 0x59, 0x01, 0xd8, 0x43, + 0xed, 0x95, 0x7f, 0x98, 0xf0, 0xd2, 0xd7, 0x79, 0x51, 0x5b, 0xdc, 0x14, 0x17, 0xfb, 0x4a, 0xe7, + 0x7d, 0xbc, 0x5e, 0x58, 0xc6, 0xcd, 0xc2, 0x32, 0x7e, 0x2d, 0x2c, 0xe3, 0x6a, 0x69, 0x35, 0x6e, + 0x96, 0x56, 0xe3, 0xdb, 0xd2, 0x6a, 0x7c, 0x7a, 0x1d, 0x33, 0x98, 0xcc, 0x42, 0x71, 0xa3, 0xab, + 0x9e, 0x03, 0xf5, 0x41, 0x72, 0xe6, 0xae, 0x7f, 0x24, 0xc2, 0x4d, 0xe9, 0xe7, 0xe8, 0x4f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x50, 0xf2, 0xed, 0xb6, 0xdf, 0x04, 0x00, 0x00, +} + +func (m *Evidence) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Evidence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Evidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Evidence_DuplicateVoteEvidence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Evidence_DuplicateVoteEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.DuplicateVoteEvidence != nil { + { + size, err := m.DuplicateVoteEvidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Evidence_LightClientAttackEvidence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Evidence_LightClientAttackEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.LightClientAttackEvidence != nil { + { + size, err := m.LightClientAttackEvidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *DuplicateVoteEvidence) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DuplicateVoteEvidence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DuplicateVoteEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n3, err3 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintEvidence(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0x2a + if m.ValidatorPower != 0 { + i = encodeVarintEvidence(dAtA, i, uint64(m.ValidatorPower)) + i-- + dAtA[i] = 0x20 + } + if m.TotalVotingPower != 0 { + i = encodeVarintEvidence(dAtA, i, uint64(m.TotalVotingPower)) + i-- + dAtA[i] = 0x18 + } + if m.VoteB != nil { + { + size, err := m.VoteB.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.VoteA != nil { + { + size, err := m.VoteA.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *LightClientAttackEvidence) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LightClientAttackEvidence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LightClientAttackEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n6, err6 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) + if err6 != nil { + return 0, err6 + } + i -= n6 + i = encodeVarintEvidence(dAtA, i, uint64(n6)) + i-- + dAtA[i] = 0x2a + if m.TotalVotingPower != 0 { + i = encodeVarintEvidence(dAtA, i, uint64(m.TotalVotingPower)) + i-- + dAtA[i] = 0x20 + } + if len(m.ByzantineValidators) > 0 { + for iNdEx := len(m.ByzantineValidators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ByzantineValidators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.CommonHeight != 0 { + i = encodeVarintEvidence(dAtA, i, uint64(m.CommonHeight)) + i-- + dAtA[i] = 0x10 + } + if m.ConflictingBlock != nil { + { + size, err := m.ConflictingBlock.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EvidenceList) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EvidenceList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EvidenceList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Evidence) > 0 { + for iNdEx := len(m.Evidence) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Evidence[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvidence(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintEvidence(dAtA []byte, offset int, v uint64) int { + offset -= sovEvidence(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Evidence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Evidence_DuplicateVoteEvidence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DuplicateVoteEvidence != nil { + l = m.DuplicateVoteEvidence.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + return n +} +func (m *Evidence_LightClientAttackEvidence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.LightClientAttackEvidence != nil { + l = m.LightClientAttackEvidence.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + return n +} +func (m *DuplicateVoteEvidence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.VoteA != nil { + l = m.VoteA.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + if m.VoteB != nil { + l = m.VoteB.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + if m.TotalVotingPower != 0 { + n += 1 + sovEvidence(uint64(m.TotalVotingPower)) + } + if m.ValidatorPower != 0 { + n += 1 + sovEvidence(uint64(m.ValidatorPower)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovEvidence(uint64(l)) + return n +} + +func (m *LightClientAttackEvidence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ConflictingBlock != nil { + l = m.ConflictingBlock.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + if m.CommonHeight != 0 { + n += 1 + sovEvidence(uint64(m.CommonHeight)) + } + if len(m.ByzantineValidators) > 0 { + for _, e := range m.ByzantineValidators { + l = e.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + } + if m.TotalVotingPower != 0 { + n += 1 + sovEvidence(uint64(m.TotalVotingPower)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovEvidence(uint64(l)) + return n +} + +func (m *EvidenceList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Evidence) > 0 { + for _, e := range m.Evidence { + l = e.Size() + n += 1 + l + sovEvidence(uint64(l)) + } + } + return n +} + +func sovEvidence(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozEvidence(x uint64) (n int) { + return sovEvidence(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Evidence) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Evidence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Evidence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DuplicateVoteEvidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &DuplicateVoteEvidence{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Evidence_DuplicateVoteEvidence{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LightClientAttackEvidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &LightClientAttackEvidence{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Evidence_LightClientAttackEvidence{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvidence(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvidence + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DuplicateVoteEvidence) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DuplicateVoteEvidence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DuplicateVoteEvidence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteA", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.VoteA == nil { + m.VoteA = &Vote{} + } + if err := m.VoteA.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteB", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.VoteB == nil { + m.VoteB = &Vote{} + } + if err := m.VoteB.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalVotingPower", wireType) + } + m.TotalVotingPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalVotingPower |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorPower", wireType) + } + m.ValidatorPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ValidatorPower |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvidence(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvidence + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LightClientAttackEvidence) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LightClientAttackEvidence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LightClientAttackEvidence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConflictingBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConflictingBlock == nil { + m.ConflictingBlock = &LightBlock{} + } + if err := m.ConflictingBlock.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CommonHeight", wireType) + } + m.CommonHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CommonHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ByzantineValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ByzantineValidators = append(m.ByzantineValidators, &Validator{}) + if err := m.ByzantineValidators[len(m.ByzantineValidators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalVotingPower", wireType) + } + m.TotalVotingPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalVotingPower |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvidence(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvidence + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EvidenceList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EvidenceList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EvidenceList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvidence + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvidence + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvidence + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Evidence = append(m.Evidence, Evidence{}) + if err := m.Evidence[len(m.Evidence)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvidence(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvidence + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipEvidence(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvidence + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvidence + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvidence + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthEvidence + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupEvidence + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthEvidence + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthEvidence = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowEvidence = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupEvidence = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/tendermint/types/params.pb.go b/api/cometbft/types/v1beta1/params.pb.go similarity index 74% rename from proto/tendermint/types/params.pb.go rename to api/cometbft/types/v1beta1/params.pb.go index 3184fdd1a1c..b12f31e022e 100644 --- a/proto/tendermint/types/params.pb.go +++ b/api/cometbft/types/v1beta1/params.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/types/params.proto +// source: cometbft/types/v1beta1/params.proto -package types +package v1beta1 import ( fmt "fmt" @@ -30,18 +30,17 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // ConsensusParams contains consensus critical parameters that determine the // validity of blocks. type ConsensusParams struct { - Block *BlockParams `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Evidence *EvidenceParams `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence,omitempty"` - Validator *ValidatorParams `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator,omitempty"` - Version *VersionParams `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` - Abci *ABCIParams `protobuf:"bytes,5,opt,name=abci,proto3" json:"abci,omitempty"` + Block BlockParams `protobuf:"bytes,1,opt,name=block,proto3" json:"block"` + Evidence EvidenceParams `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence"` + Validator ValidatorParams `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator"` + Version VersionParams `protobuf:"bytes,4,opt,name=version,proto3" json:"version"` } func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } func (*ConsensusParams) ProtoMessage() {} func (*ConsensusParams) Descriptor() ([]byte, []int) { - return fileDescriptor_e12598271a686f57, []int{0} + return fileDescriptor_be5c3dceb37e69cf, []int{0} } func (m *ConsensusParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -70,39 +69,32 @@ func (m *ConsensusParams) XXX_DiscardUnknown() { var xxx_messageInfo_ConsensusParams proto.InternalMessageInfo -func (m *ConsensusParams) GetBlock() *BlockParams { +func (m *ConsensusParams) GetBlock() BlockParams { if m != nil { return m.Block } - return nil + return BlockParams{} } -func (m *ConsensusParams) GetEvidence() *EvidenceParams { +func (m *ConsensusParams) GetEvidence() EvidenceParams { if m != nil { return m.Evidence } - return nil + return EvidenceParams{} } -func (m *ConsensusParams) GetValidator() *ValidatorParams { +func (m *ConsensusParams) GetValidator() ValidatorParams { if m != nil { return m.Validator } - return nil + return ValidatorParams{} } -func (m *ConsensusParams) GetVersion() *VersionParams { +func (m *ConsensusParams) GetVersion() VersionParams { if m != nil { return m.Version } - return nil -} - -func (m *ConsensusParams) GetAbci() *ABCIParams { - if m != nil { - return m.Abci - } - return nil + return VersionParams{} } // BlockParams contains limits on the block size. @@ -113,13 +105,18 @@ type BlockParams struct { // Max gas per block. // Note: must be greater or equal to -1 MaxGas int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` + // Minimum time increment between consecutive blocks (in milliseconds) If the + // block header timestamp is ahead of the system clock, decrease this value. + // + // Not exposed to the application. + TimeIotaMs int64 `protobuf:"varint,3,opt,name=time_iota_ms,json=timeIotaMs,proto3" json:"time_iota_ms,omitempty"` } func (m *BlockParams) Reset() { *m = BlockParams{} } func (m *BlockParams) String() string { return proto.CompactTextString(m) } func (*BlockParams) ProtoMessage() {} func (*BlockParams) Descriptor() ([]byte, []int) { - return fileDescriptor_e12598271a686f57, []int{1} + return fileDescriptor_be5c3dceb37e69cf, []int{1} } func (m *BlockParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -162,6 +159,13 @@ func (m *BlockParams) GetMaxGas() int64 { return 0 } +func (m *BlockParams) GetTimeIotaMs() int64 { + if m != nil { + return m.TimeIotaMs + } + return 0 +} + // EvidenceParams determine how we handle evidence of malfeasance. type EvidenceParams struct { // Max age of evidence, in blocks. @@ -185,7 +189,7 @@ func (m *EvidenceParams) Reset() { *m = EvidenceParams{} } func (m *EvidenceParams) String() string { return proto.CompactTextString(m) } func (*EvidenceParams) ProtoMessage() {} func (*EvidenceParams) Descriptor() ([]byte, []int) { - return fileDescriptor_e12598271a686f57, []int{2} + return fileDescriptor_be5c3dceb37e69cf, []int{2} } func (m *EvidenceParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -245,7 +249,7 @@ func (m *ValidatorParams) Reset() { *m = ValidatorParams{} } func (m *ValidatorParams) String() string { return proto.CompactTextString(m) } func (*ValidatorParams) ProtoMessage() {} func (*ValidatorParams) Descriptor() ([]byte, []int) { - return fileDescriptor_e12598271a686f57, []int{3} + return fileDescriptor_be5c3dceb37e69cf, []int{3} } func (m *ValidatorParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -283,6 +287,7 @@ func (m *ValidatorParams) GetPubKeyTypes() []string { // VersionParams contains the ABCI application version. type VersionParams struct { + // Was named app_version in Tendermint 0.34 App uint64 `protobuf:"varint,1,opt,name=app,proto3" json:"app,omitempty"` } @@ -290,7 +295,7 @@ func (m *VersionParams) Reset() { *m = VersionParams{} } func (m *VersionParams) String() string { return proto.CompactTextString(m) } func (*VersionParams) ProtoMessage() {} func (*VersionParams) Descriptor() ([]byte, []int) { - return fileDescriptor_e12598271a686f57, []int{4} + return fileDescriptor_be5c3dceb37e69cf, []int{4} } func (m *VersionParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -338,7 +343,7 @@ func (m *HashedParams) Reset() { *m = HashedParams{} } func (m *HashedParams) String() string { return proto.CompactTextString(m) } func (*HashedParams) ProtoMessage() {} func (*HashedParams) Descriptor() ([]byte, []int) { - return fileDescriptor_e12598271a686f57, []int{5} + return fileDescriptor_be5c3dceb37e69cf, []int{5} } func (m *HashedParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -381,110 +386,56 @@ func (m *HashedParams) GetBlockMaxGas() int64 { return 0 } -// ABCIParams configure functionality specific to the Application Blockchain Interface. -type ABCIParams struct { - // vote_extensions_enable_height configures the first height during which - // vote extensions will be enabled. During this specified height, and for all - // subsequent heights, precommit messages that do not contain valid extension data - // will be considered invalid. Prior to this height, vote extensions will not - // be used or accepted by validators on the network. - // - // Once enabled, vote extensions will be created by the application in ExtendVote, - // passed to the application for validation in VerifyVoteExtension and given - // to the application to use when proposing a block during PrepareProposal. - VoteExtensionsEnableHeight int64 `protobuf:"varint,1,opt,name=vote_extensions_enable_height,json=voteExtensionsEnableHeight,proto3" json:"vote_extensions_enable_height,omitempty"` -} - -func (m *ABCIParams) Reset() { *m = ABCIParams{} } -func (m *ABCIParams) String() string { return proto.CompactTextString(m) } -func (*ABCIParams) ProtoMessage() {} -func (*ABCIParams) Descriptor() ([]byte, []int) { - return fileDescriptor_e12598271a686f57, []int{6} -} -func (m *ABCIParams) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ABCIParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ABCIParams.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ABCIParams) XXX_Merge(src proto.Message) { - xxx_messageInfo_ABCIParams.Merge(m, src) -} -func (m *ABCIParams) XXX_Size() int { - return m.Size() -} -func (m *ABCIParams) XXX_DiscardUnknown() { - xxx_messageInfo_ABCIParams.DiscardUnknown(m) -} - -var xxx_messageInfo_ABCIParams proto.InternalMessageInfo - -func (m *ABCIParams) GetVoteExtensionsEnableHeight() int64 { - if m != nil { - return m.VoteExtensionsEnableHeight - } - return 0 +func init() { + proto.RegisterType((*ConsensusParams)(nil), "cometbft.types.v1beta1.ConsensusParams") + proto.RegisterType((*BlockParams)(nil), "cometbft.types.v1beta1.BlockParams") + proto.RegisterType((*EvidenceParams)(nil), "cometbft.types.v1beta1.EvidenceParams") + proto.RegisterType((*ValidatorParams)(nil), "cometbft.types.v1beta1.ValidatorParams") + proto.RegisterType((*VersionParams)(nil), "cometbft.types.v1beta1.VersionParams") + proto.RegisterType((*HashedParams)(nil), "cometbft.types.v1beta1.HashedParams") } func init() { - proto.RegisterType((*ConsensusParams)(nil), "tendermint.types.ConsensusParams") - proto.RegisterType((*BlockParams)(nil), "tendermint.types.BlockParams") - proto.RegisterType((*EvidenceParams)(nil), "tendermint.types.EvidenceParams") - proto.RegisterType((*ValidatorParams)(nil), "tendermint.types.ValidatorParams") - proto.RegisterType((*VersionParams)(nil), "tendermint.types.VersionParams") - proto.RegisterType((*HashedParams)(nil), "tendermint.types.HashedParams") - proto.RegisterType((*ABCIParams)(nil), "tendermint.types.ABCIParams") -} - -func init() { proto.RegisterFile("tendermint/types/params.proto", fileDescriptor_e12598271a686f57) } - -var fileDescriptor_e12598271a686f57 = []byte{ - // 576 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x93, 0x3f, 0x6f, 0xd3, 0x4e, - 0x18, 0xc7, 0x73, 0x75, 0xda, 0xa6, 0x4f, 0x7e, 0x69, 0xa2, 0xd3, 0x4f, 0xc2, 0x14, 0xe2, 0x04, - 0x0f, 0xa8, 0x52, 0x25, 0x1b, 0x91, 0x09, 0x84, 0x54, 0x25, 0x25, 0x6a, 0x0b, 0x2a, 0x7f, 0x2c, - 0xc4, 0xd0, 0xc5, 0x3a, 0x27, 0x57, 0xc7, 0x6a, 0xec, 0xb3, 0x7c, 0xe7, 0x28, 0x79, 0x17, 0x8c, - 0x8c, 0x1d, 0x61, 0x65, 0xe2, 0x25, 0x74, 0xec, 0xc8, 0x04, 0x28, 0x59, 0x78, 0x19, 0xc8, 0x67, - 0xbb, 0x6e, 0x12, 0xb6, 0xbb, 0x7b, 0x3e, 0x9f, 0xfb, 0xf3, 0x7d, 0x74, 0xd0, 0x14, 0x34, 0x18, - 0xd2, 0xc8, 0xf7, 0x02, 0x61, 0x8a, 0x59, 0x48, 0xb9, 0x19, 0x92, 0x88, 0xf8, 0xdc, 0x08, 0x23, - 0x26, 0x18, 0x6e, 0x14, 0x65, 0x43, 0x96, 0xf7, 0xfe, 0x77, 0x99, 0xcb, 0x64, 0xd1, 0x4c, 0x46, - 0x29, 0xb7, 0xa7, 0xb9, 0x8c, 0xb9, 0x63, 0x6a, 0xca, 0x99, 0x13, 0x5f, 0x98, 0xc3, 0x38, 0x22, - 0xc2, 0x63, 0x41, 0x5a, 0xd7, 0xbf, 0x6d, 0x40, 0xfd, 0x88, 0x05, 0x9c, 0x06, 0x3c, 0xe6, 0xef, - 0xe4, 0x09, 0xb8, 0x03, 0x9b, 0xce, 0x98, 0x0d, 0x2e, 0x55, 0xd4, 0x46, 0xfb, 0xd5, 0xa7, 0x4d, - 0x63, 0xf5, 0x2c, 0xa3, 0x97, 0x94, 0x53, 0xda, 0x4a, 0x59, 0xfc, 0x02, 0x2a, 0x74, 0xe2, 0x0d, - 0x69, 0x30, 0xa0, 0xea, 0x86, 0xf4, 0xda, 0xeb, 0x5e, 0x3f, 0x23, 0x32, 0xf5, 0xd6, 0xc0, 0x87, - 0xb0, 0x33, 0x21, 0x63, 0x6f, 0x48, 0x04, 0x8b, 0x54, 0x45, 0xea, 0x8f, 0xd6, 0xf5, 0x8f, 0x39, - 0x92, 0xf9, 0x85, 0x83, 0x9f, 0xc1, 0xf6, 0x84, 0x46, 0xdc, 0x63, 0x81, 0x5a, 0x96, 0x7a, 0xeb, - 0x1f, 0x7a, 0x0a, 0x64, 0x72, 0xce, 0xe3, 0x27, 0x50, 0x26, 0xce, 0xc0, 0x53, 0x37, 0xa5, 0xf7, - 0x70, 0xdd, 0xeb, 0xf6, 0x8e, 0x4e, 0x33, 0x49, 0x92, 0xfa, 0x29, 0x54, 0xef, 0x24, 0x80, 0x1f, - 0xc0, 0x8e, 0x4f, 0xa6, 0xb6, 0x33, 0x13, 0x94, 0xcb, 0xcc, 0x14, 0xab, 0xe2, 0x93, 0x69, 0x2f, - 0x99, 0xe3, 0x7b, 0xb0, 0x9d, 0x14, 0x5d, 0xc2, 0x65, 0x2c, 0x8a, 0xb5, 0xe5, 0x93, 0xe9, 0x31, - 0xe1, 0xaf, 0xca, 0x15, 0xa5, 0x51, 0xd6, 0xbf, 0x22, 0xd8, 0x5d, 0x4e, 0x05, 0x1f, 0x00, 0x4e, - 0x0c, 0xe2, 0x52, 0x3b, 0x88, 0x7d, 0x5b, 0xc6, 0x9b, 0xef, 0x5b, 0xf7, 0xc9, 0xb4, 0xeb, 0xd2, - 0x37, 0xb1, 0x2f, 0x2f, 0xc0, 0xf1, 0x19, 0x34, 0x72, 0x38, 0xef, 0x6c, 0x16, 0xff, 0x7d, 0x23, - 0x6d, 0xbd, 0x91, 0xb7, 0xde, 0x78, 0x99, 0x01, 0xbd, 0xca, 0xf5, 0xcf, 0x56, 0xe9, 0xf3, 0xaf, - 0x16, 0xb2, 0x76, 0xd3, 0xfd, 0xf2, 0xca, 0xf2, 0x53, 0x94, 0xe5, 0xa7, 0xe8, 0x87, 0x50, 0x5f, - 0xe9, 0x00, 0xd6, 0xa1, 0x16, 0xc6, 0x8e, 0x7d, 0x49, 0x67, 0xb6, 0xcc, 0x4a, 0x45, 0x6d, 0x65, - 0x7f, 0xc7, 0xaa, 0x86, 0xb1, 0xf3, 0x9a, 0xce, 0x3e, 0x24, 0x4b, 0xcf, 0x2b, 0xdf, 0xaf, 0x5a, - 0xe8, 0xcf, 0x55, 0x0b, 0xe9, 0x07, 0x50, 0x5b, 0xea, 0x01, 0x6e, 0x80, 0x42, 0xc2, 0x50, 0xbe, - 0xad, 0x6c, 0x25, 0xc3, 0x3b, 0xf0, 0x39, 0xfc, 0x77, 0x42, 0xf8, 0x88, 0x0e, 0x33, 0xf6, 0x31, - 0xd4, 0x65, 0x14, 0xf6, 0x6a, 0xd6, 0x35, 0xb9, 0x7c, 0x96, 0x07, 0xae, 0x43, 0xad, 0xe0, 0x8a, - 0xd8, 0xab, 0x39, 0x75, 0x4c, 0xb8, 0xfe, 0x16, 0xa0, 0x68, 0x2a, 0xee, 0x42, 0x73, 0xc2, 0x04, - 0xb5, 0xe9, 0x54, 0xd0, 0x20, 0xb9, 0x1d, 0xb7, 0x69, 0x40, 0x9c, 0x31, 0xb5, 0x47, 0xd4, 0x73, - 0x47, 0x22, 0x3b, 0x67, 0x2f, 0x81, 0xfa, 0xb7, 0x4c, 0x5f, 0x22, 0x27, 0x92, 0xe8, 0xbd, 0xff, - 0x32, 0xd7, 0xd0, 0xf5, 0x5c, 0x43, 0x37, 0x73, 0x0d, 0xfd, 0x9e, 0x6b, 0xe8, 0xd3, 0x42, 0x2b, - 0xdd, 0x2c, 0xb4, 0xd2, 0x8f, 0x85, 0x56, 0x3a, 0xef, 0xb8, 0x9e, 0x18, 0xc5, 0x8e, 0x31, 0x60, - 0xbe, 0x39, 0x60, 0x3e, 0x15, 0xce, 0x85, 0x28, 0x06, 0xe9, 0x9f, 0x5d, 0xfd, 0xee, 0xce, 0x96, - 0x5c, 0xef, 0xfc, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xb9, 0xe8, 0xce, 0x9a, 0x09, 0x04, 0x00, 0x00, + proto.RegisterFile("cometbft/types/v1beta1/params.proto", fileDescriptor_be5c3dceb37e69cf) +} + +var fileDescriptor_be5c3dceb37e69cf = []byte{ + // 545 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x93, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0xeb, 0xa5, 0x6c, 0xed, 0xeb, 0xba, 0x4e, 0x16, 0x82, 0x32, 0xa4, 0xb4, 0xca, 0xc4, + 0x98, 0x34, 0x29, 0xd1, 0xe0, 0x80, 0xc4, 0x65, 0xa2, 0x30, 0x6d, 0x68, 0x2a, 0x42, 0x11, 0x70, + 0xd8, 0x25, 0x72, 0x5a, 0x2f, 0x8b, 0xd6, 0xc4, 0x51, 0xed, 0x54, 0xed, 0xb7, 0xe0, 0xc8, 0x71, + 0x47, 0xb8, 0x71, 0xe4, 0x23, 0xec, 0xb8, 0x23, 0x27, 0x40, 0xed, 0x85, 0x8f, 0x31, 0xd9, 0x89, + 0xdb, 0x65, 0x5a, 0x6f, 0x8e, 0xfd, 0x7b, 0x7f, 0xe7, 0xff, 0x7f, 0xcf, 0xb0, 0xdd, 0x63, 0x11, + 0x15, 0xfe, 0x99, 0x70, 0xc4, 0x24, 0xa1, 0xdc, 0x19, 0xed, 0xfb, 0x54, 0x90, 0x7d, 0x27, 0x21, + 0x43, 0x12, 0x71, 0x3b, 0x19, 0x32, 0xc1, 0xf0, 0x23, 0x0d, 0xd9, 0x0a, 0xb2, 0x73, 0x68, 0xeb, + 0x61, 0xc0, 0x02, 0xa6, 0x10, 0x47, 0xae, 0x32, 0x7a, 0xcb, 0x0c, 0x18, 0x0b, 0x06, 0xd4, 0x51, + 0x5f, 0x7e, 0x7a, 0xe6, 0xf4, 0xd3, 0x21, 0x11, 0x21, 0x8b, 0xb3, 0x73, 0xeb, 0xe7, 0x0a, 0x34, + 0xde, 0xb2, 0x98, 0xd3, 0x98, 0xa7, 0xfc, 0xa3, 0xba, 0x07, 0x1f, 0xc0, 0x03, 0x7f, 0xc0, 0x7a, + 0x17, 0x4d, 0xd4, 0x46, 0xbb, 0xb5, 0x17, 0xdb, 0xf6, 0xfd, 0x37, 0xda, 0x1d, 0x09, 0x65, 0x35, + 0x9d, 0xf2, 0xd5, 0x9f, 0x56, 0xc9, 0xcd, 0xea, 0xf0, 0x31, 0x54, 0xe8, 0x28, 0xec, 0xd3, 0xb8, + 0x47, 0x9b, 0x2b, 0x4a, 0x63, 0x67, 0x99, 0xc6, 0x61, 0xce, 0x15, 0x64, 0xe6, 0xd5, 0xf8, 0x04, + 0xaa, 0x23, 0x32, 0x08, 0xfb, 0x44, 0xb0, 0x61, 0xd3, 0x50, 0x52, 0xcf, 0x97, 0x49, 0x7d, 0xd1, + 0x60, 0x41, 0x6b, 0x51, 0x8f, 0x0f, 0x61, 0x6d, 0x44, 0x87, 0x3c, 0x64, 0x71, 0xb3, 0xac, 0xa4, + 0x9e, 0x2d, 0x95, 0xca, 0xb0, 0x82, 0x90, 0xae, 0xb5, 0x28, 0xd4, 0x6e, 0x39, 0xc7, 0x4f, 0xa1, + 0x1a, 0x91, 0xb1, 0xe7, 0x4f, 0x04, 0xe5, 0x2a, 0x31, 0xc3, 0xad, 0x44, 0x64, 0xdc, 0x91, 0xdf, + 0xf8, 0x31, 0xac, 0xc9, 0xc3, 0x80, 0x70, 0x15, 0x84, 0xe1, 0xae, 0x46, 0x64, 0x7c, 0x44, 0x38, + 0x6e, 0xc3, 0xba, 0x08, 0x23, 0xea, 0x85, 0x4c, 0x10, 0x2f, 0xe2, 0xca, 0x9b, 0xe1, 0x82, 0xdc, + 0x7b, 0xcf, 0x04, 0xe9, 0x72, 0xeb, 0x07, 0x82, 0x8d, 0x62, 0x3a, 0x78, 0x0f, 0xb0, 0x54, 0x23, + 0x01, 0xf5, 0xe2, 0x34, 0xf2, 0x54, 0xd8, 0xfa, 0xce, 0x46, 0x44, 0xc6, 0x6f, 0x02, 0xfa, 0x21, + 0x8d, 0xd4, 0xcf, 0x71, 0xdc, 0x85, 0x4d, 0x0d, 0xeb, 0x9e, 0xe7, 0xcd, 0x78, 0x62, 0x67, 0x43, + 0x61, 0xeb, 0xa1, 0xb0, 0xdf, 0xe5, 0x40, 0xa7, 0x22, 0xad, 0x7e, 0xfb, 0xdb, 0x42, 0xee, 0x46, + 0xa6, 0xa7, 0x4f, 0x8a, 0x36, 0x8d, 0xa2, 0x4d, 0xeb, 0x00, 0x1a, 0x77, 0xd2, 0xc7, 0x16, 0xd4, + 0x93, 0xd4, 0xf7, 0x2e, 0xe8, 0xc4, 0x53, 0xd9, 0x36, 0x51, 0xdb, 0xd8, 0xad, 0xba, 0xb5, 0x24, + 0xf5, 0x4f, 0xe8, 0xe4, 0x93, 0xdc, 0x7a, 0x5d, 0xf9, 0x75, 0xd9, 0x42, 0xff, 0x2f, 0x5b, 0xc8, + 0xda, 0x83, 0x7a, 0x21, 0x73, 0xbc, 0x09, 0x06, 0x49, 0x12, 0xe5, 0xad, 0xec, 0xca, 0xe5, 0x2d, + 0xf8, 0x14, 0xd6, 0x8f, 0x09, 0x3f, 0xa7, 0xfd, 0x9c, 0xdd, 0x81, 0x86, 0x8a, 0xc2, 0xbb, 0xdb, + 0x87, 0xba, 0xda, 0xee, 0xea, 0x66, 0x58, 0x50, 0x5f, 0x70, 0x8b, 0x96, 0xd4, 0x34, 0x75, 0x44, + 0x78, 0xe7, 0xf3, 0xf7, 0xa9, 0x89, 0xae, 0xa6, 0x26, 0xba, 0x9e, 0x9a, 0xe8, 0xdf, 0xd4, 0x44, + 0x5f, 0x67, 0x66, 0xe9, 0x7a, 0x66, 0x96, 0x7e, 0xcf, 0xcc, 0xd2, 0xe9, 0xab, 0x20, 0x14, 0xe7, + 0xa9, 0x2f, 0xc7, 0xc6, 0x99, 0xbf, 0xd5, 0xf9, 0x82, 0x24, 0xa1, 0x73, 0xff, 0x0b, 0xf6, 0x57, + 0x55, 0xd4, 0x2f, 0x6f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xfd, 0x5e, 0xbe, 0x2b, 0xe2, 0x03, 0x00, + 0x00, } func (this *ConsensusParams) Equal(that interface{}) bool { @@ -506,19 +457,16 @@ func (this *ConsensusParams) Equal(that interface{}) bool { } else if this == nil { return false } - if !this.Block.Equal(that1.Block) { - return false - } - if !this.Evidence.Equal(that1.Evidence) { + if !this.Block.Equal(&that1.Block) { return false } - if !this.Validator.Equal(that1.Validator) { + if !this.Evidence.Equal(&that1.Evidence) { return false } - if !this.Version.Equal(that1.Version) { + if !this.Validator.Equal(&that1.Validator) { return false } - if !this.Abci.Equal(that1.Abci) { + if !this.Version.Equal(&that1.Version) { return false } return true @@ -548,6 +496,9 @@ func (this *BlockParams) Equal(that interface{}) bool { if this.MaxGas != that1.MaxGas { return false } + if this.TimeIotaMs != that1.TimeIotaMs { + return false + } return true } func (this *EvidenceParams) Equal(that interface{}) bool { @@ -660,30 +611,6 @@ func (this *HashedParams) Equal(that interface{}) bool { } return true } -func (this *ABCIParams) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*ABCIParams) - if !ok { - that2, ok := that.(ABCIParams) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if this.VoteExtensionsEnableHeight != that1.VoteExtensionsEnableHeight { - return false - } - return true -} func (m *ConsensusParams) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -704,66 +631,46 @@ func (m *ConsensusParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.Abci != nil { - { - size, err := m.Abci.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a - } - if m.Version != nil { - { - size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0x22 + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) } - if m.Validator != nil { - { - size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0x1a + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) } - if m.Evidence != nil { - { - size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + { + size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0x12 + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) } - if m.Block != nil { - { - size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintParams(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + { + size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } - i-- - dAtA[i] = 0xa + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) } + i-- + dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -787,6 +694,11 @@ func (m *BlockParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.TimeIotaMs != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.TimeIotaMs)) + i-- + dAtA[i] = 0x18 + } if m.MaxGas != 0 { i = encodeVarintParams(dAtA, i, uint64(m.MaxGas)) i-- @@ -825,12 +737,12 @@ func (m *EvidenceParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x18 } - n6, err6 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.MaxAgeDuration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.MaxAgeDuration):]) - if err6 != nil { - return 0, err6 + n5, err5 := github_com_cosmos_gogoproto_types.StdDurationMarshalTo(m.MaxAgeDuration, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdDuration(m.MaxAgeDuration):]) + if err5 != nil { + return 0, err5 } - i -= n6 - i = encodeVarintParams(dAtA, i, uint64(n6)) + i -= n5 + i = encodeVarintParams(dAtA, i, uint64(n5)) i-- dAtA[i] = 0x12 if m.MaxAgeNumBlocks != 0 { @@ -934,34 +846,6 @@ func (m *HashedParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ABCIParams) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ABCIParams) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ABCIParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.VoteExtensionsEnableHeight != 0 { - i = encodeVarintParams(dAtA, i, uint64(m.VoteExtensionsEnableHeight)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - func encodeVarintParams(dAtA []byte, offset int, v uint64) int { offset -= sovParams(v) base := offset @@ -1071,26 +955,14 @@ func (m *ConsensusParams) Size() (n int) { } var l int _ = l - if m.Block != nil { - l = m.Block.Size() - n += 1 + l + sovParams(uint64(l)) - } - if m.Evidence != nil { - l = m.Evidence.Size() - n += 1 + l + sovParams(uint64(l)) - } - if m.Validator != nil { - l = m.Validator.Size() - n += 1 + l + sovParams(uint64(l)) - } - if m.Version != nil { - l = m.Version.Size() - n += 1 + l + sovParams(uint64(l)) - } - if m.Abci != nil { - l = m.Abci.Size() - n += 1 + l + sovParams(uint64(l)) - } + l = m.Block.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.Evidence.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.Validator.Size() + n += 1 + l + sovParams(uint64(l)) + l = m.Version.Size() + n += 1 + l + sovParams(uint64(l)) return n } @@ -1106,6 +978,9 @@ func (m *BlockParams) Size() (n int) { if m.MaxGas != 0 { n += 1 + sovParams(uint64(m.MaxGas)) } + if m.TimeIotaMs != 0 { + n += 1 + sovParams(uint64(m.TimeIotaMs)) + } return n } @@ -1168,18 +1043,6 @@ func (m *HashedParams) Size() (n int) { return n } -func (m *ABCIParams) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.VoteExtensionsEnableHeight != 0 { - n += 1 + sovParams(uint64(m.VoteExtensionsEnableHeight)) - } - return n -} - func sovParams(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1244,9 +1107,6 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Block == nil { - m.Block = &BlockParams{} - } if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1280,9 +1140,6 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Evidence == nil { - m.Evidence = &EvidenceParams{} - } if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1316,9 +1173,6 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Validator == nil { - m.Validator = &ValidatorParams{} - } if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -1352,49 +1206,10 @@ func (m *ConsensusParams) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Version == nil { - m.Version = &VersionParams{} - } if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Abci", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowParams - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthParams - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthParams - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Abci == nil { - m.Abci = &ABCIParams{} - } - if err := m.Abci.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) @@ -1483,6 +1298,25 @@ func (m *BlockParams) Unmarshal(dAtA []byte) error { break } } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TimeIotaMs", wireType) + } + m.TimeIotaMs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TimeIotaMs |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) @@ -1864,75 +1698,6 @@ func (m *HashedParams) Unmarshal(dAtA []byte) error { } return nil } -func (m *ABCIParams) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowParams - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ABCIParams: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ABCIParams: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field VoteExtensionsEnableHeight", wireType) - } - m.VoteExtensionsEnableHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowParams - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.VoteExtensionsEnableHeight |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipParams(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthParams - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func skipParams(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/api/cometbft/types/v1beta1/types.pb.go b/api/cometbft/types/v1beta1/types.pb.go new file mode 100644 index 00000000000..407738b779d --- /dev/null +++ b/api/cometbft/types/v1beta1/types.pb.go @@ -0,0 +1,4543 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/types/v1beta1/types.proto + +package v1beta1 + +import ( + fmt "fmt" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + v11 "github.com/cometbft/cometbft/api/cometbft/version/v1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "github.com/cosmos/gogoproto/types" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// SignedMsgType is a type of signed message in the consensus. +type SignedMsgType int32 + +const ( + // Unknown + UnknownType SignedMsgType = 0 + // Prevote + PrevoteType SignedMsgType = 1 + // Precommit + PrecommitType SignedMsgType = 2 + // Proposal + ProposalType SignedMsgType = 32 +) + +var SignedMsgType_name = map[int32]string{ + 0: "SIGNED_MSG_TYPE_UNKNOWN", + 1: "SIGNED_MSG_TYPE_PREVOTE", + 2: "SIGNED_MSG_TYPE_PRECOMMIT", + 32: "SIGNED_MSG_TYPE_PROPOSAL", +} + +var SignedMsgType_value = map[string]int32{ + "SIGNED_MSG_TYPE_UNKNOWN": 0, + "SIGNED_MSG_TYPE_PREVOTE": 1, + "SIGNED_MSG_TYPE_PRECOMMIT": 2, + "SIGNED_MSG_TYPE_PROPOSAL": 32, +} + +func (x SignedMsgType) String() string { + return proto.EnumName(SignedMsgType_name, int32(x)) +} + +func (SignedMsgType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{0} +} + +// Header of the parts set for a block. +type PartSetHeader struct { + Total uint32 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` +} + +func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } +func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } +func (*PartSetHeader) ProtoMessage() {} +func (*PartSetHeader) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{0} +} +func (m *PartSetHeader) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PartSetHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PartSetHeader.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PartSetHeader) XXX_Merge(src proto.Message) { + xxx_messageInfo_PartSetHeader.Merge(m, src) +} +func (m *PartSetHeader) XXX_Size() int { + return m.Size() +} +func (m *PartSetHeader) XXX_DiscardUnknown() { + xxx_messageInfo_PartSetHeader.DiscardUnknown(m) +} + +var xxx_messageInfo_PartSetHeader proto.InternalMessageInfo + +func (m *PartSetHeader) GetTotal() uint32 { + if m != nil { + return m.Total + } + return 0 +} + +func (m *PartSetHeader) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +// Part of the block. +type Part struct { + Index uint32 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Bytes []byte `protobuf:"bytes,2,opt,name=bytes,proto3" json:"bytes,omitempty"` + Proof v1.Proof `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof"` +} + +func (m *Part) Reset() { *m = Part{} } +func (m *Part) String() string { return proto.CompactTextString(m) } +func (*Part) ProtoMessage() {} +func (*Part) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{1} +} +func (m *Part) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Part) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Part.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Part) XXX_Merge(src proto.Message) { + xxx_messageInfo_Part.Merge(m, src) +} +func (m *Part) XXX_Size() int { + return m.Size() +} +func (m *Part) XXX_DiscardUnknown() { + xxx_messageInfo_Part.DiscardUnknown(m) +} + +var xxx_messageInfo_Part proto.InternalMessageInfo + +func (m *Part) GetIndex() uint32 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *Part) GetBytes() []byte { + if m != nil { + return m.Bytes + } + return nil +} + +func (m *Part) GetProof() v1.Proof { + if m != nil { + return m.Proof + } + return v1.Proof{} +} + +// BlockID defines the unique ID of a block as its hash and its `PartSetHeader`. +type BlockID struct { + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + PartSetHeader PartSetHeader `protobuf:"bytes,2,opt,name=part_set_header,json=partSetHeader,proto3" json:"part_set_header"` +} + +func (m *BlockID) Reset() { *m = BlockID{} } +func (m *BlockID) String() string { return proto.CompactTextString(m) } +func (*BlockID) ProtoMessage() {} +func (*BlockID) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{2} +} +func (m *BlockID) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockID) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockID.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockID) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockID.Merge(m, src) +} +func (m *BlockID) XXX_Size() int { + return m.Size() +} +func (m *BlockID) XXX_DiscardUnknown() { + xxx_messageInfo_BlockID.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockID proto.InternalMessageInfo + +func (m *BlockID) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *BlockID) GetPartSetHeader() PartSetHeader { + if m != nil { + return m.PartSetHeader + } + return PartSetHeader{} +} + +// Header defines the structure of a block header. +type Header struct { + // basic block info + Version v11.Consensus `protobuf:"bytes,1,opt,name=version,proto3" json:"version"` + ChainID string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` + Time time.Time `protobuf:"bytes,4,opt,name=time,proto3,stdtime" json:"time"` + // prev block info + LastBlockId BlockID `protobuf:"bytes,5,opt,name=last_block_id,json=lastBlockId,proto3" json:"last_block_id"` + // hashes of block data + LastCommitHash []byte `protobuf:"bytes,6,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` + DataHash []byte `protobuf:"bytes,7,opt,name=data_hash,json=dataHash,proto3" json:"data_hash,omitempty"` + // hashes from the app output from the prev block + ValidatorsHash []byte `protobuf:"bytes,8,opt,name=validators_hash,json=validatorsHash,proto3" json:"validators_hash,omitempty"` + NextValidatorsHash []byte `protobuf:"bytes,9,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"` + ConsensusHash []byte `protobuf:"bytes,10,opt,name=consensus_hash,json=consensusHash,proto3" json:"consensus_hash,omitempty"` + AppHash []byte `protobuf:"bytes,11,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` + LastResultsHash []byte `protobuf:"bytes,12,opt,name=last_results_hash,json=lastResultsHash,proto3" json:"last_results_hash,omitempty"` + // consensus info + EvidenceHash []byte `protobuf:"bytes,13,opt,name=evidence_hash,json=evidenceHash,proto3" json:"evidence_hash,omitempty"` + ProposerAddress []byte `protobuf:"bytes,14,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"` +} + +func (m *Header) Reset() { *m = Header{} } +func (m *Header) String() string { return proto.CompactTextString(m) } +func (*Header) ProtoMessage() {} +func (*Header) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{3} +} +func (m *Header) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Header.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Header) XXX_Merge(src proto.Message) { + xxx_messageInfo_Header.Merge(m, src) +} +func (m *Header) XXX_Size() int { + return m.Size() +} +func (m *Header) XXX_DiscardUnknown() { + xxx_messageInfo_Header.DiscardUnknown(m) +} + +var xxx_messageInfo_Header proto.InternalMessageInfo + +func (m *Header) GetVersion() v11.Consensus { + if m != nil { + return m.Version + } + return v11.Consensus{} +} + +func (m *Header) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +func (m *Header) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Header) GetTime() time.Time { + if m != nil { + return m.Time + } + return time.Time{} +} + +func (m *Header) GetLastBlockId() BlockID { + if m != nil { + return m.LastBlockId + } + return BlockID{} +} + +func (m *Header) GetLastCommitHash() []byte { + if m != nil { + return m.LastCommitHash + } + return nil +} + +func (m *Header) GetDataHash() []byte { + if m != nil { + return m.DataHash + } + return nil +} + +func (m *Header) GetValidatorsHash() []byte { + if m != nil { + return m.ValidatorsHash + } + return nil +} + +func (m *Header) GetNextValidatorsHash() []byte { + if m != nil { + return m.NextValidatorsHash + } + return nil +} + +func (m *Header) GetConsensusHash() []byte { + if m != nil { + return m.ConsensusHash + } + return nil +} + +func (m *Header) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +func (m *Header) GetLastResultsHash() []byte { + if m != nil { + return m.LastResultsHash + } + return nil +} + +func (m *Header) GetEvidenceHash() []byte { + if m != nil { + return m.EvidenceHash + } + return nil +} + +func (m *Header) GetProposerAddress() []byte { + if m != nil { + return m.ProposerAddress + } + return nil +} + +// Data contains the set of transactions included in the block +type Data struct { + // Txs that will be applied by state @ block.Height+1. + // NOTE: not all txs here are valid. We're just agreeing on the order first. + // This means that block.AppHash does not include these txs. + Txs [][]byte `protobuf:"bytes,1,rep,name=txs,proto3" json:"txs,omitempty"` +} + +func (m *Data) Reset() { *m = Data{} } +func (m *Data) String() string { return proto.CompactTextString(m) } +func (*Data) ProtoMessage() {} +func (*Data) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{4} +} +func (m *Data) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Data) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Data.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Data) XXX_Merge(src proto.Message) { + xxx_messageInfo_Data.Merge(m, src) +} +func (m *Data) XXX_Size() int { + return m.Size() +} +func (m *Data) XXX_DiscardUnknown() { + xxx_messageInfo_Data.DiscardUnknown(m) +} + +var xxx_messageInfo_Data proto.InternalMessageInfo + +func (m *Data) GetTxs() [][]byte { + if m != nil { + return m.Txs + } + return nil +} + +// Vote represents a prevote or precommit vote from validators for +// consensus. +type Vote struct { + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.types.v1beta1.SignedMsgType" json:"type,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,3,opt,name=round,proto3" json:"round,omitempty"` + BlockID BlockID `protobuf:"bytes,4,opt,name=block_id,json=blockId,proto3" json:"block_id"` + Timestamp time.Time `protobuf:"bytes,5,opt,name=timestamp,proto3,stdtime" json:"timestamp"` + ValidatorAddress []byte `protobuf:"bytes,6,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` + ValidatorIndex int32 `protobuf:"varint,7,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty"` + Signature []byte `protobuf:"bytes,8,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (m *Vote) Reset() { *m = Vote{} } +func (m *Vote) String() string { return proto.CompactTextString(m) } +func (*Vote) ProtoMessage() {} +func (*Vote) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{5} +} +func (m *Vote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Vote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Vote.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Vote) XXX_Merge(src proto.Message) { + xxx_messageInfo_Vote.Merge(m, src) +} +func (m *Vote) XXX_Size() int { + return m.Size() +} +func (m *Vote) XXX_DiscardUnknown() { + xxx_messageInfo_Vote.DiscardUnknown(m) +} + +var xxx_messageInfo_Vote proto.InternalMessageInfo + +func (m *Vote) GetType() SignedMsgType { + if m != nil { + return m.Type + } + return UnknownType +} + +func (m *Vote) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Vote) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *Vote) GetBlockID() BlockID { + if m != nil { + return m.BlockID + } + return BlockID{} +} + +func (m *Vote) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +func (m *Vote) GetValidatorAddress() []byte { + if m != nil { + return m.ValidatorAddress + } + return nil +} + +func (m *Vote) GetValidatorIndex() int32 { + if m != nil { + return m.ValidatorIndex + } + return 0 +} + +func (m *Vote) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +// Commit contains the evidence that a block was committed by a set of validators. +type Commit struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` + BlockID BlockID `protobuf:"bytes,3,opt,name=block_id,json=blockId,proto3" json:"block_id"` + Signatures []CommitSig `protobuf:"bytes,4,rep,name=signatures,proto3" json:"signatures"` +} + +func (m *Commit) Reset() { *m = Commit{} } +func (m *Commit) String() string { return proto.CompactTextString(m) } +func (*Commit) ProtoMessage() {} +func (*Commit) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{6} +} +func (m *Commit) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Commit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Commit.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Commit) XXX_Merge(src proto.Message) { + xxx_messageInfo_Commit.Merge(m, src) +} +func (m *Commit) XXX_Size() int { + return m.Size() +} +func (m *Commit) XXX_DiscardUnknown() { + xxx_messageInfo_Commit.DiscardUnknown(m) +} + +var xxx_messageInfo_Commit proto.InternalMessageInfo + +func (m *Commit) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Commit) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *Commit) GetBlockID() BlockID { + if m != nil { + return m.BlockID + } + return BlockID{} +} + +func (m *Commit) GetSignatures() []CommitSig { + if m != nil { + return m.Signatures + } + return nil +} + +// CommitSig is a part of the Vote included in a Commit. +type CommitSig struct { + BlockIdFlag BlockIDFlag `protobuf:"varint,1,opt,name=block_id_flag,json=blockIdFlag,proto3,enum=cometbft.types.v1beta1.BlockIDFlag" json:"block_id_flag,omitempty"` + ValidatorAddress []byte `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` + Timestamp time.Time `protobuf:"bytes,3,opt,name=timestamp,proto3,stdtime" json:"timestamp"` + Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (m *CommitSig) Reset() { *m = CommitSig{} } +func (m *CommitSig) String() string { return proto.CompactTextString(m) } +func (*CommitSig) ProtoMessage() {} +func (*CommitSig) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{7} +} +func (m *CommitSig) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *CommitSig) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_CommitSig.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *CommitSig) XXX_Merge(src proto.Message) { + xxx_messageInfo_CommitSig.Merge(m, src) +} +func (m *CommitSig) XXX_Size() int { + return m.Size() +} +func (m *CommitSig) XXX_DiscardUnknown() { + xxx_messageInfo_CommitSig.DiscardUnknown(m) +} + +var xxx_messageInfo_CommitSig proto.InternalMessageInfo + +func (m *CommitSig) GetBlockIdFlag() BlockIDFlag { + if m != nil { + return m.BlockIdFlag + } + return BlockIDFlagUnknown +} + +func (m *CommitSig) GetValidatorAddress() []byte { + if m != nil { + return m.ValidatorAddress + } + return nil +} + +func (m *CommitSig) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +func (m *CommitSig) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +// Block proposal. +type Proposal struct { + Type SignedMsgType `protobuf:"varint,1,opt,name=type,proto3,enum=cometbft.types.v1beta1.SignedMsgType" json:"type,omitempty"` + Height int64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Round int32 `protobuf:"varint,3,opt,name=round,proto3" json:"round,omitempty"` + PolRound int32 `protobuf:"varint,4,opt,name=pol_round,json=polRound,proto3" json:"pol_round,omitempty"` + BlockID BlockID `protobuf:"bytes,5,opt,name=block_id,json=blockId,proto3" json:"block_id"` + Timestamp time.Time `protobuf:"bytes,6,opt,name=timestamp,proto3,stdtime" json:"timestamp"` + Signature []byte `protobuf:"bytes,7,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (m *Proposal) Reset() { *m = Proposal{} } +func (m *Proposal) String() string { return proto.CompactTextString(m) } +func (*Proposal) ProtoMessage() {} +func (*Proposal) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{8} +} +func (m *Proposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Proposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Proposal.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Proposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_Proposal.Merge(m, src) +} +func (m *Proposal) XXX_Size() int { + return m.Size() +} +func (m *Proposal) XXX_DiscardUnknown() { + xxx_messageInfo_Proposal.DiscardUnknown(m) +} + +var xxx_messageInfo_Proposal proto.InternalMessageInfo + +func (m *Proposal) GetType() SignedMsgType { + if m != nil { + return m.Type + } + return UnknownType +} + +func (m *Proposal) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Proposal) GetRound() int32 { + if m != nil { + return m.Round + } + return 0 +} + +func (m *Proposal) GetPolRound() int32 { + if m != nil { + return m.PolRound + } + return 0 +} + +func (m *Proposal) GetBlockID() BlockID { + if m != nil { + return m.BlockID + } + return BlockID{} +} + +func (m *Proposal) GetTimestamp() time.Time { + if m != nil { + return m.Timestamp + } + return time.Time{} +} + +func (m *Proposal) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +// SignedHeader contains a Header(H) and Commit(H+1) with signatures of validators who signed it. +type SignedHeader struct { + Header *Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + Commit *Commit `protobuf:"bytes,2,opt,name=commit,proto3" json:"commit,omitempty"` +} + +func (m *SignedHeader) Reset() { *m = SignedHeader{} } +func (m *SignedHeader) String() string { return proto.CompactTextString(m) } +func (*SignedHeader) ProtoMessage() {} +func (*SignedHeader) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{9} +} +func (m *SignedHeader) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SignedHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SignedHeader.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SignedHeader) XXX_Merge(src proto.Message) { + xxx_messageInfo_SignedHeader.Merge(m, src) +} +func (m *SignedHeader) XXX_Size() int { + return m.Size() +} +func (m *SignedHeader) XXX_DiscardUnknown() { + xxx_messageInfo_SignedHeader.DiscardUnknown(m) +} + +var xxx_messageInfo_SignedHeader proto.InternalMessageInfo + +func (m *SignedHeader) GetHeader() *Header { + if m != nil { + return m.Header + } + return nil +} + +func (m *SignedHeader) GetCommit() *Commit { + if m != nil { + return m.Commit + } + return nil +} + +// LightBlock is a combination of SignedHeader and ValidatorSet. It is used by light clients. +type LightBlock struct { + SignedHeader *SignedHeader `protobuf:"bytes,1,opt,name=signed_header,json=signedHeader,proto3" json:"signed_header,omitempty"` + ValidatorSet *ValidatorSet `protobuf:"bytes,2,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty"` +} + +func (m *LightBlock) Reset() { *m = LightBlock{} } +func (m *LightBlock) String() string { return proto.CompactTextString(m) } +func (*LightBlock) ProtoMessage() {} +func (*LightBlock) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{10} +} +func (m *LightBlock) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LightBlock) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LightBlock.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *LightBlock) XXX_Merge(src proto.Message) { + xxx_messageInfo_LightBlock.Merge(m, src) +} +func (m *LightBlock) XXX_Size() int { + return m.Size() +} +func (m *LightBlock) XXX_DiscardUnknown() { + xxx_messageInfo_LightBlock.DiscardUnknown(m) +} + +var xxx_messageInfo_LightBlock proto.InternalMessageInfo + +func (m *LightBlock) GetSignedHeader() *SignedHeader { + if m != nil { + return m.SignedHeader + } + return nil +} + +func (m *LightBlock) GetValidatorSet() *ValidatorSet { + if m != nil { + return m.ValidatorSet + } + return nil +} + +// BlockMeta contains meta information about a block. +type BlockMeta struct { + BlockID BlockID `protobuf:"bytes,1,opt,name=block_id,json=blockId,proto3" json:"block_id"` + BlockSize int64 `protobuf:"varint,2,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"` + Header Header `protobuf:"bytes,3,opt,name=header,proto3" json:"header"` + NumTxs int64 `protobuf:"varint,4,opt,name=num_txs,json=numTxs,proto3" json:"num_txs,omitempty"` +} + +func (m *BlockMeta) Reset() { *m = BlockMeta{} } +func (m *BlockMeta) String() string { return proto.CompactTextString(m) } +func (*BlockMeta) ProtoMessage() {} +func (*BlockMeta) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{11} +} +func (m *BlockMeta) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockMeta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockMeta.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockMeta) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockMeta.Merge(m, src) +} +func (m *BlockMeta) XXX_Size() int { + return m.Size() +} +func (m *BlockMeta) XXX_DiscardUnknown() { + xxx_messageInfo_BlockMeta.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockMeta proto.InternalMessageInfo + +func (m *BlockMeta) GetBlockID() BlockID { + if m != nil { + return m.BlockID + } + return BlockID{} +} + +func (m *BlockMeta) GetBlockSize() int64 { + if m != nil { + return m.BlockSize + } + return 0 +} + +func (m *BlockMeta) GetHeader() Header { + if m != nil { + return m.Header + } + return Header{} +} + +func (m *BlockMeta) GetNumTxs() int64 { + if m != nil { + return m.NumTxs + } + return 0 +} + +// TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree. +type TxProof struct { + RootHash []byte `protobuf:"bytes,1,opt,name=root_hash,json=rootHash,proto3" json:"root_hash,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Proof *v1.Proof `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof,omitempty"` +} + +func (m *TxProof) Reset() { *m = TxProof{} } +func (m *TxProof) String() string { return proto.CompactTextString(m) } +func (*TxProof) ProtoMessage() {} +func (*TxProof) Descriptor() ([]byte, []int) { + return fileDescriptor_af6831286a0350e0, []int{12} +} +func (m *TxProof) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TxProof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TxProof.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TxProof) XXX_Merge(src proto.Message) { + xxx_messageInfo_TxProof.Merge(m, src) +} +func (m *TxProof) XXX_Size() int { + return m.Size() +} +func (m *TxProof) XXX_DiscardUnknown() { + xxx_messageInfo_TxProof.DiscardUnknown(m) +} + +var xxx_messageInfo_TxProof proto.InternalMessageInfo + +func (m *TxProof) GetRootHash() []byte { + if m != nil { + return m.RootHash + } + return nil +} + +func (m *TxProof) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *TxProof) GetProof() *v1.Proof { + if m != nil { + return m.Proof + } + return nil +} + +func init() { + proto.RegisterEnum("cometbft.types.v1beta1.SignedMsgType", SignedMsgType_name, SignedMsgType_value) + proto.RegisterType((*PartSetHeader)(nil), "cometbft.types.v1beta1.PartSetHeader") + proto.RegisterType((*Part)(nil), "cometbft.types.v1beta1.Part") + proto.RegisterType((*BlockID)(nil), "cometbft.types.v1beta1.BlockID") + proto.RegisterType((*Header)(nil), "cometbft.types.v1beta1.Header") + proto.RegisterType((*Data)(nil), "cometbft.types.v1beta1.Data") + proto.RegisterType((*Vote)(nil), "cometbft.types.v1beta1.Vote") + proto.RegisterType((*Commit)(nil), "cometbft.types.v1beta1.Commit") + proto.RegisterType((*CommitSig)(nil), "cometbft.types.v1beta1.CommitSig") + proto.RegisterType((*Proposal)(nil), "cometbft.types.v1beta1.Proposal") + proto.RegisterType((*SignedHeader)(nil), "cometbft.types.v1beta1.SignedHeader") + proto.RegisterType((*LightBlock)(nil), "cometbft.types.v1beta1.LightBlock") + proto.RegisterType((*BlockMeta)(nil), "cometbft.types.v1beta1.BlockMeta") + proto.RegisterType((*TxProof)(nil), "cometbft.types.v1beta1.TxProof") +} + +func init() { + proto.RegisterFile("cometbft/types/v1beta1/types.proto", fileDescriptor_af6831286a0350e0) +} + +var fileDescriptor_af6831286a0350e0 = []byte{ + // 1243 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xda, 0x9b, 0xd8, 0x7e, 0xb6, 0x13, 0x77, 0x15, 0xb5, 0xae, 0x0b, 0x8e, 0x71, 0x69, + 0x09, 0x05, 0xd9, 0x4d, 0x10, 0x7f, 0x2a, 0x21, 0xa4, 0xe6, 0x0f, 0xa9, 0xd5, 0x26, 0x31, 0x6b, + 0xb7, 0x08, 0x2e, 0xab, 0xb1, 0x3d, 0xb1, 0x57, 0xb5, 0x77, 0x56, 0x3b, 0x63, 0x93, 0xf4, 0xc0, + 0x19, 0xf5, 0xd4, 0x2f, 0xd0, 0x0b, 0x70, 0xe0, 0x5b, 0x70, 0xed, 0x01, 0xa1, 0xde, 0xe0, 0x54, + 0x50, 0x72, 0xe6, 0xc6, 0x07, 0x40, 0xf3, 0x66, 0x76, 0x6d, 0xb7, 0x71, 0x89, 0x68, 0xc5, 0x6d, + 0xe7, 0xbd, 0xdf, 0x7b, 0xf3, 0xe6, 0xf7, 0x7e, 0xb3, 0x6f, 0xa0, 0xdc, 0x66, 0x03, 0x2a, 0x5a, + 0x07, 0xa2, 0x2a, 0x8e, 0x7c, 0xca, 0xab, 0xa3, 0xb5, 0x16, 0x15, 0x64, 0x4d, 0xad, 0x2a, 0x7e, + 0xc0, 0x04, 0xb3, 0xce, 0x87, 0x98, 0x8a, 0xb2, 0x6a, 0x4c, 0x61, 0xb9, 0xcb, 0xba, 0x0c, 0x21, + 0x55, 0xf9, 0xa5, 0xd0, 0x85, 0x95, 0x2e, 0x63, 0xdd, 0x3e, 0xad, 0xe2, 0xaa, 0x35, 0x3c, 0xa8, + 0x0a, 0x77, 0x40, 0xb9, 0x20, 0x03, 0x5f, 0x03, 0x8a, 0xd1, 0x96, 0xed, 0xe0, 0xc8, 0x17, 0xac, + 0x3a, 0x5a, 0x93, 0x60, 0x76, 0x10, 0x26, 0x88, 0xfc, 0x23, 0x1a, 0x70, 0x97, 0x79, 0x12, 0x30, + 0x51, 0x4f, 0xe1, 0xea, 0x8c, 0x9a, 0x47, 0xa4, 0xef, 0x76, 0x88, 0x60, 0x81, 0xc2, 0x95, 0x6f, + 0x40, 0xb6, 0x4e, 0x02, 0xd1, 0xa0, 0xe2, 0x16, 0x25, 0x1d, 0x1a, 0x58, 0xcb, 0x30, 0x2f, 0x98, + 0x20, 0xfd, 0xbc, 0x51, 0x32, 0x56, 0xb3, 0xb6, 0x5a, 0x58, 0x16, 0x98, 0x3d, 0xc2, 0x7b, 0xf9, + 0x58, 0xc9, 0x58, 0xcd, 0xd8, 0xf8, 0x5d, 0x76, 0xc1, 0x94, 0xa1, 0x32, 0xc2, 0xf5, 0x3a, 0xf4, + 0x30, 0x8c, 0xc0, 0x85, 0xb4, 0xb6, 0x8e, 0x04, 0xe5, 0x3a, 0x44, 0x2d, 0xac, 0x0f, 0x61, 0x1e, + 0x8f, 0x91, 0x8f, 0x97, 0x8c, 0xd5, 0xf4, 0xfa, 0xc5, 0x4a, 0x44, 0x9b, 0x3a, 0x67, 0x65, 0xb4, + 0x56, 0xa9, 0x4b, 0xc0, 0x86, 0xf9, 0xe4, 0xd9, 0xca, 0x9c, 0xad, 0xd0, 0xe5, 0x00, 0x12, 0x1b, + 0x7d, 0xd6, 0xbe, 0x5f, 0xdb, 0x8a, 0x2a, 0x31, 0xc6, 0x95, 0x58, 0x0d, 0x58, 0xf2, 0x49, 0x20, + 0x1c, 0x4e, 0x85, 0xd3, 0xc3, 0x63, 0xe0, 0xae, 0xe9, 0xf5, 0x2b, 0x95, 0xd3, 0xdb, 0x52, 0x99, + 0x3a, 0xb3, 0xde, 0x2b, 0xeb, 0x4f, 0x1a, 0xcb, 0x7f, 0x99, 0xb0, 0xa0, 0x39, 0xf9, 0x0c, 0x12, + 0x9a, 0x66, 0xdc, 0x36, 0xbd, 0x5e, 0x1c, 0xe7, 0xd5, 0x0e, 0x59, 0xf8, 0x26, 0xf3, 0x38, 0xf5, + 0xf8, 0x90, 0xeb, 0x84, 0x61, 0x90, 0x75, 0x15, 0x92, 0xed, 0x1e, 0x71, 0x3d, 0xc7, 0xed, 0x60, + 0x61, 0xa9, 0x8d, 0xf4, 0xf1, 0xb3, 0x95, 0xc4, 0xa6, 0xb4, 0xd5, 0xb6, 0xec, 0x04, 0x3a, 0x6b, + 0x1d, 0xeb, 0x3c, 0x2c, 0xf4, 0xa8, 0xdb, 0xed, 0x09, 0xa4, 0x27, 0x6e, 0xeb, 0x95, 0xf5, 0x09, + 0x98, 0x52, 0x20, 0x79, 0x13, 0x37, 0x2f, 0x54, 0x94, 0x7a, 0x2a, 0xa1, 0x7a, 0x2a, 0xcd, 0x50, + 0x3d, 0x1b, 0x49, 0xb9, 0xf1, 0xa3, 0x3f, 0x56, 0x0c, 0x1b, 0x23, 0xac, 0x1a, 0x64, 0xfb, 0x84, + 0x0b, 0xa7, 0x25, 0xd9, 0x93, 0xdb, 0xcf, 0x63, 0x8a, 0x95, 0x59, 0xbc, 0x68, 0x96, 0xf5, 0x01, + 0xd2, 0x32, 0x56, 0x99, 0x3a, 0xd6, 0x2a, 0xe4, 0x30, 0x55, 0x9b, 0x0d, 0x06, 0xae, 0x70, 0xb0, + 0x09, 0x0b, 0xd8, 0x84, 0x45, 0x69, 0xdf, 0x44, 0xf3, 0x2d, 0xd9, 0x8e, 0x4b, 0x90, 0xea, 0x10, + 0x41, 0x14, 0x24, 0x81, 0x90, 0xa4, 0x34, 0xa0, 0xf3, 0x1d, 0x58, 0x8a, 0x34, 0xc8, 0x15, 0x24, + 0xa9, 0xb2, 0x8c, 0xcd, 0x08, 0xbc, 0x0e, 0xcb, 0x1e, 0x3d, 0x14, 0xce, 0xf3, 0xe8, 0x14, 0xa2, + 0x2d, 0xe9, 0xbb, 0x37, 0x1d, 0x71, 0x05, 0x16, 0xdb, 0x61, 0x0b, 0x14, 0x16, 0x10, 0x9b, 0x8d, + 0xac, 0x08, 0xbb, 0x08, 0x49, 0xe2, 0xfb, 0x0a, 0x90, 0x46, 0x40, 0x82, 0xf8, 0x3e, 0xba, 0xae, + 0xc1, 0x39, 0x3c, 0x63, 0x40, 0xf9, 0xb0, 0x2f, 0x74, 0x92, 0x0c, 0x62, 0x96, 0xa4, 0xc3, 0x56, + 0x76, 0xc4, 0x5e, 0x86, 0x2c, 0x1d, 0xb9, 0x1d, 0xea, 0xb5, 0xa9, 0xc2, 0x65, 0x11, 0x97, 0x09, + 0x8d, 0x08, 0x7a, 0x17, 0x72, 0x7e, 0xc0, 0x7c, 0xc6, 0x69, 0xe0, 0x90, 0x4e, 0x27, 0xa0, 0x9c, + 0xe7, 0x17, 0x55, 0xbe, 0xd0, 0x7e, 0x53, 0x99, 0xcb, 0x79, 0x30, 0xb7, 0x88, 0x20, 0x56, 0x0e, + 0xe2, 0xe2, 0x90, 0xe7, 0x8d, 0x52, 0x7c, 0x35, 0x63, 0xcb, 0xcf, 0xf2, 0xdf, 0x31, 0x30, 0xef, + 0x31, 0x41, 0xad, 0x1b, 0x60, 0xca, 0x76, 0xa1, 0x08, 0x17, 0x67, 0x8b, 0xbb, 0xe1, 0x76, 0x3d, + 0xda, 0xd9, 0xe5, 0xdd, 0xe6, 0x91, 0x4f, 0x6d, 0x0c, 0x99, 0x90, 0x56, 0x6c, 0x4a, 0x5a, 0xcb, + 0x30, 0x1f, 0xb0, 0xa1, 0xd7, 0x41, 0xc5, 0xcd, 0xdb, 0x6a, 0x61, 0xdd, 0x86, 0x64, 0xa4, 0x18, + 0xf3, 0x6c, 0x8a, 0x59, 0x92, 0x8a, 0x91, 0xaa, 0xd6, 0x06, 0x3b, 0xd1, 0xd2, 0xc2, 0xd9, 0x80, + 0x54, 0xf4, 0x7b, 0xd3, 0xfa, 0x3b, 0x9b, 0x84, 0xc7, 0x61, 0xd6, 0x7b, 0x70, 0x2e, 0xd2, 0x41, + 0x44, 0xa4, 0x52, 0x5f, 0x2e, 0x72, 0x68, 0x26, 0xa7, 0x24, 0xe6, 0xa8, 0x5f, 0x53, 0x02, 0x4f, + 0x37, 0x96, 0x58, 0x0d, 0xff, 0x51, 0x6f, 0x40, 0x8a, 0xbb, 0x5d, 0x8f, 0x88, 0x61, 0x40, 0xb5, + 0x0a, 0xc7, 0x86, 0xf2, 0x2f, 0x06, 0x2c, 0x28, 0x55, 0x4f, 0xb0, 0x67, 0x9c, 0xce, 0x5e, 0x6c, + 0x16, 0x7b, 0xf1, 0x57, 0x65, 0x6f, 0x07, 0x20, 0x2a, 0x89, 0xe7, 0xcd, 0x52, 0x7c, 0x35, 0xbd, + 0xfe, 0xd6, 0xac, 0x74, 0xaa, 0xdc, 0x86, 0xdb, 0xd5, 0x17, 0x78, 0x22, 0xb4, 0x7c, 0x62, 0x40, + 0x2a, 0xf2, 0x5b, 0x3b, 0x90, 0x0d, 0x6b, 0x74, 0x0e, 0xfa, 0xa4, 0xab, 0x35, 0x75, 0xf9, 0x5f, + 0x0a, 0xfd, 0xbc, 0x4f, 0xba, 0x76, 0x5a, 0xd7, 0x26, 0x17, 0xa7, 0x77, 0x26, 0x36, 0xa3, 0x33, + 0x53, 0x52, 0x88, 0xff, 0x37, 0x29, 0x4c, 0x35, 0xcd, 0x7c, 0xbe, 0x69, 0x3f, 0xc7, 0x20, 0x59, + 0xc7, 0x9b, 0x45, 0xfa, 0xff, 0xdf, 0x7d, 0xb9, 0x04, 0x29, 0x9f, 0xf5, 0x1d, 0xe5, 0x31, 0xd1, + 0x93, 0xf4, 0x59, 0xdf, 0x7e, 0x41, 0x0e, 0xf3, 0xaf, 0xf5, 0x32, 0x2d, 0xbc, 0x06, 0x06, 0x13, + 0xcf, 0x33, 0xf8, 0x2d, 0x64, 0x14, 0x21, 0x7a, 0xf8, 0x7d, 0x24, 0x99, 0xc0, 0x99, 0xfa, 0xc2, + 0xec, 0x9b, 0x2e, 0x5e, 0xe1, 0x6d, 0x8d, 0x96, 0x71, 0x6a, 0x54, 0xe8, 0x59, 0x5c, 0x7c, 0xb9, + 0x68, 0x6d, 0x8d, 0x2e, 0x7f, 0x6f, 0x00, 0xdc, 0x91, 0x5c, 0xe3, 0xd9, 0xe5, 0x04, 0xe3, 0x58, + 0x8e, 0x33, 0x55, 0xc5, 0xdb, 0x2f, 0x6f, 0xa6, 0xae, 0x25, 0xc3, 0x27, 0x4f, 0x52, 0x83, 0xec, + 0x58, 0xaa, 0x9c, 0x86, 0x85, 0xcd, 0x4c, 0x15, 0x8d, 0x97, 0x06, 0x15, 0x76, 0x66, 0x34, 0xb1, + 0x2a, 0xff, 0x6a, 0x40, 0x0a, 0xeb, 0xdb, 0xa5, 0x82, 0x4c, 0x75, 0xd8, 0x78, 0xd5, 0x0e, 0xbf, + 0x09, 0xa0, 0x92, 0x71, 0xf7, 0x01, 0xd5, 0xea, 0x4b, 0xa1, 0xa5, 0xe1, 0x3e, 0xa0, 0xd6, 0xa7, + 0x51, 0x3b, 0xe2, 0x67, 0x69, 0x87, 0xfe, 0x11, 0x84, 0x4d, 0xb9, 0x00, 0x09, 0x6f, 0x38, 0x70, + 0xe4, 0x80, 0x31, 0x95, 0xae, 0xbd, 0xe1, 0xa0, 0x79, 0xc8, 0xcb, 0xf7, 0x21, 0xd1, 0x3c, 0xc4, + 0x97, 0x97, 0x14, 0x73, 0xc0, 0x98, 0x9e, 0xf0, 0xea, 0x99, 0x95, 0x94, 0x06, 0x1c, 0x68, 0x16, + 0x98, 0x72, 0x94, 0x87, 0x0f, 0x41, 0xf9, 0x6d, 0x55, 0xcf, 0xfa, 0xa8, 0xd3, 0xcf, 0xb9, 0x6b, + 0xbf, 0x19, 0x90, 0x9d, 0xba, 0x74, 0xd6, 0xfb, 0x70, 0xa1, 0x51, 0xdb, 0xd9, 0xdb, 0xde, 0x72, + 0x76, 0x1b, 0x3b, 0x4e, 0xf3, 0xab, 0xfa, 0xb6, 0x73, 0x77, 0xef, 0xf6, 0xde, 0xfe, 0x97, 0x7b, + 0xb9, 0xb9, 0xc2, 0xd2, 0xc3, 0xc7, 0xa5, 0xf4, 0x5d, 0xef, 0xbe, 0xc7, 0xbe, 0xf1, 0x66, 0xa1, + 0xeb, 0xf6, 0xf6, 0xbd, 0xfd, 0xe6, 0x76, 0xce, 0x50, 0xe8, 0x7a, 0x40, 0x47, 0x4c, 0x50, 0x44, + 0x5f, 0x87, 0x8b, 0xa7, 0xa0, 0x37, 0xf7, 0x77, 0x77, 0x6b, 0xcd, 0x5c, 0xac, 0x70, 0xee, 0xe1, + 0xe3, 0x52, 0xb6, 0x1e, 0x50, 0x25, 0x3f, 0x8c, 0xa8, 0x40, 0xfe, 0xc5, 0x88, 0xfd, 0xfa, 0x7e, + 0xe3, 0xe6, 0x9d, 0x5c, 0xa9, 0x90, 0x7b, 0xf8, 0xb8, 0x94, 0x09, 0xff, 0x31, 0x12, 0x5f, 0x48, + 0x7e, 0xf7, 0x43, 0x71, 0xee, 0xa7, 0x1f, 0x8b, 0xc6, 0xc6, 0x17, 0x4f, 0x8e, 0x8b, 0xc6, 0xd3, + 0xe3, 0xa2, 0xf1, 0xe7, 0x71, 0xd1, 0x78, 0x74, 0x52, 0x9c, 0x7b, 0x7a, 0x52, 0x9c, 0xfb, 0xfd, + 0xa4, 0x38, 0xf7, 0xf5, 0xc7, 0x5d, 0x57, 0xf4, 0x86, 0x2d, 0xc9, 0x4d, 0x75, 0xfc, 0xb8, 0x0f, + 0x3f, 0x88, 0xef, 0x56, 0x4f, 0x7f, 0xb1, 0xb7, 0x16, 0xf0, 0x5a, 0x7f, 0xf0, 0x4f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xd3, 0xd1, 0x3a, 0x5b, 0x86, 0x0c, 0x00, 0x00, +} + +func (m *PartSetHeader) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PartSetHeader) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PartSetHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0x12 + } + if m.Total != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Total)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Part) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Part) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Part) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Proof.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Bytes) > 0 { + i -= len(m.Bytes) + copy(dAtA[i:], m.Bytes) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Bytes))) + i-- + dAtA[i] = 0x12 + } + if m.Index != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *BlockID) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockID) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BlockID) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.PartSetHeader.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Hash) > 0 { + i -= len(m.Hash) + copy(dAtA[i:], m.Hash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Header) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Header) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ProposerAddress) > 0 { + i -= len(m.ProposerAddress) + copy(dAtA[i:], m.ProposerAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress))) + i-- + dAtA[i] = 0x72 + } + if len(m.EvidenceHash) > 0 { + i -= len(m.EvidenceHash) + copy(dAtA[i:], m.EvidenceHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.EvidenceHash))) + i-- + dAtA[i] = 0x6a + } + if len(m.LastResultsHash) > 0 { + i -= len(m.LastResultsHash) + copy(dAtA[i:], m.LastResultsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.LastResultsHash))) + i-- + dAtA[i] = 0x62 + } + if len(m.AppHash) > 0 { + i -= len(m.AppHash) + copy(dAtA[i:], m.AppHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i-- + dAtA[i] = 0x5a + } + if len(m.ConsensusHash) > 0 { + i -= len(m.ConsensusHash) + copy(dAtA[i:], m.ConsensusHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ConsensusHash))) + i-- + dAtA[i] = 0x52 + } + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x4a + } + if len(m.ValidatorsHash) > 0 { + i -= len(m.ValidatorsHash) + copy(dAtA[i:], m.ValidatorsHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ValidatorsHash))) + i-- + dAtA[i] = 0x42 + } + if len(m.DataHash) > 0 { + i -= len(m.DataHash) + copy(dAtA[i:], m.DataHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.DataHash))) + i-- + dAtA[i] = 0x3a + } + if len(m.LastCommitHash) > 0 { + i -= len(m.LastCommitHash) + copy(dAtA[i:], m.LastCommitHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.LastCommitHash))) + i-- + dAtA[i] = 0x32 + } + { + size, err := m.LastBlockId.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + n4, err4 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time):]) + if err4 != nil { + return 0, err4 + } + i -= n4 + i = encodeVarintTypes(dAtA, i, uint64(n4)) + i-- + dAtA[i] = 0x22 + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x18 + } + if len(m.ChainID) > 0 { + i -= len(m.ChainID) + copy(dAtA[i:], m.ChainID) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainID))) + i-- + dAtA[i] = 0x12 + } + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Data) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Data) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Data) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Txs) > 0 { + for iNdEx := len(m.Txs) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Txs[iNdEx]) + copy(dAtA[i:], m.Txs[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Txs[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Vote) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Vote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signature) > 0 { + i -= len(m.Signature) + copy(dAtA[i:], m.Signature) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Signature))) + i-- + dAtA[i] = 0x42 + } + if m.ValidatorIndex != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.ValidatorIndex)) + i-- + dAtA[i] = 0x38 + } + if len(m.ValidatorAddress) > 0 { + i -= len(m.ValidatorAddress) + copy(dAtA[i:], m.ValidatorAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ValidatorAddress))) + i-- + dAtA[i] = 0x32 + } + n6, err6 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) + if err6 != nil { + return 0, err6 + } + i -= n6 + i = encodeVarintTypes(dAtA, i, uint64(n6)) + i-- + dAtA[i] = 0x2a + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x18 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if m.Type != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Commit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Commit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Commit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signatures) > 0 { + for iNdEx := len(m.Signatures) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Signatures[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x10 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *CommitSig) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CommitSig) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *CommitSig) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signature) > 0 { + i -= len(m.Signature) + copy(dAtA[i:], m.Signature) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Signature))) + i-- + dAtA[i] = 0x22 + } + n9, err9 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) + if err9 != nil { + return 0, err9 + } + i -= n9 + i = encodeVarintTypes(dAtA, i, uint64(n9)) + i-- + dAtA[i] = 0x1a + if len(m.ValidatorAddress) > 0 { + i -= len(m.ValidatorAddress) + copy(dAtA[i:], m.ValidatorAddress) + i = encodeVarintTypes(dAtA, i, uint64(len(m.ValidatorAddress))) + i-- + dAtA[i] = 0x12 + } + if m.BlockIdFlag != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.BlockIdFlag)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Proposal) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Proposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Proposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signature) > 0 { + i -= len(m.Signature) + copy(dAtA[i:], m.Signature) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Signature))) + i-- + dAtA[i] = 0x3a + } + n10, err10 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) + if err10 != nil { + return 0, err10 + } + i -= n10 + i = encodeVarintTypes(dAtA, i, uint64(n10)) + i-- + dAtA[i] = 0x32 + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if m.PolRound != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.PolRound)) + i-- + dAtA[i] = 0x20 + } + if m.Round != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Round)) + i-- + dAtA[i] = 0x18 + } + if m.Height != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if m.Type != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Type)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SignedHeader) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SignedHeader) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SignedHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Commit != nil { + { + size, err := m.Commit.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Header != nil { + { + size, err := m.Header.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *LightBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LightBlock) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LightBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ValidatorSet != nil { + { + size, err := m.ValidatorSet.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.SignedHeader != nil { + { + size, err := m.SignedHeader.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *BlockMeta) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockMeta) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BlockMeta) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.NumTxs != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.NumTxs)) + i-- + dAtA[i] = 0x20 + } + { + size, err := m.Header.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.BlockSize != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.BlockSize)) + i-- + dAtA[i] = 0x10 + } + { + size, err := m.BlockID.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *TxProof) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TxProof) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TxProof) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Proof != nil { + { + size, err := m.Proof.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Data) > 0 { + i -= len(m.Data) + copy(dAtA[i:], m.Data) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i-- + dAtA[i] = 0x12 + } + if len(m.RootHash) > 0 { + i -= len(m.RootHash) + copy(dAtA[i:], m.RootHash) + i = encodeVarintTypes(dAtA, i, uint64(len(m.RootHash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *PartSetHeader) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Total != 0 { + n += 1 + sovTypes(uint64(m.Total)) + } + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Part) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Index != 0 { + n += 1 + sovTypes(uint64(m.Index)) + } + l = len(m.Bytes) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Proof.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *BlockID) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.PartSetHeader.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *Header) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Version.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Time) + n += 1 + l + sovTypes(uint64(l)) + l = m.LastBlockId.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.LastCommitHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.DataHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ConsensusHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.LastResultsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.EvidenceHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ProposerAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Data) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Txs) > 0 { + for _, b := range m.Txs { + l = len(b) + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *Vote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovTypes(uint64(m.Type)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + l = m.BlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.ValidatorIndex != 0 { + n += 1 + sovTypes(uint64(m.ValidatorIndex)) + } + l = len(m.Signature) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Commit) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + l = m.BlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Signatures) > 0 { + for _, e := range m.Signatures { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *CommitSig) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BlockIdFlag != 0 { + n += 1 + sovTypes(uint64(m.BlockIdFlag)) + } + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.Signature) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Proposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Type != 0 { + n += 1 + sovTypes(uint64(m.Type)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Round != 0 { + n += 1 + sovTypes(uint64(m.Round)) + } + if m.PolRound != 0 { + n += 1 + sovTypes(uint64(m.PolRound)) + } + l = m.BlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovTypes(uint64(l)) + l = len(m.Signature) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *SignedHeader) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Header != nil { + l = m.Header.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *LightBlock) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SignedHeader != nil { + l = m.SignedHeader.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.ValidatorSet != nil { + l = m.ValidatorSet.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *BlockMeta) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.BlockID.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.BlockSize != 0 { + n += 1 + sovTypes(uint64(m.BlockSize)) + } + l = m.Header.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.NumTxs != 0 { + n += 1 + sovTypes(uint64(m.NumTxs)) + } + return n +} + +func (m *TxProof) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RootHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Proof != nil { + l = m.Proof.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *PartSetHeader) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PartSetHeader: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PartSetHeader: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) + } + m.Total = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Total |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Part) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Part: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Part: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Bytes", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Bytes = append(m.Bytes[:0], dAtA[iNdEx:postIndex]...) + if m.Bytes == nil { + m.Bytes = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Proof.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockID) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockID: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockID: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PartSetHeader", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PartSetHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Header) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Header: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Header: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockId", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastBlockId.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastCommitHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastCommitHash = append(m.LastCommitHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastCommitHash == nil { + m.LastCommitHash = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DataHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DataHash = append(m.DataHash[:0], dAtA[iNdEx:postIndex]...) + if m.DataHash == nil { + m.DataHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorsHash = append(m.ValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.ValidatorsHash == nil { + m.ValidatorsHash = []byte{} + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConsensusHash = append(m.ConsensusHash[:0], dAtA[iNdEx:postIndex]...) + if m.ConsensusHash == nil { + m.ConsensusHash = []byte{} + } + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastResultsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastResultsHash = append(m.LastResultsHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastResultsHash == nil { + m.LastResultsHash = []byte{} + } + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EvidenceHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.EvidenceHash = append(m.EvidenceHash[:0], dAtA[iNdEx:postIndex]...) + if m.EvidenceHash == nil { + m.EvidenceHash = []byte{} + } + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ProposerAddress == nil { + m.ProposerAddress = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Data) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Data: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Data: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Txs", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Txs = append(m.Txs, make([]byte, postIndex-iNdEx)) + copy(m.Txs[len(m.Txs)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Vote) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Vote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Vote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddress = append(m.ValidatorAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ValidatorAddress == nil { + m.ValidatorAddress = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorIndex", wireType) + } + m.ValidatorIndex = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ValidatorIndex |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...) + if m.Signature == nil { + m.Signature = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Commit) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Commit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Commit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signatures", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signatures = append(m.Signatures, CommitSig{}) + if err := m.Signatures[len(m.Signatures)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CommitSig) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CommitSig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CommitSig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockIdFlag", wireType) + } + m.BlockIdFlag = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockIdFlag |= BlockIDFlag(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddress = append(m.ValidatorAddress[:0], dAtA[iNdEx:postIndex]...) + if m.ValidatorAddress == nil { + m.ValidatorAddress = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...) + if m.Signature == nil { + m.Signature = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Proposal) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Proposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Proposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + m.Type = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Type |= SignedMsgType(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Round", wireType) + } + m.Round = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Round |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PolRound", wireType) + } + m.PolRound = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PolRound |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...) + if m.Signature == nil { + m.Signature = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SignedHeader) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SignedHeader: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SignedHeader: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Header == nil { + m.Header = &Header{} + } + if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Commit == nil { + m.Commit = &Commit{} + } + if err := m.Commit.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LightBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LightBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LightBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedHeader", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SignedHeader == nil { + m.SignedHeader = &SignedHeader{} + } + if err := m.SignedHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorSet", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ValidatorSet == nil { + m.ValidatorSet = &ValidatorSet{} + } + if err := m.ValidatorSet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockMeta) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockMeta: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockMeta: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.BlockID.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockSize", wireType) + } + m.BlockSize = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockSize |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NumTxs", wireType) + } + m.NumTxs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NumTxs |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TxProof) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TxProof: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TxProof: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RootHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RootHash = append(m.RootHash[:0], dAtA[iNdEx:postIndex]...) + if m.RootHash == nil { + m.RootHash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proof == nil { + m.Proof = &v1.Proof{} + } + if err := m.Proof.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/types/v1beta1/validator.pb.go b/api/cometbft/types/v1beta1/validator.pb.go new file mode 100644 index 00000000000..fdcc6887193 --- /dev/null +++ b/api/cometbft/types/v1beta1/validator.pb.go @@ -0,0 +1,998 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/types/v1beta1/validator.proto + +package v1beta1 + +import ( + fmt "fmt" + v1 "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// BlockIdFlag indicates which BlockID the signature is for +type BlockIDFlag int32 + +const ( + // Indicates an error condition + BlockIDFlagUnknown BlockIDFlag = 0 + // The vote was not received + BlockIDFlagAbsent BlockIDFlag = 1 + // Voted for the block that received the majority + BlockIDFlagCommit BlockIDFlag = 2 + // Voted for nil + BlockIDFlagNil BlockIDFlag = 3 +) + +var BlockIDFlag_name = map[int32]string{ + 0: "BLOCK_ID_FLAG_UNKNOWN", + 1: "BLOCK_ID_FLAG_ABSENT", + 2: "BLOCK_ID_FLAG_COMMIT", + 3: "BLOCK_ID_FLAG_NIL", +} + +var BlockIDFlag_value = map[string]int32{ + "BLOCK_ID_FLAG_UNKNOWN": 0, + "BLOCK_ID_FLAG_ABSENT": 1, + "BLOCK_ID_FLAG_COMMIT": 2, + "BLOCK_ID_FLAG_NIL": 3, +} + +func (x BlockIDFlag) String() string { + return proto.EnumName(BlockIDFlag_name, int32(x)) +} + +func (BlockIDFlag) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_2e1661b4f555b138, []int{0} +} + +// ValidatorSet defines a set of validators. +type ValidatorSet struct { + Validators []*Validator `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"` + Proposer *Validator `protobuf:"bytes,2,opt,name=proposer,proto3" json:"proposer,omitempty"` + TotalVotingPower int64 `protobuf:"varint,3,opt,name=total_voting_power,json=totalVotingPower,proto3" json:"total_voting_power,omitempty"` +} + +func (m *ValidatorSet) Reset() { *m = ValidatorSet{} } +func (m *ValidatorSet) String() string { return proto.CompactTextString(m) } +func (*ValidatorSet) ProtoMessage() {} +func (*ValidatorSet) Descriptor() ([]byte, []int) { + return fileDescriptor_2e1661b4f555b138, []int{0} +} +func (m *ValidatorSet) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ValidatorSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ValidatorSet.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ValidatorSet) XXX_Merge(src proto.Message) { + xxx_messageInfo_ValidatorSet.Merge(m, src) +} +func (m *ValidatorSet) XXX_Size() int { + return m.Size() +} +func (m *ValidatorSet) XXX_DiscardUnknown() { + xxx_messageInfo_ValidatorSet.DiscardUnknown(m) +} + +var xxx_messageInfo_ValidatorSet proto.InternalMessageInfo + +func (m *ValidatorSet) GetValidators() []*Validator { + if m != nil { + return m.Validators + } + return nil +} + +func (m *ValidatorSet) GetProposer() *Validator { + if m != nil { + return m.Proposer + } + return nil +} + +func (m *ValidatorSet) GetTotalVotingPower() int64 { + if m != nil { + return m.TotalVotingPower + } + return 0 +} + +// Validator represents a node participating in the consensus protocol. +type Validator struct { + Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + PubKey v1.PublicKey `protobuf:"bytes,2,opt,name=pub_key,json=pubKey,proto3" json:"pub_key"` + VotingPower int64 `protobuf:"varint,3,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` + ProposerPriority int64 `protobuf:"varint,4,opt,name=proposer_priority,json=proposerPriority,proto3" json:"proposer_priority,omitempty"` +} + +func (m *Validator) Reset() { *m = Validator{} } +func (m *Validator) String() string { return proto.CompactTextString(m) } +func (*Validator) ProtoMessage() {} +func (*Validator) Descriptor() ([]byte, []int) { + return fileDescriptor_2e1661b4f555b138, []int{1} +} +func (m *Validator) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Validator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Validator.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Validator) XXX_Merge(src proto.Message) { + xxx_messageInfo_Validator.Merge(m, src) +} +func (m *Validator) XXX_Size() int { + return m.Size() +} +func (m *Validator) XXX_DiscardUnknown() { + xxx_messageInfo_Validator.DiscardUnknown(m) +} + +var xxx_messageInfo_Validator proto.InternalMessageInfo + +func (m *Validator) GetAddress() []byte { + if m != nil { + return m.Address + } + return nil +} + +func (m *Validator) GetPubKey() v1.PublicKey { + if m != nil { + return m.PubKey + } + return v1.PublicKey{} +} + +func (m *Validator) GetVotingPower() int64 { + if m != nil { + return m.VotingPower + } + return 0 +} + +func (m *Validator) GetProposerPriority() int64 { + if m != nil { + return m.ProposerPriority + } + return 0 +} + +// SimpleValidator is a Validator, which is serialized and hashed in consensus. +// Address is removed because it's redundant with the pubkey. +// Proposer priority is removed because it changes every round. +type SimpleValidator struct { + PubKey *v1.PublicKey `protobuf:"bytes,1,opt,name=pub_key,json=pubKey,proto3" json:"pub_key,omitempty"` + VotingPower int64 `protobuf:"varint,2,opt,name=voting_power,json=votingPower,proto3" json:"voting_power,omitempty"` +} + +func (m *SimpleValidator) Reset() { *m = SimpleValidator{} } +func (m *SimpleValidator) String() string { return proto.CompactTextString(m) } +func (*SimpleValidator) ProtoMessage() {} +func (*SimpleValidator) Descriptor() ([]byte, []int) { + return fileDescriptor_2e1661b4f555b138, []int{2} +} +func (m *SimpleValidator) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SimpleValidator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SimpleValidator.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SimpleValidator) XXX_Merge(src proto.Message) { + xxx_messageInfo_SimpleValidator.Merge(m, src) +} +func (m *SimpleValidator) XXX_Size() int { + return m.Size() +} +func (m *SimpleValidator) XXX_DiscardUnknown() { + xxx_messageInfo_SimpleValidator.DiscardUnknown(m) +} + +var xxx_messageInfo_SimpleValidator proto.InternalMessageInfo + +func (m *SimpleValidator) GetPubKey() *v1.PublicKey { + if m != nil { + return m.PubKey + } + return nil +} + +func (m *SimpleValidator) GetVotingPower() int64 { + if m != nil { + return m.VotingPower + } + return 0 +} + +func init() { + proto.RegisterEnum("cometbft.types.v1beta1.BlockIDFlag", BlockIDFlag_name, BlockIDFlag_value) + proto.RegisterType((*ValidatorSet)(nil), "cometbft.types.v1beta1.ValidatorSet") + proto.RegisterType((*Validator)(nil), "cometbft.types.v1beta1.Validator") + proto.RegisterType((*SimpleValidator)(nil), "cometbft.types.v1beta1.SimpleValidator") +} + +func init() { + proto.RegisterFile("cometbft/types/v1beta1/validator.proto", fileDescriptor_2e1661b4f555b138) +} + +var fileDescriptor_2e1661b4f555b138 = []byte{ + // 515 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x3f, 0x6f, 0xda, 0x40, + 0x18, 0x87, 0x7d, 0x10, 0x25, 0xe9, 0x81, 0x5a, 0x38, 0x25, 0x11, 0xb2, 0x14, 0xd7, 0x61, 0xa8, + 0xe8, 0x1f, 0xd9, 0xa2, 0x95, 0xda, 0xa5, 0x1d, 0x80, 0x34, 0x15, 0x82, 0x18, 0x0a, 0x49, 0x2a, + 0x75, 0xb1, 0x6c, 0xb8, 0xba, 0x27, 0x8c, 0xef, 0x64, 0x1f, 0x8e, 0xfc, 0x0d, 0x2a, 0xa6, 0x7e, + 0x01, 0xa6, 0x76, 0xe8, 0xde, 0xbd, 0x73, 0xc6, 0x6c, 0xed, 0x54, 0x55, 0xf0, 0x45, 0x2a, 0x0c, + 0xb6, 0x89, 0x20, 0x52, 0xb6, 0xf3, 0xbd, 0xbf, 0xe7, 0x7d, 0x1f, 0x9f, 0xf4, 0xc2, 0x47, 0x3d, + 0x3a, 0xc4, 0xdc, 0xfc, 0xc4, 0x55, 0x1e, 0x30, 0xec, 0xa9, 0x7e, 0xd9, 0xc4, 0xdc, 0x28, 0xab, + 0xbe, 0x61, 0x93, 0xbe, 0xc1, 0xa9, 0xab, 0x30, 0x97, 0x72, 0x8a, 0x0e, 0xa2, 0x9c, 0x12, 0xe6, + 0x94, 0x65, 0x4e, 0xdc, 0xb3, 0xa8, 0x45, 0xc3, 0x88, 0x3a, 0x3f, 0x2d, 0xd2, 0xe2, 0x61, 0xdc, + 0xb5, 0xe7, 0x06, 0x8c, 0x53, 0xd5, 0x2f, 0xab, 0x03, 0x1c, 0x78, 0x8b, 0x72, 0xf1, 0x17, 0x80, + 0xd9, 0x8b, 0x68, 0x40, 0x17, 0x73, 0x54, 0x81, 0x30, 0x1e, 0xe8, 0x15, 0x80, 0x9c, 0x2e, 0x65, + 0x9e, 0x1f, 0x29, 0x9b, 0x47, 0x2a, 0x31, 0xd9, 0x59, 0x81, 0xd0, 0x1b, 0xb8, 0xcb, 0x5c, 0xca, + 0xa8, 0x87, 0xdd, 0x42, 0x4a, 0x06, 0x77, 0x6b, 0x10, 0x23, 0xe8, 0x19, 0x44, 0x9c, 0x72, 0xc3, + 0xd6, 0x7d, 0xca, 0x89, 0x63, 0xe9, 0x8c, 0x5e, 0x62, 0xb7, 0x90, 0x96, 0x41, 0x29, 0xdd, 0xc9, + 0x85, 0x95, 0x8b, 0xb0, 0xd0, 0x9e, 0xdf, 0x17, 0x7f, 0x02, 0x78, 0x2f, 0xee, 0x82, 0x0a, 0x70, + 0xc7, 0xe8, 0xf7, 0x5d, 0xec, 0xcd, 0xd5, 0x41, 0x29, 0xdb, 0x89, 0x3e, 0xd1, 0x6b, 0xb8, 0xc3, + 0x46, 0xa6, 0x3e, 0xc0, 0xc1, 0xd2, 0xe9, 0x30, 0x71, 0x5a, 0xbc, 0x8c, 0xe2, 0x97, 0x95, 0xf6, + 0xc8, 0xb4, 0x49, 0xaf, 0x81, 0x83, 0xea, 0xd6, 0xd5, 0xdf, 0x87, 0x42, 0x67, 0x9b, 0x8d, 0xcc, + 0x06, 0x0e, 0xd0, 0x11, 0xcc, 0x6e, 0xb0, 0xc9, 0xf8, 0x89, 0x08, 0x7a, 0x0a, 0xf3, 0xd1, 0x2f, + 0xe8, 0xcc, 0x25, 0xd4, 0x25, 0x3c, 0x28, 0x6c, 0x2d, 0xac, 0xa3, 0x42, 0x7b, 0x79, 0x5f, 0xb4, + 0xe1, 0x83, 0x2e, 0x19, 0x32, 0x1b, 0x27, 0xea, 0x2f, 0x13, 0x41, 0x70, 0x07, 0xc1, 0x5b, 0xd5, + 0x52, 0x6b, 0x6a, 0x4f, 0x7e, 0x03, 0x98, 0xa9, 0xda, 0xb4, 0x37, 0xa8, 0x1f, 0x9f, 0xd8, 0x86, + 0x85, 0xca, 0x70, 0xbf, 0xda, 0x6c, 0xd5, 0x1a, 0x7a, 0xfd, 0x58, 0x3f, 0x69, 0x56, 0xde, 0xe9, + 0xe7, 0x5a, 0x43, 0x6b, 0x7d, 0xd0, 0x72, 0x82, 0x78, 0x30, 0x9e, 0xc8, 0x68, 0x25, 0x7b, 0xee, + 0x0c, 0x1c, 0x7a, 0xe9, 0x20, 0x15, 0xee, 0xdd, 0x44, 0x2a, 0xd5, 0xee, 0x5b, 0xed, 0x2c, 0x07, + 0xc4, 0xfd, 0xf1, 0x44, 0xce, 0xaf, 0x10, 0x15, 0xd3, 0xc3, 0x0e, 0x5f, 0x07, 0x6a, 0xad, 0xd3, + 0xd3, 0xfa, 0x59, 0x2e, 0xb5, 0x06, 0xd4, 0xe8, 0x70, 0x48, 0x38, 0x7a, 0x0c, 0xf3, 0x37, 0x01, + 0xad, 0xde, 0xcc, 0xa5, 0x45, 0x34, 0x9e, 0xc8, 0xf7, 0x57, 0xd2, 0x1a, 0xb1, 0xc5, 0xdd, 0x2f, + 0xdf, 0x24, 0xe1, 0xc7, 0x77, 0x09, 0x54, 0xdf, 0x5f, 0x4d, 0x25, 0x70, 0x3d, 0x95, 0xc0, 0xbf, + 0xa9, 0x04, 0xbe, 0xce, 0x24, 0xe1, 0x7a, 0x26, 0x09, 0x7f, 0x66, 0x92, 0xf0, 0xf1, 0x95, 0x45, + 0xf8, 0xe7, 0x91, 0x39, 0x7f, 0x43, 0x35, 0x59, 0x81, 0xe8, 0x60, 0x30, 0xa2, 0x6e, 0x5e, 0x37, + 0x73, 0x3b, 0x5c, 0x8c, 0x17, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x49, 0x07, 0x50, 0x2d, 0x8f, + 0x03, 0x00, 0x00, +} + +func (m *ValidatorSet) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ValidatorSet) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ValidatorSet) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TotalVotingPower != 0 { + i = encodeVarintValidator(dAtA, i, uint64(m.TotalVotingPower)) + i-- + dAtA[i] = 0x18 + } + if m.Proposer != nil { + { + size, err := m.Proposer.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintValidator(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Validators) > 0 { + for iNdEx := len(m.Validators) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Validators[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintValidator(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Validator) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Validator) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Validator) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposerPriority != 0 { + i = encodeVarintValidator(dAtA, i, uint64(m.ProposerPriority)) + i-- + dAtA[i] = 0x20 + } + if m.VotingPower != 0 { + i = encodeVarintValidator(dAtA, i, uint64(m.VotingPower)) + i-- + dAtA[i] = 0x18 + } + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintValidator(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintValidator(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *SimpleValidator) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SimpleValidator) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SimpleValidator) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.VotingPower != 0 { + i = encodeVarintValidator(dAtA, i, uint64(m.VotingPower)) + i-- + dAtA[i] = 0x10 + } + if m.PubKey != nil { + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintValidator(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintValidator(dAtA []byte, offset int, v uint64) int { + offset -= sovValidator(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ValidatorSet) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovValidator(uint64(l)) + } + } + if m.Proposer != nil { + l = m.Proposer.Size() + n += 1 + l + sovValidator(uint64(l)) + } + if m.TotalVotingPower != 0 { + n += 1 + sovValidator(uint64(m.TotalVotingPower)) + } + return n +} + +func (m *Validator) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovValidator(uint64(l)) + } + l = m.PubKey.Size() + n += 1 + l + sovValidator(uint64(l)) + if m.VotingPower != 0 { + n += 1 + sovValidator(uint64(m.VotingPower)) + } + if m.ProposerPriority != 0 { + n += 1 + sovValidator(uint64(m.ProposerPriority)) + } + return n +} + +func (m *SimpleValidator) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PubKey != nil { + l = m.PubKey.Size() + n += 1 + l + sovValidator(uint64(l)) + } + if m.VotingPower != 0 { + n += 1 + sovValidator(uint64(m.VotingPower)) + } + return n +} + +func sovValidator(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozValidator(x uint64) (n int) { + return sovValidator(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ValidatorSet) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ValidatorSet: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ValidatorSet: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthValidator + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthValidator + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, &Validator{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposer", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthValidator + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthValidator + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proposer == nil { + m.Proposer = &Validator{} + } + if err := m.Proposer.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalVotingPower", wireType) + } + m.TotalVotingPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalVotingPower |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipValidator(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthValidator + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Validator) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Validator: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Validator: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthValidator + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthValidator + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthValidator + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthValidator + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VotingPower", wireType) + } + m.VotingPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VotingPower |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposerPriority", wireType) + } + m.ProposerPriority = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposerPriority |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipValidator(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthValidator + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SimpleValidator) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SimpleValidator: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SimpleValidator: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthValidator + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthValidator + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PubKey == nil { + m.PubKey = &v1.PublicKey{} + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VotingPower", wireType) + } + m.VotingPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowValidator + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VotingPower |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipValidator(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthValidator + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipValidator(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowValidator + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowValidator + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowValidator + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthValidator + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupValidator + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthValidator + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthValidator = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowValidator = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupValidator = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/cometbft/types/v1beta2/params.pb.go b/api/cometbft/types/v1beta2/params.pb.go new file mode 100644 index 00000000000..a6213bb4ece --- /dev/null +++ b/api/cometbft/types/v1beta2/params.pb.go @@ -0,0 +1,774 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cometbft/types/v1beta2/params.proto + +package v1beta2 + +import ( + fmt "fmt" + v1beta1 "github.com/cometbft/cometbft/api/cometbft/types/v1beta1" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ConsensusParams contains consensus critical parameters that determine the +// validity of blocks. +type ConsensusParams struct { + Block *BlockParams `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Evidence *v1beta1.EvidenceParams `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence,omitempty"` + Validator *v1beta1.ValidatorParams `protobuf:"bytes,3,opt,name=validator,proto3" json:"validator,omitempty"` + Version *v1beta1.VersionParams `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` +} + +func (m *ConsensusParams) Reset() { *m = ConsensusParams{} } +func (m *ConsensusParams) String() string { return proto.CompactTextString(m) } +func (*ConsensusParams) ProtoMessage() {} +func (*ConsensusParams) Descriptor() ([]byte, []int) { + return fileDescriptor_530f7a66f5f74d85, []int{0} +} +func (m *ConsensusParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsensusParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsensusParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsensusParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsensusParams.Merge(m, src) +} +func (m *ConsensusParams) XXX_Size() int { + return m.Size() +} +func (m *ConsensusParams) XXX_DiscardUnknown() { + xxx_messageInfo_ConsensusParams.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsensusParams proto.InternalMessageInfo + +func (m *ConsensusParams) GetBlock() *BlockParams { + if m != nil { + return m.Block + } + return nil +} + +func (m *ConsensusParams) GetEvidence() *v1beta1.EvidenceParams { + if m != nil { + return m.Evidence + } + return nil +} + +func (m *ConsensusParams) GetValidator() *v1beta1.ValidatorParams { + if m != nil { + return m.Validator + } + return nil +} + +func (m *ConsensusParams) GetVersion() *v1beta1.VersionParams { + if m != nil { + return m.Version + } + return nil +} + +// BlockParams contains limits on the block size. +type BlockParams struct { + // Max block size, in bytes. + // Note: must be greater than 0 + MaxBytes int64 `protobuf:"varint,1,opt,name=max_bytes,json=maxBytes,proto3" json:"max_bytes,omitempty"` + // Max gas per block. + // Note: must be greater or equal to -1 + MaxGas int64 `protobuf:"varint,2,opt,name=max_gas,json=maxGas,proto3" json:"max_gas,omitempty"` +} + +func (m *BlockParams) Reset() { *m = BlockParams{} } +func (m *BlockParams) String() string { return proto.CompactTextString(m) } +func (*BlockParams) ProtoMessage() {} +func (*BlockParams) Descriptor() ([]byte, []int) { + return fileDescriptor_530f7a66f5f74d85, []int{1} +} +func (m *BlockParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BlockParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BlockParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *BlockParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_BlockParams.Merge(m, src) +} +func (m *BlockParams) XXX_Size() int { + return m.Size() +} +func (m *BlockParams) XXX_DiscardUnknown() { + xxx_messageInfo_BlockParams.DiscardUnknown(m) +} + +var xxx_messageInfo_BlockParams proto.InternalMessageInfo + +func (m *BlockParams) GetMaxBytes() int64 { + if m != nil { + return m.MaxBytes + } + return 0 +} + +func (m *BlockParams) GetMaxGas() int64 { + if m != nil { + return m.MaxGas + } + return 0 +} + +func init() { + proto.RegisterType((*ConsensusParams)(nil), "cometbft.types.v1beta2.ConsensusParams") + proto.RegisterType((*BlockParams)(nil), "cometbft.types.v1beta2.BlockParams") +} + +func init() { + proto.RegisterFile("cometbft/types/v1beta2/params.proto", fileDescriptor_530f7a66f5f74d85) +} + +var fileDescriptor_530f7a66f5f74d85 = []byte{ + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4e, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, + 0x49, 0x34, 0xd2, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, + 0x12, 0x83, 0x29, 0xd2, 0x03, 0x2b, 0xd2, 0x83, 0x2a, 0x92, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, + 0x2b, 0xd1, 0x07, 0xb1, 0x20, 0xaa, 0xa5, 0xb0, 0x1b, 0x69, 0x88, 0x62, 0xa4, 0xd2, 0x0c, 0x26, + 0x2e, 0x7e, 0xe7, 0xfc, 0xbc, 0xe2, 0xd4, 0xbc, 0xe2, 0xd2, 0xe2, 0x00, 0xb0, 0x8c, 0x90, 0x25, + 0x17, 0x6b, 0x52, 0x4e, 0x7e, 0x72, 0xb6, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, 0x91, 0xb2, 0x1e, + 0x76, 0x6b, 0xf5, 0x9c, 0x40, 0x8a, 0x20, 0x7a, 0x82, 0x20, 0x3a, 0x84, 0x9c, 0xb8, 0x38, 0x52, + 0xcb, 0x32, 0x53, 0x52, 0xf3, 0x92, 0x53, 0x25, 0x98, 0xc0, 0xba, 0xd5, 0xb0, 0xeb, 0x36, 0xd4, + 0x73, 0x85, 0xaa, 0x83, 0x1a, 0x00, 0xd7, 0x27, 0xe4, 0xca, 0xc5, 0x59, 0x96, 0x98, 0x93, 0x99, + 0x92, 0x58, 0x92, 0x5f, 0x24, 0xc1, 0x0c, 0x36, 0x44, 0x1d, 0x97, 0x21, 0x61, 0x30, 0x85, 0x50, + 0x53, 0x10, 0x3a, 0x85, 0xec, 0xb9, 0xd8, 0xcb, 0x52, 0x8b, 0x8a, 0x33, 0xf3, 0xf3, 0x24, 0x58, + 0xc0, 0x86, 0xa8, 0xe2, 0x34, 0x04, 0xa2, 0x0c, 0x6a, 0x04, 0x4c, 0x97, 0x92, 0x27, 0x17, 0x37, + 0x92, 0x0f, 0x85, 0xa4, 0xb9, 0x38, 0x73, 0x13, 0x2b, 0xe2, 0x93, 0x2a, 0x4b, 0x52, 0x8b, 0xc1, + 0x21, 0xc3, 0x1c, 0xc4, 0x91, 0x9b, 0x58, 0xe1, 0x04, 0xe2, 0x0b, 0x89, 0x73, 0xb1, 0x83, 0x24, + 0xd3, 0x13, 0x8b, 0xc1, 0xde, 0x66, 0x0e, 0x62, 0xcb, 0x4d, 0xac, 0x70, 0x4f, 0x2c, 0xf6, 0x62, + 0xe1, 0x60, 0x16, 0x60, 0x71, 0x0a, 0x5d, 0xf1, 0x48, 0x8e, 0xf1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, + 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, + 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xcc, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0x40, 0xce, 0xd3, 0x87, + 0xc7, 0x19, 0x9c, 0x91, 0x58, 0x90, 0xa9, 0x8f, 0x3d, 0x71, 0x24, 0xb1, 0x81, 0xe3, 0xd0, 0x18, + 0x10, 0x00, 0x00, 0xff, 0xff, 0x28, 0xa8, 0xb8, 0xff, 0x3d, 0x02, 0x00, 0x00, +} + +func (this *ConsensusParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ConsensusParams) + if !ok { + that2, ok := that.(ConsensusParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Block.Equal(that1.Block) { + return false + } + if !this.Evidence.Equal(that1.Evidence) { + return false + } + if !this.Validator.Equal(that1.Validator) { + return false + } + if !this.Version.Equal(that1.Version) { + return false + } + return true +} +func (this *BlockParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*BlockParams) + if !ok { + that2, ok := that.(BlockParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MaxBytes != that1.MaxBytes { + return false + } + if this.MaxGas != that1.MaxGas { + return false + } + return true +} +func (m *ConsensusParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsensusParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsensusParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Version != nil { + { + size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if m.Validator != nil { + { + size, err := m.Validator.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Evidence != nil { + { + size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Block != nil { + { + size, err := m.Block.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintParams(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *BlockParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BlockParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MaxGas != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.MaxGas)) + i-- + dAtA[i] = 0x10 + } + if m.MaxBytes != 0 { + i = encodeVarintParams(dAtA, i, uint64(m.MaxBytes)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintParams(dAtA []byte, offset int, v uint64) int { + offset -= sovParams(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ConsensusParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Block != nil { + l = m.Block.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Evidence != nil { + l = m.Evidence.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Validator != nil { + l = m.Validator.Size() + n += 1 + l + sovParams(uint64(l)) + } + if m.Version != nil { + l = m.Version.Size() + n += 1 + l + sovParams(uint64(l)) + } + return n +} + +func (m *BlockParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxBytes != 0 { + n += 1 + sovParams(uint64(m.MaxBytes)) + } + if m.MaxGas != 0 { + n += 1 + sovParams(uint64(m.MaxGas)) + } + return n +} + +func sovParams(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozParams(x uint64) (n int) { + return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ConsensusParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsensusParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Block", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Block == nil { + m.Block = &BlockParams{} + } + if err := m.Block.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Evidence == nil { + m.Evidence = &v1beta1.EvidenceParams{} + } + if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Validator == nil { + m.Validator = &v1beta1.ValidatorParams{} + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Version == nil { + m.Version = &v1beta1.VersionParams{} + } + if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *BlockParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxBytes", wireType) + } + m.MaxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxBytes |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxGas", wireType) + } + m.MaxGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxGas |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipParams(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthParams + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupParams + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthParams + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowParams = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group") +) diff --git a/proto/tendermint/version/types.pb.go b/api/cometbft/version/v1/types.pb.go similarity index 86% rename from proto/tendermint/version/types.pb.go rename to api/cometbft/version/v1/types.pb.go index f7393bf9037..29b0fde5e55 100644 --- a/proto/tendermint/version/types.pb.go +++ b/api/cometbft/version/v1/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/version/types.proto +// source: cometbft/version/v1/types.proto -package version +package v1 import ( fmt "fmt" @@ -35,7 +35,7 @@ func (m *App) Reset() { *m = App{} } func (m *App) String() string { return proto.CompactTextString(m) } func (*App) ProtoMessage() {} func (*App) Descriptor() ([]byte, []int) { - return fileDescriptor_f9b42966edc5edad, []int{0} + return fileDescriptor_f76e29b77f2d731e, []int{0} } func (m *App) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -90,7 +90,7 @@ func (m *Consensus) Reset() { *m = Consensus{} } func (m *Consensus) String() string { return proto.CompactTextString(m) } func (*Consensus) ProtoMessage() {} func (*Consensus) Descriptor() ([]byte, []int) { - return fileDescriptor_f9b42966edc5edad, []int{1} + return fileDescriptor_f76e29b77f2d731e, []int{1} } func (m *Consensus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -134,28 +134,28 @@ func (m *Consensus) GetApp() uint64 { } func init() { - proto.RegisterType((*App)(nil), "tendermint.version.App") - proto.RegisterType((*Consensus)(nil), "tendermint.version.Consensus") + proto.RegisterType((*App)(nil), "cometbft.version.v1.App") + proto.RegisterType((*Consensus)(nil), "cometbft.version.v1.Consensus") } -func init() { proto.RegisterFile("tendermint/version/types.proto", fileDescriptor_f9b42966edc5edad) } +func init() { proto.RegisterFile("cometbft/version/v1/types.proto", fileDescriptor_f76e29b77f2d731e) } -var fileDescriptor_f9b42966edc5edad = []byte{ - // 223 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x49, 0xcd, 0x4b, - 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x2f, 0x4b, 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0xd3, 0x2f, - 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x42, 0xc8, 0xeb, 0x41, - 0xe5, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xd2, 0xfa, 0x20, 0x16, 0x44, 0xa5, 0x92, 0x2d, - 0x17, 0xb3, 0x63, 0x41, 0x81, 0x90, 0x14, 0x17, 0x07, 0x98, 0x9f, 0x9c, 0x9f, 0x23, 0xc1, 0xa8, - 0xc0, 0xa8, 0xc1, 0x12, 0x04, 0xe7, 0x83, 0xe4, 0x8a, 0xf3, 0xd3, 0x4a, 0xca, 0x13, 0x8b, 0x52, - 0x25, 0x98, 0x14, 0x18, 0x35, 0x38, 0x83, 0xe0, 0x7c, 0x25, 0x4b, 0x2e, 0x4e, 0xe7, 0xfc, 0xbc, - 0xe2, 0xd4, 0xbc, 0xe2, 0xd2, 0x62, 0x21, 0x11, 0x2e, 0xd6, 0xa4, 0x9c, 0xfc, 0xe4, 0x6c, 0xa8, - 0x09, 0x10, 0x8e, 0x90, 0x00, 0x17, 0x73, 0x62, 0x41, 0x01, 0x58, 0x27, 0x4b, 0x10, 0x88, 0x69, - 0xc5, 0xf2, 0x62, 0x81, 0x3c, 0xa3, 0x93, 0xff, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, - 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, - 0x31, 0x44, 0x99, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x27, 0xe7, - 0xe7, 0xa6, 0x96, 0x24, 0xa5, 0x95, 0x20, 0x18, 0x10, 0x2f, 0x60, 0x06, 0x40, 0x12, 0x1b, 0x58, - 0xc6, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x1a, 0xc7, 0x18, 0x2b, 0x1d, 0x01, 0x00, 0x00, +var fileDescriptor_f76e29b77f2d731e = []byte{ + // 224 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xce, 0xcf, 0x4d, + 0x2d, 0x49, 0x4a, 0x2b, 0xd1, 0x2f, 0x4b, 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0xd3, 0x2f, 0x33, 0xd4, + 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x86, 0x29, 0xd0, + 0x83, 0x2a, 0xd0, 0x2b, 0x33, 0x94, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xcb, 0xeb, 0x83, 0x58, + 0x10, 0xa5, 0x4a, 0xb6, 0x5c, 0xcc, 0x8e, 0x05, 0x05, 0x42, 0x52, 0x5c, 0x1c, 0x60, 0x7e, 0x72, + 0x7e, 0x8e, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x4b, 0x10, 0x9c, 0x0f, 0x92, 0x2b, 0xce, 0x4f, 0x2b, + 0x29, 0x4f, 0x2c, 0x4a, 0x95, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x0c, 0x82, 0xf3, 0x95, 0x2c, 0xb9, + 0x38, 0x9d, 0xf3, 0xf3, 0x8a, 0x53, 0xf3, 0x8a, 0x4b, 0x8b, 0x85, 0x44, 0xb8, 0x58, 0x93, 0x72, + 0xf2, 0x93, 0xb3, 0xa1, 0x26, 0x40, 0x38, 0x42, 0x02, 0x5c, 0xcc, 0x89, 0x05, 0x05, 0x60, 0x9d, + 0x2c, 0x41, 0x20, 0xa6, 0x15, 0xcb, 0x8b, 0x05, 0xf2, 0x8c, 0x4e, 0x7e, 0x27, 0x1e, 0xc9, 0x31, + 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, + 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0x65, 0x92, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, + 0x9f, 0xab, 0x0f, 0xf7, 0x2a, 0x9c, 0x91, 0x58, 0x90, 0xa9, 0x8f, 0x25, 0x00, 0x92, 0xd8, 0xc0, + 0x0e, 0x36, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x26, 0x83, 0x70, 0xc1, 0x1e, 0x01, 0x00, 0x00, } func (this *Consensus) Equal(that interface{}) bool { diff --git a/api/go.mod b/api/go.mod new file mode 100644 index 00000000000..faf64ac1d89 --- /dev/null +++ b/api/go.mod @@ -0,0 +1,19 @@ +module github.com/cometbft/cometbft/api + +go 1.22 + +require ( + github.com/cosmos/gogoproto v1.4.12 + github.com/golang/protobuf v1.5.3 + google.golang.org/grpc v1.62.1 +) + +require ( + github.com/google/go-cmp v0.6.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/protobuf v1.33.0 // indirect +) diff --git a/api/go.sum b/api/go.sum new file mode 100644 index 00000000000..a543a8883db --- /dev/null +++ b/api/go.sum @@ -0,0 +1,16 @@ +github.com/cosmos/gogoproto v1.4.12 h1:vB6Lbe/rtnYGjQuFxkPiPYiCybqFT8QvLipDZP8JpFE= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +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/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +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.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= diff --git a/buf.gen.yaml b/buf.gen.yaml index a36032410ce..4581fa7e320 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -1,9 +1,10 @@ version: v1 plugins: - - name: gogofaster - out: ./proto/ + - name: gocosmos + out: ./api/ opt: - Mgoogle/protobuf/timestamp.proto=github.com/cosmos/gogoproto/types - Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration + - Mgoogle/protobuf/wrappers.proto=github.com/cosmos/gogoproto/types - plugins=grpc - paths=source_relative diff --git a/buf.yaml b/buf.yaml deleted file mode 100644 index 5f837667856..00000000000 --- a/buf.yaml +++ /dev/null @@ -1,13 +0,0 @@ -build: - roots: - - proto -lint: - use: - - BASIC - - FILE_LOWER_SNAKE_CASE - - UNARY_RPC - ignore: - - gogoproto -breaking: - use: - - FILE diff --git a/cmd/cometbft/commands/compact.go b/cmd/cometbft/commands/compact.go index a72cd69f1ab..b103dba6e19 100644 --- a/cmd/cometbft/commands/compact.go +++ b/cmd/cometbft/commands/compact.go @@ -14,8 +14,9 @@ import ( ) var CompactGoLevelDBCmd = &cobra.Command{ - Use: "experimental-compact-goleveldb", - Short: "force compacts the CometBFT storage engine (only GoLevelDB supported)", + Use: "experimental-compact-goleveldb", + Aliases: []string{"experimental_compact_goleveldb"}, + Short: "force compacts the CometBFT storage engine (only GoLevelDB supported)", Long: ` This is a temporary utility command that performs a force compaction on the state and blockstores to reduce disk space for a pruning node. This should only be run @@ -24,7 +25,7 @@ the planned refactor to the storage engine. Currently, only GoLevelDB is supported. `, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if config.DBBackend != "goleveldb" { return errors.New("compaction is currently only supported with goleveldb") } diff --git a/cmd/cometbft/commands/debug/debug.go b/cmd/cometbft/commands/debug/debug.go index 0d9430e89ec..2476968048b 100644 --- a/cmd/cometbft/commands/debug/debug.go +++ b/cmd/cometbft/commands/debug/debug.go @@ -32,8 +32,8 @@ func init() { DebugCmd.PersistentFlags().StringVar( &nodeRPCAddr, flagNodeRPCAddr, - "tcp://localhost:26657", - "the CometBFT node's RPC address (:)", + "tcp://localhost:26657/v1", + "the CometBFT node's RPC address (:) and version", ) DebugCmd.AddCommand(killCmd) diff --git a/cmd/cometbft/commands/debug/dump.go b/cmd/cometbft/commands/debug/dump.go index 8db59080ea8..e0bb4331ce9 100644 --- a/cmd/cometbft/commands/debug/dump.go +++ b/cmd/cometbft/commands/debug/dump.go @@ -13,6 +13,7 @@ import ( cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/libs/cli" rpchttp "github.com/cometbft/cometbft/rpc/client/http" + cmttime "github.com/cometbft/cometbft/types/time" ) var dumpCmd = &cobra.Command{ @@ -58,7 +59,7 @@ func dumpCmdHandler(_ *cobra.Command, args []string) error { } } - rpc, err := rpchttp.New(nodeRPCAddr, "/websocket") + rpc, err := rpchttp.New(nodeRPCAddr) if err != nil { return fmt.Errorf("failed to create new http client: %w", err) } @@ -79,7 +80,7 @@ func dumpCmdHandler(_ *cobra.Command, args []string) error { } func dumpDebugData(outDir string, conf *cfg.Config, rpc *rpchttp.HTTP) { - start := time.Now().UTC() + start := cmttime.Now() tmpDir, err := os.MkdirTemp(outDir, "cometbft_debug_tmp") if err != nil { @@ -126,7 +127,7 @@ func dumpDebugData(outDir string, conf *cfg.Config, rpc *rpchttp.HTTP) { } } - outFile := filepath.Join(outDir, fmt.Sprintf("%s.zip", start.Format(time.RFC3339))) + outFile := filepath.Join(outDir, start.Format(time.RFC3339)+".zip") if err := zipDir(tmpDir, outFile); err != nil { logger.Error("failed to create and compress archive", "file", outFile, "error", err) } diff --git a/cmd/cometbft/commands/debug/io.go b/cmd/cometbft/commands/debug/io.go index 01a14ea710f..8470210bee3 100644 --- a/cmd/cometbft/commands/debug/io.go +++ b/cmd/cometbft/commands/debug/io.go @@ -67,7 +67,6 @@ func zipDir(src, dest string) error { _, err = io.Copy(headerWriter, file) return err }) - } // copyFile copies a file from src to dest and returns an error upon failure. The @@ -104,7 +103,7 @@ func copyFile(src, dest string) error { // writeStateToFile pretty JSON encodes an object and writes it to file composed // of dir and filename. It returns an error upon failure to encode or write to // file. -func writeStateJSONToFile(state interface{}, dir, filename string) error { +func writeStateJSONToFile(state any, dir, filename string) error { stateJSON, err := json.MarshalIndent(state, "", " ") if err != nil { return fmt.Errorf("failed to encode state dump: %w", err) diff --git a/cmd/cometbft/commands/debug/kill.go b/cmd/cometbft/commands/debug/kill.go index 3a1c993bcdc..da1e62836e2 100644 --- a/cmd/cometbft/commands/debug/kill.go +++ b/cmd/cometbft/commands/debug/kill.go @@ -32,8 +32,8 @@ $ cometbft debug 34255 /path/to/cmt-debug.zip`, RunE: killCmdHandler, } -func killCmdHandler(cmd *cobra.Command, args []string) error { - pid, err := strconv.ParseUint(args[0], 10, 64) +func killCmdHandler(_ *cobra.Command, args []string) error { + pid, err := strconv.Atoi(args[0]) if err != nil { return err } @@ -43,7 +43,7 @@ func killCmdHandler(cmd *cobra.Command, args []string) error { return errors.New("invalid output file") } - rpc, err := rpchttp.New(nodeRPCAddr, "/websocket") + rpc, err := rpchttp.New(nodeRPCAddr) if err != nil { return fmt.Errorf("failed to create new http client: %w", err) } @@ -100,7 +100,7 @@ func killCmdHandler(cmd *cobra.Command, args []string) error { // is tailed and piped to a file under the directory dir. An error is returned // if the output file cannot be created or the tail command cannot be started. // An error is not returned if any subsequent syscall fails. -func killProc(pid uint64, dir string) error { +func killProc(pid int, dir string) error { // pipe STDERR output from tailing the CometBFT process to a file // // NOTE: This will only work on UNIX systems. @@ -123,7 +123,7 @@ func killProc(pid uint64, dir string) error { go func() { // Killing the CometBFT process with the '-ABRT|-6' signal will result in // a goroutine stacktrace. - p, err := os.FindProcess(int(pid)) + p, err := os.FindProcess(pid) if err != nil { fmt.Fprintf(os.Stderr, "failed to find PID to kill CometBFT process: %s", err) } else if err = p.Signal(syscall.SIGABRT); err != nil { diff --git a/cmd/cometbft/commands/debug/util.go b/cmd/cometbft/commands/debug/util.go index 0972a03a1da..800beb868af 100644 --- a/cmd/cometbft/commands/debug/util.go +++ b/cmd/cometbft/commands/debug/util.go @@ -6,7 +6,6 @@ import ( "io" "net/http" "os" - "path" "path/filepath" cfg "github.com/cometbft/cometbft/config" @@ -67,7 +66,7 @@ func copyConfig(home, dir string) error { func dumpProfile(dir, addr, profile string, debug int) error { endpoint := fmt.Sprintf("%s/debug/pprof/%s?debug=%d", addr, profile, debug) - //nolint:gosec,nolintlint + //nolint:gosec,nolintlint,noctx resp, err := http.Get(endpoint) if err != nil { return fmt.Errorf("failed to query for %s profile: %w", profile, err) @@ -79,5 +78,5 @@ func dumpProfile(dir, addr, profile string, debug int) error { return fmt.Errorf("failed to read %s profile response body: %w", profile, err) } - return os.WriteFile(path.Join(dir, fmt.Sprintf("%s.out", profile)), body, os.ModePerm) + return os.WriteFile(filepath.Join(dir, profile+".out"), body, os.ModePerm) } diff --git a/cmd/cometbft/commands/gen_node_key.go b/cmd/cometbft/commands/gen_node_key.go index 952e20fe610..c96f2564885 100644 --- a/cmd/cometbft/commands/gen_node_key.go +++ b/cmd/cometbft/commands/gen_node_key.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - cmtos "github.com/cometbft/cometbft/libs/os" + cmtos "github.com/cometbft/cometbft/internal/os" "github.com/cometbft/cometbft/p2p" ) @@ -15,11 +15,10 @@ var GenNodeKeyCmd = &cobra.Command{ Use: "gen-node-key", Aliases: []string{"gen_node_key"}, Short: "Generate a node key for this node and print its ID", - PreRun: deprecateSnakeCase, RunE: genNodeKey, } -func genNodeKey(cmd *cobra.Command, args []string) error { +func genNodeKey(*cobra.Command, []string) error { nodeKeyFile := config.NodeKeyFile() if cmtos.FileExists(nodeKeyFile) { return fmt.Errorf("node key at %s already exists", nodeKeyFile) diff --git a/cmd/cometbft/commands/gen_validator.go b/cmd/cometbft/commands/gen_validator.go index d0792306ca2..072b26576dd 100644 --- a/cmd/cometbft/commands/gen_validator.go +++ b/cmd/cometbft/commands/gen_validator.go @@ -15,11 +15,10 @@ var GenValidatorCmd = &cobra.Command{ Use: "gen-validator", Aliases: []string{"gen_validator"}, Short: "Generate new validator keypair", - PreRun: deprecateSnakeCase, Run: genValidator, } -func genValidator(cmd *cobra.Command, args []string) { +func genValidator(*cobra.Command, []string) { pv := privval.GenFilePV("", "") jsbz, err := cmtjson.Marshal(pv) if err != nil { diff --git a/cmd/cometbft/commands/init.go b/cmd/cometbft/commands/init.go index af7f60e6638..495c8a993a1 100644 --- a/cmd/cometbft/commands/init.go +++ b/cmd/cometbft/commands/init.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" cfg "github.com/cometbft/cometbft/config" - cmtos "github.com/cometbft/cometbft/libs/os" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtos "github.com/cometbft/cometbft/internal/os" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/privval" "github.com/cometbft/cometbft/types" @@ -21,7 +21,7 @@ var InitFilesCmd = &cobra.Command{ RunE: initFiles, } -func initFiles(cmd *cobra.Command, args []string) error { +func initFiles(*cobra.Command, []string) error { return initFilesWithConfig(config) } diff --git a/cmd/cometbft/commands/inspect.go b/cmd/cometbft/commands/inspect.go index d8ccecf04ef..7191ffe04a9 100644 --- a/cmd/cometbft/commands/inspect.go +++ b/cmd/cometbft/commands/inspect.go @@ -9,10 +9,10 @@ import ( "github.com/spf13/cobra" cfg "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/inspect" - "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/indexer/block" - "github.com/cometbft/cometbft/store" + "github.com/cometbft/cometbft/internal/inspect" + "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer/block" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/types" ) @@ -39,12 +39,12 @@ func init() { config.RPC.ListenAddress, "RPC listenener address. Port required") InspectCmd.Flags(). String("db-backend", - config.DBBackend, "database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb") + config.DBBackend, "database backend: goleveldb | rocksdb | badgerdb | pebbledb") InspectCmd.Flags(). String("db-dir", config.DBPath, "database directory") } -func runInspect(cmd *cobra.Command, args []string) error { +func runInspect(cmd *cobra.Command, _ []string) error { ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() @@ -59,7 +59,7 @@ func runInspect(cmd *cobra.Command, args []string) error { if err != nil { return err } - blockStore := store.NewBlockStore(blockStoreDB) + blockStore := store.NewBlockStore(blockStoreDB, store.WithDBKeyLayout(config.Storage.ExperimentalKeyLayout)) defer blockStore.Close() stateDB, err := cfg.DefaultDBProvider(&cfg.DBContext{ID: "state", Config: config}) @@ -77,11 +77,8 @@ func runInspect(cmd *cobra.Command, args []string) error { if err != nil { return err } - ins := inspect.New(config.RPC, blockStore, stateStore, txIndexer, blockIndexer, logger) + ins := inspect.New(config.RPC, blockStore, stateStore, txIndexer, blockIndexer) logger.Info("starting inspect server") - if err := ins.Run(ctx); err != nil { - return err - } - return nil + return ins.Run(ctx) } diff --git a/cmd/cometbft/commands/light.go b/cmd/cometbft/commands/light.go index 073dbc6ff10..d4a28d5e870 100644 --- a/cmd/cometbft/commands/light.go +++ b/cmd/cometbft/commands/light.go @@ -14,10 +14,9 @@ import ( "github.com/spf13/cobra" dbm "github.com/cometbft/cometbft-db" - + cmtos "github.com/cometbft/cometbft/internal/os" "github.com/cometbft/cometbft/libs/log" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtos "github.com/cometbft/cometbft/libs/os" "github.com/cometbft/cometbft/light" lproxy "github.com/cometbft/cometbft/light/proxy" lrpc "github.com/cometbft/cometbft/light/rpc" @@ -25,7 +24,7 @@ import ( rpcserver "github.com/cometbft/cometbft/rpc/jsonrpc/server" ) -// LightCmd represents the base command when called without any subcommands +// LightCmd represents the base command when called without any subcommands. var LightCmd = &cobra.Command{ Use: "light [chainID]", Short: "Run a light client proxy server, verifying CometBFT rpc", @@ -100,7 +99,7 @@ func init() { ) } -func runProxy(cmd *cobra.Command, args []string) error { +func runProxy(_ *cobra.Command, args []string) error { // Initialize logger. logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) var option log.Option diff --git a/cmd/cometbft/commands/probe_upnp.go b/cmd/cometbft/commands/probe_upnp.go deleted file mode 100644 index cf22bb5ae2b..00000000000 --- a/cmd/cometbft/commands/probe_upnp.go +++ /dev/null @@ -1,34 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/spf13/cobra" - - cmtjson "github.com/cometbft/cometbft/libs/json" - "github.com/cometbft/cometbft/p2p/upnp" -) - -// ProbeUpnpCmd adds capabilities to test the UPnP functionality. -var ProbeUpnpCmd = &cobra.Command{ - Use: "probe-upnp", - Aliases: []string{"probe_upnp"}, - Short: "Test UPnP functionality", - RunE: probeUpnp, - PreRun: deprecateSnakeCase, -} - -func probeUpnp(cmd *cobra.Command, args []string) error { - capabilities, err := upnp.Probe(logger) - if err != nil { - fmt.Println("Probe failed: ", err) - } else { - fmt.Println("Probe success!") - jsonBytes, err := cmtjson.Marshal(capabilities) - if err != nil { - return err - } - fmt.Println(string(jsonBytes)) - } - return nil -} diff --git a/cmd/cometbft/commands/reindex_event.go b/cmd/cometbft/commands/reindex_event.go index 958502d718e..41393c5dd76 100644 --- a/cmd/cometbft/commands/reindex_event.go +++ b/cmd/cometbft/commands/reindex_event.go @@ -8,16 +8,15 @@ import ( "github.com/spf13/cobra" dbm "github.com/cometbft/cometbft-db" - abcitypes "github.com/cometbft/cometbft/abci/types" cmtcfg "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/libs/progressbar" - "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/indexer" - blockidxkv "github.com/cometbft/cometbft/state/indexer/block/kv" - "github.com/cometbft/cometbft/state/indexer/sink/psql" - "github.com/cometbft/cometbft/state/txindex" - "github.com/cometbft/cometbft/state/txindex/kv" + "github.com/cometbft/cometbft/internal/progressbar" + "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + blockidxkv "github.com/cometbft/cometbft/internal/state/indexer/block/kv" + "github.com/cometbft/cometbft/internal/state/indexer/sink/psql" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/internal/state/txindex/kv" "github.com/cometbft/cometbft/types" ) @@ -32,13 +31,14 @@ var ( // ReIndexEventCmd constructs a command to re-index events in a block height interval. var ReIndexEventCmd = &cobra.Command{ - Use: "reindex-event", - Short: "reindex events to the event store backends", + Use: "reindex-event", + Aliases: []string{"reindex_event"}, + Short: "reindex events to the event store backends", Long: ` reindex-event is an offline tooling to re-index block and tx events to the eventsinks, -you can run this command when the event store backend dropped/disconnected or you want to -replace the backend. The default start-height is 0, meaning the tooling will start -reindex from the base block height(inclusive); and the default end-height is 0, meaning +you can run this command when the event store backend dropped/disconnected or you want to +replace the backend. The default start-height is 0, meaning the tooling will start +reindex from the base block height(inclusive); and the default end-height is 0, meaning the tooling will reindex until the latest block height(inclusive). User can omit either or both arguments. @@ -51,7 +51,7 @@ want to use this command. cometbft reindex-event --end-height 10 cometbft reindex-event --start-height 2 --end-height 10 `, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { bs, ss, err := loadStateAndBlockStore(config) if err != nil { fmt.Println(reindexFailed, err) @@ -149,7 +149,7 @@ func eventReIndex(cmd *cobra.Command, args eventReIndexArgs) error { case <-cmd.Context().Done(): return fmt.Errorf("event re-index terminated at height %d: %w", height, cmd.Context().Err()) default: - block := args.blockStore.LoadBlock(height) + block, _ := args.blockStore.LoadBlock(height) if block == nil { return fmt.Errorf("not able to load block at height %d from the blockstore", height) } diff --git a/cmd/cometbft/commands/reindex_event_test.go b/cmd/cometbft/commands/reindex_event_test.go index 2fc684ef579..2dead3fe3d8 100644 --- a/cmd/cometbft/commands/reindex_event_test.go +++ b/cmd/cometbft/commands/reindex_event_test.go @@ -10,13 +10,12 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abcitypes "github.com/cometbft/cometbft/abci/types" cmtcfg "github.com/cometbft/cometbft/config" + blockmocks "github.com/cometbft/cometbft/internal/state/indexer/mocks" + "github.com/cometbft/cometbft/internal/state/mocks" + txmocks "github.com/cometbft/cometbft/internal/state/txindex/mocks" "github.com/cometbft/cometbft/internal/test" - blockmocks "github.com/cometbft/cometbft/state/indexer/mocks" - "github.com/cometbft/cometbft/state/mocks" - txmocks "github.com/cometbft/cometbft/state/txindex/mocks" "github.com/cometbft/cometbft/types" ) @@ -28,7 +27,7 @@ const ( func setupReIndexEventCmd() *cobra.Command { reIndexEventCmd := &cobra.Command{ Use: ReIndexEventCmd.Use, - Run: func(cmd *cobra.Command, args []string) {}, + Run: func(_ *cobra.Command, _ []string) {}, } _ = reIndexEventCmd.ExecuteContext(context.Background()) @@ -135,11 +134,11 @@ func TestReIndexEvent(t *testing.T) { mockBlockStore. On("Base").Return(base). On("Height").Return(height). - On("LoadBlock", base).Return(nil).Once(). - On("LoadBlock", base).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}}). - On("LoadBlock", height).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}}) + On("LoadBlock", base).Return(nil, nil).Once(). + On("LoadBlock", base).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}}, &types.BlockMeta{}). + On("LoadBlock", height).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}}, &types.BlockMeta{}) - abciResp := &abcitypes.ResponseFinalizeBlock{ + abciResp := &abcitypes.FinalizeBlockResponse{ TxResults: []*abcitypes.ExecTxResult{ {Code: 1}, }, diff --git a/cmd/cometbft/commands/replay.go b/cmd/cometbft/commands/replay.go deleted file mode 100644 index ceb96f873d1..00000000000 --- a/cmd/cometbft/commands/replay.go +++ /dev/null @@ -1,28 +0,0 @@ -package commands - -import ( - "github.com/spf13/cobra" - - "github.com/cometbft/cometbft/consensus" -) - -// ReplayCmd allows replaying of messages from the WAL. -var ReplayCmd = &cobra.Command{ - Use: "replay", - Short: "Replay messages from WAL", - Run: func(cmd *cobra.Command, args []string) { - consensus.RunReplayFile(config.BaseConfig, config.Consensus, false) - }, -} - -// ReplayConsoleCmd allows replaying of messages from the WAL in a -// console. -var ReplayConsoleCmd = &cobra.Command{ - Use: "replay-console", - Aliases: []string{"replay_console"}, - Short: "Replay messages from WAL in a console", - Run: func(cmd *cobra.Command, args []string) { - consensus.RunReplayFile(config.BaseConfig, config.Consensus, true) - }, - PreRun: deprecateSnakeCase, -} diff --git a/cmd/cometbft/commands/reset.go b/cmd/cometbft/commands/reset.go index 4eadbad91a7..b1f4bc26164 100644 --- a/cmd/cometbft/commands/reset.go +++ b/cmd/cometbft/commands/reset.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" + cmtos "github.com/cometbft/cometbft/internal/os" "github.com/cometbft/cometbft/libs/log" - cmtos "github.com/cometbft/cometbft/libs/os" "github.com/cometbft/cometbft/privval" ) @@ -18,17 +18,16 @@ var ResetAllCmd = &cobra.Command{ Aliases: []string{"unsafe_reset_all"}, Short: "(unsafe) Remove all the data and WAL, reset this node's validator to genesis state", RunE: resetAllCmd, - PreRun: deprecateSnakeCase, } var keepAddrBook bool // ResetStateCmd removes the database of the specified CometBFT core instance. var ResetStateCmd = &cobra.Command{ - Use: "reset-state", - Short: "Remove all the data and WAL", - PreRun: deprecateSnakeCase, - RunE: func(cmd *cobra.Command, args []string) (err error) { + Use: "reset-state", + Aliases: []string{"reset_state"}, + Short: "Remove all the data and WAL", + RunE: func(cmd *cobra.Command, _ []string) (err error) { config, err = ParseConfig(cmd) if err != nil { return err @@ -47,13 +46,12 @@ var ResetPrivValidatorCmd = &cobra.Command{ Use: "unsafe-reset-priv-validator", Aliases: []string{"unsafe_reset_priv_validator"}, Short: "(unsafe) Reset this node's validator to genesis state", - PreRun: deprecateSnakeCase, RunE: resetPrivValidator, } // XXX: this is totally unsafe. // it's only suitable for testnets. -func resetAllCmd(cmd *cobra.Command, args []string) (err error) { +func resetAllCmd(cmd *cobra.Command, _ []string) (err error) { config, err = ParseConfig(cmd) if err != nil { return err @@ -70,7 +68,7 @@ func resetAllCmd(cmd *cobra.Command, args []string) (err error) { // XXX: this is totally unsafe. // it's only suitable for testnets. -func resetPrivValidator(cmd *cobra.Command, args []string) (err error) { +func resetPrivValidator(cmd *cobra.Command, _ []string) (err error) { config, err = ParseConfig(cmd) if err != nil { return err @@ -94,7 +92,7 @@ func resetAll(dbDir, addrBookFile, privValKeyFile, privValStateFile string, logg logger.Error("Error removing all blockchain history", "dir", dbDir, "err", err) } - if err := cmtos.EnsureDir(dbDir, 0700); err != nil { + if err := cmtos.EnsureDir(dbDir, 0o700); err != nil { logger.Error("unable to recreate dbDir", "err", err) } @@ -151,7 +149,7 @@ func resetState(dbDir string, logger log.Logger) error { } } - if err := cmtos.EnsureDir(dbDir, 0700); err != nil { + if err := cmtos.EnsureDir(dbDir, 0o700); err != nil { logger.Error("unable to recreate dbDir", "err", err) } return nil diff --git a/cmd/cometbft/commands/rollback.go b/cmd/cometbft/commands/rollback.go index 0471a0a0597..2b27ae6c8c5 100644 --- a/cmd/cometbft/commands/rollback.go +++ b/cmd/cometbft/commands/rollback.go @@ -7,11 +7,10 @@ import ( "github.com/spf13/cobra" dbm "github.com/cometbft/cometbft-db" - cfg "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/libs/os" - "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/store" + "github.com/cometbft/cometbft/internal/os" + "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" ) var removeBlock = false @@ -27,12 +26,12 @@ var RollbackStateCmd = &cobra.Command{ A state rollback is performed to recover from an incorrect application state transition, when CometBFT has persisted an incorrect app hash and is thus unable to make progress. Rollback overwrites a state at height n with the state at height n - 1. -The application should also roll back to height n - 1. If the --hard flag is not used, -no blocks will be removed so upon restarting CometBFT the transactions in block n will be +The application should also roll back to height n - 1. If the --hard flag is not used, +no blocks will be removed so upon restarting CometBFT the transactions in block n will be re-executed against the application. Using --hard will also remove block n. This can be done multiple times. `, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { height, hash, err := RollbackState(config, removeBlock) if err != nil { return fmt.Errorf("failed to rollback state: %w", err) @@ -78,7 +77,7 @@ func loadStateAndBlockStore(config *cfg.Config) (*store.BlockStore, state.Store, if err != nil { return nil, nil, err } - blockStore := store.NewBlockStore(blockStoreDB) + blockStore := store.NewBlockStore(blockStoreDB, store.WithDBKeyLayout(config.Storage.ExperimentalKeyLayout)) if !os.FileExists(filepath.Join(config.DBDir(), "state.db")) { return nil, nil, fmt.Errorf("no statestore found in %v", config.DBDir()) diff --git a/cmd/cometbft/commands/root.go b/cmd/cometbft/commands/root.go index 1d5fce3f3ae..d1d3553ac6d 100644 --- a/cmd/cometbft/commands/root.go +++ b/cmd/cometbft/commands/root.go @@ -3,7 +3,6 @@ package commands import ( "fmt" "os" - "strings" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -28,7 +27,7 @@ func registerFlagsRootCmd(cmd *cobra.Command) { } // ParseConfig retrieves the default environment configuration, -// sets up the CometBFT root and ensures that the root exists +// sets up the CometBFT root and ensures that the root exists. func ParseConfig(cmd *cobra.Command) (*cfg.Config, error) { conf := cfg.DefaultConfig() err := viper.Unmarshal(conf) @@ -37,13 +36,14 @@ func ParseConfig(cmd *cobra.Command) (*cfg.Config, error) { } var home string - if os.Getenv("CMTHOME") != "" { + switch { + case os.Getenv("CMTHOME") != "": home = os.Getenv("CMTHOME") - } else if os.Getenv("TMHOME") != "" { - //XXX: Deprecated. + case os.Getenv("TMHOME") != "": + // XXX: Deprecated. home = os.Getenv("TMHOME") logger.Error("Deprecated environment variable TMHOME identified. CMTHOME should be used instead.") - } else { + default: home, err = cmd.Flags().GetString(cli.HomeFlag) if err != nil { return nil, err @@ -69,7 +69,7 @@ func ParseConfig(cmd *cobra.Command) (*cfg.Config, error) { var RootCmd = &cobra.Command{ Use: "cometbft", Short: "BFT state machine replication for applications in any programming languages", - PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { + PersistentPreRunE: func(cmd *cobra.Command, _ []string) (err error) { if cmd.Name() == VersionCmd.Name() { return nil } @@ -96,10 +96,3 @@ var RootCmd = &cobra.Command{ return nil }, } - -// deprecateSnakeCase is a util function for 0.34.1. Should be removed in 0.35 -func deprecateSnakeCase(cmd *cobra.Command, args []string) { - if strings.Contains(cmd.CalledAs(), "_") { - fmt.Println("Deprecated: snake_case commands will be replaced by hyphen-case commands in the next major release") - } -} diff --git a/cmd/cometbft/commands/root_test.go b/cmd/cometbft/commands/root_test.go index 40909d86eb4..ee7c386a548 100644 --- a/cmd/cometbft/commands/root_test.go +++ b/cmd/cometbft/commands/root_test.go @@ -13,44 +13,27 @@ import ( "github.com/stretchr/testify/require" cfg "github.com/cometbft/cometbft/config" + cmtos "github.com/cometbft/cometbft/internal/os" "github.com/cometbft/cometbft/libs/cli" - cmtos "github.com/cometbft/cometbft/libs/os" -) - -var ( - defaultRoot = os.ExpandEnv("$HOME/.some/test/dir") ) // clearConfig clears env vars, the given root dir, and resets viper. -func clearConfig(dir string) { - if err := os.Unsetenv("CMTHOME"); err != nil { - panic(err) - } - if err := os.Unsetenv("CMT_HOME"); err != nil { - panic(err) - } - if err := os.Unsetenv("TMHOME"); err != nil { - //XXX: Deprecated. - panic(err) - } - if err := os.Unsetenv("TM_HOME"); err != nil { - //XXX: Deprecated. - panic(err) - } +func clearConfig(t *testing.T, dir string) { + t.Helper() + os.Clearenv() + err := os.RemoveAll(dir) + require.NoError(t, err) - if err := os.RemoveAll(dir); err != nil { - panic(err) - } viper.Reset() config = cfg.DefaultConfig() } -// prepare new rootCmd +// prepare new rootCmd. func testRootCmd() *cobra.Command { rootCmd := &cobra.Command{ Use: RootCmd.Use, PersistentPreRunE: RootCmd.PersistentPreRunE, - Run: func(cmd *cobra.Command, args []string) {}, + Run: func(_ *cobra.Command, _ []string) {}, } registerFlagsRootCmd(rootCmd) var l string @@ -58,11 +41,12 @@ func testRootCmd() *cobra.Command { return rootCmd } -func testSetup(rootDir string, args []string, env map[string]string) error { - clearConfig(defaultRoot) +func testSetup(t *testing.T, root string, args []string, env map[string]string) error { + t.Helper() + clearConfig(t, root) rootCmd := testRootCmd() - cmd := cli.PrepareBaseCmd(rootCmd, "CMT", defaultRoot) + cmd := cli.PrepareBaseCmd(rootCmd, "CMT", root) // run with the args and env args = append([]string{rootCmd.Use}, args...) @@ -70,23 +54,28 @@ func testSetup(rootDir string, args []string, env map[string]string) error { } func TestRootHome(t *testing.T) { - newRoot := filepath.Join(defaultRoot, "something-else") + tmpDir := os.TempDir() + root := filepath.Join(tmpDir, "adir") + newRoot := filepath.Join(tmpDir, "something-else") + defer clearConfig(t, root) + defer clearConfig(t, newRoot) + cases := []struct { args []string env map[string]string root string }{ - {nil, nil, defaultRoot}, + {nil, nil, root}, {[]string{"--home", newRoot}, nil, newRoot}, - {nil, map[string]string{"TMHOME": newRoot}, newRoot}, //XXX: Deprecated. + {nil, map[string]string{"TMHOME": newRoot}, newRoot}, // XXX: Deprecated. {nil, map[string]string{"CMTHOME": newRoot}, newRoot}, } for i, tc := range cases { - idxString := strconv.Itoa(i) + idxString := "idx: " + strconv.Itoa(i) - err := testSetup(defaultRoot, tc.args, tc.env) - require.Nil(t, err, idxString) + err := testSetup(t, root, tc.args, tc.env) + require.NoError(t, err, idxString) assert.Equal(t, tc.root, config.RootDir, idxString) assert.Equal(t, tc.root, config.P2P.RootDir, idxString) @@ -96,7 +85,6 @@ func TestRootHome(t *testing.T) { } func TestRootFlagsEnv(t *testing.T) { - // defaults defaults := cfg.DefaultConfig() defaultLogLvl := defaults.LogLevel @@ -118,16 +106,17 @@ func TestRootFlagsEnv(t *testing.T) { for i, tc := range cases { idxString := strconv.Itoa(i) - - err := testSetup(defaultRoot, tc.args, tc.env) - require.Nil(t, err, idxString) + root := filepath.Join(os.TempDir(), "adir2_"+idxString) + idxString = "idx: " + idxString + defer clearConfig(t, root) + err := testSetup(t, root, tc.args, tc.env) + require.NoError(t, err, idxString) assert.Equal(t, tc.logLevel, config.LogLevel, idxString) } } func TestRootConfig(t *testing.T) { - // write non-default config nonDefaultLogLvl := "abc:debug" cvals := map[string]string{ @@ -148,25 +137,26 @@ func TestRootConfig(t *testing.T) { for i, tc := range cases { idxString := strconv.Itoa(i) - clearConfig(defaultRoot) - + root := filepath.Join(os.TempDir(), "adir3_"+idxString) + idxString = "idx: " + idxString + defer clearConfig(t, root) // XXX: path must match cfg.defaultConfigPath - configFilePath := filepath.Join(defaultRoot, "config") - err := cmtos.EnsureDir(configFilePath, 0700) - require.Nil(t, err) + configFilePath := filepath.Join(root, "config") + err := cmtos.EnsureDir(configFilePath, 0o700) + require.NoError(t, err) // write the non-defaults to a different path // TODO: support writing sub configs so we can test that too err = WriteConfigVals(configFilePath, cvals) - require.Nil(t, err) + require.NoError(t, err) rootCmd := testRootCmd() - cmd := cli.PrepareBaseCmd(rootCmd, "CMT", defaultRoot) + cmd := cli.PrepareBaseCmd(rootCmd, "CMT", root) // run with the args and env tc.args = append([]string{rootCmd.Use}, tc.args...) err = cli.RunWithArgs(cmd, tc.args, tc.env) - require.Nil(t, err, idxString) + require.NoError(t, err, idxString) assert.Equal(t, tc.logLvl, config.LogLevel, idxString) } @@ -180,5 +170,5 @@ func WriteConfigVals(dir string, vals map[string]string) error { data += fmt.Sprintf("%s = \"%s\"\n", k, v) } cfile := filepath.Join(dir, "config.toml") - return os.WriteFile(cfile, []byte(data), 0600) + return os.WriteFile(cfile, []byte(data), 0o600) } diff --git a/cmd/cometbft/commands/run_node.go b/cmd/cometbft/commands/run_node.go index 2765b92e6e1..3f9a6a1971c 100644 --- a/cmd/cometbft/commands/run_node.go +++ b/cmd/cometbft/commands/run_node.go @@ -1,25 +1,19 @@ package commands import ( - "bytes" - "crypto/sha256" + "encoding/hex" "fmt" - "io" - "os" "github.com/spf13/cobra" - cfg "github.com/cometbft/cometbft/config" - cmtos "github.com/cometbft/cometbft/libs/os" + cmtos "github.com/cometbft/cometbft/internal/os" nm "github.com/cometbft/cometbft/node" ) -var ( - genesisHash []byte -) +var genesisHash []byte // AddNodeFlags exposes some common configuration options on the command-line -// These are exposed for convenience of commands embedding a CometBFT node +// These are exposed for convenience of commands embedding a CometBFT node. func AddNodeFlags(cmd *cobra.Command) { // bind flags cmd.Flags().String("moniker", config.Moniker, "node name") @@ -50,10 +44,6 @@ func AddNodeFlags(cmd *cobra.Command) { // rpc flags cmd.Flags().String("rpc.laddr", config.RPC.ListenAddress, "RPC listen address. Port required") - cmd.Flags().String( - "rpc.grpc_laddr", - config.RPC.GRPCListenAddress, - "GRPC listen address (BroadcastTx only). Port required") cmd.Flags().Bool("rpc.unsafe", config.RPC.Unsafe, "enabled unsafe rpc methods") cmd.Flags().String("rpc.pprof_laddr", config.RPC.PprofListenAddress, "pprof listen address (https://golang.org/pkg/net/http/pprof)") @@ -65,10 +55,8 @@ func AddNodeFlags(cmd *cobra.Command) { cmd.Flags().String("p2p.external-address", config.P2P.ExternalAddress, "ip:port address to advertise to peers for them to dial") cmd.Flags().String("p2p.seeds", config.P2P.Seeds, "comma-delimited ID@host:port seed nodes") cmd.Flags().String("p2p.persistent_peers", config.P2P.PersistentPeers, "comma-delimited ID@host:port persistent peers") - cmd.Flags().String("p2p.bootstrap_peers", config.P2P.BootstrapPeers, "comma-delimited ID@host:port peers to be added to the addressbook on startup") cmd.Flags().String("p2p.unconditional_peer_ids", config.P2P.UnconditionalPeerIDs, "comma-delimited IDs of unconditional peers") - cmd.Flags().Bool("p2p.upnp", config.P2P.UPNP, "enable/disable UPNP port forwarding") cmd.Flags().Bool("p2p.pex", config.P2P.PexReactor, "enable/disable Peer-Exchange") cmd.Flags().Bool("p2p.seed_mode", config.P2P.SeedMode, "enable/disable seed mode") cmd.Flags().String("p2p.private_peer_ids", config.P2P.PrivatePeerIDs, "comma-delimited private peer IDs") @@ -87,7 +75,7 @@ func AddNodeFlags(cmd *cobra.Command) { cmd.Flags().String( "db_backend", config.DBBackend, - "database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb") + "database backend: goleveldb | rocksdb | badgerdb | pebbledb") cmd.Flags().String( "db_dir", config.DBPath, @@ -101,9 +89,9 @@ func NewRunNodeCmd(nodeProvider nm.Provider) *cobra.Command { Use: "start", Aliases: []string{"node", "run"}, Short: "Run the CometBFT node", - RunE: func(cmd *cobra.Command, args []string) error { - if err := checkGenesisHash(config); err != nil { - return err + RunE: func(_ *cobra.Command, _ []string) error { + if len(genesisHash) != 0 { + config.Storage.GenesisHash = hex.EncodeToString(genesisHash) } n, err := nodeProvider(config, logger) @@ -134,30 +122,3 @@ func NewRunNodeCmd(nodeProvider nm.Provider) *cobra.Command { AddNodeFlags(cmd) return cmd } - -func checkGenesisHash(config *cfg.Config) error { - if len(genesisHash) == 0 || config.Genesis == "" { - return nil - } - - // Calculate SHA-256 hash of the genesis file. - f, err := os.Open(config.GenesisFile()) - if err != nil { - return fmt.Errorf("can't open genesis file: %w", err) - } - defer f.Close() - h := sha256.New() - if _, err := io.Copy(h, f); err != nil { - return fmt.Errorf("error when hashing genesis file: %w", err) - } - actualHash := h.Sum(nil) - - // Compare with the flag. - if !bytes.Equal(genesisHash, actualHash) { - return fmt.Errorf( - "--genesis_hash=%X does not match %s hash: %X", - genesisHash, config.GenesisFile(), actualHash) - } - - return nil -} diff --git a/cmd/cometbft/commands/show_node_id.go b/cmd/cometbft/commands/show_node_id.go index 07a1937f613..17bc0ed20c4 100644 --- a/cmd/cometbft/commands/show_node_id.go +++ b/cmd/cometbft/commands/show_node_id.go @@ -14,10 +14,9 @@ var ShowNodeIDCmd = &cobra.Command{ Aliases: []string{"show_node_id"}, Short: "Show this node's ID", RunE: showNodeID, - PreRun: deprecateSnakeCase, } -func showNodeID(cmd *cobra.Command, args []string) error { +func showNodeID(*cobra.Command, []string) error { nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) if err != nil { return err diff --git a/cmd/cometbft/commands/show_validator.go b/cmd/cometbft/commands/show_validator.go index 80d970d2015..4d8d97f4881 100644 --- a/cmd/cometbft/commands/show_validator.go +++ b/cmd/cometbft/commands/show_validator.go @@ -5,8 +5,8 @@ import ( "github.com/spf13/cobra" + cmtos "github.com/cometbft/cometbft/internal/os" cmtjson "github.com/cometbft/cometbft/libs/json" - cmtos "github.com/cometbft/cometbft/libs/os" "github.com/cometbft/cometbft/privval" ) @@ -16,10 +16,9 @@ var ShowValidatorCmd = &cobra.Command{ Aliases: []string{"show_validator"}, Short: "Show this node's validator info", RunE: showValidator, - PreRun: deprecateSnakeCase, } -func showValidator(cmd *cobra.Command, args []string) error { +func showValidator(*cobra.Command, []string) error { keyFilePath := config.PrivValidatorKeyFile() if !cmtos.FileExists(keyFilePath) { return fmt.Errorf("private validator file %s does not exist", keyFilePath) diff --git a/cmd/cometbft/commands/testnet.go b/cmd/cometbft/commands/testnet.go index 4fc6501b5a8..b9cd505792e 100644 --- a/cmd/cometbft/commands/testnet.go +++ b/cmd/cometbft/commands/testnet.go @@ -11,8 +11,8 @@ import ( "github.com/spf13/viper" cfg "github.com/cometbft/cometbft/config" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/libs/bytes" - cmtrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/privval" "github.com/cometbft/cometbft/types" @@ -37,7 +37,7 @@ var ( ) const ( - nodeDirPerm = 0755 + nodeDirPerm = 0o755 ) func init() { @@ -94,7 +94,7 @@ Example: RunE: testnetFiles, } -func testnetFiles(cmd *cobra.Command, args []string) error { +func testnetFiles(*cobra.Command, []string) error { if len(hostnames) > 0 && len(hostnames) != (nValidators+nNonValidators) { return fmt.Errorf( "testnet needs precisely %d hostnames (number of validators plus non-validators) if --hostname parameter is used", diff --git a/cmd/cometbft/commands/version.go b/cmd/cometbft/commands/version.go index 020b69da034..a4176702740 100644 --- a/cmd/cometbft/commands/version.go +++ b/cmd/cometbft/commands/version.go @@ -13,14 +13,14 @@ import ( var VersionCmd = &cobra.Command{ Use: "version", Short: "Show version info", - Run: func(cmd *cobra.Command, args []string) { - cmtVersion := version.TMCoreSemVer - if version.TMGitCommitHash != "" { - cmtVersion += "+" + version.TMGitCommitHash + Run: func(_ *cobra.Command, _ []string) { + cmtVersion := version.CMTSemVer + if version.CMTGitCommitHash != "" { + cmtVersion += "+" + version.CMTGitCommitHash } if verbose { - values, _ := json.MarshalIndent(struct { + values, err := json.MarshalIndent(struct { CometBFT string `json:"cometbft"` ABCI string `json:"abci"` BlockProtocol uint64 `json:"block_protocol"` @@ -31,6 +31,9 @@ var VersionCmd = &cobra.Command{ BlockProtocol: version.BlockProtocol, P2PProtocol: version.P2PProtocol, }, "", " ") + if err != nil { + panic(fmt.Sprintf("failed to marshal version info: %v", err)) + } fmt.Println(string(values)) } else { fmt.Println(cmtVersion) diff --git a/cmd/cometbft/main.go b/cmd/cometbft/main.go index f24e227ebba..0ca1ce8d24d 100644 --- a/cmd/cometbft/main.go +++ b/cmd/cometbft/main.go @@ -16,10 +16,7 @@ func main() { rootCmd.AddCommand( cmd.GenValidatorCmd, cmd.InitFilesCmd, - cmd.ProbeUpnpCmd, cmd.LightCmd, - cmd.ReplayCmd, - cmd.ReplayConsoleCmd, cmd.ResetAllCmd, cmd.ResetPrivValidatorCmd, cmd.ResetStateCmd, @@ -48,7 +45,7 @@ func main() { // Create & start node rootCmd.AddCommand(cmd.NewRunNodeCmd(nodeFunc)) - cmd := cli.PrepareBaseCmd(rootCmd, "CMT", os.ExpandEnv(filepath.Join("$HOME", cfg.DefaultTendermintDir))) + cmd := cli.PrepareBaseCmd(rootCmd, "CMT", os.ExpandEnv(filepath.Join("$HOME", cfg.DefaultCometDir))) if err := cmd.Execute(); err != nil { panic(err) } diff --git a/cmd/priv_val_server/main.go b/cmd/priv_val_server/main.go index fa2edc9342f..4d3926a55a7 100644 --- a/cmd/priv_val_server/main.go +++ b/cmd/priv_val_server/main.go @@ -6,10 +6,9 @@ import ( "time" "github.com/cometbft/cometbft/crypto/ed25519" + cmtnet "github.com/cometbft/cometbft/internal/net" + cmtos "github.com/cometbft/cometbft/internal/os" "github.com/cometbft/cometbft/libs/log" - cmtnet "github.com/cometbft/cometbft/libs/net" - cmtos "github.com/cometbft/cometbft/libs/os" - "github.com/cometbft/cometbft/privval" ) diff --git a/codecov.yml b/codecov.yml index 57c4bb16036..94448646568 100644 --- a/codecov.yml +++ b/codecov.yml @@ -19,7 +19,6 @@ ignore: - "DOCKER" - "scripts" - "**/*.pb.go" - - "libs/pubsub/query/query.peg.go" - "*.md" - "*.rst" - "*.yml" diff --git a/common.mk b/common.mk index 2ab35eaf1d0..e606d14fa40 100644 --- a/common.mk +++ b/common.mk @@ -3,13 +3,16 @@ BUILD_TAGS ?= cometbft COMMIT_HASH := $(shell git rev-parse --short HEAD) -LD_FLAGS = -X github.com/cometbft/cometbft/version.TMGitCommitHash=$(COMMIT_HASH) +LD_FLAGS = -X github.com/cometbft/cometbft/version.CMTGitCommitHash=$(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))) +ifeq (nostrip,$(findstring nostrip,$(COMETBFT_BUILD_OPTIONS))) + #prepare for delve + BUILD_FLAGS+= -gcflags "all=-N -l" +else BUILD_FLAGS += -trimpath LD_FLAGS += -s -w endif @@ -20,10 +23,10 @@ ifeq (race,$(findstring race,$(COMETBFT_BUILD_OPTIONS))) BUILD_FLAGS += -race endif -# handle cleveldb -ifeq (cleveldb,$(findstring cleveldb,$(COMETBFT_BUILD_OPTIONS))) +# handle clock_skew +ifeq (clock_skew,$(findstring clock_skew,$(COMETBFT_BUILD_OPTIONS))) CGO_ENABLED=1 - BUILD_TAGS += cleveldb + BUILD_TAGS += clock_skew endif # handle badgerdb @@ -37,7 +40,13 @@ ifeq (rocksdb,$(findstring rocksdb,$(COMETBFT_BUILD_OPTIONS))) BUILD_TAGS += rocksdb endif -# handle boltdb -ifeq (boltdb,$(findstring boltdb,$(COMETBFT_BUILD_OPTIONS))) - BUILD_TAGS += boltdb +# handle pebbledb +ifeq (pebbledb,$(findstring pebbledb,$(COMETBFT_BUILD_OPTIONS))) + BUILD_TAGS += pebbledb +endif + +# handle bls12381 +ifeq (bls12381,$(findstring bls12381,$(COMETBFT_BUILD_OPTIONS))) + CGO_ENABLED=1 + BUILD_TAGS += bls12381 endif diff --git a/config/config.go b/config/config.go index 00127a550b9..b8b7a5ccc26 100644 --- a/config/config.go +++ b/config/config.go @@ -8,28 +8,30 @@ import ( "os" "path/filepath" "regexp" + "strings" "time" + cmterrors "github.com/cometbft/cometbft/types/errors" "github.com/cometbft/cometbft/version" ) const ( - // FuzzModeDrop is a mode in which we randomly drop reads/writes, connections or sleep + // FuzzModeDrop is a mode in which we randomly drop reads/writes, connections or sleep. FuzzModeDrop = iota - // FuzzModeDelay is a mode in which we randomly sleep + // FuzzModeDelay is a mode in which we randomly sleep. FuzzModeDelay - // LogFormatPlain is a format for colored text + // LogFormatPlain is a format for colored text. LogFormatPlain = "plain" - // LogFormatJSON is a format for json output + // LogFormatJSON is a format for json output. LogFormatJSON = "json" // DefaultLogLevel defines a default log level as INFO. DefaultLogLevel = "info" - DefaultTendermintDir = ".cometbft" - DefaultConfigDir = "config" - DefaultDataDir = "data" + DefaultCometDir = ".cometbft" + DefaultConfigDir = "config" + DefaultDataDir = "data" DefaultConfigFileName = "config.toml" DefaultGenesisJSONName = "genesis.json" @@ -39,6 +41,15 @@ const ( DefaultNodeKeyName = "node_key.json" DefaultAddrBookName = "addrbook.json" + + DefaultPruningInterval = 10 * time.Second + + v0 = "v0" + v1 = "v1" + v2 = "v2" + + MempoolTypeFlood = "flood" + MempoolTypeNop = "nop" ) // NOTE: Most of the structs & relevant comments + the @@ -63,13 +74,14 @@ var ( semverRegexp = regexp.MustCompile(`^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`) ) -// Config defines the top level configuration for a CometBFT node +// Config defines the top level configuration for a CometBFT node. type Config struct { // Top level options use an anonymous struct BaseConfig `mapstructure:",squash"` // Options for services RPC *RPCConfig `mapstructure:"rpc"` + GRPC *GRPCConfig `mapstructure:"grpc"` P2P *P2PConfig `mapstructure:"p2p"` Mempool *MempoolConfig `mapstructure:"mempool"` StateSync *StateSyncConfig `mapstructure:"statesync"` @@ -80,11 +92,12 @@ type Config struct { Instrumentation *InstrumentationConfig `mapstructure:"instrumentation"` } -// DefaultConfig returns a default configuration for a CometBFT node +// DefaultConfig returns a default configuration for a CometBFT node. func DefaultConfig() *Config { return &Config{ BaseConfig: DefaultBaseConfig(), RPC: DefaultRPCConfig(), + GRPC: DefaultGRPCConfig(), P2P: DefaultP2PConfig(), Mempool: DefaultMempoolConfig(), StateSync: DefaultStateSyncConfig(), @@ -96,11 +109,12 @@ func DefaultConfig() *Config { } } -// TestConfig returns a configuration that can be used for testing +// TestConfig returns a configuration that can be used for testing. func TestConfig() *Config { return &Config{ BaseConfig: TestBaseConfig(), RPC: TestRPCConfig(), + GRPC: TestGRPCConfig(), P2P: TestP2PConfig(), Mempool: TestMempoolConfig(), StateSync: TestStateSyncConfig(), @@ -112,7 +126,7 @@ func TestConfig() *Config { } } -// SetRoot sets the RootDir for all Config structs +// SetRoot sets the RootDir for all Config structs. func (cfg *Config) SetRoot(root string) *Config { cfg.BaseConfig.RootDir = root cfg.RPC.RootDir = root @@ -129,41 +143,49 @@ func (cfg *Config) ValidateBasic() error { return err } if err := cfg.RPC.ValidateBasic(); err != nil { - return fmt.Errorf("error in [rpc] section: %w", err) + return ErrInSection{Section: "rpc", Err: err} + } + if err := cfg.GRPC.ValidateBasic(); err != nil { + return fmt.Errorf("error in [grpc] section: %w", err) } if err := cfg.P2P.ValidateBasic(); err != nil { - return fmt.Errorf("error in [p2p] section: %w", err) + return ErrInSection{Section: "p2p", Err: err} } if err := cfg.Mempool.ValidateBasic(); err != nil { - return fmt.Errorf("error in [mempool] section: %w", err) + return ErrInSection{Section: "mempool", Err: err} } if err := cfg.StateSync.ValidateBasic(); err != nil { - return fmt.Errorf("error in [statesync] section: %w", err) + return ErrInSection{Section: "statesync", Err: err} } if err := cfg.BlockSync.ValidateBasic(); err != nil { - return fmt.Errorf("error in [blocksync] section: %w", err) + return ErrInSection{Section: "blocksync", Err: err} } if err := cfg.Consensus.ValidateBasic(); err != nil { - return fmt.Errorf("error in [consensus] section: %w", err) + return ErrInSection{Section: "consensus", Err: err} + } + if err := cfg.Storage.ValidateBasic(); err != nil { + return fmt.Errorf("error in [storage] section: %w", err) } if err := cfg.Instrumentation.ValidateBasic(); err != nil { - return fmt.Errorf("error in [instrumentation] section: %w", err) + return ErrInSection{Section: "instrumentation", Err: err} + } + if !cfg.Consensus.CreateEmptyBlocks && cfg.Mempool.Type == MempoolTypeNop { + return errors.New("`nop` mempool does not support create_empty_blocks = false") } return nil } -// CheckDeprecated returns any deprecation warnings. These are printed to the operator on startup -func (cfg *Config) CheckDeprecated() []string { +// CheckDeprecated returns any deprecation warnings. These are printed to the operator on startup. +func (*Config) CheckDeprecated() []string { var warnings []string return warnings } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // BaseConfig -// BaseConfig defines the base configuration for a CometBFT node -type BaseConfig struct { //nolint: maligned - +// BaseConfig defines the base configuration for a CometBFT node. +type BaseConfig struct { // The version of the CometBFT binary that created // or last modified the config file Version string `mapstructure:"version"` @@ -179,25 +201,25 @@ type BaseConfig struct { //nolint: maligned // A custom human readable name for this node Moniker string `mapstructure:"moniker"` - // Database backend: goleveldb | cleveldb | boltdb | rocksdb - // * goleveldb (github.com/syndtr/goleveldb - most popular implementation) - // - pure go + // Database backend: goleveldb | rocksdb | badgerdb | pebbledb + // * goleveldb (github.com/syndtr/goleveldb) + // - UNMAINTAINED // - stable - // * cleveldb (uses levigo wrapper) - // - fast - // - requires gcc - // - use cleveldb build tag (go build -tags cleveldb) - // * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt) - // - EXPERIMENTAL - // - may be faster is some use-cases (random reads - indexer) - // - use boltdb build tag (go build -tags boltdb) - // * rocksdb (uses github.com/tecbot/gorocksdb) + // - pure go + // * rocksdb (uses github.com/linxGnu/grocksdb) // - EXPERIMENTAL // - requires gcc // - use rocksdb build tag (go build -tags rocksdb) // * badgerdb (uses github.com/dgraph-io/badger) // - EXPERIMENTAL + // - stable + // - pure go // - use badgerdb build tag (go build -tags badgerdb) + // * pebbledb (uses github.com/cockroachdb/pebble) + // - EXPERIMENTAL + // - stable + // - pure go + // - use pebbledb build tag (go build -tags pebbledb) DBBackend string `mapstructure:"db_backend"` // Database directory @@ -233,10 +255,10 @@ type BaseConfig struct { //nolint: maligned FilterPeers bool `mapstructure:"filter_peers"` // false } -// DefaultBaseConfig returns a default base configuration for a CometBFT node +// DefaultBaseConfig returns a default base configuration for a CometBFT node. func DefaultBaseConfig() BaseConfig { return BaseConfig{ - Version: version.TMCoreSemVer, + Version: version.CMTSemVer, Genesis: defaultGenesisJSONPath, PrivValidatorKey: defaultPrivValKeyPath, PrivValidatorState: defaultPrivValStatePath, @@ -252,7 +274,7 @@ func DefaultBaseConfig() BaseConfig { } } -// TestBaseConfig returns a base configuration for testing a CometBFT node +// TestBaseConfig returns a base configuration for testing a CometBFT node. func TestBaseConfig() BaseConfig { cfg := DefaultBaseConfig() cfg.ProxyApp = "kvstore" @@ -260,27 +282,27 @@ func TestBaseConfig() BaseConfig { return cfg } -// GenesisFile returns the full path to the genesis.json file +// GenesisFile returns the full path to the genesis.json file. func (cfg BaseConfig) GenesisFile() string { return rootify(cfg.Genesis, cfg.RootDir) } -// PrivValidatorKeyFile returns the full path to the priv_validator_key.json file +// PrivValidatorKeyFile returns the full path to the priv_validator_key.json file. func (cfg BaseConfig) PrivValidatorKeyFile() string { return rootify(cfg.PrivValidatorKey, cfg.RootDir) } -// PrivValidatorFile returns the full path to the priv_validator_state.json file +// PrivValidatorFile returns the full path to the priv_validator_state.json file. func (cfg BaseConfig) PrivValidatorStateFile() string { return rootify(cfg.PrivValidatorState, cfg.RootDir) } -// NodeKeyFile returns the full path to the node_key.json file +// NodeKeyFile returns the full path to the node_key.json file. func (cfg BaseConfig) NodeKeyFile() string { return rootify(cfg.NodeKey, cfg.RootDir) } -// DBDir returns the full path to the database directory +// DBDir returns the full path to the database directory. func (cfg BaseConfig) DBDir() string { return rootify(cfg.DBPath, cfg.RootDir) } @@ -302,10 +324,10 @@ func (cfg BaseConfig) ValidateBasic() error { return nil } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // RPCConfig -// RPCConfig defines the configuration options for the CometBFT RPC server +// RPCConfig defines the configuration options for the CometBFT RPC server. type RPCConfig struct { RootDir string `mapstructure:"home"` @@ -324,22 +346,10 @@ type RPCConfig struct { // A list of non simple headers the client is allowed to use with cross-domain requests. CORSAllowedHeaders []string `mapstructure:"cors_allowed_headers"` - // TCP or UNIX socket address for the gRPC server to listen on - // NOTE: This server only supports /broadcast_tx_commit - GRPCListenAddress string `mapstructure:"grpc_laddr"` - - // Maximum number of simultaneous connections. - // Does not include RPC (HTTP&WebSocket) connections. See max_open_connections - // If you want to accept a larger number than the default, make sure - // you increase your OS limits. - // 0 - unlimited. - GRPCMaxOpenConnections int `mapstructure:"grpc_max_open_connections"` - // Activate unsafe RPC commands like /dial_persistent_peers and /unsafe_flush_mempool Unsafe bool `mapstructure:"unsafe"` // Maximum number of simultaneous connections (including WebSocket). - // Does not include gRPC connections. See grpc_max_open_connections // If you want to accept a larger number than the default, make sure // you increase your OS limits. // 0 - unlimited. @@ -352,9 +362,9 @@ type RPCConfig struct { // of broadcast_tx_commit calls per block. MaxSubscriptionClients int `mapstructure:"max_subscription_clients"` - // Maximum number of unique queries a given client can /subscribe to - // If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set - // to the estimated maximum number of broadcast_tx_commit calls per block. + // Maximum number of unique queries a given client can /subscribe to. If + // you're using /broadcast_tx_commit, set to the estimated maximum number + // of broadcast_tx_commit calls per block. MaxSubscriptionsPerClient int `mapstructure:"max_subscriptions_per_client"` // The number of events that can be buffered per subscription before @@ -415,15 +425,13 @@ type RPCConfig struct { PprofListenAddress string `mapstructure:"pprof_laddr"` } -// DefaultRPCConfig returns a default configuration for the RPC server +// DefaultRPCConfig returns a default configuration for the RPC server. func DefaultRPCConfig() *RPCConfig { return &RPCConfig{ - ListenAddress: "tcp://127.0.0.1:26657", - CORSAllowedOrigins: []string{}, - CORSAllowedMethods: []string{http.MethodHead, http.MethodGet, http.MethodPost}, - CORSAllowedHeaders: []string{"Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time"}, - GRPCListenAddress: "", - GRPCMaxOpenConnections: 900, + ListenAddress: "tcp://127.0.0.1:26657", + CORSAllowedOrigins: []string{}, + CORSAllowedMethods: []string{http.MethodHead, http.MethodGet, http.MethodPost}, + CORSAllowedHeaders: []string{"Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time"}, Unsafe: false, MaxOpenConnections: 900, @@ -442,11 +450,10 @@ func DefaultRPCConfig() *RPCConfig { } } -// TestRPCConfig returns a configuration for testing the RPC server +// TestRPCConfig returns a configuration for testing the RPC server. func TestRPCConfig() *RPCConfig { cfg := DefaultRPCConfig() cfg.ListenAddress = "tcp://127.0.0.1:36657" - cfg.GRPCListenAddress = "tcp://127.0.0.1:36658" cfg.Unsafe = true return cfg } @@ -454,23 +461,17 @@ func TestRPCConfig() *RPCConfig { // ValidateBasic performs basic validation (checking param bounds, etc.) and // returns an error if any check fails. func (cfg *RPCConfig) ValidateBasic() error { - if cfg.GRPCMaxOpenConnections < 0 { - return errors.New("grpc_max_open_connections can't be negative") - } if cfg.MaxOpenConnections < 0 { - return errors.New("max_open_connections can't be negative") + return cmterrors.ErrNegativeField{Field: "max_open_connections"} } if cfg.MaxSubscriptionClients < 0 { - return errors.New("max_subscription_clients can't be negative") + return cmterrors.ErrNegativeField{Field: "max_subscription_clients"} } if cfg.MaxSubscriptionsPerClient < 0 { - return errors.New("max_subscriptions_per_client can't be negative") + return cmterrors.ErrNegativeField{Field: "max_subscriptions_per_client"} } if cfg.SubscriptionBufferSize < minSubscriptionBufferSize { - return fmt.Errorf( - "experimental_subscription_buffer_size must be >= %d", - minSubscriptionBufferSize, - ) + return ErrSubscriptionBufferSizeInvalid } if cfg.WebSocketWriteBufferSize < cfg.SubscriptionBufferSize { return fmt.Errorf( @@ -479,13 +480,13 @@ func (cfg *RPCConfig) ValidateBasic() error { ) } if cfg.TimeoutBroadcastTxCommit < 0 { - return errors.New("timeout_broadcast_tx_commit can't be negative") + return cmterrors.ErrNegativeField{Field: "timeout_broadcast_tx_commit"} } if cfg.MaxBodyBytes < 0 { - return errors.New("max_body_bytes can't be negative") + return cmterrors.ErrNegativeField{Field: "max_body_bytes"} } if cfg.MaxHeaderBytes < 0 { - return errors.New("max_header_bytes can't be negative") + return cmterrors.ErrNegativeField{Field: "max_header_bytes"} } return nil } @@ -519,10 +520,155 @@ func (cfg RPCConfig) IsTLSEnabled() bool { return cfg.TLSCertFile != "" && cfg.TLSKeyFile != "" } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// GRPCConfig + +// GRPCConfig defines the configuration for the CometBFT gRPC server. +type GRPCConfig struct { + // TCP or Unix socket address for the gRPC server to listen on. If empty, + // the gRPC server will be disabled. + ListenAddress string `mapstructure:"laddr"` + + // The gRPC version service provides version information about the node and + // the protocols it uses. + VersionService *GRPCVersionServiceConfig `mapstructure:"version_service"` + + // The gRPC block service provides block information + BlockService *GRPCBlockServiceConfig `mapstructure:"block_service"` + + // The gRPC block results service provides the block results for a given height + // If no height is provided, the block results of the latest height are returned + BlockResultsService *GRPCBlockResultsServiceConfig `mapstructure:"block_results_service"` + + // The "privileged" section provides configuration for the gRPC server + // dedicated to privileged clients. + Privileged *GRPCPrivilegedConfig `mapstructure:"privileged"` +} + +func DefaultGRPCConfig() *GRPCConfig { + return &GRPCConfig{ + ListenAddress: "", + VersionService: DefaultGRPCVersionServiceConfig(), + BlockService: DefaultGRPCBlockServiceConfig(), + BlockResultsService: DefaultGRPCBlockResultsServiceConfig(), + Privileged: DefaultGRPCPrivilegedConfig(), + } +} + +func TestGRPCConfig() *GRPCConfig { + return &GRPCConfig{ + ListenAddress: "tcp://127.0.0.1:36670", + VersionService: TestGRPCVersionServiceConfig(), + BlockService: TestGRPCBlockServiceConfig(), + BlockResultsService: DefaultGRPCBlockResultsServiceConfig(), + Privileged: TestGRPCPrivilegedConfig(), + } +} + +func (cfg *GRPCConfig) ValidateBasic() error { + if len(cfg.ListenAddress) > 0 { + addrParts := strings.SplitN(cfg.ListenAddress, "://", 2) + if len(addrParts) != 2 { + return fmt.Errorf( + "invalid listening address %s (use fully formed addresses, including the tcp:// or unix:// prefix)", + cfg.ListenAddress, + ) + } + } + return nil +} + +type GRPCVersionServiceConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +type GRPCBlockResultsServiceConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +func DefaultGRPCVersionServiceConfig() *GRPCVersionServiceConfig { + return &GRPCVersionServiceConfig{ + Enabled: true, + } +} + +func DefaultGRPCBlockResultsServiceConfig() *GRPCBlockResultsServiceConfig { + return &GRPCBlockResultsServiceConfig{ + Enabled: true, + } +} + +func TestGRPCVersionServiceConfig() *GRPCVersionServiceConfig { + return &GRPCVersionServiceConfig{ + Enabled: true, + } +} + +type GRPCBlockServiceConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +func DefaultGRPCBlockServiceConfig() *GRPCBlockServiceConfig { + return &GRPCBlockServiceConfig{ + Enabled: true, + } +} + +func TestGRPCBlockServiceConfig() *GRPCBlockServiceConfig { + return &GRPCBlockServiceConfig{ + Enabled: true, + } +} + +// ----------------------------------------------------------------------------- +// GRPCPrivilegedConfig + +// GRPCPrivilegedConfig defines the configuration for the CometBFT gRPC server +// exposing privileged endpoints. +type GRPCPrivilegedConfig struct { + // TCP or Unix socket address for the gRPC server for privileged clients + // to listen on. If empty, the privileged gRPC server will be disabled. + ListenAddress string `mapstructure:"laddr"` + + // The gRPC pruning service provides control over the depth of block + // storage information that the node + PruningService *GRPCPruningServiceConfig `mapstructure:"pruning_service"` +} + +func DefaultGRPCPrivilegedConfig() *GRPCPrivilegedConfig { + return &GRPCPrivilegedConfig{ + ListenAddress: "", + PruningService: DefaultGRPCPruningServiceConfig(), + } +} + +func TestGRPCPrivilegedConfig() *GRPCPrivilegedConfig { + return &GRPCPrivilegedConfig{ + ListenAddress: "tcp://127.0.0.1:36671", + PruningService: TestGRPCPruningServiceConfig(), + } +} + +type GRPCPruningServiceConfig struct { + Enabled bool `mapstructure:"enabled"` +} + +func DefaultGRPCPruningServiceConfig() *GRPCPruningServiceConfig { + return &GRPCPruningServiceConfig{ + Enabled: false, + } +} + +func TestGRPCPruningServiceConfig() *GRPCPruningServiceConfig { + return &GRPCPruningServiceConfig{ + Enabled: true, + } +} + +// ----------------------------------------------------------------------------- // P2PConfig -// P2PConfig defines the configuration options for the CometBFT peer-to-peer networking layer +// P2PConfig defines the configuration options for the CometBFT peer-to-peer networking layer. type P2PConfig struct { //nolint: maligned RootDir string `mapstructure:"home"` @@ -536,17 +682,9 @@ type P2PConfig struct { //nolint: maligned // We only use these if we can’t connect to peers in the addrbook Seeds string `mapstructure:"seeds"` - // Comma separated list of peers to be added to the peer store - // on startup. Either BootstrapPeers or PersistentPeers are - // needed for peer discovery - BootstrapPeers string `mapstructure:"bootstrap_peers"` - // Comma separated list of nodes to keep persistent connections to PersistentPeers string `mapstructure:"persistent_peers"` - // UPNP port forwarding - UPNP bool `mapstructure:"upnp"` - // Path to address book AddrBook string `mapstructure:"addr_book_file"` @@ -601,17 +739,16 @@ type P2PConfig struct { //nolint: maligned // Testing params. // Force dial to fail TestDialFail bool `mapstructure:"test_dial_fail"` - // FUzz connection + // Fuzz connection TestFuzz bool `mapstructure:"test_fuzz"` TestFuzzConfig *FuzzConnConfig `mapstructure:"test_fuzz_config"` } -// DefaultP2PConfig returns a default configuration for the peer-to-peer layer +// DefaultP2PConfig returns a default configuration for the peer-to-peer layer. func DefaultP2PConfig() *P2PConfig { return &P2PConfig{ ListenAddress: "tcp://0.0.0.0:26656", ExternalAddress: "", - UPNP: false, AddrBook: defaultAddrBookPath, AddrBookStrict: true, MaxNumInboundPeers: 40, @@ -632,7 +769,7 @@ func DefaultP2PConfig() *P2PConfig { } } -// TestP2PConfig returns a configuration for testing the peer-to-peer layer +// TestP2PConfig returns a configuration for testing the peer-to-peer layer. func TestP2PConfig() *P2PConfig { cfg := DefaultP2PConfig() cfg.ListenAddress = "tcp://127.0.0.1:36656" @@ -641,7 +778,7 @@ func TestP2PConfig() *P2PConfig { return cfg } -// AddrBookFile returns the full path to the address book +// AddrBookFile returns the full path to the address book. func (cfg *P2PConfig) AddrBookFile() string { return rootify(cfg.AddrBook, cfg.RootDir) } @@ -650,25 +787,25 @@ func (cfg *P2PConfig) AddrBookFile() string { // returns an error if any check fails. func (cfg *P2PConfig) ValidateBasic() error { if cfg.MaxNumInboundPeers < 0 { - return errors.New("max_num_inbound_peers can't be negative") + return cmterrors.ErrNegativeField{Field: "max_num_inbound_peers"} } if cfg.MaxNumOutboundPeers < 0 { - return errors.New("max_num_outbound_peers can't be negative") + return cmterrors.ErrNegativeField{Field: "max_num_outbound_peers"} } if cfg.FlushThrottleTimeout < 0 { - return errors.New("flush_throttle_timeout can't be negative") + return cmterrors.ErrNegativeField{Field: "flush_throttle_timeout"} } if cfg.PersistentPeersMaxDialPeriod < 0 { - return errors.New("persistent_peers_max_dial_period can't be negative") + return cmterrors.ErrNegativeField{Field: "persistent_peers_max_dial_period"} } if cfg.MaxPacketMsgPayloadSize < 0 { - return errors.New("max_packet_msg_payload_size can't be negative") + return cmterrors.ErrNegativeField{Field: "max_packet_msg_payload_size"} } if cfg.SendRate < 0 { - return errors.New("send_rate can't be negative") + return cmterrors.ErrNegativeField{Field: "send_rate"} } if cfg.RecvRate < 0 { - return errors.New("recv_rate can't be negative") + return cmterrors.ErrNegativeField{Field: "recv_rate"} } return nil } @@ -693,7 +830,7 @@ func DefaultFuzzConnConfig() *FuzzConnConfig { } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // MempoolConfig // MempoolConfig defines the configuration options for the CometBFT mempool @@ -703,6 +840,15 @@ func DefaultFuzzConnConfig() *FuzzConnConfig { // implementation (previously called v0), and a prioritized mempool (v1), which // was removed (see https://github.com/cometbft/cometbft/issues/260). type MempoolConfig struct { + // The type of mempool for this node to use. + // + // Possible types: + // - "flood" : concurrent linked list mempool with flooding gossip protocol + // (default) + // - "nop" : nop-mempool (short for no operation; the ABCI app is + // responsible for storing, disseminating and proposing txs). + // "create_empty_blocks=false" is not supported. + Type string `mapstructure:"type"` // RootDir is the root directory for all data. This should be configured via // the $CMTHOME env variable or --home cmd flag rather than overriding this // struct field. @@ -726,9 +872,12 @@ type MempoolConfig struct { WalPath string `mapstructure:"wal_dir"` // Maximum number of transactions in the mempool Size int `mapstructure:"size"` - // Limit the total size of all txs in the mempool. - // This only accounts for raw transactions (e.g. given 1MB transactions and - // max_txs_bytes=5MB, mempool will only accept 5 transactions). + // Maximum size in bytes of a single transaction accepted into the mempool. + MaxTxBytes int `mapstructure:"max_tx_bytes"` + // The maximum size in bytes of all transactions stored in the mempool. + // This is the raw, total transaction size. For example, given 1MB + // transactions and a 5MB maximum mempool byte size, the mempool will + // only accept five transactions. MaxTxsBytes int64 `mapstructure:"max_txs_bytes"` // Size of the cache (used to filter transactions we saw earlier) in transactions CacheSize int `mapstructure:"cache_size"` @@ -736,38 +885,48 @@ type MempoolConfig struct { // Set to true if it's not possible for any invalid transaction to become // valid again in the future. KeepInvalidTxsInCache bool `mapstructure:"keep-invalid-txs-in-cache"` - // Maximum size of a single transaction - // NOTE: the max size of a tx transmitted over the network is {max_tx_bytes}. - MaxTxBytes int `mapstructure:"max_tx_bytes"` - // Maximum size of a batch of transactions to send to a peer - // Including space needed by encoding (one varint per transaction). - // XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796 - MaxBatchBytes int `mapstructure:"max_batch_bytes"` -} - -// DefaultMempoolConfig returns a default configuration for the CometBFT mempool + // Experimental parameters to limit gossiping txs to up to the specified number of peers. + // We use two independent upper values for persistent and non-persistent peers. + // Unconditional peers are not affected by this feature. + // If we are connected to more than the specified number of persistent peers, only send txs to + // ExperimentalMaxGossipConnectionsToPersistentPeers of them. If one of those + // persistent peers disconnects, activate another persistent peer. + // Similarly for non-persistent peers, with an upper limit of + // ExperimentalMaxGossipConnectionsToNonPersistentPeers. + // If set to 0, the feature is disabled for the corresponding group of peers, that is, the + // number of active connections to that group of peers is not bounded. + // For non-persistent peers, if enabled, a value of 10 is recommended based on experimental + // performance results using the default P2P configuration. + ExperimentalMaxGossipConnectionsToPersistentPeers int `mapstructure:"experimental_max_gossip_connections_to_persistent_peers"` + ExperimentalMaxGossipConnectionsToNonPersistentPeers int `mapstructure:"experimental_max_gossip_connections_to_non_persistent_peers"` +} + +// DefaultMempoolConfig returns a default configuration for the CometBFT mempool. func DefaultMempoolConfig() *MempoolConfig { return &MempoolConfig{ + Type: MempoolTypeFlood, Recheck: true, Broadcast: true, WalPath: "", // Each signature verification takes .5ms, Size reduced until we implement // ABCI Recheck Size: 5000, - MaxTxsBytes: 1024 * 1024 * 1024, // 1GB + MaxTxBytes: 1024 * 1024, // 1MiB + MaxTxsBytes: 64 * 1024 * 1024, // 64MiB, enough to fill 16 blocks of 4 MiB CacheSize: 10000, - MaxTxBytes: 1024 * 1024, // 1MB + ExperimentalMaxGossipConnectionsToNonPersistentPeers: 0, + ExperimentalMaxGossipConnectionsToPersistentPeers: 0, } } -// TestMempoolConfig returns a configuration for testing the CometBFT mempool +// TestMempoolConfig returns a configuration for testing the CometBFT mempool. func TestMempoolConfig() *MempoolConfig { cfg := DefaultMempoolConfig() cfg.CacheSize = 1000 return cfg } -// WalDir returns the full path to the mempool's write-ahead log +// WalDir returns the full path to the mempool's write-ahead log. func (cfg *MempoolConfig) WalDir() string { return rootify(cfg.WalPath, cfg.RootDir) } @@ -780,25 +939,37 @@ func (cfg *MempoolConfig) WalEnabled() bool { // ValidateBasic performs basic validation (checking param bounds, etc.) and // returns an error if any check fails. func (cfg *MempoolConfig) ValidateBasic() error { + switch cfg.Type { + case MempoolTypeFlood, MempoolTypeNop: + case "": // allow empty string to be backwards compatible + default: + return fmt.Errorf("unknown mempool type: %q", cfg.Type) + } if cfg.Size < 0 { - return errors.New("size can't be negative") + return cmterrors.ErrNegativeField{Field: "size"} } if cfg.MaxTxsBytes < 0 { - return errors.New("max_txs_bytes can't be negative") + return cmterrors.ErrNegativeField{Field: "max_txs_bytes"} } if cfg.CacheSize < 0 { - return errors.New("cache_size can't be negative") + return cmterrors.ErrNegativeField{Field: "cache_size"} } if cfg.MaxTxBytes < 0 { - return errors.New("max_tx_bytes can't be negative") + return cmterrors.ErrNegativeField{Field: "max_tx_bytes"} + } + if cfg.ExperimentalMaxGossipConnectionsToPersistentPeers < 0 { + return cmterrors.ErrNegativeField{Field: "experimental_max_gossip_connections_to_persistent_peers"} + } + if cfg.ExperimentalMaxGossipConnectionsToNonPersistentPeers < 0 { + return cmterrors.ErrNegativeField{Field: "experimental_max_gossip_connections_to_non_persistent_peers"} } return nil } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // StateSyncConfig -// StateSyncConfig defines the configuration for the CometBFT state sync service +// StateSyncConfig defines the configuration for the CometBFT state sync service. type StateSyncConfig struct { Enable bool `mapstructure:"enable"` TempDir string `mapstructure:"temp_dir"` @@ -820,7 +991,7 @@ func (cfg *StateSyncConfig) TrustHashBytes() []byte { return bytes } -// DefaultStateSyncConfig returns a default configuration for the state sync service +// DefaultStateSyncConfig returns a default configuration for the state sync service. func DefaultStateSyncConfig() *StateSyncConfig { return &StateSyncConfig{ TrustPeriod: 168 * time.Hour, @@ -830,7 +1001,7 @@ func DefaultStateSyncConfig() *StateSyncConfig { } } -// TestStateSyncConfig returns a default configuration for the state sync service +// TestStateSyncConfig returns a default configuration for the state sync service. func TestStateSyncConfig() *StateSyncConfig { return DefaultStateSyncConfig() } @@ -839,33 +1010,33 @@ func TestStateSyncConfig() *StateSyncConfig { func (cfg *StateSyncConfig) ValidateBasic() error { if cfg.Enable { if len(cfg.RPCServers) == 0 { - return errors.New("rpc_servers is required") + return cmterrors.ErrRequiredField{Field: "rpc_servers"} } if len(cfg.RPCServers) < 2 { - return errors.New("at least two rpc_servers entries is required") + return ErrNotEnoughRPCServers } for _, server := range cfg.RPCServers { if len(server) == 0 { - return errors.New("found empty rpc_servers entry") + return ErrEmptyRPCServerEntry } } if cfg.DiscoveryTime != 0 && cfg.DiscoveryTime < 5*time.Second { - return errors.New("discovery time must be 0s or greater than five seconds") + return ErrInsufficientDiscoveryTime } if cfg.TrustPeriod <= 0 { - return errors.New("trusted_period is required") + return cmterrors.ErrRequiredField{Field: "trusted_period"} } if cfg.TrustHeight <= 0 { - return errors.New("trusted_height is required") + return cmterrors.ErrRequiredField{Field: "trusted_height"} } if len(cfg.TrustHash) == 0 { - return errors.New("trusted_hash is required") + return cmterrors.ErrRequiredField{Field: "trusted_hash"} } _, err := hex.DecodeString(cfg.TrustHash) @@ -874,26 +1045,26 @@ func (cfg *StateSyncConfig) ValidateBasic() error { } if cfg.ChunkRequestTimeout < 5*time.Second { - return errors.New("chunk_request_timeout must be at least 5 seconds") + return ErrInsufficientChunkRequestTimeout } if cfg.ChunkFetchers <= 0 { - return errors.New("chunk_fetchers is required") + return cmterrors.ErrRequiredField{Field: "chunk_fetchers"} } } return nil } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // BlockSyncConfig -// BlockSyncConfig (formerly known as FastSync) defines the configuration for the CometBFT block sync service +// BlockSyncConfig (formerly known as FastSync) defines the configuration for the CometBFT block sync service. type BlockSyncConfig struct { Version string `mapstructure:"version"` } -// DefaultBlockSyncConfig returns a default configuration for the block sync service +// DefaultBlockSyncConfig returns a default configuration for the block sync service. func DefaultBlockSyncConfig() *BlockSyncConfig { return &BlockSyncConfig{ Version: "v0", @@ -908,16 +1079,16 @@ func TestBlockSyncConfig() *BlockSyncConfig { // ValidateBasic performs basic validation. func (cfg *BlockSyncConfig) ValidateBasic() error { switch cfg.Version { - case "v0": + case v0: return nil - case "v1", "v2": - return fmt.Errorf("blocksync version %s has been deprecated. Please use v0 instead", cfg.Version) + case v1, v2: + return ErrDeprecatedBlocksyncVersion{Version: cfg.Version, Allowed: []string{v0}} default: - return fmt.Errorf("unknown blocksync version %s", cfg.Version) + return ErrUnknownBlocksyncVersion{cfg.Version} } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // ConsensusConfig // ConsensusConfig defines the configuration for the Tendermint consensus algorithm, adopted by CometBFT, @@ -953,33 +1124,35 @@ type ConsensusConfig struct { CreateEmptyBlocksInterval time.Duration `mapstructure:"create_empty_blocks_interval"` // Reactor sleep duration parameters - PeerGossipSleepDuration time.Duration `mapstructure:"peer_gossip_sleep_duration"` - PeerQueryMaj23SleepDuration time.Duration `mapstructure:"peer_query_maj23_sleep_duration"` + PeerGossipSleepDuration time.Duration `mapstructure:"peer_gossip_sleep_duration"` + PeerQueryMaj23SleepDuration time.Duration `mapstructure:"peer_query_maj23_sleep_duration"` + PeerGossipIntraloopSleepDuration time.Duration `mapstructure:"peer_gossip_intraloop_sleep_duration"` // upper bound on randomly selected values DoubleSignCheckHeight int64 `mapstructure:"double_sign_check_height"` } -// DefaultConsensusConfig returns a default configuration for the consensus service +// DefaultConsensusConfig returns a default configuration for the consensus service. func DefaultConsensusConfig() *ConsensusConfig { return &ConsensusConfig{ - WalPath: filepath.Join(DefaultDataDir, "cs.wal", "wal"), - TimeoutPropose: 3000 * time.Millisecond, - TimeoutProposeDelta: 500 * time.Millisecond, - TimeoutPrevote: 1000 * time.Millisecond, - TimeoutPrevoteDelta: 500 * time.Millisecond, - TimeoutPrecommit: 1000 * time.Millisecond, - TimeoutPrecommitDelta: 500 * time.Millisecond, - TimeoutCommit: 1000 * time.Millisecond, - SkipTimeoutCommit: false, - CreateEmptyBlocks: true, - CreateEmptyBlocksInterval: 0 * time.Second, - PeerGossipSleepDuration: 100 * time.Millisecond, - PeerQueryMaj23SleepDuration: 2000 * time.Millisecond, - DoubleSignCheckHeight: int64(0), - } -} - -// TestConsensusConfig returns a configuration for testing the consensus service + WalPath: filepath.Join(DefaultDataDir, "cs.wal", "wal"), + TimeoutPropose: 3000 * time.Millisecond, + TimeoutProposeDelta: 500 * time.Millisecond, + TimeoutPrevote: 1000 * time.Millisecond, + TimeoutPrevoteDelta: 500 * time.Millisecond, + TimeoutPrecommit: 1000 * time.Millisecond, + TimeoutPrecommitDelta: 500 * time.Millisecond, + TimeoutCommit: 1000 * time.Millisecond, + SkipTimeoutCommit: false, + CreateEmptyBlocks: true, + CreateEmptyBlocksInterval: 0 * time.Second, + PeerGossipSleepDuration: 100 * time.Millisecond, + PeerQueryMaj23SleepDuration: 2000 * time.Millisecond, + PeerGossipIntraloopSleepDuration: 0 * time.Second, + DoubleSignCheckHeight: int64(0), + } +} + +// TestConsensusConfig returns a configuration for testing the consensus service. func TestConsensusConfig() *ConsensusConfig { cfg := DefaultConsensusConfig() cfg.TimeoutPropose = 40 * time.Millisecond @@ -997,26 +1170,26 @@ func TestConsensusConfig() *ConsensusConfig { return cfg } -// WaitForTxs returns true if the consensus should wait for transactions before entering the propose step +// WaitForTxs returns true if the consensus should wait for transactions before entering the propose step. func (cfg *ConsensusConfig) WaitForTxs() bool { return !cfg.CreateEmptyBlocks || cfg.CreateEmptyBlocksInterval > 0 } -// Propose returns the amount of time to wait for a proposal +// Propose returns the amount of time to wait for a proposal. func (cfg *ConsensusConfig) Propose(round int32) time.Duration { return time.Duration( cfg.TimeoutPropose.Nanoseconds()+cfg.TimeoutProposeDelta.Nanoseconds()*int64(round), ) * time.Nanosecond } -// Prevote returns the amount of time to wait for straggler votes after receiving any +2/3 prevotes +// Prevote returns the amount of time to wait for straggler votes after receiving any +2/3 prevotes. func (cfg *ConsensusConfig) Prevote(round int32) time.Duration { return time.Duration( cfg.TimeoutPrevote.Nanoseconds()+cfg.TimeoutPrevoteDelta.Nanoseconds()*int64(round), ) * time.Nanosecond } -// Precommit returns the amount of time to wait for straggler votes after receiving any +2/3 precommits +// Precommit returns the amount of time to wait for straggler votes after receiving any +2/3 precommits. func (cfg *ConsensusConfig) Precommit(round int32) time.Duration { return time.Duration( cfg.TimeoutPrecommit.Nanoseconds()+cfg.TimeoutPrecommitDelta.Nanoseconds()*int64(round), @@ -1029,7 +1202,7 @@ func (cfg *ConsensusConfig) Commit(t time.Time) time.Time { return t.Add(cfg.TimeoutCommit) } -// WalFile returns the full path to the write-ahead log file +// WalFile returns the full path to the write-ahead log file. func (cfg *ConsensusConfig) WalFile() string { if cfg.walFile != "" { return cfg.walFile @@ -1037,7 +1210,7 @@ func (cfg *ConsensusConfig) WalFile() string { return rootify(cfg.WalPath, cfg.RootDir) } -// SetWalFile sets the path to the write-ahead log file +// SetWalFile sets the path to the write-ahead log file. func (cfg *ConsensusConfig) SetWalFile(walFile string) { cfg.walFile = walFile } @@ -1046,42 +1219,42 @@ func (cfg *ConsensusConfig) SetWalFile(walFile string) { // returns an error if any check fails. func (cfg *ConsensusConfig) ValidateBasic() error { if cfg.TimeoutPropose < 0 { - return errors.New("timeout_propose can't be negative") + return cmterrors.ErrNegativeField{Field: "timeout_propose"} } if cfg.TimeoutProposeDelta < 0 { - return errors.New("timeout_propose_delta can't be negative") + return cmterrors.ErrNegativeField{Field: "timeout_propose_delta"} } if cfg.TimeoutPrevote < 0 { - return errors.New("timeout_prevote can't be negative") + return cmterrors.ErrNegativeField{Field: "timeout_prevote"} } if cfg.TimeoutPrevoteDelta < 0 { - return errors.New("timeout_prevote_delta can't be negative") + return cmterrors.ErrNegativeField{Field: "timeout_prevote_delta"} } if cfg.TimeoutPrecommit < 0 { - return errors.New("timeout_precommit can't be negative") + return cmterrors.ErrNegativeField{Field: "timeout_precommit"} } if cfg.TimeoutPrecommitDelta < 0 { - return errors.New("timeout_precommit_delta can't be negative") + return cmterrors.ErrNegativeField{Field: "timeout_precommit_delta"} } if cfg.TimeoutCommit < 0 { - return errors.New("timeout_commit can't be negative") + return cmterrors.ErrNegativeField{Field: "timeout_commit"} } if cfg.CreateEmptyBlocksInterval < 0 { - return errors.New("create_empty_blocks_interval can't be negative") + return cmterrors.ErrNegativeField{Field: "create_empty_blocks_interval"} } if cfg.PeerGossipSleepDuration < 0 { - return errors.New("peer_gossip_sleep_duration can't be negative") + return cmterrors.ErrNegativeField{Field: "peer_gossip_sleep_duration"} } if cfg.PeerQueryMaj23SleepDuration < 0 { - return errors.New("peer_query_maj23_sleep_duration can't be negative") + return cmterrors.ErrNegativeField{Field: "peer_query_maj23_sleep_duration"} } if cfg.DoubleSignCheckHeight < 0 { - return errors.New("double_sign_check_height can't be negative") + return cmterrors.ErrNegativeField{Field: "double_sign_check_height"} } return nil } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // StorageConfig // StorageConfig allows more fine-grained control over certain storage-related @@ -1091,13 +1264,49 @@ type StorageConfig struct { // required for `/block_results` RPC queries, and to reindex events in the // command-line tool. DiscardABCIResponses bool `mapstructure:"discard_abci_responses"` + // Configuration related to storage pruning. + Pruning *PruningConfig `mapstructure:"pruning"` + // Compaction on pruning - enable or disable in-process compaction. + // If the DB backend supports it, this will force the DB to compact + // the database levels and save on storage space. Setting this to true + // is most beneficial when used in combination with pruning as it will + // phyisically delete the entries marked for deletion. + // false by default (forcing compaction is disabled). + Compact bool `mapstructure:"compact"` + // Compaction interval - number of blocks to try explicit compaction on. + // This parameter should be tuned depending on the number of items + // you expect to delete between two calls to forced compaction. + // If your retain height is 1 block, it is too much of an overhead + // to try compaction every block. But it should also not be a very + // large multiple of your retain height as it might occur bigger overheads. + // 1000 by default. + CompactionInterval int64 `mapstructure:"compaction_interval"` + // Hex representation of the hash of the genesis file. + // This is an optional parameter set when an operator provides + // a hash via the command line. + // It is used to verify the hash of the actual genesis file. + // Note that if the provided has does not match the hash of the genesis file + // the node will report an error and not boot. + GenesisHash string `mapstructure:"genesis_hash"` + + // The representation of keys in the database. + // The current representation of keys in Comet's stores is considered to be v1 + // Users can experiment with a different layout by setting this field to v2. + // Not that this is an experimental feature and switching back from v2 to v1 + // is not supported by CometBFT. + ExperimentalKeyLayout string `mapstructure:"experimental_db_key_layout"` } // DefaultStorageConfig returns the default configuration options relating to // CometBFT storage optimization. func DefaultStorageConfig() *StorageConfig { return &StorageConfig{ - DiscardABCIResponses: false, + DiscardABCIResponses: false, + Pruning: DefaultPruningConfig(), + Compact: false, + CompactionInterval: 1000, + GenesisHash: "", + ExperimentalKeyLayout: "v1", } } @@ -1106,7 +1315,19 @@ func DefaultStorageConfig() *StorageConfig { func TestStorageConfig() *StorageConfig { return &StorageConfig{ DiscardABCIResponses: false, + Pruning: TestPruningConfig(), + GenesisHash: "", + } +} + +func (cfg *StorageConfig) ValidateBasic() error { + if err := cfg.Pruning.ValidateBasic(); err != nil { + return fmt.Errorf("error in [pruning] section: %w", err) + } + if cfg.ExperimentalKeyLayout != "v1" && cfg.ExperimentalKeyLayout != "v2" { + return fmt.Errorf("unsupported version of DB Key layout, expected v1 or v2, got %s", cfg.ExperimentalKeyLayout) } + return nil } // ----------------------------------------------------------------------------- @@ -1149,7 +1370,7 @@ func TestTxIndexConfig() *TxIndexConfig { return DefaultTxIndexConfig() } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // InstrumentationConfig // InstrumentationConfig defines the configuration for metrics reporting. @@ -1193,7 +1414,7 @@ func TestInstrumentationConfig() *InstrumentationConfig { // returns an error if any check fails. func (cfg *InstrumentationConfig) ValidateBasic() error { if cfg.MaxOpenConnections < 0 { - return errors.New("max_open_connections can't be negative") + return cmterrors.ErrNegativeField{Field: "max_open_connections"} } return nil } @@ -1202,10 +1423,10 @@ func (cfg *InstrumentationConfig) IsPrometheusEnabled() bool { return cfg.Prometheus && cfg.PrometheusListenAddr != "" } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Utils -// helper function to make config creation independent of root dir +// helper function to make config creation independent of root dir. func rootify(path, root string) string { if filepath.IsAbs(path) { return path @@ -1213,7 +1434,7 @@ func rootify(path, root string) string { return filepath.Join(root, path) } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Moniker var defaultMoniker = getDefaultMoniker() @@ -1227,3 +1448,89 @@ func getDefaultMoniker() string { } return moniker } + +// ----------------------------------------------------------------------------- +// PruningConfig + +type PruningConfig struct { + // The time period between automated background pruning operations. + Interval time.Duration `mapstructure:"interval"` + // Data companion-related pruning configuration. + DataCompanion *DataCompanionPruningConfig `mapstructure:"data_companion"` +} + +func DefaultPruningConfig() *PruningConfig { + return &PruningConfig{ + Interval: DefaultPruningInterval, + DataCompanion: DefaultDataCompanionPruningConfig(), + } +} + +func TestPruningConfig() *PruningConfig { + return &PruningConfig{ + Interval: DefaultPruningInterval, + DataCompanion: TestDataCompanionPruningConfig(), + } +} + +func (cfg *PruningConfig) ValidateBasic() error { + if cfg.Interval <= 0 { + return errors.New("interval must be > 0") + } + if err := cfg.DataCompanion.ValidateBasic(); err != nil { + return fmt.Errorf("error in [data_companion] section: %w", err) + } + return nil +} + +// ----------------------------------------------------------------------------- +// DataCompanionPruningConfig + +type DataCompanionPruningConfig struct { + // Whether automatic pruning respects values set by the data companion. + // Disabled by default. All other parameters in this section are ignored + // when this is disabled. + // + // If disabled, only the application retain height will influence block + // pruning (but not block results pruning). Only enabling this at a later + // stage will potentially mean that blocks below the application-set retain + // height at the time will not be available to the data companion. + Enabled bool `mapstructure:"enabled"` + // The initial value for the data companion block retain height if the data + // companion has not yet explicitly set one. If the data companion has + // already set a block retain height, this is ignored. + InitialBlockRetainHeight int64 `mapstructure:"initial_block_retain_height"` + // The initial value for the data companion block results retain height if + // the data companion has not yet explicitly set one. If the data companion + // has already set a block results retain height, this is ignored. + InitialBlockResultsRetainHeight int64 `mapstructure:"initial_block_results_retain_height"` +} + +func DefaultDataCompanionPruningConfig() *DataCompanionPruningConfig { + return &DataCompanionPruningConfig{ + Enabled: false, + InitialBlockRetainHeight: 0, + InitialBlockResultsRetainHeight: 0, + } +} + +func TestDataCompanionPruningConfig() *DataCompanionPruningConfig { + return &DataCompanionPruningConfig{ + Enabled: false, + InitialBlockRetainHeight: 0, + InitialBlockResultsRetainHeight: 0, + } +} + +func (cfg *DataCompanionPruningConfig) ValidateBasic() error { + if !cfg.Enabled { + return nil + } + if cfg.InitialBlockRetainHeight < 0 { + return errors.New("initial_block_retain_height cannot be negative") + } + if cfg.InitialBlockResultsRetainHeight < 0 { + return errors.New("initial_block_results_retain_height cannot be negative") + } + return nil +} diff --git a/config/config_test.go b/config/config_test.go index 8f01bdc6e33..b8fd48ac0f3 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -29,16 +29,20 @@ func TestDefaultConfig(t *testing.T) { assert.Equal("/foo/bar", cfg.GenesisFile()) assert.Equal("/opt/data", cfg.DBDir()) assert.Equal("/foo/wal/mem", cfg.Mempool.WalDir()) - } func TestConfigValidateBasic(t *testing.T) { cfg := config.DefaultConfig() - assert.NoError(t, cfg.ValidateBasic()) + require.NoError(t, cfg.ValidateBasic()) // tamper with timeout_propose cfg.Consensus.TimeoutPropose = -10 * time.Second - assert.Error(t, cfg.ValidateBasic()) + require.Error(t, cfg.ValidateBasic()) + cfg.Consensus.TimeoutPropose = 3 * time.Second + + cfg.Consensus.CreateEmptyBlocks = false + cfg.Mempool.Type = config.MempoolTypeNop + require.Error(t, cfg.ValidateBasic()) } func TestTLSConfiguration(t *testing.T) { @@ -59,19 +63,18 @@ func TestTLSConfiguration(t *testing.T) { func TestBaseConfigValidateBasic(t *testing.T) { cfg := config.TestBaseConfig() - assert.NoError(t, cfg.ValidateBasic()) + require.NoError(t, cfg.ValidateBasic()) // tamper with log format cfg.LogFormat = "invalid" - assert.Error(t, cfg.ValidateBasic()) + require.Error(t, cfg.ValidateBasic()) } func TestRPCConfigValidateBasic(t *testing.T) { cfg := config.TestRPCConfig() - assert.NoError(t, cfg.ValidateBasic()) + require.NoError(t, cfg.ValidateBasic()) fieldsToTest := []string{ - "GRPCMaxOpenConnections", "MaxOpenConnections", "MaxSubscriptionClients", "MaxSubscriptionsPerClient", @@ -82,14 +85,14 @@ func TestRPCConfigValidateBasic(t *testing.T) { for _, fieldName := range fieldsToTest { reflect.ValueOf(cfg).Elem().FieldByName(fieldName).SetInt(-1) - assert.Error(t, cfg.ValidateBasic()) + require.Error(t, cfg.ValidateBasic()) reflect.ValueOf(cfg).Elem().FieldByName(fieldName).SetInt(0) } } func TestP2PConfigValidateBasic(t *testing.T) { cfg := config.TestP2PConfig() - assert.NoError(t, cfg.ValidateBasic()) + require.NoError(t, cfg.ValidateBasic()) fieldsToTest := []string{ "MaxNumInboundPeers", @@ -102,14 +105,14 @@ func TestP2PConfigValidateBasic(t *testing.T) { for _, fieldName := range fieldsToTest { reflect.ValueOf(cfg).Elem().FieldByName(fieldName).SetInt(-1) - assert.Error(t, cfg.ValidateBasic()) + require.Error(t, cfg.ValidateBasic()) reflect.ValueOf(cfg).Elem().FieldByName(fieldName).SetInt(0) } } func TestMempoolConfigValidateBasic(t *testing.T) { cfg := config.TestMempoolConfig() - assert.NoError(t, cfg.ValidateBasic()) + require.NoError(t, cfg.ValidateBasic()) fieldsToTest := []string{ "Size", @@ -120,9 +123,12 @@ func TestMempoolConfigValidateBasic(t *testing.T) { for _, fieldName := range fieldsToTest { reflect.ValueOf(cfg).Elem().FieldByName(fieldName).SetInt(-1) - assert.Error(t, cfg.ValidateBasic()) + require.Error(t, cfg.ValidateBasic()) reflect.ValueOf(cfg).Elem().FieldByName(fieldName).SetInt(0) } + + reflect.ValueOf(cfg).Elem().FieldByName("Type").SetString("invalid") + require.Error(t, cfg.ValidateBasic()) } func TestStateSyncConfigValidateBasic(t *testing.T) { @@ -132,14 +138,14 @@ func TestStateSyncConfigValidateBasic(t *testing.T) { func TestBlockSyncConfigValidateBasic(t *testing.T) { cfg := config.TestBlockSyncConfig() - assert.NoError(t, cfg.ValidateBasic()) + require.NoError(t, cfg.ValidateBasic()) // tamper with version cfg.Version = "v1" - assert.Error(t, cfg.ValidateBasic()) + require.Error(t, cfg.ValidateBasic()) cfg.Version = "invalid" - assert.Error(t, cfg.ValidateBasic()) + require.Error(t, cfg.ValidateBasic()) } func TestConsensusConfig_ValidateBasic(t *testing.T) { @@ -176,9 +182,9 @@ func TestConsensusConfig_ValidateBasic(t *testing.T) { err := cfg.ValidateBasic() if tc.expectErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -186,9 +192,9 @@ func TestConsensusConfig_ValidateBasic(t *testing.T) { func TestInstrumentationConfigValidateBasic(t *testing.T) { cfg := config.TestInstrumentationConfig() - assert.NoError(t, cfg.ValidateBasic()) + require.NoError(t, cfg.ValidateBasic()) // tamper with maximum open connections cfg.MaxOpenConnections = -1 - assert.Error(t, cfg.ValidateBasic()) + require.Error(t, cfg.ValidateBasic()) } diff --git a/config/db.go b/config/db.go index 2f0235fd827..77c5b2ba279 100644 --- a/config/db.go +++ b/config/db.go @@ -4,9 +4,8 @@ import ( "context" dbm "github.com/cometbft/cometbft-db" - + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" ) // ServiceProvider takes a config and a logger and returns a ready to go Node. diff --git a/config/errors.go b/config/errors.go new file mode 100644 index 00000000000..88b320e27ff --- /dev/null +++ b/config/errors.go @@ -0,0 +1,46 @@ +package config + +import ( + "errors" + "fmt" +) + +var ( + ErrEmptyRPCServerEntry = errors.New("found empty rpc_servers entry") + ErrNotEnoughRPCServers = errors.New("at least two rpc_servers entries are required") + ErrInsufficientDiscoveryTime = errors.New("snapshot discovery time must be at least five seconds") + ErrInsufficientChunkRequestTimeout = errors.New("timeout for re-requesting a chunk (chunk_request_timeout) is less than 5 seconds") + ErrUnknownLogFormat = errors.New("unknown log_format (must be 'plain' or 'json')") + ErrSubscriptionBufferSizeInvalid = fmt.Errorf("experimental_subscription_buffer_size must be >= %d", minSubscriptionBufferSize) +) + +// ErrInSection is returned if validate basic does not pass for any underlying config service. +type ErrInSection struct { + Err error + Section string +} + +func (e ErrInSection) Error() string { + return fmt.Sprintf("error in [%s] section: %s", e.Section, e.Err.Error()) +} + +func (e ErrInSection) Unwrap() error { + return e.Err +} + +type ErrDeprecatedBlocksyncVersion struct { + Version string + Allowed []string +} + +func (e ErrDeprecatedBlocksyncVersion) Error() string { + return fmt.Sprintf("blocksync version %s has been deprecated. Please use %s instead", e.Version, e.Allowed) +} + +type ErrUnknownBlocksyncVersion struct { + Version string +} + +func (e ErrUnknownBlocksyncVersion) Error() string { + return "unknown blocksync version " + e.Version +} diff --git a/config/toml.go b/config/toml.go index 598f40f1967..214ffd2db0a 100644 --- a/config/toml.go +++ b/config/toml.go @@ -6,11 +6,11 @@ import ( "strings" "text/template" - cmtos "github.com/cometbft/cometbft/libs/os" + cmtos "github.com/cometbft/cometbft/internal/os" ) // DefaultDirPerm is the default permissions used when creating directories. -const DefaultDirPerm = 0700 +const DefaultDirPerm = 0o700 var configTemplate *template.Template @@ -24,7 +24,7 @@ func init() { } } -/****** these are for production settings ***********/ +// ****** these are for production settings *********** // // EnsureRoot creates the root, config, and data directories if they don't exist, // and panics if it fails. @@ -48,7 +48,7 @@ func EnsureRoot(rootDir string) { } // XXX: this func should probably be called by cmd/cometbft/commands/init.go -// alongside the writing of the genesis.json and priv_validator.json +// alongside the writing of the genesis.json and priv_validator.json. func writeDefaultConfigFile(configFilePath string) { WriteConfigFile(configFilePath, DefaultConfig()) } @@ -61,11 +61,11 @@ func WriteConfigFile(configFilePath string, config *Config) { panic(err) } - cmtos.MustWriteFile(configFilePath, buffer.Bytes(), 0644) + cmtos.MustWriteFile(configFilePath, buffer.Bytes(), 0o644) } // Note: any changes to the comments/variables/mapstructure -// must be reflected in the appropriate struct in config/config.go +// must be reflected in the appropriate struct in config/config.go. const defaultConfigTemplate = `# This is a TOML config file. # For more information, see https://github.com/toml-lang/toml @@ -89,25 +89,25 @@ proxy_app = "{{ .BaseConfig.ProxyApp }}" # A custom human readable name for this node moniker = "{{ .BaseConfig.Moniker }}" -# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb -# * goleveldb (github.com/syndtr/goleveldb - most popular implementation) -# - pure go +# Database backend: goleveldb | rocksdb | badgerdb | pebbledb +# * goleveldb (github.com/syndtr/goleveldb) +# - UNMAINTAINED # - stable -# * cleveldb (uses levigo wrapper) -# - fast -# - requires gcc -# - use cleveldb build tag (go build -tags cleveldb) -# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt) -# - EXPERIMENTAL -# - may be faster is some use-cases (random reads - indexer) -# - use boltdb build tag (go build -tags boltdb) -# * rocksdb (uses github.com/tecbot/gorocksdb) +# - pure go +# * rocksdb (uses github.com/linxGnu/grocksdb) # - EXPERIMENTAL # - requires gcc # - use rocksdb build tag (go build -tags rocksdb) # * badgerdb (uses github.com/dgraph-io/badger) # - EXPERIMENTAL +# - stable +# - pure go # - use badgerdb build tag (go build -tags badgerdb) +# * pebbledb (uses github.com/cockroachdb/pebble) +# - EXPERIMENTAL +# - stable +# - pure go +# - use pebbledb build tag (go build -tags pebbledb) db_backend = "{{ .BaseConfig.DBBackend }}" # Database directory @@ -168,24 +168,10 @@ cors_allowed_methods = [{{ range .RPC.CORSAllowedMethods }}{{ printf "%q, " . }} # A list of non simple headers the client is allowed to use with cross-domain requests cors_allowed_headers = [{{ range .RPC.CORSAllowedHeaders }}{{ printf "%q, " . }}{{end}}] -# TCP or UNIX socket address for the gRPC server to listen on -# NOTE: This server only supports /broadcast_tx_commit -grpc_laddr = "{{ .RPC.GRPCListenAddress }}" - -# Maximum number of simultaneous connections. -# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections -# If you want to accept a larger number than the default, make sure -# you increase your OS limits. -# 0 - unlimited. -# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} -# 1024 - 40 - 10 - 50 = 924 = ~900 -grpc_max_open_connections = {{ .RPC.GRPCMaxOpenConnections }} - # Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool unsafe = {{ .RPC.Unsafe }} # Maximum number of simultaneous connections (including WebSocket). -# Does not include gRPC connections. See grpc_max_open_connections # If you want to accept a larger number than the default, make sure # you increase your OS limits. # 0 - unlimited. @@ -193,14 +179,14 @@ unsafe = {{ .RPC.Unsafe }} # 1024 - 40 - 10 - 50 = 924 = ~900 max_open_connections = {{ .RPC.MaxOpenConnections }} -# Maximum number of unique clientIDs that can /subscribe +# Maximum number of unique clientIDs that can /subscribe. # If you're using /broadcast_tx_commit, set to the estimated maximum number # of broadcast_tx_commit calls per block. max_subscription_clients = {{ .RPC.MaxSubscriptionClients }} -# Maximum number of unique queries a given client can /subscribe to -# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to -# the estimated # maximum number of broadcast_tx_commit calls per block. +# Maximum number of unique queries a given client can /subscribe to. +# If you're using /broadcast_tx_commit, set to the estimated maximum number +# of broadcast_tx_commit calls per block. max_subscriptions_per_client = {{ .RPC.MaxSubscriptionsPerClient }} # Experimental parameter to specify the maximum number of events a node will @@ -253,13 +239,73 @@ tls_cert_file = "{{ .RPC.TLSCertFile }}" # The path to a file containing matching private key that is used to create the HTTPS server. # Might be either absolute path or path related to CometBFT's config directory. -# NOTE: both tls-cert-file and tls-key-file must be present for CometBFT to create HTTPS server. +# NOTE: both tls_cert_file and tls_key_file must be present for CometBFT to create HTTPS server. # Otherwise, HTTP server is run. tls_key_file = "{{ .RPC.TLSKeyFile }}" # pprof listen address (https://golang.org/pkg/net/http/pprof) pprof_laddr = "{{ .RPC.PprofListenAddress }}" +####################################################### +### gRPC Server Configuration Options ### +####################################################### + +# +# Note that the gRPC server is exposed unauthenticated. It is critical that +# this server not be exposed directly to the public internet. If this service +# must be accessed via the public internet, please ensure that appropriate +# precautions are taken (e.g. fronting with a reverse proxy like nginx with TLS +# termination and authentication, using DDoS protection services like +# CloudFlare, etc.). +# + +[grpc] + +# TCP or UNIX socket address for the RPC server to listen on. If not specified, +# the gRPC server will be disabled. +laddr = "{{ .GRPC.ListenAddress }}" + +# +# Each gRPC service can be turned on/off, and in some cases configured, +# individually. If the gRPC server is not enabled, all individual services' +# configurations are ignored. +# + +# The gRPC version service provides version information about the node and the +# protocols it uses. +[grpc.version_service] +enabled = {{ .GRPC.VersionService.Enabled }} + +# The gRPC block service returns block information +[grpc.block_service] +enabled = {{ .GRPC.BlockService.Enabled }} + +# The gRPC block results service returns block results for a given height. If no height +# is given, it will return the block results from the latest height. +[grpc.block_results_service] +enabled = {{ .GRPC.BlockResultsService.Enabled }} + +# +# Configuration for privileged gRPC endpoints, which should **never** be exposed +# to the public internet. +# +[grpc.privileged] +# The host/port on which to expose privileged gRPC endpoints. +laddr = "{{ .GRPC.Privileged.ListenAddress }}" + +# +# Configuration specifically for the gRPC pruning service, which is considered a +# privileged service. +# +[grpc.privileged.pruning_service] + +# Only controls whether the pruning service is accessible via the gRPC API - not +# whether a previously set pruning service retain height is honored by the +# node. See the [storage.pruning] section for control over pruning. +# +# Disabled by default. +enabled = {{ .GRPC.Privileged.PruningService.Enabled }} + ####################################################### ### P2P Configuration Options ### ####################################################### @@ -268,27 +314,17 @@ pprof_laddr = "{{ .RPC.PprofListenAddress }}" # Address to listen for incoming connections laddr = "{{ .P2P.ListenAddress }}" -# Address to advertise to peers for them to dial -# If empty, will use the same port as the laddr, -# and will introspect on the listener or use UPnP -# to figure out the address. ip and port are required -# example: 159.89.10.97:26656 +# Address to advertise to peers for them to dial. If empty, will use the same +# port as the laddr, and will introspect on the listener to figure out the +# address. IP and port are required. Example: 159.89.10.97:26656 external_address = "{{ .P2P.ExternalAddress }}" # Comma separated list of seed nodes to connect to seeds = "{{ .P2P.Seeds }}" -# Comma separated list of peers to be added to the peer store -# on startup. Either BootstrapPeers or PersistentPeers are -# needed for peer discovery -bootstrap_peers = "{{ .P2P.BootstrapPeers }}" - # Comma separated list of nodes to keep persistent connections to persistent_peers = "{{ .P2P.PersistentPeers }}" -# UPNP port forwarding -upnp = {{ .P2P.UPNP }} - # Path to address book addr_book_file = "{{ js .P2P.AddrBook }}" @@ -340,36 +376,50 @@ handshake_timeout = "{{ .P2P.HandshakeTimeout }}" dial_timeout = "{{ .P2P.DialTimeout }}" ####################################################### -### Mempool Configuration Option ### +### Mempool Configuration Options ### ####################################################### [mempool] -# Recheck (default: true) defines whether CometBFT should recheck the +# The type of mempool for this node to use. +# +# Possible types: +# - "flood" : concurrent linked list mempool with flooding gossip protocol +# (default) +# - "nop" : nop-mempool (short for no operation; the ABCI app is responsible +# for storing, disseminating and proposing txs). "create_empty_blocks=false" is +# not supported. +type = "flood" + +# recheck (default: true) defines whether CometBFT should recheck the # validity for all remaining transaction in the mempool after a block. # Since a block affects the application state, some transactions in the # mempool may become invalid. If this does not apply to your application, # you can disable rechecking. recheck = {{ .Mempool.Recheck }} -# Broadcast (default: true) defines whether the mempool should relay +# broadcast (default: true) defines whether the mempool should relay # transactions to other peers. Setting this to false will stop the mempool # from relaying transactions to other peers until they are included in a # block. In other words, if Broadcast is disabled, only the peer you send # the tx to will see it until it is included in a block. broadcast = {{ .Mempool.Broadcast }} -# WalPath (default: "") configures the location of the Write Ahead Log +# wal_dir (default: "") configures the location of the Write Ahead Log # (WAL) for the mempool. The WAL is disabled by default. To enable, set -# WalPath to where you want the WAL to be written (e.g. +# wal_dir to where you want the WAL to be written (e.g. # "data/mempool.wal"). wal_dir = "{{ js .Mempool.WalPath }}" # Maximum number of transactions in the mempool size = {{ .Mempool.Size }} -# Limit the total size of all txs in the mempool. -# This only accounts for raw transactions (e.g. given 1MB transactions and -# max_txs_bytes=5MB, mempool will only accept 5 transactions). +# Maximum size in bytes of a single transaction accepted into the mempool. +max_tx_bytes = {{ .Mempool.MaxTxBytes }} + +# The maximum size in bytes of all transactions stored in the mempool. +# This is the raw, total transaction size. For example, given 1MB +# transactions and a 5MB maximum mempool byte size, the mempool will +# only accept five transactions. max_txs_bytes = {{ .Mempool.MaxTxsBytes }} # Size of the cache (used to filter transactions we saw earlier) in transactions @@ -380,14 +430,20 @@ cache_size = {{ .Mempool.CacheSize }} # again in the future. keep-invalid-txs-in-cache = {{ .Mempool.KeepInvalidTxsInCache }} -# Maximum size of a single transaction. -# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes}. -max_tx_bytes = {{ .Mempool.MaxTxBytes }} - -# Maximum size of a batch of transactions to send to a peer -# Including space needed by encoding (one varint per transaction). -# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796 -max_batch_bytes = {{ .Mempool.MaxBatchBytes }} +# Experimental parameters to limit gossiping txs to up to the specified number of peers. +# We use two independent upper values for persistent and non-persistent peers. +# Unconditional peers are not affected by this feature. +# If we are connected to more than the specified number of persistent peers, only send txs to +# ExperimentalMaxGossipConnectionsToPersistentPeers of them. If one of those +# persistent peers disconnects, activate another persistent peer. +# Similarly for non-persistent peers, with an upper limit of +# ExperimentalMaxGossipConnectionsToNonPersistentPeers. +# If set to 0, the feature is disabled for the corresponding group of peers, that is, the +# number of active connections to that group of peers is not bounded. +# For non-persistent peers, if enabled, a value of 10 is recommended based on experimental +# performance results using the default P2P configuration. +experimental_max_gossip_connections_to_persistent_peers = {{ .Mempool.ExperimentalMaxGossipConnectionsToPersistentPeers }} +experimental_max_gossip_connections_to_non_persistent_peers = {{ .Mempool.ExperimentalMaxGossipConnectionsToNonPersistentPeers }} ####################################################### ### State Sync Configuration Options ### @@ -477,6 +533,7 @@ create_empty_blocks_interval = "{{ .Consensus.CreateEmptyBlocksInterval }}" # Reactor sleep duration parameters peer_gossip_sleep_duration = "{{ .Consensus.PeerGossipSleepDuration }}" +peer_gossip_intraloop_sleep_duration = "{{ .Consensus.PeerGossipIntraloopSleepDuration }}" peer_query_maj23_sleep_duration = "{{ .Consensus.PeerQueryMaj23SleepDuration }}" ####################################################### @@ -490,6 +547,65 @@ peer_query_maj23_sleep_duration = "{{ .Consensus.PeerQueryMaj23SleepDuration }}" # reindex events in the command-line tool. discard_abci_responses = {{ .Storage.DiscardABCIResponses}} +# The representation of keys in the database. +# The current representation of keys in Comet's stores is considered to be v1 +# Users can experiment with a different layout by setting this field to v2. +# Note that this is an experimental feature and switching back from v2 to v1 +# is not supported by CometBFT. +# If the database was initially created with v1, it is necessary to migrate the DB +# before switching to v2. The migration is not done automatically. +# v1 - the legacy layout existing in Comet prior to v1. +# v2 - Order preserving representation ordering entries by height. +experimental_db_key_layout = "{{ .Storage.ExperimentalKeyLayout }}" + +# If set to true, CometBFT will force compaction to happen for databases that support this feature. +# and save on storage space. Setting this to true is most benefits when used in combination +# with pruning as it will physically delete the entries marked for deletion. +# false by default (forcing compaction is disabled). +compact = {{ .Storage.Compact }} + +# To avoid forcing compaction every time, this parameter instructs CometBFT to wait +# the given amount of blocks to be pruned before triggering compaction. +# It should be tuned depending on the number of items. If your retain height is 1 block, +# it is too much of an overhead to try compaction every block. But it should also not be a very +# large multiple of your retain height as it might occur bigger overheads. +compaction_interval = "{{ .Storage.CompactionInterval }}" + +# Hash of the Genesis file (as hex string), passed to CometBFT via the command line. +# If this hash mismatches the hash that CometBFT computes on the genesis file, +# the node is not able to boot. +genesis_hash = "{{ .Storage.GenesisHash }}" + +[storage.pruning] + +# The time period between automated background pruning operations. +interval = "{{ .Storage.Pruning.Interval }}" + +# +# Storage pruning configuration relating only to the data companion. +# +[storage.pruning.data_companion] + +# Whether automatic pruning respects values set by the data companion. Disabled +# by default. All other parameters in this section are ignored when this is +# disabled. +# +# If disabled, only the application retain height will influence block pruning +# (but not block results pruning). Only enabling this at a later stage will +# potentially mean that blocks below the application-set retain height at the +# time will not be available to the data companion. +enabled = {{ .Storage.Pruning.DataCompanion.Enabled }} + +# The initial value for the data companion block retain height if the data +# companion has not yet explicitly set one. If the data companion has already +# set a block retain height, this is ignored. +initial_block_retain_height = {{ .Storage.Pruning.DataCompanion.InitialBlockRetainHeight }} + +# The initial value for the data companion block results retain height if the +# data companion has not yet explicitly set one. If the data companion has +# already set a block results retain height, this is ignored. +initial_block_results_retain_height = {{ .Storage.Pruning.DataCompanion.InitialBlockResultsRetainHeight }} + ####################################################### ### Transaction Indexer Configuration Options ### ####################################################### diff --git a/config/toml_test.go b/config/toml_test.go index 58a103e9371..7434dd61028 100644 --- a/config/toml_test.go +++ b/config/toml_test.go @@ -13,10 +13,11 @@ import ( ) func ensureFiles(t *testing.T, rootDir string, files ...string) { + t.Helper() for _, f := range files { p := filepath.Join(rootDir, f) _, err := os.Stat(p) - assert.NoError(t, err, p) + require.NoError(t, err, p) } } @@ -25,7 +26,7 @@ func TestEnsureRoot(t *testing.T) { // setup temp dir for test tmpDir, err := os.MkdirTemp("", "config-test") - require.Nil(err) + require.NoError(err) defer os.RemoveAll(tmpDir) // create root dir @@ -33,7 +34,7 @@ func TestEnsureRoot(t *testing.T) { // make sure config is set properly data, err := os.ReadFile(filepath.Join(tmpDir, config.DefaultConfigDir, config.DefaultConfigFileName)) - require.Nil(err) + require.NoError(err) assertValidConfig(t, string(data)) @@ -50,7 +51,7 @@ func TestEnsureTestRoot(t *testing.T) { // make sure config is set properly data, err := os.ReadFile(filepath.Join(rootDir, config.DefaultConfigDir, config.DefaultConfigFileName)) - require.Nil(err) + require.NoError(err) assertValidConfig(t, string(data)) @@ -62,7 +63,7 @@ func TestEnsureTestRoot(t *testing.T) { func assertValidConfig(t *testing.T, configFile string) { t.Helper() // list of words we expect in the config - var elems = []string{ + elems := []string{ "moniker", "seeds", "proxy_app", diff --git a/consensus/replay_file.go b/consensus/replay_file.go deleted file mode 100644 index 269dcc0fd82..00000000000 --- a/consensus/replay_file.go +++ /dev/null @@ -1,339 +0,0 @@ -package consensus - -import ( - "bufio" - "context" - "errors" - "fmt" - "io" - "os" - "strconv" - "strings" - - dbm "github.com/cometbft/cometbft-db" - - cfg "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/libs/log" - cmtos "github.com/cometbft/cometbft/libs/os" - "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/store" - "github.com/cometbft/cometbft/types" -) - -const ( - // event bus subscriber - subscriber = "replay-file" -) - -//-------------------------------------------------------- -// replay messages interactively or all at once - -// replay the wal file -func RunReplayFile(config cfg.BaseConfig, csConfig *cfg.ConsensusConfig, console bool) { - consensusState := newConsensusStateForReplay(config, csConfig) - - if err := consensusState.ReplayFile(csConfig.WalFile(), console); err != nil { - cmtos.Exit(fmt.Sprintf("Error during consensus replay: %v", err)) - } -} - -// Replay msgs in file or start the console -func (cs *State) ReplayFile(file string, console bool) error { - if cs.IsRunning() { - return errors.New("cs is already running, cannot replay") - } - if cs.wal != nil { - return errors.New("cs wal is open, cannot replay") - } - - cs.startForReplay() - - // ensure all new step events are regenerated as expected - - ctx := context.Background() - newStepSub, err := cs.eventBus.Subscribe(ctx, subscriber, types.EventQueryNewRoundStep) - if err != nil { - return fmt.Errorf("failed to subscribe %s to %v", subscriber, types.EventQueryNewRoundStep) - } - defer func() { - if err := cs.eventBus.Unsubscribe(ctx, subscriber, types.EventQueryNewRoundStep); err != nil { - cs.Logger.Error("Error unsubscribing to event bus", "err", err) - } - }() - - // just open the file for reading, no need to use wal - fp, err := os.OpenFile(file, os.O_RDONLY, 0o600) - if err != nil { - return err - } - - pb := newPlayback(file, fp, cs, cs.state.Copy()) - defer pb.fp.Close() - - var nextN int // apply N msgs in a row - var msg *TimedWALMessage - for { - if nextN == 0 && console { - nextN = pb.replayConsoleLoop() - } - - msg, err = pb.dec.Decode() - if err == io.EOF { - return nil - } else if err != nil { - return err - } - - if err := pb.cs.readReplayMessage(msg, newStepSub); err != nil { - return err - } - - if nextN > 0 { - nextN-- - } - pb.count++ - } -} - -//------------------------------------------------ -// playback manager - -type playback struct { - cs *State - - fp *os.File - dec *WALDecoder - count int // how many lines/msgs into the file are we - - // replays can be reset to beginning - fileName string // so we can close/reopen the file - genesisState sm.State // so the replay session knows where to restart from -} - -func newPlayback(fileName string, fp *os.File, cs *State, genState sm.State) *playback { - return &playback{ - cs: cs, - fp: fp, - fileName: fileName, - genesisState: genState, - dec: NewWALDecoder(fp), - } -} - -// go back count steps by resetting the state and running (pb.count - count) steps -func (pb *playback) replayReset(count int, newStepSub types.Subscription) error { - if err := pb.cs.Stop(); err != nil { - return err - } - pb.cs.Wait() - - newCS := NewState(pb.cs.config, pb.genesisState.Copy(), pb.cs.blockExec, - pb.cs.blockStore, pb.cs.txNotifier, pb.cs.evpool) - newCS.SetEventBus(pb.cs.eventBus) - newCS.startForReplay() - - if err := pb.fp.Close(); err != nil { - return err - } - fp, err := os.OpenFile(pb.fileName, os.O_RDONLY, 0o600) - if err != nil { - return err - } - pb.fp = fp - pb.dec = NewWALDecoder(fp) - count = pb.count - count - fmt.Printf("Reseting from %d to %d\n", pb.count, count) - pb.count = 0 - pb.cs = newCS - var msg *TimedWALMessage - for i := 0; i < count; i++ { - msg, err = pb.dec.Decode() - if err == io.EOF { - return nil - } else if err != nil { - return err - } - if err := pb.cs.readReplayMessage(msg, newStepSub); err != nil { - return err - } - pb.count++ - } - return nil -} - -func (cs *State) startForReplay() { - cs.Logger.Error("Replay commands are disabled until someone updates them and writes tests") - /* TODO:! - // since we replay tocks we just ignore ticks - go func() { - for { - select { - case <-cs.tickChan: - case <-cs.Quit: - return - } - } - }()*/ -} - -// console function for parsing input and running commands -func (pb *playback) replayConsoleLoop() int { - for { - fmt.Printf("> ") - bufReader := bufio.NewReader(os.Stdin) - line, more, err := bufReader.ReadLine() - if more { - cmtos.Exit("input is too long") - } else if err != nil { - cmtos.Exit(err.Error()) - } - - tokens := strings.Split(string(line), " ") - if len(tokens) == 0 { - continue - } - - switch tokens[0] { - case "next": - // "next" -> replay next message - // "next N" -> replay next N messages - - if len(tokens) == 1 { - return 0 - } - i, err := strconv.Atoi(tokens[1]) - if err != nil { - fmt.Println("next takes an integer argument") - } else { - return i - } - - case "back": - // "back" -> go back one message - // "back N" -> go back N messages - - // NOTE: "back" is not supported in the state machine design, - // so we restart and replay up to - - ctx := context.Background() - // ensure all new step events are regenerated as expected - - newStepSub, err := pb.cs.eventBus.Subscribe(ctx, subscriber, types.EventQueryNewRoundStep) - if err != nil { - cmtos.Exit(fmt.Sprintf("failed to subscribe %s to %v", subscriber, types.EventQueryNewRoundStep)) - } - defer func() { - if err := pb.cs.eventBus.Unsubscribe(ctx, subscriber, types.EventQueryNewRoundStep); err != nil { - pb.cs.Logger.Error("Error unsubscribing from eventBus", "err", err) - } - }() - - if len(tokens) == 1 { - if err := pb.replayReset(1, newStepSub); err != nil { - pb.cs.Logger.Error("Replay reset error", "err", err) - } - } else { - i, err := strconv.Atoi(tokens[1]) - if err != nil { - fmt.Println("back takes an integer argument") - } else if i > pb.count { - fmt.Printf("argument to back must not be larger than the current count (%d)\n", pb.count) - } else if err := pb.replayReset(i, newStepSub); err != nil { - pb.cs.Logger.Error("Replay reset error", "err", err) - } - } - - case "rs": - // "rs" -> print entire round state - // "rs short" -> print height/round/step - // "rs " -> print another field of the round state - - rs := pb.cs.RoundState - if len(tokens) == 1 { - fmt.Println(rs) - } else { - switch tokens[1] { - case "short": - fmt.Printf("%v/%v/%v\n", rs.Height, rs.Round, rs.Step) - case "validators": - fmt.Println(rs.Validators) - case "proposal": - fmt.Println(rs.Proposal) - case "proposal_block": - fmt.Printf("%v %v\n", rs.ProposalBlockParts.StringShort(), rs.ProposalBlock.StringShort()) - case "locked_round": - fmt.Println(rs.LockedRound) - case "locked_block": - fmt.Printf("%v %v\n", rs.LockedBlockParts.StringShort(), rs.LockedBlock.StringShort()) - case "votes": - fmt.Println(rs.Votes.StringIndented(" ")) - - default: - fmt.Println("Unknown option", tokens[1]) - } - } - case "n": - fmt.Println(pb.count) - } - } -} - -//-------------------------------------------------------------------------------- - -// convenience for replay mode -func newConsensusStateForReplay(config cfg.BaseConfig, csConfig *cfg.ConsensusConfig) *State { - dbType := dbm.BackendType(config.DBBackend) - // Get BlockStore - blockStoreDB, err := dbm.NewDB("blockstore", dbType, config.DBDir()) - if err != nil { - cmtos.Exit(err.Error()) - } - blockStore := store.NewBlockStore(blockStoreDB) - - // Get State - stateDB, err := dbm.NewDB("state", dbType, config.DBDir()) - if err != nil { - cmtos.Exit(err.Error()) - } - stateStore := sm.NewStore(stateDB, sm.StoreOptions{ - DiscardABCIResponses: false, - }) - gdoc, err := sm.MakeGenesisDocFromFile(config.GenesisFile()) - if err != nil { - cmtos.Exit(err.Error()) - } - state, err := sm.MakeGenesisState(gdoc) - if err != nil { - cmtos.Exit(err.Error()) - } - - // Create proxyAppConn connection (consensus, mempool, query) - clientCreator := proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()) - proxyApp := proxy.NewAppConns(clientCreator, proxy.NopMetrics()) - err = proxyApp.Start() - if err != nil { - cmtos.Exit(fmt.Sprintf("Error starting proxy app conns: %v", err)) - } - - eventBus := types.NewEventBus() - if err := eventBus.Start(); err != nil { - cmtos.Exit(fmt.Sprintf("Failed to start event bus: %v", err)) - } - - handshaker := NewHandshaker(stateStore, state, blockStore, gdoc) - handshaker.SetEventBus(eventBus) - err = handshaker.Handshake(proxyApp) - if err != nil { - cmtos.Exit(fmt.Sprintf("Error on handshake: %v", err)) - } - - mempool, evpool := emptyMempool{}, sm.EmptyEvidencePool{} - blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool, blockStore) - - consensusState := NewState(csConfig, state.Copy(), blockExec, - blockStore, mempool, evpool) - - consensusState.SetEventBus(eventBus) - return consensusState -} diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go deleted file mode 100644 index f6d6a8eb5b8..00000000000 --- a/consensus/replay_stubs.go +++ /dev/null @@ -1,79 +0,0 @@ -package consensus - -import ( - "context" - - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/clist" - mempl "github.com/cometbft/cometbft/mempool" - "github.com/cometbft/cometbft/proxy" - "github.com/cometbft/cometbft/types" -) - -//----------------------------------------------------------------------------- - -type emptyMempool struct{} - -var _ mempl.Mempool = emptyMempool{} - -func (emptyMempool) Lock() {} -func (emptyMempool) Unlock() {} -func (emptyMempool) Size() int { return 0 } -func (emptyMempool) SizeBytes() int64 { return 0 } -func (emptyMempool) CheckTx(_ types.Tx, _ func(*abci.ResponseCheckTx), _ mempl.TxInfo) error { - return nil -} - -func (txmp emptyMempool) RemoveTxByKey(txKey types.TxKey) error { - return nil -} - -func (emptyMempool) ReapMaxBytesMaxGas(_, _ int64) types.Txs { return types.Txs{} } -func (emptyMempool) ReapMaxTxs(n int) types.Txs { return types.Txs{} } -func (emptyMempool) Update( - _ int64, - _ types.Txs, - _ []*abci.ExecTxResult, - _ mempl.PreCheckFunc, - _ mempl.PostCheckFunc, -) error { - return nil -} -func (emptyMempool) Flush() {} -func (emptyMempool) FlushAppConn() error { return nil } -func (emptyMempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } -func (emptyMempool) EnableTxsAvailable() {} -func (emptyMempool) TxsBytes() int64 { return 0 } - -func (emptyMempool) TxsFront() *clist.CElement { return nil } -func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } - -func (emptyMempool) InitWAL() error { return nil } -func (emptyMempool) CloseWAL() {} - -//----------------------------------------------------------------------------- -// mockProxyApp uses ABCIResponses to give the right results. -// -// Useful because we don't want to call Commit() twice for the same block on -// the real app. - -func newMockProxyApp(finalizeBlockResponse *abci.ResponseFinalizeBlock) proxy.AppConnConsensus { - clientCreator := proxy.NewLocalClientCreator(&mockProxyApp{ - finalizeBlockResponse: finalizeBlockResponse, - }) - cli, _ := clientCreator.NewABCIClient() - err := cli.Start() - if err != nil { - panic(err) - } - return proxy.NewAppConnConsensus(cli, proxy.NopMetrics()) -} - -type mockProxyApp struct { - abci.BaseApplication - finalizeBlockResponse *abci.ResponseFinalizeBlock -} - -func (mock *mockProxyApp) FinalizeBlock(_ context.Context, req *abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) { - return mock.finalizeBlockResponse, nil -} diff --git a/consensus/state_test.go b/consensus/state_test.go deleted file mode 100644 index a2e64972fff..00000000000 --- a/consensus/state_test.go +++ /dev/null @@ -1,2524 +0,0 @@ -package consensus - -import ( - "bytes" - "context" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/cometbft/cometbft/abci/example/kvstore" - abci "github.com/cometbft/cometbft/abci/types" - abcimocks "github.com/cometbft/cometbft/abci/types/mocks" - cstypes "github.com/cometbft/cometbft/consensus/types" - "github.com/cometbft/cometbft/crypto/tmhash" - "github.com/cometbft/cometbft/internal/test" - cmtbytes "github.com/cometbft/cometbft/libs/bytes" - "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/protoio" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - cmtrand "github.com/cometbft/cometbft/libs/rand" - p2pmock "github.com/cometbft/cometbft/p2p/mock" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - "github.com/cometbft/cometbft/types" -) - -/* - -ProposeSuite -x * TestProposerSelection0 - round robin ordering, round 0 -x * TestProposerSelection2 - round robin ordering, round 2++ -x * TestEnterProposeNoValidator - timeout into prevote round -x * TestEnterPropose - finish propose without timing out (we have the proposal) -x * TestBadProposal - 2 vals, bad proposal (bad block state hash), should prevote and precommit nil -x * TestOversizedBlock - block with too many txs should be rejected -FullRoundSuite -x * TestFullRound1 - 1 val, full successful round -x * TestFullRoundNil - 1 val, full round of nil -x * TestFullRound2 - 2 vals, both required for full round -LockSuite -x * TestLockNoPOL - 2 vals, 4 rounds. one val locked, precommits nil every round except first. -x * TestLockPOLRelock - 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka -x * TestLockPOLUnlock - 4 vals, one precommits, other 3 polka nil at next round, so we unlock and precomit nil -x * TestLockPOLSafety1 - 4 vals. We shouldn't change lock based on polka at earlier round -x * TestLockPOLSafety2 - 4 vals. After unlocking, we shouldn't relock based on polka at earlier round - * TestNetworkLock - once +1/3 precommits, network should be locked - * TestNetworkLockPOL - once +1/3 precommits, the block with more recent polka is committed -SlashingSuite -x * TestSlashingPrevotes - a validator prevoting twice in a round gets slashed -x * TestSlashingPrecommits - a validator precomitting twice in a round gets slashed -CatchupSuite - * TestCatchup - if we might be behind and we've seen any 2/3 prevotes, round skip to new round, precommit, or prevote -HaltSuite -x * TestHalt1 - if we see +2/3 precommits after timing out into new round, we should still commit - -*/ - -//---------------------------------------------------------------------------------------------------- -// ProposeSuite - -func TestStateProposerSelection0(t *testing.T) { - cs1, vss := randState(4) - height, round := cs1.Height, cs1.Round - - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - - startTestRound(cs1, height, round) - - // Wait for new round so proposer is set. - ensureNewRound(newRoundCh, height, round) - - // Commit a block and ensure proposer for the next height is correct. - prop := cs1.GetRoundState().Validators.GetProposer() - pv, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - address := pv.Address() - if !bytes.Equal(prop.Address, address) { - t.Fatalf("expected proposer to be validator %d. Got %X", 0, prop.Address) - } - - // Wait for complete proposal. - ensureNewProposal(proposalCh, height, round) - - rs := cs1.GetRoundState() - signAddVotes(cs1, cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), true, vss[1:]...) - - // Wait for new round so next validator is set. - ensureNewRound(newRoundCh, height+1, 0) - - prop = cs1.GetRoundState().Validators.GetProposer() - pv1, err := vss[1].GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - if !bytes.Equal(prop.Address, addr) { - panic(fmt.Sprintf("expected proposer to be validator %d. Got %X", 1, prop.Address)) - } -} - -// Now let's do it all again, but starting from round 2 instead of 0 -func TestStateProposerSelection2(t *testing.T) { - cs1, vss := randState(4) // test needs more work for more than 3 validators - height := cs1.Height - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - - // this time we jump in at round 2 - incrementRound(vss[1:]...) - incrementRound(vss[1:]...) - - var round int32 = 2 - startTestRound(cs1, height, round) - - ensureNewRound(newRoundCh, height, round) // wait for the new round - - // everyone just votes nil. we get a new proposer each round - for i := int32(0); int(i) < len(vss); i++ { - prop := cs1.GetRoundState().Validators.GetProposer() - pvk, err := vss[int(i+round)%len(vss)].GetPubKey() - require.NoError(t, err) - addr := pvk.Address() - correctProposer := addr - if !bytes.Equal(prop.Address, correctProposer) { - panic(fmt.Sprintf( - "expected RoundState.Validators.GetProposer() to be validator %d. Got %X", - int(i+2)%len(vss), - prop.Address)) - } - - rs := cs1.GetRoundState() - signAddVotes(cs1, cmtproto.PrecommitType, nil, rs.ProposalBlockParts.Header(), true, vss[1:]...) - ensureNewRound(newRoundCh, height, i+round+1) // wait for the new round event each round - incrementRound(vss[1:]...) - } - -} - -// a non-validator should timeout into the prevote round -func TestStateEnterProposeNoPrivValidator(t *testing.T) { - cs, _ := randState(1) - cs.SetPrivValidator(nil) - height, round := cs.Height, cs.Round - - // Listen for propose timeout event - timeoutCh := subscribe(cs.eventBus, types.EventQueryTimeoutPropose) - - startTestRound(cs, height, round) - - // if we're not a validator, EnterPropose should timeout - ensureNewTimeout(timeoutCh, height, round, cs.config.TimeoutPropose.Nanoseconds()) - - if cs.GetRoundState().Proposal != nil { - t.Error("Expected to make no proposal, since no privValidator") - } -} - -// a validator should not timeout of the prevote round (TODO: unless the block is really big!) -func TestStateEnterProposeYesPrivValidator(t *testing.T) { - cs, _ := randState(1) - height, round := cs.Height, cs.Round - - // Listen for propose timeout event - - timeoutCh := subscribe(cs.eventBus, types.EventQueryTimeoutPropose) - proposalCh := subscribe(cs.eventBus, types.EventQueryCompleteProposal) - - cs.enterNewRound(height, round) - cs.startRoutines(3) - - ensureNewProposal(proposalCh, height, round) - - // Check that Proposal, ProposalBlock, ProposalBlockParts are set. - rs := cs.GetRoundState() - if rs.Proposal == nil { - t.Error("rs.Proposal should be set") - } - if rs.ProposalBlock == nil { - t.Error("rs.ProposalBlock should be set") - } - if rs.ProposalBlockParts.Total() == 0 { - t.Error("rs.ProposalBlockParts should be set") - } - - // if we're a validator, enterPropose should not timeout - ensureNoNewTimeout(timeoutCh, cs.config.TimeoutPropose.Nanoseconds()) -} - -func TestStateBadProposal(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(2) - height, round := cs1.Height, cs1.Round - vs2 := vss[1] - - partSize := types.BlockPartSizeBytes - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - voteCh := subscribe(cs1.eventBus, types.EventQueryVote) - - propBlock, err := cs1.createProposalBlock(ctx) // changeProposer(t, cs1, vs2) - require.NoError(t, err) - - // make the second validator the proposer by incrementing round - round++ - incrementRound(vss[1:]...) - - // make the block bad by tampering with statehash - stateHash := propBlock.AppHash - if len(stateHash) == 0 { - stateHash = make([]byte, 32) - } - stateHash[0] = (stateHash[0] + 1) % 255 - propBlock.AppHash = stateHash - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} - proposal := types.NewProposal(vs2.Height, round, -1, blockID) - p := proposal.ToProto() - if err := vs2.SignProposal(cs1.state.ChainID, p); err != nil { - t.Fatal("failed to sign bad proposal", err) - } - - proposal.Signature = p.Signature - - // set the proposal block - if err := cs1.SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - - // start the machine - startTestRound(cs1, height, round) - - // wait for proposal - ensureProposal(proposalCh, height, round, blockID) - - // wait for prevote - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], nil) - - // add bad prevote from vs2 and wait for it - bps, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - signAddVotes(cs1, cmtproto.PrevoteType, propBlock.Hash(), bps.Header(), false, vs2) - ensurePrevote(voteCh, height, round) - - // wait for precommit - ensurePrecommit(voteCh, height, round) - validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - - bps2, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - signAddVotes(cs1, cmtproto.PrecommitType, propBlock.Hash(), bps2.Header(), true, vs2) -} - -func TestStateOversizedBlock(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(2) - cs1.state.ConsensusParams.Block.MaxBytes = 2000 - height, round := cs1.Height, cs1.Round - vs2 := vss[1] - - partSize := types.BlockPartSizeBytes - - timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - voteCh := subscribe(cs1.eventBus, types.EventQueryVote) - - propBlock, err := cs1.createProposalBlock(ctx) - require.NoError(t, err) - propBlock.Data.Txs = []types.Tx{cmtrand.Bytes(2001)} - propBlock.Header.DataHash = propBlock.Data.Hash() - - // make the second validator the proposer by incrementing round - round++ - incrementRound(vss[1:]...) - - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} - proposal := types.NewProposal(height, round, -1, blockID) - p := proposal.ToProto() - if err := vs2.SignProposal(cs1.state.ChainID, p); err != nil { - t.Fatal("failed to sign bad proposal", err) - } - proposal.Signature = p.Signature - - totalBytes := 0 - for i := 0; i < int(propBlockParts.Total()); i++ { - part := propBlockParts.GetPart(i) - totalBytes += len(part.Bytes) - } - - if err := cs1.SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - - // start the machine - startTestRound(cs1, height, round) - - t.Log("Block Sizes", "Limit", cs1.state.ConsensusParams.Block.MaxBytes, "Current", totalBytes) - - // c1 should log an error with the block part message as it exceeds the consensus params. The - // block is not added to cs.ProposalBlock so the node timeouts. - ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) - - // and then should send nil prevote and precommit regardless of whether other validators prevote and - // precommit on it - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], nil) - - bps, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - signAddVotes(cs1, cmtproto.PrevoteType, propBlock.Hash(), bps.Header(), false, vs2) - ensurePrevote(voteCh, height, round) - ensurePrecommit(voteCh, height, round) - validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - - bps2, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - signAddVotes(cs1, cmtproto.PrecommitType, propBlock.Hash(), bps2.Header(), true, vs2) -} - -//---------------------------------------------------------------------------------------------------- -// FullRoundSuite - -// propose, prevote, and precommit a block -func TestStateFullRound1(t *testing.T) { - cs, vss := randState(1) - height, round := cs.Height, cs.Round - - // NOTE: buffer capacity of 0 ensures we can validate prevote and last commit - // before consensus can move to the next height (and cause a race condition) - if err := cs.eventBus.Stop(); err != nil { - t.Error(err) - } - eventBus := types.NewEventBusWithBufferCapacity(0) - eventBus.SetLogger(log.TestingLogger().With("module", "events")) - cs.SetEventBus(eventBus) - if err := eventBus.Start(); err != nil { - t.Error(err) - } - - voteCh := subscribeUnBuffered(cs.eventBus, types.EventQueryVote) - propCh := subscribe(cs.eventBus, types.EventQueryCompleteProposal) - newRoundCh := subscribe(cs.eventBus, types.EventQueryNewRound) - - // Maybe it would be better to call explicitly startRoutines(4) - startTestRound(cs, height, round) - - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(propCh, height, round) - propBlockHash := cs.GetRoundState().ProposalBlock.Hash() - - ensurePrevote(voteCh, height, round) // wait for prevote - validatePrevote(t, cs, round, vss[0], propBlockHash) - - ensurePrecommit(voteCh, height, round) // wait for precommit - - // we're going to roll right into new height - ensureNewRound(newRoundCh, height+1, 0) - - validateLastPrecommit(t, cs, vss[0], propBlockHash) -} - -// nil is proposed, so prevote and precommit nil -func TestStateFullRoundNil(t *testing.T) { - cs, _ := randState(1) - height, round := cs.Height, cs.Round - - voteCh := subscribeUnBuffered(cs.eventBus, types.EventQueryVote) - - cs.enterPrevote(height, round) - cs.startRoutines(4) - - ensurePrevoteMatch(t, voteCh, height, round, nil) // prevote - ensurePrecommitMatch(t, voteCh, height, round, nil) // precommit -} - -// run through propose, prevote, precommit commit with two validators -// where the first validator has to wait for votes from the second -func TestStateFullRound2(t *testing.T) { - cs1, vss := randState(2) - vs2 := vss[1] - height, round := cs1.Height, cs1.Round - - voteCh := subscribeUnBuffered(cs1.eventBus, types.EventQueryVote) - newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlock) - - // start round and wait for propose and prevote - startTestRound(cs1, height, round) - - ensurePrevote(voteCh, height, round) // prevote - - // we should be stuck in limbo waiting for more prevotes - rs := cs1.GetRoundState() - propBlockHash, propPartSetHeader := rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header() - - // prevote arrives from vs2: - signAddVotes(cs1, cmtproto.PrevoteType, propBlockHash, propPartSetHeader, false, vs2) - ensurePrevote(voteCh, height, round) // prevote - - ensurePrecommit(voteCh, height, round) // precommit - // the proposed block should now be locked and our precommit added - validatePrecommit(t, cs1, 0, 0, vss[0], propBlockHash, propBlockHash) - - // we should be stuck in limbo waiting for more precommits - - // precommit arrives from vs2: - signAddVotes(cs1, cmtproto.PrecommitType, propBlockHash, propPartSetHeader, true, vs2) - ensurePrecommit(voteCh, height, round) - - // wait to finish commit, propose in next height - ensureNewBlock(newBlockCh, height) -} - -//------------------------------------------------------------------------------------------ -// LockSuite - -// two validators, 4 rounds. -// two vals take turns proposing. val1 locks on first one, precommits nil on everything else -func TestStateLockNoPOL(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(2) - vs2 := vss[1] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - voteCh := subscribeUnBuffered(cs1.eventBus, types.EventQueryVote) - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - - /* - Round1 (cs1, B) // B B // B B2 - */ - - // start round and wait for prevote - cs1.enterNewRound(height, round) - cs1.startRoutines(0) - - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - roundState := cs1.GetRoundState() - theBlockHash := roundState.ProposalBlock.Hash() - thePartSetHeader := roundState.ProposalBlockParts.Header() - - ensurePrevote(voteCh, height, round) // prevote - - // we should now be stuck in limbo forever, waiting for more prevotes - // prevote arrives from vs2: - signAddVotes(cs1, cmtproto.PrevoteType, theBlockHash, thePartSetHeader, false, vs2) - ensurePrevote(voteCh, height, round) // prevote - - ensurePrecommit(voteCh, height, round) // precommit - // the proposed block should now be locked and our precommit added - validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash) - - // we should now be stuck in limbo forever, waiting for more precommits - // lets add one for a different block - hash := make([]byte, len(theBlockHash)) - copy(hash, theBlockHash) - hash[0] = (hash[0] + 1) % 255 - signAddVotes(cs1, cmtproto.PrecommitType, hash, thePartSetHeader, true, vs2) - ensurePrecommit(voteCh, height, round) // precommit - - // (note we're entering precommit for a second time this round) - // but with invalid args. then we enterPrecommitWait, and the timeout to new round - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - /// - - round++ // moving to the next round - ensureNewRound(newRoundCh, height, round) - t.Log("#### ONTO ROUND 1") - /* - Round2 (cs1, B) // B B2 - */ - - incrementRound(vs2) - - // now we're on a new round and not the proposer, so wait for timeout - ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) - - rs := cs1.GetRoundState() - - require.Nil(t, rs.ProposalBlock, "Expected proposal block to be nil") - - // wait to finish prevote - ensurePrevote(voteCh, height, round) - // we should have prevoted our locked block - validatePrevote(t, cs1, round, vss[0], rs.LockedBlock.Hash()) - - // add a conflicting prevote from the other validator - bps, err := rs.LockedBlock.MakePartSet(partSize) - require.NoError(t, err) - - signAddVotes(cs1, cmtproto.PrevoteType, hash, bps.Header(), false, vs2) - ensurePrevote(voteCh, height, round) - - // now we're going to enter prevote again, but with invalid args - // and then prevote wait, which should timeout. then wait for precommit - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) - - ensurePrecommit(voteCh, height, round) // precommit - // the proposed block should still be locked and our precommit added - // we should precommit nil and be locked on the proposal - validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash) - - // add conflicting precommit from vs2 - bps2, err := rs.LockedBlock.MakePartSet(partSize) - require.NoError(t, err) - signAddVotes(cs1, cmtproto.PrecommitType, hash, bps2.Header(), true, vs2) - ensurePrecommit(voteCh, height, round) - - // (note we're entering precommit for a second time this round, but with invalid args - // then we enterPrecommitWait and timeout into NewRound - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - round++ // entering new round - ensureNewRound(newRoundCh, height, round) - t.Log("#### ONTO ROUND 2") - /* - Round3 (vs2, _) // B, B2 - */ - - incrementRound(vs2) - - ensureNewProposal(proposalCh, height, round) - rs = cs1.GetRoundState() - - // now we're on a new round and are the proposer - if !bytes.Equal(rs.ProposalBlock.Hash(), rs.LockedBlock.Hash()) { - panic(fmt.Sprintf( - "Expected proposal block to be locked block. Got %v, Expected %v", - rs.ProposalBlock, - rs.LockedBlock)) - } - - ensurePrevote(voteCh, height, round) // prevote - validatePrevote(t, cs1, round, vss[0], rs.LockedBlock.Hash()) - - bps0, err := rs.ProposalBlock.MakePartSet(partSize) - require.NoError(t, err) - signAddVotes(cs1, cmtproto.PrevoteType, hash, bps0.Header(), false, vs2) - ensurePrevote(voteCh, height, round) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) - ensurePrecommit(voteCh, height, round) // precommit - - validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash) // precommit nil but be locked on proposal - - bps1, err := rs.ProposalBlock.MakePartSet(partSize) - require.NoError(t, err) - signAddVotes( - cs1, - cmtproto.PrecommitType, - hash, - bps1.Header(), - true, - vs2) // NOTE: conflicting precommits at same height - ensurePrecommit(voteCh, height, round) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - cs2, _ := randState(2) // needed so generated block is different than locked block - // before we time out into new round, set next proposal block - prop, propBlock := decideProposal(ctx, t, cs2, vs2, vs2.Height, vs2.Round+1) - if prop == nil || propBlock == nil { - t.Fatal("Failed to create proposal block with vs2") - } - - incrementRound(vs2) - - round++ // entering new round - ensureNewRound(newRoundCh, height, round) - t.Log("#### ONTO ROUND 3") - /* - Round4 (vs2, C) // B C // B C - */ - - // now we're on a new round and not the proposer - // so set the proposal block - bps3, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - if err := cs1.SetProposalAndBlock(prop, propBlock, bps3, ""); err != nil { - t.Fatal(err) - } - - ensureNewProposal(proposalCh, height, round) - ensurePrevote(voteCh, height, round) // prevote - // prevote for locked block (not proposal) - validatePrevote(t, cs1, 3, vss[0], cs1.LockedBlock.Hash()) - - // prevote for proposed block - bps4, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - signAddVotes(cs1, cmtproto.PrevoteType, propBlock.Hash(), bps4.Header(), false, vs2) - ensurePrevote(voteCh, height, round) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) - ensurePrecommit(voteCh, height, round) - validatePrecommit(t, cs1, round, 0, vss[0], nil, theBlockHash) // precommit nil but locked on proposal - - bps5, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - signAddVotes( - cs1, - cmtproto.PrecommitType, - propBlock.Hash(), - bps5.Header(), - true, - vs2) // NOTE: conflicting precommits at same height - ensurePrecommit(voteCh, height, round) -} - -// 4 vals in two rounds, -// in round one: v1 precommits, other 3 only prevote so the block isn't committed -// in round two: v1 prevotes the same block that the node is locked on -// the others prevote a new block hence v1 changes lock and precommits the new block with the others -func TestStateLockPOLRelock(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader) - - // everything done from perspective of cs1 - - /* - Round1 (cs1, B) // B B B B// B nil B nil - - eg. vs2 and vs4 didn't see the 2/3 prevotes - */ - - // start round and wait for propose and prevote - startTestRound(cs1, height, round) - - ensureNewRound(newRoundCh, height, round) - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - theBlockHash := rs.ProposalBlock.Hash() - theBlockParts := rs.ProposalBlockParts.Header() - - ensurePrevote(voteCh, height, round) // prevote - - signAddVotes(cs1, cmtproto.PrevoteType, theBlockHash, theBlockParts, false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) // our precommit - // the proposed block should now be locked and our precommit added - validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash) - - // add precommits from the rest - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - // before we timeout to the new round set the new proposal - cs2 := newState(cs1.state, vs2, kvstore.NewInMemoryApplication()) - prop, propBlock := decideProposal(ctx, t, cs2, vs2, vs2.Height, vs2.Round+1) - if prop == nil || propBlock == nil { - t.Fatal("Failed to create proposal block with vs2") - } - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - propBlockHash := propBlock.Hash() - require.NotEqual(t, propBlockHash, theBlockHash) - - incrementRound(vs2, vs3, vs4) - - // timeout to new round - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - round++ // moving to the next round - //XXX: this isnt guaranteed to get there before the timeoutPropose ... - if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - - ensureNewRound(newRoundCh, height, round) - t.Log("### ONTO ROUND 1") - - /* - Round2 (vs2, C) // B C C C // C C C _) - - cs1 changes lock! - */ - - // now we're on a new round and not the proposer - // but we should receive the proposal - ensureNewProposal(proposalCh, height, round) - - // go to prevote, node should prevote for locked block (not the new proposal) - this is relocking - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], theBlockHash) - - // now lets add prevotes from everyone else for the new block - signAddVotes(cs1, cmtproto.PrevoteType, propBlockHash, propBlockParts.Header(), false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // we should have unlocked and locked on the new block, sending a precommit for this new block - validatePrecommit(t, cs1, round, round, vss[0], propBlockHash, propBlockHash) - - // more prevote creating a majority on the new block and this is then committed - signAddVotes(cs1, cmtproto.PrecommitType, propBlockHash, propBlockParts.Header(), true, vs2, vs3) - ensureNewBlockHeader(newBlockCh, height, propBlockHash) - - ensureNewRound(newRoundCh, height+1, 0) -} - -// 4 vals, one precommits, other 3 polka at next round, so we unlock and precomit the polka -func TestStateLockPOLUnlock(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // everything done from perspective of cs1 - - /* - Round1 (cs1, B) // B B B B // B nil B nil - eg. didn't see the 2/3 prevotes - */ - - // start round and wait for propose and prevote - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - theBlockHash := rs.ProposalBlock.Hash() - theBlockParts := rs.ProposalBlockParts.Header() - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], theBlockHash) - - signAddVotes(cs1, cmtproto.PrevoteType, theBlockHash, theBlockParts, false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // the proposed block should now be locked and our precommit added - validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash) - - // add precommits from the rest - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs4) - signAddVotes(cs1, cmtproto.PrecommitType, theBlockHash, theBlockParts, true, vs3) - - // before we time out into new round, set next proposal block - prop, propBlock := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round+1) - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - // timeout to new round - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - rs = cs1.GetRoundState() - lockedBlockHash := rs.LockedBlock.Hash() - - incrementRound(vs2, vs3, vs4) - round++ // moving to the next round - - ensureNewRound(newRoundCh, height, round) - t.Log("#### ONTO ROUND 1") - /* - Round2 (vs2, C) // B nil nil nil // nil nil nil _ - cs1 unlocks! - */ - //XXX: this isnt guaranteed to get there before the timeoutPropose ... - if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - - ensureNewProposal(proposalCh, height, round) - - // go to prevote, prevote for locked block (not proposal) - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], lockedBlockHash) - // now lets add prevotes from everyone else for nil (a polka!) - signAddVotes(cs1, cmtproto.PrevoteType, nil, types.PartSetHeader{}, false, vs2, vs3, vs4) - - // the polka makes us unlock and precommit nil - ensureNewUnlock(unlockCh, height, round) - ensurePrecommit(voteCh, height, round) - - // we should have unlocked and committed nil - // NOTE: since we don't relock on nil, the lock round is -1 - validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3) - ensureNewRound(newRoundCh, height, round+1) -} - -// 4 vals, v1 locks on proposed block in the first round but the other validators only prevote -// In the second round, v1 misses the proposal but sees a majority prevote an unknown block so -// v1 should unlock and precommit nil. In the third round another block is proposed, all vals -// prevote and now v1 can lock onto the third block and precommit that -func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - // everything done from perspective of cs1 - - /* - Round0 (cs1, A) // A A A A// A nil nil nil - */ - - // start round and wait for propose and prevote - startTestRound(cs1, height, round) - - ensureNewRound(newRoundCh, height, round) - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - firstBlockHash := rs.ProposalBlock.Hash() - firstBlockParts := rs.ProposalBlockParts.Header() - - ensurePrevote(voteCh, height, round) // prevote - - signAddVotes(cs1, cmtproto.PrevoteType, firstBlockHash, firstBlockParts, false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) // our precommit - // the proposed block should now be locked and our precommit added - validatePrecommit(t, cs1, round, round, vss[0], firstBlockHash, firstBlockHash) - - // add precommits from the rest - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - // before we timeout to the new round set the new proposal - cs2 := newState(cs1.state, vs2, kvstore.NewInMemoryApplication()) - prop, propBlock := decideProposal(ctx, t, cs2, vs2, vs2.Height, vs2.Round+1) - if prop == nil || propBlock == nil { - t.Fatal("Failed to create proposal block with vs2") - } - secondBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - secondBlockHash := propBlock.Hash() - require.NotEqual(t, secondBlockHash, firstBlockHash) - - incrementRound(vs2, vs3, vs4) - - // timeout to new round - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - round++ // moving to the next round - - ensureNewRound(newRoundCh, height, round) - t.Log("### ONTO ROUND 1") - - /* - Round1 (vs2, B) // A B B B // nil nil nil nil) - */ - - // now we're on a new round but v1 misses the proposal - - // go to prevote, node should prevote for locked block (not the new proposal) - this is relocking - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], firstBlockHash) - - // now lets add prevotes from everyone else for the new block - signAddVotes(cs1, cmtproto.PrevoteType, secondBlockHash, secondBlockParts.Header(), false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // we should have unlocked and locked on the new block, sending a precommit for this new block - validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - - if err := cs1.SetProposalAndBlock(prop, propBlock, secondBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - - // more prevote creating a majority on the new block and this is then committed - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - // before we timeout to the new round set the new proposal - cs3 := newState(cs1.state, vs3, kvstore.NewInMemoryApplication()) - prop, propBlock = decideProposal(ctx, t, cs3, vs3, vs3.Height, vs3.Round+1) - if prop == nil || propBlock == nil { - t.Fatal("Failed to create proposal block with vs2") - } - thirdPropBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - thirdPropBlockHash := propBlock.Hash() - require.NotEqual(t, secondBlockHash, thirdPropBlockHash) - - incrementRound(vs2, vs3, vs4) - - // timeout to new round - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - round++ // moving to the next round - ensureNewRound(newRoundCh, height, round) - t.Log("### ONTO ROUND 2") - - /* - Round2 (vs3, C) // C C C C // C nil nil nil) - */ - - if err := cs1.SetProposalAndBlock(prop, propBlock, thirdPropBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - - ensurePrevote(voteCh, height, round) - // we are no longer locked to the first block so we should be able to prevote - validatePrevote(t, cs1, round, vss[0], thirdPropBlockHash) - - signAddVotes(cs1, cmtproto.PrevoteType, thirdPropBlockHash, thirdPropBlockParts.Header(), false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // we have a majority, now vs1 can change lock to the third block - validatePrecommit(t, cs1, round, round, vss[0], thirdPropBlockHash, thirdPropBlockHash) -} - -// 4 vals -// a polka at round 1 but we miss it -// then a polka at round 2 that we lock on -// then we see the polka from round 1 but shouldn't unlock -func TestStateLockPOLSafety1(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round and wait for propose and prevote - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - propBlock := rs.ProposalBlock - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], propBlock.Hash()) - - // the others sign a polka but we don't see it - bps, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - prevotes := signVotes(cmtproto.PrevoteType, propBlock.Hash(), bps.Header(), false, vs2, vs3, vs4) - - t.Logf("old prop hash %v", fmt.Sprintf("%X", propBlock.Hash())) - - // we do see them precommit nil - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - // cs1 precommit nil - ensurePrecommit(voteCh, height, round) - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - t.Log("### ONTO ROUND 1") - - prop, propBlock := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round+1) - propBlockHash := propBlock.Hash() - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - incrementRound(vs2, vs3, vs4) - - round++ // moving to the next round - ensureNewRound(newRoundCh, height, round) - - //XXX: this isnt guaranteed to get there before the timeoutPropose ... - if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - /*Round2 - // we timeout and prevote our lock - // a polka happened but we didn't see it! - */ - - ensureNewProposal(proposalCh, height, round) - - rs = cs1.GetRoundState() - - if rs.LockedBlock != nil { - panic("we should not be locked!") - } - t.Logf("new prop hash %v", fmt.Sprintf("%X", propBlockHash)) - - // go to prevote, prevote for proposal block - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], propBlockHash) - - // now we see the others prevote for it, so we should lock on it - signAddVotes(cs1, cmtproto.PrevoteType, propBlockHash, propBlockParts.Header(), false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // we should have precommitted - validatePrecommit(t, cs1, round, round, vss[0], propBlockHash, propBlockHash) - - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - incrementRound(vs2, vs3, vs4) - round++ // moving to the next round - - ensureNewRound(newRoundCh, height, round) - - t.Log("### ONTO ROUND 2") - /*Round3 - we see the polka from round 1 but we shouldn't unlock! - */ - - // timeout of propose - ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) - - // finish prevote - ensurePrevote(voteCh, height, round) - // we should prevote what we're locked on - validatePrevote(t, cs1, round, vss[0], propBlockHash) - - newStepCh := subscribe(cs1.eventBus, types.EventQueryNewRoundStep) - - // before prevotes from the previous round are added - // add prevotes from the earlier round - addVotes(cs1, prevotes...) - - t.Log("Done adding prevotes!") - - ensureNoNewRoundStep(newStepCh) -} - -// 4 vals. -// polka P0 at R0, P1 at R1, and P2 at R2, -// we lock on P0 at R0, don't see P1, and unlock using P2 at R2 -// then we should make sure we don't lock using P1 - -// What we want: -// dont see P0, lock on P1 at R1, dont unlock using P0 at R2 -func TestStateLockPOLSafety2(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // the block for R0: gets polkad but we miss it - // (even though we signed it, shhh) - _, propBlock0 := decideProposal(ctx, t, cs1, vss[0], height, round) - propBlockHash0 := propBlock0.Hash() - propBlockParts0, err := propBlock0.MakePartSet(partSize) - require.NoError(t, err) - propBlockID0 := types.BlockID{Hash: propBlockHash0, PartSetHeader: propBlockParts0.Header()} - - // the others sign a polka but we don't see it - prevotes := signVotes(cmtproto.PrevoteType, propBlockHash0, propBlockParts0.Header(), false, vs2, vs3, vs4) - - // the block for round 1 - prop1, propBlock1 := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round+1) - propBlockHash1 := propBlock1.Hash() - propBlockParts1, err := propBlock1.MakePartSet(partSize) - require.NoError(t, err) - - incrementRound(vs2, vs3, vs4) - - round++ // moving to the next round - t.Log("### ONTO Round 1") - // jump in at round 1 - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - if err := cs1.SetProposalAndBlock(prop1, propBlock1, propBlockParts1, "some peer"); err != nil { - t.Fatal(err) - } - ensureNewProposal(proposalCh, height, round) - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], propBlockHash1) - - signAddVotes(cs1, cmtproto.PrevoteType, propBlockHash1, propBlockParts1.Header(), false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // the proposed block should now be locked and our precommit added - validatePrecommit(t, cs1, round, round, vss[0], propBlockHash1, propBlockHash1) - - // add precommits from the rest - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs4) - signAddVotes(cs1, cmtproto.PrecommitType, propBlockHash1, propBlockParts1.Header(), true, vs3) - - incrementRound(vs2, vs3, vs4) - - // timeout of precommit wait to new round - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - round++ // moving to the next round - // in round 2 we see the polkad block from round 0 - newProp := types.NewProposal(height, round, 0, propBlockID0) - p := newProp.ToProto() - if err := vs3.SignProposal(cs1.state.ChainID, p); err != nil { - t.Fatal(err) - } - - newProp.Signature = p.Signature - - if err := cs1.SetProposalAndBlock(newProp, propBlock0, propBlockParts0, "some peer"); err != nil { - t.Fatal(err) - } - - // Add the pol votes - addVotes(cs1, prevotes...) - - ensureNewRound(newRoundCh, height, round) - t.Log("### ONTO Round 2") - /*Round2 - // now we see the polka from round 1, but we shouldnt unlock - */ - ensureNewProposal(proposalCh, height, round) - - ensureNoNewUnlock(unlockCh) - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], propBlockHash1) - -} - -// 4 vals. -// polka P0 at R0 for B0. We lock B0 on P0 at R0. P0 unlocks value at R1. - -// What we want: -// P0 proposes B0 at R3. -func TestProposeValidBlock(t *testing.T) { - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - unlockCh := subscribe(cs1.eventBus, types.EventQueryUnlock) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round and wait for propose and prevote - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - propBlock := rs.ProposalBlock - propBlockHash := propBlock.Hash() - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], propBlockHash) - - // the others sign a polka - bps, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - signAddVotes(cs1, cmtproto.PrevoteType, propBlockHash, bps.Header(), false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // we should have precommitted - validatePrecommit(t, cs1, round, round, vss[0], propBlockHash, propBlockHash) - - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - incrementRound(vs2, vs3, vs4) - round++ // moving to the next round - - ensureNewRound(newRoundCh, height, round) - - t.Log("### ONTO ROUND 2") - - // timeout of propose - ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], propBlockHash) - - signAddVotes(cs1, cmtproto.PrevoteType, nil, types.PartSetHeader{}, false, vs2, vs3, vs4) - - ensureNewUnlock(unlockCh, height, round) - - ensurePrecommit(voteCh, height, round) - // we should have precommitted - validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - - incrementRound(vs2, vs3, vs4) - incrementRound(vs2, vs3, vs4) - - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - round += 2 // moving to the next round - - ensureNewRound(newRoundCh, height, round) - t.Log("### ONTO ROUND 3") - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - round++ // moving to the next round - - ensureNewRound(newRoundCh, height, round) - - t.Log("### ONTO ROUND 4") - - ensureNewProposal(proposalCh, height, round) - - rs = cs1.GetRoundState() - assert.True(t, bytes.Equal(rs.ProposalBlock.Hash(), propBlockHash)) - assert.True(t, bytes.Equal(rs.ProposalBlock.Hash(), rs.ValidBlock.Hash())) - assert.True(t, rs.Proposal.POLRound == rs.ValidRound) - assert.True(t, bytes.Equal(rs.Proposal.BlockID.Hash, rs.ValidBlock.Hash())) -} - -// What we want: -// P0 miss to lock B but set valid block to B after receiving delayed prevote. -func TestSetValidBlockOnDelayedPrevote(t *testing.T) { - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round and wait for propose and prevote - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - propBlock := rs.ProposalBlock - propBlockHash := propBlock.Hash() - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], propBlockHash) - - // vs2 send prevote for propBlock - signAddVotes(cs1, cmtproto.PrevoteType, propBlockHash, propBlockParts.Header(), false, vs2) - - // vs3 send prevote nil - signAddVotes(cs1, cmtproto.PrevoteType, nil, types.PartSetHeader{}, false, vs3) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) - - ensurePrecommit(voteCh, height, round) - // we should have precommitted - validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - - rs = cs1.GetRoundState() - - assert.True(t, rs.ValidBlock == nil) - assert.True(t, rs.ValidBlockParts == nil) - assert.True(t, rs.ValidRound == -1) - - // vs2 send (delayed) prevote for propBlock - signAddVotes(cs1, cmtproto.PrevoteType, propBlockHash, propBlockParts.Header(), false, vs4) - - ensureNewValidBlock(validBlockCh, height, round) - - rs = cs1.GetRoundState() - - assert.True(t, bytes.Equal(rs.ValidBlock.Hash(), propBlockHash)) - assert.True(t, rs.ValidBlockParts.Header().Equals(propBlockParts.Header())) - assert.True(t, rs.ValidRound == round) -} - -// What we want: -// P0 miss to lock B as Proposal Block is missing, but set valid block to B after -// receiving delayed Block Proposal. -func TestSetValidBlockOnDelayedProposal(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - - round++ // move to round in which P0 is not proposer - incrementRound(vs2, vs3, vs4) - - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], nil) - - prop, propBlock := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round+1) - propBlockHash := propBlock.Hash() - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - // vs2, vs3 and vs4 send prevote for propBlock - signAddVotes(cs1, cmtproto.PrevoteType, propBlockHash, propBlockParts.Header(), false, vs2, vs3, vs4) - ensureNewValidBlock(validBlockCh, height, round) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) - - ensurePrecommit(voteCh, height, round) - validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - - if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - - assert.True(t, bytes.Equal(rs.ValidBlock.Hash(), propBlockHash)) - assert.True(t, rs.ValidBlockParts.Header().Equals(propBlockParts.Header())) - assert.True(t, rs.ValidRound == round) -} - -func TestProcessProposalAccept(t *testing.T) { - for _, testCase := range []struct { - name string - accept bool - expectedNilPrevote bool - }{ - { - name: "accepted block is prevoted", - accept: true, - expectedNilPrevote: false, - }, - { - name: "rejected block is not prevoted", - accept: false, - expectedNilPrevote: true, - }, - } { - t.Run(testCase.name, func(t *testing.T) { - m := abcimocks.NewApplication(t) - status := abci.ResponseProcessProposal_REJECT - if testCase.accept { - status = abci.ResponseProcessProposal_ACCEPT - } - m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: status}, nil) - m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil).Maybe() - cs1, _ := randStateWithApp(4, m) - height, round := cs1.Height, cs1.Round - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - var prevoteHash cmtbytes.HexBytes - if !testCase.expectedNilPrevote { - prevoteHash = rs.ProposalBlock.Hash() - } - ensurePrevoteMatch(t, voteCh, height, round, prevoteHash) - }) - } -} - -// TestExtendVoteCalledWhenEnabled tests that the vote extension methods are called at the -// correct point in the consensus algorithm when vote extensions are enabled. -func TestExtendVoteCalledWhenEnabled(t *testing.T) { - for _, testCase := range []struct { - name string - enabled bool - }{ - { - name: "enabled", - enabled: true, - }, - { - name: "disabled", - enabled: false, - }, - } { - t.Run(testCase.name, func(t *testing.T) { - m := abcimocks.NewApplication(t) - m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil) - m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil) - if testCase.enabled { - m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{ - VoteExtension: []byte("extension"), - }, nil) - m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{ - Status: abci.ResponseVerifyVoteExtension_ACCEPT, - }, nil) - } - m.On("Commit", mock.Anything, mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe() - m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil).Maybe() - height := int64(1) - if !testCase.enabled { - height = 0 - } - cs1, vss := randStateWithAppWithHeight(4, m, height) - - height, round := cs1.Height, cs1.Round - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - ensureNewProposal(proposalCh, height, round) - - m.AssertNotCalled(t, "ExtendVote", mock.Anything) - - rs := cs1.GetRoundState() - - blockID := types.BlockID{ - Hash: rs.ProposalBlock.Hash(), - PartSetHeader: rs.ProposalBlockParts.Header(), - } - signAddVotes(cs1, cmtproto.PrevoteType, blockID.Hash, blockID.PartSetHeader, false, vss[1:]...) - ensurePrevoteMatch(t, voteCh, height, round, blockID.Hash) - - ensurePrecommit(voteCh, height, round) - - if testCase.enabled { - m.AssertCalled(t, "ExtendVote", context.TODO(), &abci.RequestExtendVote{ - Height: height, - Hash: blockID.Hash, - }) - } else { - m.AssertNotCalled(t, "ExtendVote", mock.Anything, mock.Anything) - } - - signAddVotes(cs1, cmtproto.PrecommitType, blockID.Hash, blockID.PartSetHeader, testCase.enabled, vss[1:]...) - ensureNewRound(newRoundCh, height+1, 0) - m.AssertExpectations(t) - - // Only 3 of the vote extensions are seen, as consensus proceeds as soon as the +2/3 threshold - // is observed by the consensus engine. - for _, pv := range vss[1:3] { - pv, err := pv.GetPubKey() - require.NoError(t, err) - addr := pv.Address() - if testCase.enabled { - m.AssertCalled(t, "VerifyVoteExtension", context.TODO(), &abci.RequestVerifyVoteExtension{ - Hash: blockID.Hash, - ValidatorAddress: addr, - Height: height, - VoteExtension: []byte("extension"), - }) - } else { - m.AssertNotCalled(t, "VerifyVoteExtension", mock.Anything, mock.Anything) - } - } - }) - } - -} - -// TestVerifyVoteExtensionNotCalledOnAbsentPrecommit tests that the VerifyVoteExtension -// method is not called for a validator's vote that is never delivered. -func TestVerifyVoteExtensionNotCalledOnAbsentPrecommit(t *testing.T) { - m := abcimocks.NewApplication(t) - m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil) - m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil) - m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{ - VoteExtension: []byte("extension"), - }, nil) - m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{ - Status: abci.ResponseVerifyVoteExtension_ACCEPT, - }, nil) - m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil).Maybe() - m.On("Commit", mock.Anything, mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe() - cs1, vss := randStateWithApp(4, m) - height, round := cs1.Height, cs1.Round - cs1.state.ConsensusParams.ABCI.VoteExtensionsEnableHeight = cs1.Height - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - - blockID := types.BlockID{ - Hash: rs.ProposalBlock.Hash(), - PartSetHeader: rs.ProposalBlockParts.Header(), - } - signAddVotes(cs1, cmtproto.PrevoteType, blockID.Hash, blockID.PartSetHeader, false, vss...) - ensurePrevoteMatch(t, voteCh, height, round, blockID.Hash) - - ensurePrecommit(voteCh, height, round) - - m.AssertCalled(t, "ExtendVote", context.TODO(), &abci.RequestExtendVote{ - Height: height, - Hash: blockID.Hash, - }) - - signAddVotes(cs1, cmtproto.PrecommitType, blockID.Hash, blockID.PartSetHeader, true, vss[2:]...) - ensureNewRound(newRoundCh, height+1, 0) - m.AssertExpectations(t) - - // vss[1] did not issue a precommit for the block, ensure that a vote extension - // for its address was not sent to the application. - pv, err := vss[1].GetPubKey() - require.NoError(t, err) - addr = pv.Address() - - m.AssertNotCalled(t, "VerifyVoteExtension", context.TODO(), &abci.RequestVerifyVoteExtension{ - Hash: blockID.Hash, - ValidatorAddress: addr, - Height: height, - VoteExtension: []byte("extension"), - }) - -} - -// TestPrepareProposalReceivesVoteExtensions tests that the PrepareProposal method -// is called with the vote extensions from the previous height. The test functions -// by completing a consensus height with a mock application as the proposer. The -// test then proceeds to fail several rounds of consensus until the mock application -// is the proposer again and ensures that the mock application receives the set of -// vote extensions from the previous consensus instance. -func TestPrepareProposalReceivesVoteExtensions(t *testing.T) { - // create a list of vote extensions, one for each validator. - voteExtensions := [][]byte{ - []byte("extension 0"), - []byte("extension 1"), - []byte("extension 2"), - []byte("extension 3"), - } - - m := abcimocks.NewApplication(t) - m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{ - VoteExtension: voteExtensions[0], - }, nil) - m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil) - - // capture the prepare proposal request. - rpp := &abci.RequestPrepareProposal{} - m.On("PrepareProposal", mock.Anything, mock.MatchedBy(func(r *abci.RequestPrepareProposal) bool { - rpp = r - return true - })).Return(&abci.ResponsePrepareProposal{}, nil) - - m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil) - m.On("Commit", mock.Anything, mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe() - m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil) - - cs1, vss := randStateWithApp(4, m) - height, round := cs1.Height, cs1.Round - - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - ensureNewProposal(proposalCh, height, round) - - rs := cs1.GetRoundState() - blockID := types.BlockID{ - Hash: rs.ProposalBlock.Hash(), - PartSetHeader: rs.ProposalBlockParts.Header(), - } - signAddVotes(cs1, cmtproto.PrevoteType, blockID.Hash, blockID.PartSetHeader, false, vss[1:]...) - - // create a precommit for each validator with the associated vote extension. - for i, vs := range vss[1:] { - signAddPrecommitWithExtension(t, cs1, blockID.Hash, blockID.PartSetHeader, voteExtensions[i+1], vs) - } - - ensurePrevote(voteCh, height, round) - - // ensure that the height is committed. - ensurePrecommitMatch(t, voteCh, height, round, blockID.Hash) - incrementHeight(vss[1:]...) - - height++ - round = 0 - ensureNewRound(newRoundCh, height, round) - incrementRound(vss[1:]...) - incrementRound(vss[1:]...) - incrementRound(vss[1:]...) - round = 3 - - blockID2 := types.BlockID{} - signAddVotes(cs1, cmtproto.PrecommitType, blockID2.Hash, blockID2.PartSetHeader, true, vss[1:]...) - ensureNewRound(newRoundCh, height, round) - ensureNewProposal(proposalCh, height, round) - - // ensure that the proposer received the list of vote extensions from the - // previous height. - require.Len(t, rpp.LocalLastCommit.Votes, len(vss)) - for i := range vss { - vote := &rpp.LocalLastCommit.Votes[i] - require.Equal(t, vote.VoteExtension, voteExtensions[i]) - - require.NotZero(t, len(vote.ExtensionSignature)) - cve := cmtproto.CanonicalVoteExtension{ - Extension: vote.VoteExtension, - Height: height - 1, //the vote extension was signed in the previous height - Round: int64(rpp.LocalLastCommit.Round), - ChainId: test.DefaultTestChainID, - } - extSignBytes, err := protoio.MarshalDelimited(&cve) - require.NoError(t, err) - pubKey, err := vss[i].PrivValidator.GetPubKey() - require.NoError(t, err) - require.True(t, pubKey.VerifySignature(extSignBytes, vote.ExtensionSignature)) - } -} - -func TestFinalizeBlockCalled(t *testing.T) { - for _, testCase := range []struct { - name string - voteNil bool - expectCalled bool - }{ - { - name: "finalize block called when block committed", - voteNil: false, - expectCalled: true, - }, - { - name: "not called when block not committed", - voteNil: true, - expectCalled: false, - }, - } { - t.Run(testCase.name, func(t *testing.T) { - m := abcimocks.NewApplication(t) - m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{ - Status: abci.ResponseProcessProposal_ACCEPT, - }, nil) - m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil) - // We only expect VerifyVoteExtension to be called on non-nil precommits. - // https://github.com/tendermint/tendermint/issues/8487 - if !testCase.voteNil { - m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{}, nil) - m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{ - Status: abci.ResponseVerifyVoteExtension_ACCEPT, - }, nil) - } - r := &abci.ResponseFinalizeBlock{AppHash: []byte("the_hash")} - m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(r, nil).Maybe() - m.On("Commit", mock.Anything, mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe() - - cs1, vss := randStateWithApp(4, m) - height, round := cs1.Height, cs1.Round - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - - blockID := types.BlockID{} - nextRound := round + 1 - nextHeight := height - if !testCase.voteNil { - nextRound = 0 - nextHeight = height + 1 - blockID = types.BlockID{ - Hash: rs.ProposalBlock.Hash(), - PartSetHeader: rs.ProposalBlockParts.Header(), - } - } - - signAddVotes(cs1, cmtproto.PrevoteType, blockID.Hash, blockID.PartSetHeader, false, vss[1:]...) - ensurePrevoteMatch(t, voteCh, height, round, rs.ProposalBlock.Hash()) - - signAddVotes(cs1, cmtproto.PrecommitType, blockID.Hash, blockID.PartSetHeader, true, vss[1:]...) - ensurePrecommit(voteCh, height, round) - - ensureNewRound(newRoundCh, nextHeight, nextRound) - m.AssertExpectations(t) - - if !testCase.expectCalled { - m.AssertNotCalled(t, "FinalizeBlock", context.TODO(), mock.Anything) - } else { - m.AssertCalled(t, "FinalizeBlock", context.TODO(), mock.Anything) - } - }) - } -} - -// TestVoteExtensionEnableHeight tests that 'ExtensionRequireHeight' correctly -// enforces that vote extensions be present in consensus for heights greater than -// or equal to the configured value. -func TestVoteExtensionEnableHeight(t *testing.T) { - for _, testCase := range []struct { - name string - enableHeight int64 - hasExtension bool - expectExtendCalled bool - expectVerifyCalled bool - expectSuccessfulRound bool - }{ - { - name: "extension present but not enabled", - hasExtension: true, - enableHeight: 0, - expectExtendCalled: false, - expectVerifyCalled: false, - expectSuccessfulRound: false, - }, - { - name: "extension absent but not required", - hasExtension: false, - enableHeight: 0, - expectExtendCalled: false, - expectVerifyCalled: false, - expectSuccessfulRound: true, - }, - { - name: "extension present and required", - hasExtension: true, - enableHeight: 1, - expectExtendCalled: true, - expectVerifyCalled: true, - expectSuccessfulRound: true, - }, - { - name: "extension absent but required", - hasExtension: false, - enableHeight: 1, - expectExtendCalled: true, - expectVerifyCalled: false, - expectSuccessfulRound: false, - }, - { - name: "extension absent but required in future height", - hasExtension: false, - enableHeight: 2, - expectExtendCalled: false, - expectVerifyCalled: false, - expectSuccessfulRound: true, - }, - } { - t.Run(testCase.name, func(t *testing.T) { - numValidators := 3 - m := abcimocks.NewApplication(t) - m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{ - Status: abci.ResponseProcessProposal_ACCEPT, - }, nil) - m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil) - if testCase.expectExtendCalled { - m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ResponseExtendVote{}, nil) - } - if testCase.expectVerifyCalled { - m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.ResponseVerifyVoteExtension{ - Status: abci.ResponseVerifyVoteExtension_ACCEPT, - }, nil).Times(numValidators - 1) - } - m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.ResponseFinalizeBlock{}, nil).Maybe() - m.On("Commit", mock.Anything, mock.Anything).Return(&abci.ResponseCommit{}, nil).Maybe() - cs1, vss := randStateWithAppWithHeight(numValidators, m, testCase.enableHeight) - cs1.state.ConsensusParams.ABCI.VoteExtensionsEnableHeight = testCase.enableHeight - height, round := cs1.Height, cs1.Round - - timeoutCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - startTestRound(cs1, cs1.Height, round) - ensureNewRound(newRoundCh, height, round) - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - - // sign all of the votes - signAddVotes(cs1, cmtproto.PrevoteType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), false, vss[1:]...) - ensurePrevoteMatch(t, voteCh, height, round, rs.ProposalBlock.Hash()) - - var ext []byte - if testCase.hasExtension { - ext = []byte("extension") - } - - for _, vs := range vss[1:] { - vote, err := vs.signVote(cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), ext, testCase.hasExtension) - require.NoError(t, err) - addVotes(cs1, vote) - } - if testCase.expectSuccessfulRound { - ensurePrecommit(voteCh, height, round) - height++ - ensureNewRound(newRoundCh, height, round) - } else { - ensureNoNewTimeout(timeoutCh, cs1.config.Precommit(round).Nanoseconds()) - } - - m.AssertExpectations(t) - }) - } -} - -// 4 vals, 3 Nil Precommits at P0 -// What we want: -// P0 waits for timeoutPrecommit before starting next round -func TestWaitingTimeoutOnNilPolka(t *testing.T) { - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - - // start round - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - ensureNewRound(newRoundCh, height, round+1) -} - -// 4 vals, 3 Prevotes for nil from the higher round. -// What we want: -// P0 waits for timeoutPropose in the next round before entering prevote -func TestWaitingTimeoutProposeOnNewRound(t *testing.T) { - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - ensurePrevote(voteCh, height, round) - - incrementRound(vss[1:]...) - signAddVotes(cs1, cmtproto.PrevoteType, nil, types.PartSetHeader{}, false, vs2, vs3, vs4) - - round++ // moving to the next round - ensureNewRound(newRoundCh, height, round) - - rs := cs1.GetRoundState() - assert.True(t, rs.Step == cstypes.RoundStepPropose) // P0 does not prevote before timeoutPropose expires - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Propose(round).Nanoseconds()) - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], nil) -} - -// 4 vals, 3 Precommits for nil from the higher round. -// What we want: -// P0 jump to higher round, precommit and start precommit wait -func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) { - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - ensurePrevote(voteCh, height, round) - - incrementRound(vss[1:]...) - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2, vs3, vs4) - - round++ // moving to the next round - ensureNewRound(newRoundCh, height, round) - - ensurePrecommit(voteCh, height, round) - validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) - - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - round++ // moving to the next round - ensureNewRound(newRoundCh, height, round) -} - -// 4 vals, 3 Prevotes for nil in the current round. -// What we want: -// P0 wait for timeoutPropose to expire before sending prevote. -func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) { - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, int32(1) - - timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round in which PO is not proposer - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - incrementRound(vss[1:]...) - signAddVotes(cs1, cmtproto.PrevoteType, nil, types.PartSetHeader{}, false, vs2, vs3, vs4) - - ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], nil) -} - -// What we want: -// P0 emit NewValidBlock event upon receiving 2/3+ Precommit for B but hasn't received block B yet -func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, int32(1) - - incrementRound(vs2, vs3, vs4) - - partSize := types.BlockPartSizeBytes - - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) - - _, propBlock := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round) - propBlockHash := propBlock.Hash() - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - // start round in which PO is not proposer - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - // vs2, vs3 and vs4 send precommit for propBlock - signAddVotes(cs1, cmtproto.PrecommitType, propBlockHash, propBlockParts.Header(), true, vs2, vs3, vs4) - ensureNewValidBlock(validBlockCh, height, round) - - rs := cs1.GetRoundState() - assert.True(t, rs.Step == cstypes.RoundStepCommit) - assert.True(t, rs.ProposalBlock == nil) - assert.True(t, rs.ProposalBlockParts.Header().Equals(propBlockParts.Header())) - -} - -// What we want: -// P0 receives 2/3+ Precommit for B for round 0, while being in round 1. It emits NewValidBlock event. -// After receiving block, it executes block and moves to the next height. -func TestCommitFromPreviousRound(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, int32(1) - - partSize := types.BlockPartSizeBytes - - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - - prop, propBlock := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round) - propBlockHash := propBlock.Hash() - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - // start round in which PO is not proposer - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - // vs2, vs3 and vs4 send precommit for propBlock for the previous round - signAddVotes(cs1, cmtproto.PrecommitType, propBlockHash, propBlockParts.Header(), true, vs2, vs3, vs4) - - ensureNewValidBlock(validBlockCh, height, round) - - rs := cs1.GetRoundState() - assert.True(t, rs.Step == cstypes.RoundStepCommit) - assert.True(t, rs.CommitRound == vs2.Round) - assert.True(t, rs.ProposalBlock == nil) - assert.True(t, rs.ProposalBlockParts.Header().Equals(propBlockParts.Header())) - - if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - - ensureNewProposal(proposalCh, height, round) - ensureNewRound(newRoundCh, height+1, 0) -} - -type fakeTxNotifier struct { - ch chan struct{} -} - -func (n *fakeTxNotifier) TxsAvailable() <-chan struct{} { - return n.ch -} - -func (n *fakeTxNotifier) Notify() { - n.ch <- struct{}{} -} - -// 2 vals precommit votes for a block but node times out waiting for the third. Move to next round -// and third precommit arrives which leads to the commit of that header and the correct -// start of the next round -func TestStartNextHeightCorrectlyAfterTimeout(t *testing.T) { - config.Consensus.SkipTimeoutCommit = false - cs1, vss := randState(4) - cs1.txNotifier = &fakeTxNotifier{ch: make(chan struct{})} - - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) - precommitTimeoutCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round and wait for propose and prevote - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - theBlockHash := rs.ProposalBlock.Hash() - theBlockParts := rs.ProposalBlockParts.Header() - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], theBlockHash) - - signAddVotes(cs1, cmtproto.PrevoteType, theBlockHash, theBlockParts, false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // the proposed block should now be locked and our precommit added - validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash) - - // add precommits - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2) - signAddVotes(cs1, cmtproto.PrecommitType, theBlockHash, theBlockParts, true, vs3) - - // wait till timeout occurs - ensurePrecommitTimeout(precommitTimeoutCh) - - ensureNewRound(newRoundCh, height, round+1) - - // majority is now reached - signAddVotes(cs1, cmtproto.PrecommitType, theBlockHash, theBlockParts, true, vs4) - - ensureNewBlockHeader(newBlockHeader, height, theBlockHash) - - cs1.txNotifier.(*fakeTxNotifier).Notify() - - ensureNewTimeout(timeoutProposeCh, height+1, round, cs1.config.Propose(round).Nanoseconds()) - rs = cs1.GetRoundState() - assert.False( - t, - rs.TriggeredTimeoutPrecommit, - "triggeredTimeoutPrecommit should be false at the beginning of each round") -} - -func TestResetTimeoutPrecommitUponNewHeight(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - config.Consensus.SkipTimeoutCommit = false - cs1, vss := randState(4) - - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - - partSize := types.BlockPartSizeBytes - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round and wait for propose and prevote - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - theBlockHash := rs.ProposalBlock.Hash() - theBlockParts := rs.ProposalBlockParts.Header() - - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], theBlockHash) - - signAddVotes(cs1, cmtproto.PrevoteType, theBlockHash, theBlockParts, false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - validatePrecommit(t, cs1, round, round, vss[0], theBlockHash, theBlockHash) - - // add precommits - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2) - signAddVotes(cs1, cmtproto.PrecommitType, theBlockHash, theBlockParts, true, vs3) - signAddVotes(cs1, cmtproto.PrecommitType, theBlockHash, theBlockParts, true, vs4) - - ensureNewBlockHeader(newBlockHeader, height, theBlockHash) - - prop, propBlock := decideProposal(ctx, t, cs1, vs2, height+1, 0) - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - if err := cs1.SetProposalAndBlock(prop, propBlock, propBlockParts, "some peer"); err != nil { - t.Fatal(err) - } - ensureNewProposal(proposalCh, height+1, 0) - - rs = cs1.GetRoundState() - assert.False( - t, - rs.TriggeredTimeoutPrecommit, - "triggeredTimeoutPrecommit should be false at the beginning of each height") -} - -//------------------------------------------------------------------------------------------ -// SlashingSuite -// TODO: Slashing - -/* -func TestStateSlashingPrevotes(t *testing.T) { - cs1, vss := randState(2) - vs2 := vss[1] - - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress()) - - // start round and wait for propose and prevote - startTestRound(cs1, cs1.Height, 0) - <-newRoundCh - re := <-proposalCh - <-voteCh // prevote - - rs := re.(types.EventDataRoundState).RoundState.(*cstypes.RoundState) - - // we should now be stuck in limbo forever, waiting for more prevotes - // add one for a different block should cause us to go into prevote wait - hash := rs.ProposalBlock.Hash() - hash[0] = byte(hash[0]+1) % 255 - signAddVotes(cs1, cmtproto.PrevoteType, hash, rs.ProposalBlockParts.Header(), vs2) - - <-timeoutWaitCh - - // NOTE: we have to send the vote for different block first so we don't just go into precommit round right - // away and ignore more prevotes (and thus fail to slash!) - - // add the conflicting vote - signAddVotes(cs1, cmtproto.PrevoteType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vs2) - - // XXX: Check for existence of Dupeout info -} - -func TestStateSlashingPrecommits(t *testing.T) { - cs1, vss := randState(2) - vs2 := vss[1] - - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - voteCh := subscribeToVoter(cs1, cs1.privValidator.GetAddress()) - - // start round and wait for propose and prevote - startTestRound(cs1, cs1.Height, 0) - <-newRoundCh - re := <-proposalCh - <-voteCh // prevote - - // add prevote from vs2 - signAddVotes(cs1, cmtproto.PrevoteType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vs2) - - <-voteCh // precommit - - // we should now be stuck in limbo forever, waiting for more prevotes - // add one for a different block should cause us to go into prevote wait - hash := rs.ProposalBlock.Hash() - hash[0] = byte(hash[0]+1) % 255 - signAddVotes(cs1, cmtproto.PrecommitType, hash, rs.ProposalBlockParts.Header(), vs2) - - // NOTE: we have to send the vote for different block first so we don't just go into precommit round right - // away and ignore more prevotes (and thus fail to slash!) - - // add precommit from vs2 - signAddVotes(cs1, cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), vs2) - - // XXX: Check for existence of Dupeout info -} -*/ - -//------------------------------------------------------------------------------------------ -// CatchupSuite - -//------------------------------------------------------------------------------------------ -// HaltSuite - -// 4 vals. -// we receive a final precommit after going into next round, but others might have gone to commit already! -func TestStateHalt1(t *testing.T) { - cs1, vss := randState(4) - vs2, vs3, vs4 := vss[1], vss[2], vss[3] - height, round := cs1.Height, cs1.Round - partSize := types.BlockPartSizeBytes - - proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) - timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) - newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) - newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlock) - pv1, err := cs1.privValidator.GetPubKey() - require.NoError(t, err) - addr := pv1.Address() - voteCh := subscribeToVoter(cs1, addr) - - // start round and wait for propose and prevote - startTestRound(cs1, height, round) - ensureNewRound(newRoundCh, height, round) - - ensureNewProposal(proposalCh, height, round) - rs := cs1.GetRoundState() - propBlock := rs.ProposalBlock - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - - ensurePrevote(voteCh, height, round) - - signAddVotes(cs1, cmtproto.PrevoteType, propBlock.Hash(), propBlockParts.Header(), false, vs2, vs3, vs4) - - ensurePrecommit(voteCh, height, round) - // the proposed block should now be locked and our precommit added - validatePrecommit(t, cs1, round, round, vss[0], propBlock.Hash(), propBlock.Hash()) - - // add precommits from the rest - signAddVotes(cs1, cmtproto.PrecommitType, nil, types.PartSetHeader{}, true, vs2) // didnt receive proposal - signAddVotes(cs1, cmtproto.PrecommitType, propBlock.Hash(), propBlockParts.Header(), true, vs3) - // we receive this later, but vs3 might receive it earlier and with ours will go to commit! - precommit4 := signVote(vs4, cmtproto.PrecommitType, propBlock.Hash(), propBlockParts.Header(), true) - - incrementRound(vs2, vs3, vs4) - - // timeout to new round - ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) - - round++ // moving to the next round - - ensureNewRound(newRoundCh, height, round) - rs = cs1.GetRoundState() - - t.Log("### ONTO ROUND 1") - /*Round2 - // we timeout and prevote our lock - // a polka happened but we didn't see it! - */ - - // go to prevote, prevote for locked block - ensurePrevote(voteCh, height, round) - validatePrevote(t, cs1, round, vss[0], rs.LockedBlock.Hash()) - - // now we receive the precommit from the previous round - addVotes(cs1, precommit4) - - // receiving that precommit should take us straight to commit - ensureNewBlock(newBlockCh, height) - - ensureNewRound(newRoundCh, height+1, 0) -} - -func TestStateOutputsBlockPartsStats(t *testing.T) { - // create dummy peer - cs, _ := randState(1) - peer := p2pmock.NewPeer(nil) - - // 1) new block part - parts := types.NewPartSetFromData(cmtrand.Bytes(100), 10) - msg := &BlockPartMessage{ - Height: 1, - Round: 0, - Part: parts.GetPart(0), - } - - cs.ProposalBlockParts = types.NewPartSetFromHeader(parts.Header()) - cs.handleMsg(msgInfo{msg, peer.ID()}) - - statsMessage := <-cs.statsMsgQueue - require.Equal(t, msg, statsMessage.Msg, "") - require.Equal(t, peer.ID(), statsMessage.PeerID, "") - - // sending the same part from different peer - cs.handleMsg(msgInfo{msg, "peer2"}) - - // sending the part with the same height, but different round - msg.Round = 1 - cs.handleMsg(msgInfo{msg, peer.ID()}) - - // sending the part from the smaller height - msg.Height = 0 - cs.handleMsg(msgInfo{msg, peer.ID()}) - - // sending the part from the bigger height - msg.Height = 3 - cs.handleMsg(msgInfo{msg, peer.ID()}) - - select { - case <-cs.statsMsgQueue: - t.Errorf("should not output stats message after receiving the known block part!") - case <-time.After(50 * time.Millisecond): - } - -} - -func TestStateOutputVoteStats(t *testing.T) { - cs, vss := randState(2) - // create dummy peer - peer := p2pmock.NewPeer(nil) - - randBytes := cmtrand.Bytes(tmhash.Size) - - vote := signVote(vss[1], cmtproto.PrecommitType, randBytes, types.PartSetHeader{}, true) - - voteMessage := &VoteMessage{vote} - cs.handleMsg(msgInfo{voteMessage, peer.ID()}) - - statsMessage := <-cs.statsMsgQueue - require.Equal(t, voteMessage, statsMessage.Msg, "") - require.Equal(t, peer.ID(), statsMessage.PeerID, "") - - // sending the same part from different peer - cs.handleMsg(msgInfo{&VoteMessage{vote}, "peer2"}) - - // sending the vote for the bigger height - incrementHeight(vss[1]) - vote = signVote(vss[1], cmtproto.PrecommitType, randBytes, types.PartSetHeader{}, true) - - cs.handleMsg(msgInfo{&VoteMessage{vote}, peer.ID()}) - - select { - case <-cs.statsMsgQueue: - t.Errorf("should not output stats message after receiving the known vote or vote from bigger height") - case <-time.After(50 * time.Millisecond): - } - -} - -func TestSignSameVoteTwice(t *testing.T) { - _, vss := randState(2) - - randBytes := cmtrand.Bytes(tmhash.Size) - - vote := signVote(vss[1], - cmtproto.PrecommitType, - randBytes, - types.PartSetHeader{Total: 10, Hash: randBytes}, - true, - ) - - vote2 := signVote(vss[1], - cmtproto.PrecommitType, - randBytes, - types.PartSetHeader{Total: 10, Hash: randBytes}, - true, - ) - - require.Equal(t, vote, vote2) -} - -// subscribe subscribes test client to the given query and returns a channel with cap = 1. -func subscribe(eventBus *types.EventBus, q cmtpubsub.Query) <-chan cmtpubsub.Message { - sub, err := eventBus.Subscribe(context.Background(), testSubscriber, q) - if err != nil { - panic(fmt.Sprintf("failed to subscribe %s to %v", testSubscriber, q)) - } - return sub.Out() -} - -// subscribe subscribes test client to the given query and returns a channel with cap = 0. -func subscribeUnBuffered(eventBus *types.EventBus, q cmtpubsub.Query) <-chan cmtpubsub.Message { - sub, err := eventBus.SubscribeUnbuffered(context.Background(), testSubscriber, q) - if err != nil { - panic(fmt.Sprintf("failed to subscribe %s to %v", testSubscriber, q)) - } - return sub.Out() -} - -func signAddPrecommitWithExtension( - t *testing.T, - cs *State, - hash []byte, - header types.PartSetHeader, - extension []byte, - stub *validatorStub) { - v, err := stub.signVote(cmtproto.PrecommitType, hash, header, extension, true) - require.NoError(t, err, "failed to sign vote") - addVotes(cs, v) -} diff --git a/crypto/armor/armor.go b/crypto/armor/armor.go index 99e2c3b3a28..af61b20b009 100644 --- a/crypto/armor/armor.go +++ b/crypto/armor/armor.go @@ -8,21 +8,34 @@ import ( "golang.org/x/crypto/openpgp/armor" //nolint: staticcheck ) -func EncodeArmor(blockType string, headers map[string]string, data []byte) string { +// ErrEncode represents an error from calling [EncodeArmor]. +type ErrEncode struct { + Err error +} + +func (e ErrEncode) Error() string { + return fmt.Sprintf("armor: could not encode ASCII armor: %v", e.Err) +} + +func (e ErrEncode) Unwrap() error { + return e.Err +} + +func EncodeArmor(blockType string, headers map[string]string, data []byte) (string, error) { buf := new(bytes.Buffer) w, err := armor.Encode(buf, blockType, headers) if err != nil { - panic(fmt.Errorf("could not encode ascii armor: %s", err)) + return "", ErrEncode{Err: err} } _, err = w.Write(data) if err != nil { - panic(fmt.Errorf("could not encode ascii armor: %s", err)) + return "", ErrEncode{Err: err} } err = w.Close() if err != nil { - panic(fmt.Errorf("could not encode ascii armor: %s", err)) + return "", ErrEncode{Err: err} } - return buf.String() + return buf.String(), nil } func DecodeArmor(armorStr string) (blockType string, headers map[string]string, data []byte, err error) { diff --git a/crypto/armor/armor_test.go b/crypto/armor/armor_test.go index 8ecfaa0e1e9..051d285297f 100644 --- a/crypto/armor/armor_test.go +++ b/crypto/armor/armor_test.go @@ -10,11 +10,12 @@ import ( func TestArmor(t *testing.T) { blockType := "MINT TEST" data := []byte("somedata") - armorStr := EncodeArmor(blockType, nil, data) + armorStr, err := EncodeArmor(blockType, nil, data) + require.NoError(t, err, "%+v", err) // Decode armorStr and test for equivalence. blockType2, _, data2, err := DecodeArmor(armorStr) - require.Nil(t, err, "%+v", err) + require.NoError(t, err, "%+v", err) assert.Equal(t, blockType, blockType2) assert.Equal(t, data, data2) } diff --git a/crypto/batch/batch.go b/crypto/batch/batch.go index 7587bc711ab..530caafdab7 100644 --- a/crypto/batch/batch.go +++ b/crypto/batch/batch.go @@ -23,6 +23,9 @@ func CreateBatchVerifier(pk crypto.PubKey) (crypto.BatchVerifier, bool) { // SupportsBatchVerifier checks if a key type implements the batch verifier // interface. func SupportsBatchVerifier(pk crypto.PubKey) bool { + if pk == nil { + return false + } switch pk.Type() { case ed25519.KeyType, sr25519.KeyType: return true diff --git a/crypto/bls12381/doc.go b/crypto/bls12381/doc.go new file mode 100644 index 00000000000..77331365d34 --- /dev/null +++ b/crypto/bls12381/doc.go @@ -0,0 +1 @@ +package bls12381 diff --git a/crypto/bls12381/key.go b/crypto/bls12381/key.go new file mode 100644 index 00000000000..51acac4ab73 --- /dev/null +++ b/crypto/bls12381/key.go @@ -0,0 +1,111 @@ +//go:build !bls12381 || !((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) + +package bls12381 + +import ( + "github.com/cometbft/cometbft/crypto" +) + +const ( + // PrivKeySize defines the length of the PrivKey byte array. + PrivKeySize = 32 + // PubKeySize defines the length of the PubKey byte array. + PubKeySize = 48 + // SignatureLength defines the byte length of a BLS signature. + SignatureLength = 96 + // KeyType is the string constant for the bls12_381 algorithm. + KeyType = "bls12_381" + // Enabled indicates if this curve is enabled. + Enabled = false +) + +// -------------------------------------. +const ( + PubKeyName = "cometbft/PubKeyBLS12_381" +) + +// =============================================================================================== +// Private Key +// =============================================================================================== + +// PrivKey is a wrapper around the Ethereum bls12_381 private key type. This +// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum +// bls12_381 private key type. + +// Compile-time type assertion. +var _ crypto.PrivKey = &PrivKey{} + +// PrivKey represents a BLS private key noop when blst is not set as a build flag and cgo is disabled. +type PrivKey []byte + +func NewPrivateKeyFromBytes([]byte) (PrivKey, error) { + panic("bls12_381 is disabled") +} + +func GenPrivKey() (PrivKey, error) { + panic("bls12_381 is disabled") +} + +// Bytes returns the byte representation of the ECDSA Private Key. +func (privKey PrivKey) Bytes() []byte { + return privKey +} + +// PubKey returns the ECDSA private key's public key. If the privkey is not valid +// it returns a nil value. +func (PrivKey) PubKey() crypto.PubKey { + panic("bls12_381 is disabled") +} + +// Equals returns true if two ECDSA private keys are equal and false otherwise. +func (PrivKey) Equals(crypto.PrivKey) bool { + panic("bls12_381 is disabled") +} + +// Type returns eth_bls12_381. +func (PrivKey) Type() string { + return KeyType +} + +func (PrivKey) Sign([]byte) ([]byte, error) { + panic("bls12_381 is disabled") +} + +// =============================================================================================== +// Public Key +// =============================================================================================== + +// Pubkey is a wrapper around the Ethereum bls12_381 public key type. This +// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum +// bls12_381 public key type. + +// Compile-time type assertion. +var _ crypto.PubKey = &PubKey{} + +// PubKey represents a BLS private key noop when blst is not set as a build flag and cgo is disabled. +type PubKey []byte + +// Address returns the address of the ECDSA public key. +// The function will return an empty address if the public key is invalid. +func (PubKey) Address() crypto.Address { + panic("bls12_381 is disabled") +} + +func (PubKey) VerifySignature([]byte, []byte) bool { + panic("bls12_381 is disabled") +} + +// Bytes returns the pubkey byte format. +func (PubKey) Bytes() []byte { + panic("bls12_381 is disabled") +} + +// Type returns eth_bls12_381. +func (PubKey) Type() string { + return KeyType +} + +// Equals returns true if the pubkey type is the same and their bytes are deeply equal. +func (PubKey) Equals(crypto.PubKey) bool { + panic("bls12_381 is disabled") +} diff --git a/crypto/bls12381/key_bls12381.go b/crypto/bls12381/key_bls12381.go new file mode 100644 index 00000000000..b527f2c99e1 --- /dev/null +++ b/crypto/bls12381/key_bls12381.go @@ -0,0 +1,159 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && bls12381 + +package bls12381 + +import ( + "bytes" + + sha256 "github.com/minio/sha256-simd" + + "github.com/cometbft/cometbft/crypto" + bls12381 "github.com/cosmos/crypto/curves/bls12381" + + "github.com/cometbft/cometbft/crypto/tmhash" + cmtjson "github.com/cometbft/cometbft/libs/json" +) + +const ( + // PrivKeySize defines the length of the PrivKey byte array. + PrivKeySize = 32 + // PubKeySize defines the length of the PubKey byte array. + PubKeySize = 48 + // SignatureLength defines the byte length of a BLS signature. + SignatureLength = 96 + // KeyType is the string constant for the bls12_381 algorithm. + KeyType = "bls12_381" + // Enabled indicates if this curve is enabled. + Enabled = true +) + +// -------------------------------------. +const ( + PrivKeyName = "cometbft/PrivKeyBLS12_381" + PubKeyName = "cometbft/PubKeyBLS12_381" +) + +func init() { + cmtjson.RegisterType(PubKey{}, PubKeyName) + cmtjson.RegisterType(PrivKey{}, PrivKeyName) +} + +// =============================================================================================== +// Private Key +// =============================================================================================== + +// PrivKey is a wrapper around the Ethereum bls12_381 private key type. This +// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum +// bls12_381 private key type. + +var _ crypto.PrivKey = &PrivKey{} + +type PrivKey []byte + +func NewPrivateKeyFromBytes(bz []byte) (PrivKey, error) { + secretKey, err := bls12381.SecretKeyFromBytes(bz) + if err != nil { + return nil, err + } + return secretKey.Marshal(), nil +} + +func GenPrivKey() (PrivKey, error) { + secretKey, err := bls12381.RandKey() + return PrivKey(secretKey.Marshal()), err +} + +// Bytes returns the byte representation of the Private Key. +func (privKey PrivKey) Bytes() []byte { + return privKey +} + +// PubKey returns the private key's public key. If the privkey is not valid +// it returns a nil value. +func (privKey PrivKey) PubKey() crypto.PubKey { + secretKey, _ := bls12381.SecretKeyFromBytes(privKey) + + return PubKey(secretKey.PublicKey().Marshal()) +} + +// Equals returns true if two private keys are equal and false otherwise. +func (privKey PrivKey) Equals(other crypto.PrivKey) bool { + return privKey.Type() == other.Type() && bytes.Equal(privKey.Bytes(), other.Bytes()) +} + +// Type returns eth_bls12_381. +func (PrivKey) Type() string { + return KeyType +} + +func (privKey PrivKey) Sign(digestBz []byte) ([]byte, error) { + secretKey, err := bls12381.SecretKeyFromBytes(privKey) + if err != nil { + return nil, err + } + + bz := digestBz + if len(bz) > 32 { + hash := sha256.Sum256(bz) + bz = hash[:] + } + + sig := secretKey.Sign(bz) + return sig.Marshal(), nil +} + +// =============================================================================================== +// Public Key +// =============================================================================================== + +// Pubkey is a wrapper around the Ethereum bls12_381 public key type. This +// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum +// bls12_381 public key type. + +var _ crypto.PubKey = &PubKey{} + +type PubKey []byte + +// Address returns the address of the public key. +// The function will panic if the public key is invalid. +func (pubKey PubKey) Address() crypto.Address { + pk, _ := bls12381.PublicKeyFromBytes(pubKey) + if len(pk.Marshal()) != PubKeySize { + panic("pubkey is incorrect size") + } + // TODO: do we want to keep this address format? + return crypto.Address(tmhash.SumTruncated(pubKey)) +} + +func (pubKey PubKey) VerifySignature(msg, sig []byte) bool { + if len(sig) != SignatureLength { + return false + } + bz := msg + if len(msg) > 32 { + hash := sha256.Sum256(msg) + bz = hash[:] + } + + pubK, _ := bls12381.PublicKeyFromBytes(pubKey) + ok, err := bls12381.VerifySignature(sig, [32]byte(bz[:32]), pubK) + if err != nil { + return false + } + return ok +} + +// Bytes returns the pubkey byte format. +func (pubKey PubKey) Bytes() []byte { + return pubKey +} + +// Type returns eth_bls12_381. +func (PubKey) Type() string { + return KeyType +} + +// Equals returns true if the pubkey type is the same and their bytes are deeply equal. +func (pubKey PubKey) Equals(other crypto.PubKey) bool { + return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes()) +} diff --git a/crypto/bls12381/key_test.go b/crypto/bls12381/key_test.go new file mode 100644 index 00000000000..514df56ff13 --- /dev/null +++ b/crypto/bls12381/key_test.go @@ -0,0 +1,39 @@ +//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && bls12381 + +package bls12381_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cometbft/cometbft/crypto" + "github.com/cometbft/cometbft/crypto/bls12381" +) + +func TestSignAndValidateBLS12381(t *testing.T) { + privKey, err := bls12381.GenPrivKey() + require.NoError(t, err) + pubKey := privKey.PubKey() + + msg := crypto.CRandBytes(32) + sig, err := privKey.Sign(msg) + require.NoError(t, err) + + // Test the signature + assert.True(t, pubKey.VerifySignature(msg, sig)) + + // Mutate the signature, just one bit. + // TODO: Replace this with a much better fuzzer, tendermint/ed25519/issues/10 + sig[7] ^= byte(0x01) + + assert.False(t, pubKey.VerifySignature(msg, sig)) + + msg = crypto.CRandBytes(192) + sig, err = privKey.Sign(msg) + require.NoError(t, err) + + // Test the signature + assert.True(t, pubKey.VerifySignature(msg, sig)) +} diff --git a/crypto/crypto.go b/crypto/crypto.go index e4825b13259..6507e5f0cbf 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -23,7 +23,7 @@ type PubKey interface { Address() Address Bytes() []byte VerifySignature(msg []byte, sig []byte) bool - Equals(PubKey) bool + Equals(other PubKey) bool Type() string } @@ -31,7 +31,7 @@ type PrivKey interface { Bytes() []byte Sign(msg []byte) ([]byte, error) PubKey() PubKey - Equals(PrivKey) bool + Equals(other PrivKey) bool Type() string } @@ -42,7 +42,7 @@ type Symmetric interface { } // If a new key type implements batch verification, -// the key type must be registered in github.com/cometbft/cometbft/crypto/batch +// the key type must be registered in github.com/cometbft/cometbft/crypto/batch. type BatchVerifier interface { // Add appends an entry into the BatchVerifier. Add(key PubKey, message, signature []byte) error diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go index 7d2eb4e6971..3d091f63ffd 100644 --- a/crypto/ed25519/ed25519.go +++ b/crypto/ed25519/ed25519.go @@ -15,7 +15,20 @@ import ( cmtjson "github.com/cometbft/cometbft/libs/json" ) -//------------------------------------- +var ( + ErrNotEd25519Key = errors.New("ed25519: pubkey is not Ed25519") + ErrInvalidSignature = errors.New("ed25519: invalid signature") +) + +// ErrInvalidKeyLen describes an error resulting from an passing in a +// key with an invalid key in the call to [BatchVerifier.Add]. +type ErrInvalidKeyLen struct { + Got, Want int +} + +func (e ErrInvalidKeyLen) Error() string { + return fmt.Sprintf("ed25519: invalid key length: got %d, want %d", e.Got, e.Want) +} var ( _ crypto.PrivKey = PrivKey{} @@ -34,7 +47,7 @@ var ( const ( PrivKeyName = "tendermint/PrivKeyEd25519" PubKeyName = "tendermint/PubKeyEd25519" - // PubKeySize is is the size, in bytes, of public keys as used in this package. + // PubKeySize is the size, in bytes, of public keys as used in this package. PubKeySize = 32 // PrivateKeySize is the size, in bytes, of private keys as used in this package. PrivateKeySize = 64 @@ -114,7 +127,7 @@ func (privKey PrivKey) Equals(other crypto.PrivKey) bool { return false } -func (privKey PrivKey) Type() string { +func (PrivKey) Type() string { return KeyType } @@ -145,7 +158,7 @@ func GenPrivKeyFromSecret(secret []byte) PrivKey { return PrivKey(ed25519.NewKeyFromSeed(seed)) } -//------------------------------------- +// ------------------------------------- var _ crypto.PubKey = PubKey{} @@ -178,7 +191,7 @@ func (pubKey PubKey) String() string { return fmt.Sprintf("PubKeyEd25519{%X}", []byte(pubKey)) } -func (pubKey PubKey) Type() string { +func (PubKey) Type() string { return KeyType } @@ -190,7 +203,7 @@ func (pubKey PubKey) Equals(other crypto.PubKey) bool { return false } -//------------------------------------- +// ------------------------------------- // BatchVerifier implements batch verification for ed25519. type BatchVerifier struct { @@ -204,18 +217,18 @@ func NewBatchVerifier() crypto.BatchVerifier { func (b *BatchVerifier) Add(key crypto.PubKey, msg, signature []byte) error { pkEd, ok := key.(PubKey) if !ok { - return fmt.Errorf("pubkey is not Ed25519") + return ErrNotEd25519Key } pkBytes := pkEd.Bytes() if l := len(pkBytes); l != PubKeySize { - return fmt.Errorf("pubkey size is incorrect; expected: %d, got %d", PubKeySize, l) + return ErrInvalidKeyLen{Got: l, Want: PubKeySize} } // check that the signature is the correct length if len(signature) != SignatureSize { - return errors.New("invalid signature") + return ErrInvalidSignature } cachingVerifier.AddWithOptions(b.BatchVerifier, ed25519.PublicKey(pkBytes), msg, signature, verifyOptions) diff --git a/crypto/ed25519/ed25519_test.go b/crypto/ed25519/ed25519_test.go index 65696290929..3405165c314 100644 --- a/crypto/ed25519/ed25519_test.go +++ b/crypto/ed25519/ed25519_test.go @@ -16,7 +16,7 @@ func TestSignAndValidateEd25519(t *testing.T) { msg := crypto.CRandBytes(128) sig, err := privKey.Sign(msg) - require.Nil(t, err) + require.NoError(t, err) // Test the signature assert.True(t, pubKey.VerifySignature(msg, sig)) diff --git a/crypto/encoding/codec.go b/crypto/encoding/codec.go index 5980f88d4d5..5c0c6e19a0f 100644 --- a/crypto/encoding/codec.go +++ b/crypto/encoding/codec.go @@ -3,20 +3,45 @@ package encoding import ( "fmt" + pc "github.com/cometbft/cometbft/api/cometbft/crypto/v1" "github.com/cometbft/cometbft/crypto" + "github.com/cometbft/cometbft/crypto/bls12381" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/crypto/secp256k1" "github.com/cometbft/cometbft/libs/json" - pc "github.com/cometbft/cometbft/proto/tendermint/crypto" ) +// ErrUnsupportedKey describes an error resulting from the use of an +// unsupported key in [PubKeyToProto] or [PubKeyFromProto]. +type ErrUnsupportedKey struct { + Key any +} + +func (e ErrUnsupportedKey) Error() string { + return fmt.Sprintf("encoding: unsupported key %v", e.Key) +} + +// InvalidKeyLen describes an error resulting from the use of a key with +// an invalid length in [PubKeyFromProto]. +type ErrInvalidKeyLen struct { + Key any + Got, Want int +} + +func (e ErrInvalidKeyLen) Error() string { + return fmt.Sprintf("encoding: invalid key length for %v, got %d, want %d", e.Key, e.Got, e.Want) +} + func init() { json.RegisterType((*pc.PublicKey)(nil), "tendermint.crypto.PublicKey") json.RegisterType((*pc.PublicKey_Ed25519)(nil), "tendermint.crypto.PublicKey_Ed25519") json.RegisterType((*pc.PublicKey_Secp256K1)(nil), "tendermint.crypto.PublicKey_Secp256K1") + if bls12381.Enabled { + json.RegisterType((*pc.PublicKey_Bls12381)(nil), "tendermint.crypto.PublicKey_Bls12381") + } } -// PubKeyToProto takes crypto.PubKey and transforms it to a protobuf Pubkey +// PubKeyToProto takes crypto.PubKey and transforms it to a protobuf Pubkey. func PubKeyToProto(k crypto.PubKey) (pc.PublicKey, error) { var kp pc.PublicKey switch k := k.(type) { @@ -32,32 +57,63 @@ func PubKeyToProto(k crypto.PubKey) (pc.PublicKey, error) { Secp256K1: k, }, } + case bls12381.PubKey: + if !bls12381.Enabled { + return kp, ErrUnsupportedKey{Key: k} + } + + kp = pc.PublicKey{ + Sum: &pc.PublicKey_Bls12381{ + Bls12381: k, + }, + } default: - return kp, fmt.Errorf("toproto: key type %v is not supported", k) + return kp, ErrUnsupportedKey{Key: k} } return kp, nil } -// PubKeyFromProto takes a protobuf Pubkey and transforms it to a crypto.Pubkey +// PubKeyFromProto takes a protobuf Pubkey and transforms it to a crypto.Pubkey. func PubKeyFromProto(k pc.PublicKey) (crypto.PubKey, error) { switch k := k.Sum.(type) { case *pc.PublicKey_Ed25519: if len(k.Ed25519) != ed25519.PubKeySize { - return nil, fmt.Errorf("invalid size for PubKeyEd25519. Got %d, expected %d", - len(k.Ed25519), ed25519.PubKeySize) + return nil, ErrInvalidKeyLen{ + Key: k, + Got: len(k.Ed25519), + Want: ed25519.PubKeySize, + } } pk := make(ed25519.PubKey, ed25519.PubKeySize) copy(pk, k.Ed25519) return pk, nil case *pc.PublicKey_Secp256K1: if len(k.Secp256K1) != secp256k1.PubKeySize { - return nil, fmt.Errorf("invalid size for PubKeySecp256k1. Got %d, expected %d", - len(k.Secp256K1), secp256k1.PubKeySize) + return nil, ErrInvalidKeyLen{ + Key: k, + Got: len(k.Secp256K1), + Want: secp256k1.PubKeySize, + } } pk := make(secp256k1.PubKey, secp256k1.PubKeySize) copy(pk, k.Secp256K1) return pk, nil + case *pc.PublicKey_Bls12381: + if !bls12381.Enabled { + return nil, ErrUnsupportedKey{Key: k} + } + + if len(k.Bls12381) != bls12381.PubKeySize { + return nil, ErrInvalidKeyLen{ + Key: k, + Got: len(k.Bls12381), + Want: bls12381.PubKeySize, + } + } + pk := make(bls12381.PubKey, bls12381.PubKeySize) + copy(pk, k.Bls12381) + return pk, nil default: - return nil, fmt.Errorf("fromproto: key type %v is not supported", k) + return nil, ErrUnsupportedKey{Key: k} } } diff --git a/crypto/internal/benchmarking/bench.go b/crypto/internal/benchmarking/bench.go index de1c97974bb..20b5964b920 100644 --- a/crypto/internal/benchmarking/bench.go +++ b/crypto/internal/benchmarking/bench.go @@ -38,7 +38,6 @@ func BenchmarkSigning(b *testing.B, priv crypto.PrivKey) { b.ResetTimer() for i := 0; i < b.N; i++ { _, err := priv.Sign(message) - if err != nil { b.FailNow() } diff --git a/crypto/merkle/bench_test.go b/crypto/merkle/bench_test.go new file mode 100644 index 00000000000..0520bd23893 --- /dev/null +++ b/crypto/merkle/bench_test.go @@ -0,0 +1,42 @@ +package merkle + +import ( + "crypto/sha256" + "strings" + "testing" +) + +var sink any + +type innerHashTest struct { + left, right string +} + +var innerHashTests = []*innerHashTest{ + {"aaaaaaaaaaaaaaa", " "}, + {"", ""}, + {" ", "a ff b f1 a"}, + {"ffff122fff", "ffff122fff"}, + {"😎💡✅alalalalalalalalalallalallaallalaallalalalalalalalaallalalalalalala", "😎💡✅alalalalalalalalalallalallaallalaallalalalalalalalaallalalalalalalaffff122fff"}, + {strings.Repeat("ff", 1<<10), strings.Repeat("00af", 4<<10)}, + {strings.Repeat("f", sha256.Size), strings.Repeat("00af", 10<<10)}, + {"aaaaaaaaaaaaaaaaaaaaaaaaaaaffff122fffaaaaaaaaa", "aaaaaaaaaffff1aaaaaaaaaaaaaaaaaa22fffaaaaaaaaa"}, +} + +func BenchmarkInnerHash(b *testing.B) { + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + for _, tt := range innerHashTests { + got := innerHash([]byte(tt.left), []byte(tt.right)) + if g, w := len(got), sha256.Size; g != w { + b.Fatalf("size discrepancy: got %d, want %d", g, w) + } + sink = got + } + } + + if sink == nil { + b.Fatal("Benchmark did not run!") + } +} diff --git a/crypto/merkle/hash.go b/crypto/merkle/hash.go index be2010aefcc..dc527cac067 100644 --- a/crypto/merkle/hash.go +++ b/crypto/merkle/hash.go @@ -6,23 +6,23 @@ import ( "github.com/cometbft/cometbft/crypto/tmhash" ) -// TODO: make these have a large predefined capacity +// TODO: make these have a large predefined capacity. var ( leafPrefix = []byte{0} innerPrefix = []byte{1} ) -// returns tmhash() +// returns tmhash(). func emptyHash() []byte { return tmhash.Sum([]byte{}) } -// returns tmhash(0x00 || leaf) +// returns tmhash(0x00 || leaf). func leafHash(leaf []byte) []byte { return tmhash.Sum(append(leafPrefix, leaf...)) } -// returns tmhash(0x00 || leaf) +// returns tmhash(0x00 || leaf). func leafHashOpt(s hash.Hash, leaf []byte) []byte { s.Reset() s.Write(leafPrefix) @@ -30,13 +30,9 @@ func leafHashOpt(s hash.Hash, leaf []byte) []byte { return s.Sum(nil) } -// returns tmhash(0x01 || left || right) +// returns tmhash(0x01 || left || right). func innerHash(left []byte, right []byte) []byte { - data := make([]byte, len(innerPrefix)+len(left)+len(right)) - n := copy(data, innerPrefix) - n += copy(data[n:], left) - copy(data[n:], right) - return tmhash.Sum(data) + return tmhash.SumMany(innerPrefix, left, right) } func innerHashOpt(s hash.Hash, left []byte, right []byte) []byte { diff --git a/crypto/merkle/proof.go b/crypto/merkle/proof.go index 25defd5bb55..30313f7d349 100644 --- a/crypto/merkle/proof.go +++ b/crypto/merkle/proof.go @@ -5,17 +5,43 @@ import ( "errors" "fmt" + cmtcrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" "github.com/cometbft/cometbft/crypto/tmhash" - cmtcrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" ) const ( // MaxAunts is the maximum number of aunts that can be included in a Proof. // This corresponds to a tree of size 2^100, which should be sufficient for all conceivable purposes. - // This maximum helps prevent Denial-of-Service attacks by limitting the size of the proofs. + // This maximum helps prevent Denial-of-Service attacks by limiting the size of the proofs. MaxAunts = 100 ) +var ErrMaxAuntsLenExceeded = fmt.Errorf("merkle: maximum aunts length, %d, exceeded", MaxAunts) + +type ErrInvalidHash struct { + Err error +} + +func (e ErrInvalidHash) Error() string { + return fmt.Sprintf("merkle: invalid hash: %s", e.Err) +} + +func (e ErrInvalidHash) Unwrap() error { + return e.Err +} + +type ErrInvalidProof struct { + Err error +} + +func (e ErrInvalidProof) Error() string { + return fmt.Sprintf("merkle: invalid proof: %s", e.Err) +} + +func (e ErrInvalidProof) Unwrap() error { + return e.Err +} + // Proof represents a Merkle proof. // NOTE: The convention for proofs is to include leaf hashes but to // exclude the root hash. @@ -24,10 +50,10 @@ const ( // everything. This also affects the generalized proof system as // well. type Proof struct { - Total int64 `json:"total"` // Total number of items. - Index int64 `json:"index"` // Index of item to prove. - LeafHash []byte `json:"leaf_hash"` // Hash of item value. - Aunts [][]byte `json:"aunts"` // Hashes from leaf's sibling to a root's child. + Total int64 `json:"total"` // Total number of items. + Index int64 `json:"index"` // Index of item to prove. + LeafHash []byte `json:"leaf_hash"` // Hash of item value. + Aunts [][]byte `json:"aunts,omitempty"` // Hashes from leaf's sibling to a root's child. } // ProofsFromByteSlices computes inclusion proof for given items. @@ -44,31 +70,49 @@ func ProofsFromByteSlices(items [][]byte) (rootHash []byte, proofs []*Proof) { Aunts: trail.FlattenAunts(), } } - return + return rootHash, proofs } // Verify that the Proof proves the root hash. -// Check sp.Index/sp.Total manually if needed +// Check sp.Index/sp.Total manually if needed. func (sp *Proof) Verify(rootHash []byte, leaf []byte) error { + if rootHash == nil { + return ErrInvalidHash{ + Err: errors.New("nil root"), + } + } if sp.Total < 0 { - return errors.New("proof total must be positive") + return ErrInvalidProof{ + Err: errors.New("negative proof total"), + } } if sp.Index < 0 { - return errors.New("proof index cannot be negative") + return ErrInvalidProof{ + Err: errors.New("negative proof index"), + } } leafHash := leafHash(leaf) if !bytes.Equal(sp.LeafHash, leafHash) { - return fmt.Errorf("invalid leaf hash: wanted %X got %X", leafHash, sp.LeafHash) + return ErrInvalidHash{ + Err: fmt.Errorf("leaf %x, want %x", sp.LeafHash, leafHash), + } + } + computedHash, err := sp.computeRootHash() + if err != nil { + return ErrInvalidHash{ + Err: fmt.Errorf("compute root hash: %w", err), + } } - computedHash := sp.ComputeRootHash() if !bytes.Equal(computedHash, rootHash) { - return fmt.Errorf("invalid root hash: wanted %X got %X", rootHash, computedHash) + return ErrInvalidHash{ + Err: fmt.Errorf("root %x, want %x", computedHash, rootHash), + } } return nil } -// Compute the root hash given a leaf hash. Does not verify the result. -func (sp *Proof) ComputeRootHash() []byte { +// Compute the root hash given a leaf hash. +func (sp *Proof) computeRootHash() ([]byte, error) { return computeHashFromAunts( sp.Index, sp.Total, @@ -97,20 +141,28 @@ func (sp *Proof) StringIndented(indent string) string { // and it expects at most MaxAunts elements in Aunts. func (sp *Proof) ValidateBasic() error { if sp.Total < 0 { - return errors.New("negative Total") + return ErrInvalidProof{ + Err: errors.New("negative proof total"), + } } if sp.Index < 0 { - return errors.New("negative Index") + return ErrInvalidProof{ + Err: errors.New("negative proof index"), + } } if len(sp.LeafHash) != tmhash.Size { - return fmt.Errorf("expected LeafHash size to be %d, got %d", tmhash.Size, len(sp.LeafHash)) + return ErrInvalidHash{ + Err: fmt.Errorf("leaf length %d, want %d", len(sp.LeafHash), tmhash.Size), + } } if len(sp.Aunts) > MaxAunts { - return fmt.Errorf("expected no more than %d aunts, got %d", MaxAunts, len(sp.Aunts)) + return ErrMaxAuntsLenExceeded } for i, auntHash := range sp.Aunts { if len(auntHash) != tmhash.Size { - return fmt.Errorf("expected Aunts#%d size to be %d, got %d", i, tmhash.Size, len(auntHash)) + return ErrInvalidHash{ + Err: fmt.Errorf("aunt#%d hash length %d, want %d", i, len(auntHash), tmhash.Size), + } } } return nil @@ -132,7 +184,7 @@ func (sp *Proof) ToProto() *cmtcrypto.Proof { func ProofFromProto(pb *cmtcrypto.Proof) (*Proof, error) { if pb == nil { - return nil, errors.New("nil proof") + return nil, ErrInvalidProof{Err: errors.New("nil proof")} } sp := new(Proof) @@ -148,35 +200,36 @@ func ProofFromProto(pb *cmtcrypto.Proof) (*Proof, error) { // Use the leafHash and innerHashes to get the root merkle hash. // If the length of the innerHashes slice isn't exactly correct, the result is nil. // Recursive impl. -func computeHashFromAunts(index, total int64, leafHash []byte, innerHashes [][]byte) []byte { +func computeHashFromAunts(index, total int64, leafHash []byte, innerHashes [][]byte) ([]byte, error) { if index >= total || index < 0 || total <= 0 { - return nil + return nil, fmt.Errorf("invalid index %d and/or total %d", index, total) } switch total { case 0: panic("Cannot call computeHashFromAunts() with 0 total") case 1: if len(innerHashes) != 0 { - return nil + return nil, errors.New("unexpected inner hashes") } - return leafHash + return leafHash, nil default: if len(innerHashes) == 0 { - return nil + return nil, errors.New("expected at least one inner hash") } numLeft := getSplitPoint(total) if index < numLeft { - leftHash := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) - if leftHash == nil { - return nil + leftHash, err := computeHashFromAunts(index, numLeft, leafHash, innerHashes[:len(innerHashes)-1]) + if err != nil { + return nil, err } - return innerHash(leftHash, innerHashes[len(innerHashes)-1]) + + return innerHash(leftHash, innerHashes[len(innerHashes)-1]), nil } - rightHash := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) - if rightHash == nil { - return nil + rightHash, err := computeHashFromAunts(index-numLeft, total-numLeft, leafHash, innerHashes[:len(innerHashes)-1]) + if err != nil { + return nil, err } - return innerHash(innerHashes[len(innerHashes)-1], rightHash) + return innerHash(innerHashes[len(innerHashes)-1], rightHash), nil } } @@ -204,7 +257,6 @@ func (spn *ProofNode) FlattenAunts() [][]byte { case spn.Right != nil: innerHashes = append(innerHashes, spn.Right.Hash) default: - break } spn = spn.Parent } diff --git a/crypto/merkle/proof_key_path.go b/crypto/merkle/proof_key_path.go index ca8b5f0523e..bff53a9b68f 100644 --- a/crypto/merkle/proof_key_path.go +++ b/crypto/merkle/proof_key_path.go @@ -82,11 +82,21 @@ func (pth KeyPath) String() string { return res } +type ErrInvalidKey struct { + Err error +} + +func (e ErrInvalidKey) Error() string { + return fmt.Sprintf("merkle: invalid key error: %v", e.Err) +} + // Decode a path to a list of keys. Path must begin with `/`. // Each key must use a known encoding. func KeyPathToKeys(path string) (keys [][]byte, err error) { if path == "" || path[0] != '/' { - return nil, errors.New("key path string must start with a forward slash '/'") + return nil, ErrInvalidKey{ + Err: errors.New("key path string must start with a forward slash '/'"), + } } parts := strings.Split(path[1:], "/") keys = make([][]byte, len(parts)) @@ -95,13 +105,17 @@ func KeyPathToKeys(path string) (keys [][]byte, err error) { hexPart := part[2:] key, err := hex.DecodeString(hexPart) if err != nil { - return nil, fmt.Errorf("decoding hex-encoded part #%d: /%s: %w", i, part, err) + return nil, ErrInvalidKey{ + Err: fmt.Errorf("decoding hex-encoded part #%d: /%s: %w", i, part, err), + } } keys[i] = key } else { key, err := url.PathUnescape(part) if err != nil { - return nil, fmt.Errorf("decoding url-encoded part #%d: /%s: %w", i, part, err) + return nil, ErrInvalidKey{ + Err: fmt.Errorf("decoding url-encoded part #%d: /%s: %w", i, part, err), + } } keys[i] = []byte(key) // TODO Test this with random bytes, I'm not sure that it works for arbitrary bytes... } diff --git a/crypto/merkle/proof_key_path_test.go b/crypto/merkle/proof_key_path_test.go index 0d6d3354d33..aadb3f76c80 100644 --- a/crypto/merkle/proof_key_path_test.go +++ b/crypto/merkle/proof_key_path_test.go @@ -2,7 +2,7 @@ package merkle import ( // it is ok to use math/rand here: we do not need a cryptographically secure random - // number generator here and we can run the tests a bit faster + // number generator here and we can run the tests a bit faster. crand "crypto/rand" "math/rand" "testing" @@ -35,7 +35,7 @@ func TestKeyPath(t *testing.T) { } res, err := KeyPathToKeys(path.String()) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, len(keys), len(res)) for i, key := range keys { diff --git a/crypto/merkle/proof_op.go b/crypto/merkle/proof_op.go index 62820303503..0457bf9345a 100644 --- a/crypto/merkle/proof_op.go +++ b/crypto/merkle/proof_op.go @@ -5,10 +5,12 @@ import ( "errors" "fmt" - cmtcrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" + cmtcrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" ) -//---------------------------------------- +var ErrKeyPathNotConsumed = errors.New("merkle: keypath not consumed") + +// ---------------------------------------- // ProofOp gets converted to an instance of ProofOperator: // ProofOperator is a layer for calculating intermediate Merkle roots @@ -19,56 +21,62 @@ import ( // ProofOp() encodes the ProofOperator in a generic way so it can later be // decoded with OpDecoder. type ProofOperator interface { - Run([][]byte) ([][]byte, error) + Run(leaves [][]byte) ([][]byte, error) GetKey() []byte ProofOp() cmtcrypto.ProofOp } -//---------------------------------------- +// ---------------------------------------- // Operations on a list of ProofOperators // ProofOperators is a slice of ProofOperator(s). // Each operator will be applied to the input value sequentially -// and the last Merkle root will be verified with already known data +// and the last Merkle root will be verified with already known data. type ProofOperators []ProofOperator func (poz ProofOperators) VerifyValue(root []byte, keypath string, value []byte) (err error) { return poz.Verify(root, keypath, [][]byte{value}) } -func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) (err error) { +func (poz ProofOperators) Verify(root []byte, keypath string, args [][]byte) error { keys, err := KeyPathToKeys(keypath) if err != nil { - return + return err } for i, op := range poz { key := op.GetKey() if len(key) != 0 { if len(keys) == 0 { - return fmt.Errorf("key path has insufficient # of parts: expected no more keys but got %+v", string(key)) + return ErrInvalidKey{ + Err: fmt.Errorf("key path has insufficient # of parts: expected no more keys but got %+v", string(key)), + } } lastKey := keys[len(keys)-1] if !bytes.Equal(lastKey, key) { - return fmt.Errorf("key mismatch on operation #%d: expected %+v but got %+v", i, string(lastKey), string(key)) + return ErrInvalidKey{ + Err: fmt.Errorf("key mismatch on operation #%d: expected %+v but got %+v", i, string(lastKey), string(key)), + } } keys = keys[:len(keys)-1] } args, err = op.Run(args) if err != nil { - return + return err } } if !bytes.Equal(root, args[0]) { - return fmt.Errorf("calculated root hash is invalid: expected %X but got %X", root, args[0]) + return ErrInvalidHash{ + Err: fmt.Errorf("root %x, want %x", args[0], root), + } } if len(keys) != 0 { - return errors.New("keypath not consumed all") + return ErrKeyPathNotConsumed } return nil } -//---------------------------------------- +// ---------------------------------------- // ProofRuntime - main entrypoint type OpDecoder func(cmtcrypto.ProofOp) (ProofOperator, error) @@ -94,7 +102,9 @@ func (prt *ProofRuntime) RegisterOpDecoder(typ string, dec OpDecoder) { func (prt *ProofRuntime) Decode(pop cmtcrypto.ProofOp) (ProofOperator, error) { decoder := prt.decoders[pop.Type] if decoder == nil { - return nil, fmt.Errorf("unrecognized proof type %v", pop.Type) + return nil, ErrInvalidProof{ + Err: fmt.Errorf("unrecognized proof type %v", pop.Type), + } } return decoder(pop) } @@ -104,7 +114,9 @@ func (prt *ProofRuntime) DecodeProof(proof *cmtcrypto.ProofOps) (ProofOperators, for _, pop := range proof.Ops { operator, err := prt.Decode(pop) if err != nil { - return nil, fmt.Errorf("decoding a proof operator: %w", err) + return nil, ErrInvalidProof{ + Err: fmt.Errorf("decoding a proof operator: %w", err), + } } poz = append(poz, operator) } @@ -115,7 +127,7 @@ func (prt *ProofRuntime) VerifyValue(proof *cmtcrypto.ProofOps, root []byte, key return prt.Verify(proof, root, keypath, [][]byte{value}) } -// TODO In the long run we'll need a method of classifcation of ops, +// TODO In the long run we'll need a method of classification of ops, // whether existence or absence or perhaps a third? func (prt *ProofRuntime) VerifyAbsence(proof *cmtcrypto.ProofOps, root []byte, keypath string) (err error) { return prt.Verify(proof, root, keypath, nil) @@ -124,7 +136,9 @@ func (prt *ProofRuntime) VerifyAbsence(proof *cmtcrypto.ProofOps, root []byte, k func (prt *ProofRuntime) Verify(proof *cmtcrypto.ProofOps, root []byte, keypath string, args [][]byte) (err error) { poz, err := prt.DecodeProof(proof) if err != nil { - return fmt.Errorf("decoding proof: %w", err) + return ErrInvalidProof{ + Err: fmt.Errorf("decoding proof: %w", err), + } } return poz.Verify(root, keypath, args) } @@ -135,5 +149,5 @@ func (prt *ProofRuntime) Verify(proof *cmtcrypto.ProofOps, root []byte, keypath func DefaultProofRuntime() (prt *ProofRuntime) { prt = NewProofRuntime() prt.RegisterOpDecoder(ProofOpValue, ValueOpDecoder) - return + return prt } diff --git a/crypto/merkle/proof_test.go b/crypto/merkle/proof_test.go index dc023aff3e2..f7ca2a55443 100644 --- a/crypto/merkle/proof_test.go +++ b/crypto/merkle/proof_test.go @@ -1,6 +1,7 @@ package merkle import ( + "bytes" "errors" "fmt" "testing" @@ -8,7 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmtcrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" + cmtcrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + "github.com/cometbft/cometbft/crypto/tmhash" ) const ProofOpDomino = "test:domino" @@ -62,7 +64,7 @@ func (dop DominoOp) GetKey() []byte { return []byte(dop.key) } -//---------------------------------------- +// ---------------------------------------- func TestProofOperators(t *testing.T) { var err error @@ -79,58 +81,58 @@ func TestProofOperators(t *testing.T) { // Good popz := ProofOperators([]ProofOperator{op1, op2, op3, op4}) err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.Nil(t, err) + require.NoError(t, err) err = popz.VerifyValue(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", bz("INPUT1")) - assert.Nil(t, err) + require.NoError(t, err) // BAD INPUT err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1_WRONG")}) - assert.NotNil(t, err) + require.Error(t, err) err = popz.VerifyValue(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", bz("INPUT1_WRONG")) - assert.NotNil(t, err) + require.Error(t, err) // BAD KEY 1 err = popz.Verify(bz("OUTPUT4"), "/KEY3/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD KEY 2 err = popz.Verify(bz("OUTPUT4"), "KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD KEY 3 err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1/", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD KEY 4 err = popz.Verify(bz("OUTPUT4"), "//KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD KEY 5 err = popz.Verify(bz("OUTPUT4"), "/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD OUTPUT 1 err = popz.Verify(bz("OUTPUT4_WRONG"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD OUTPUT 2 err = popz.Verify(bz(""), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD POPZ 1 popz = []ProofOperator{op1, op2, op4} err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD POPZ 2 popz = []ProofOperator{op4, op3, op2, op1} err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) // BAD POPZ 3 popz = []ProofOperator{} err = popz.Verify(bz("OUTPUT4"), "/KEY4/KEY2/KEY1", [][]byte{bz("INPUT1")}) - assert.NotNil(t, err) + require.Error(t, err) } func bz(s string) []byte { @@ -143,15 +145,21 @@ func TestProofValidateBasic(t *testing.T) { malleateProof func(*Proof) errStr string }{ - {"Good", func(sp *Proof) {}, ""}, - {"Negative Total", func(sp *Proof) { sp.Total = -1 }, "negative Total"}, - {"Negative Index", func(sp *Proof) { sp.Index = -1 }, "negative Index"}, - {"Invalid LeafHash", func(sp *Proof) { sp.LeafHash = make([]byte, 10) }, - "expected LeafHash size to be 32, got 10"}, - {"Too many Aunts", func(sp *Proof) { sp.Aunts = make([][]byte, MaxAunts+1) }, - "expected no more than 100 aunts, got 101"}, - {"Invalid Aunt", func(sp *Proof) { sp.Aunts[0] = make([]byte, 10) }, - "expected Aunts#0 size to be 32, got 10"}, + {"Good", func(_ *Proof) {}, ""}, + {"Negative Total", func(sp *Proof) { sp.Total = -1 }, "negative proof total"}, + {"Negative Index", func(sp *Proof) { sp.Index = -1 }, "negative proof index"}, + { + "Invalid LeafHash", func(sp *Proof) { sp.LeafHash = make([]byte, 10) }, + "leaf length 10, want 32", + }, + { + "Too many Aunts", func(sp *Proof) { sp.Aunts = make([][]byte, MaxAunts+1) }, + "maximum aunts length, 100, exceeded", + }, + { + "Invalid Aunt", func(sp *Proof) { sp.Aunts[0] = make([]byte, 10) }, + "aunt#0 hash length 10, want 32", + }, } for _, tc := range testCases { @@ -170,6 +178,7 @@ func TestProofValidateBasic(t *testing.T) { }) } } + func TestVoteProtobuf(t *testing.T) { _, proofs := ProofsFromByteSlices([][]byte{ []byte("apple"), @@ -198,3 +207,26 @@ func TestVoteProtobuf(t *testing.T) { } } } + +// TestVsa2022_100 verifies https://blog.verichains.io/p/vsa-2022-100-tendermint-forging-membership-proof +func TestVsa2022_100(t *testing.T) { + // a fake key-value pair and its hash + key := []byte{0x13} + value := []byte{0x37} + vhash := tmhash.Sum(value) + bz := new(bytes.Buffer) + _ = encodeByteSlice(bz, key) + _ = encodeByteSlice(bz, vhash) + kvhash := tmhash.Sum(append([]byte{0}, bz.Bytes()...)) + + // the malicious `op` + op := NewValueOp( + key, + &Proof{LeafHash: kvhash}, + ) + + // the nil root + var root []byte + + require.Error(t, ProofOperators{op}.Verify(root, "/"+string(key), [][]byte{value})) +} diff --git a/crypto/merkle/proof_value.go b/crypto/merkle/proof_value.go index 7c267e7efb8..dbb9600d9d5 100644 --- a/crypto/merkle/proof_value.go +++ b/crypto/merkle/proof_value.go @@ -2,10 +2,11 @@ package merkle import ( "bytes" + "errors" "fmt" + cmtcrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" "github.com/cometbft/cometbft/crypto/tmhash" - cmtcrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" ) const ProofOpValue = "simple:v" @@ -39,12 +40,16 @@ func NewValueOp(key []byte, proof *Proof) ValueOp { func ValueOpDecoder(pop cmtcrypto.ProofOp) (ProofOperator, error) { if pop.Type != ProofOpValue { - return nil, fmt.Errorf("unexpected ProofOp.Type; got %v, want %v", pop.Type, ProofOpValue) + return nil, ErrInvalidProof{ + Err: fmt.Errorf("unexpected ProofOp.Type; got %v, want %v", pop.Type, ProofOpValue), + } } var pbop cmtcrypto.ValueOp // a bit strange as we'll discard this, but it works. err := pbop.Unmarshal(pop.Data) if err != nil { - return nil, fmt.Errorf("decoding ProofOp.Data into ValueOp: %w", err) + return nil, ErrInvalidProof{ + Err: fmt.Errorf("decoding ProofOp.Data into ValueOp: %w", err), + } } sp, err := ProofFromProto(pbop.Proof) @@ -74,9 +79,13 @@ func (op ValueOp) String() string { return fmt.Sprintf("ValueOp{%v}", op.GetKey()) } +// ErrTooManyArgs is returned when the input to [ValueOp.Run] has length +// exceeding 1. +var ErrTooManyArgs = errors.New("merkle: len(args) != 1") + func (op ValueOp) Run(args [][]byte) ([][]byte, error) { if len(args) != 1 { - return nil, fmt.Errorf("expected 1 arg, got %v", len(args)) + return nil, ErrTooManyArgs } value := args[0] hasher := tmhash.New() @@ -90,11 +99,17 @@ func (op ValueOp) Run(args [][]byte) ([][]byte, error) { kvhash := leafHash(bz.Bytes()) if !bytes.Equal(kvhash, op.Proof.LeafHash) { - return nil, fmt.Errorf("leaf hash mismatch: want %X got %X", op.Proof.LeafHash, kvhash) + return nil, ErrInvalidHash{ + Err: fmt.Errorf("leaf %x, want %x", kvhash, op.Proof.LeafHash), + } } + rootHash, err := op.Proof.computeRootHash() + if err != nil { + return nil, err + } return [][]byte{ - op.Proof.ComputeRootHash(), + rootHash, }, nil } diff --git a/crypto/merkle/tree.go b/crypto/merkle/tree.go index 896b67c5952..467a8527c66 100644 --- a/crypto/merkle/tree.go +++ b/crypto/merkle/tree.go @@ -97,7 +97,7 @@ func HashFromByteSlicesIterative(input [][]byte) []byte { } } -// getSplitPoint returns the largest power of 2 less than length +// getSplitPoint returns the largest power of 2 less than length. func getSplitPoint(length int64) int64 { if length < 1 { panic("Trying to split a tree with size < 1") diff --git a/crypto/merkle/tree_test.go b/crypto/merkle/tree_test.go index 72f1402d657..6e389d331bd 100644 --- a/crypto/merkle/tree_test.go +++ b/crypto/merkle/tree_test.go @@ -7,10 +7,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmtrand "github.com/cometbft/cometbft/libs/rand" - . "github.com/cometbft/cometbft/libs/test" - "github.com/cometbft/cometbft/crypto/tmhash" + cmtrand "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/libs/test" ) type testItem []byte @@ -44,7 +43,6 @@ func TestHashFromByteSlices(t *testing.T) { } func TestProof(t *testing.T) { - // Try an empty proof first rootHash, proofs := ProofsFromByteSlices([][]byte{}) require.Equal(t, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", hex.EncodeToString(rootHash)) @@ -68,7 +66,7 @@ func TestProof(t *testing.T) { proof := proofs[i] // Check total/index - require.EqualValues(t, proof.Index, i, "Unmatched indicies: %d vs %d", proof.Index, i) + require.EqualValues(t, proof.Index, i, "Unmatched indices: %d vs %d", proof.Index, i) require.EqualValues(t, proof.Total, total, "Unmatched totals: %d vs %d", proof.Total, total) @@ -92,17 +90,16 @@ func TestProof(t *testing.T) { proof.Aunts = origAunts // Mutating the itemHash should make it fail. - err = proof.Verify(rootHash, MutateByteSlice(item)) + err = proof.Verify(rootHash, test.MutateByteSlice(item)) require.Error(t, err, "Expected verification to fail for mutated leaf hash") // Mutating the rootHash should make it fail. - err = proof.Verify(MutateByteSlice(rootHash), item) + err = proof.Verify(test.MutateByteSlice(rootHash), item) require.Error(t, err, "Expected verification to fail for mutated root hash") } } func TestHashAlternatives(t *testing.T) { - total := 100 items := make([][]byte, total) diff --git a/crypto/merkle/types.go b/crypto/merkle/types.go index 6a5c7e6a362..f95b96d8a5f 100644 --- a/crypto/merkle/types.go +++ b/crypto/merkle/types.go @@ -20,20 +20,20 @@ type Tree interface { Save() (hash []byte) Load(hash []byte) Copy() Tree - Iterate(func(key []byte, value []byte) (stop bool)) (stopped bool) + Iterate(fx func(key []byte, value []byte) (stop bool)) (stopped bool) IterateRange(start []byte, end []byte, ascending bool, fx func(key []byte, value []byte) (stop bool)) (stopped bool) } -//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- -// Uvarint length prefixed byteslice +// Uvarint length prefixed byteslice. func encodeByteSlice(w io.Writer, bz []byte) (err error) { var buf [binary.MaxVarintLen64]byte n := binary.PutUvarint(buf[:], uint64(len(bz))) _, err = w.Write(buf[0:n]) if err != nil { - return + return err } _, err = w.Write(bz) - return + return err } diff --git a/crypto/random.go b/crypto/random.go index 275fb1044f2..543b7c91133 100644 --- a/crypto/random.go +++ b/crypto/random.go @@ -6,7 +6,7 @@ import ( "io" ) -// This only uses the OS's randomness +// This only uses the OS's randomness. func randBytes(numBytes int) []byte { b := make([]byte, numBytes) _, err := crand.Read(b) @@ -16,7 +16,7 @@ func randBytes(numBytes int) []byte { return b } -// This only uses the OS's randomness +// This only uses the OS's randomness. func CRandBytes(numBytes int) []byte { return randBytes(numBytes) } diff --git a/crypto/secp256k1/secp256k1.go b/crypto/secp256k1/secp256k1.go index c6e31f1e794..2581c801a9a 100644 --- a/crypto/secp256k1/secp256k1.go +++ b/crypto/secp256k1/secp256k1.go @@ -16,7 +16,7 @@ import ( cmtjson "github.com/cometbft/cometbft/libs/json" ) -// ------------------------------------- +// -------------------------------------. const ( PrivKeyName = "tendermint/PrivKeySecp256k1" PubKeyName = "tendermint/PubKeySecp256k1" @@ -59,7 +59,7 @@ func (privKey PrivKey) Equals(other crypto.PrivKey) bool { return false } -func (privKey PrivKey) Type() string { +func (PrivKey) Type() string { return KeyType } @@ -137,7 +137,7 @@ func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { return sig[1:], nil } -//------------------------------------- +// ------------------------------------- var _ crypto.PubKey = PubKey{} @@ -152,7 +152,7 @@ const PubKeySize = 33 // This prefix is followed with the x-coordinate. type PubKey []byte -// Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) +// Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey)). func (pubKey PubKey) Address() crypto.Address { if len(pubKey) != PubKeySize { panic("length of pubkey is incorrect") @@ -183,7 +183,7 @@ func (pubKey PubKey) Equals(other crypto.PubKey) bool { return false } -func (pubKey PubKey) Type() string { +func (PubKey) Type() string { return KeyType } @@ -205,7 +205,7 @@ func (pubKey PubKey) VerifySignature(msg []byte, sigStr []byte) bool { // see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93 // Serialize() would negate S value if it is over half order. // Hence, if the signature is different after Serialize() if should be rejected. - var modifiedSignature, parseErr = ecdsa.ParseDERSignature(signature.Serialize()) + modifiedSignature, parseErr := ecdsa.ParseDERSignature(signature.Serialize()) if parseErr != nil { return false } diff --git a/crypto/secp256k1/secp256k1_internal_test.go b/crypto/secp256k1/secp256k1_internal_test.go index ae1f55e4926..7e1e1aa8cfd 100644 --- a/crypto/secp256k1/secp256k1_internal_test.go +++ b/crypto/secp256k1/secp256k1_internal_test.go @@ -5,14 +5,12 @@ import ( "math/big" "testing" - "github.com/stretchr/testify/require" - secp256k1 "github.com/btcsuite/btcd/btcec/v2" + "github.com/stretchr/testify/require" ) func Test_genPrivKey(t *testing.T) { - - empty := make([]byte, 32) + empty := make([]byte, 0, 32) oneB := big.NewInt(1).Bytes() onePadded := make([]byte, 32) copy(onePadded[32-len(oneB):32], oneB) @@ -39,8 +37,8 @@ func Test_genPrivKey(t *testing.T) { } got := genPrivKey(bytes.NewReader(tt.notSoRand)) fe := new(big.Int).SetBytes(got[:]) - require.True(t, fe.Cmp(secp256k1.S256().N) < 0) - require.True(t, fe.Sign() > 0) + require.Less(t, fe.Cmp(secp256k1.S256().N), 0, "expected %v to be less than %v", fe, secp256k1.S256().N) + require.Greater(t, fe.Sign(), 0) }) } } @@ -64,9 +62,9 @@ func TestSignatureVerificationAndRejectUpperS(t *testing.T) { require.True(t, pub.VerifySignature(msg, sigStr)) // malleate: - var S256 secp256k1.ModNScalar - S256.SetByteSlice(secp256k1.S256().N.Bytes()) - s.Negate().Add(&S256) + var s256 secp256k1.ModNScalar + s256.SetByteSlice(secp256k1.S256().N.Bytes()) + s.Negate().Add(&s256) require.True(t, s.IsOverHalfOrder()) rBytes := r.Bytes() diff --git a/crypto/secp256k1/secp256k1_test.go b/crypto/secp256k1/secp256k1_test.go index 195d9dde709..758a33e93a7 100644 --- a/crypto/secp256k1/secp256k1_test.go +++ b/crypto/secp256k1/secp256k1_test.go @@ -5,14 +5,13 @@ import ( "math/big" "testing" + underlyingsecp256k1 "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil/base58" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/secp256k1" - - underlyingSecp256k1 "github.com/btcsuite/btcd/btcec/v2" ) type keyData struct { @@ -54,7 +53,7 @@ func TestSignAndValidateSecp256k1(t *testing.T) { msg := crypto.CRandBytes(128) sig, err := privKey.Sign(msg) - require.Nil(t, err) + require.NoError(t, err) assert.True(t, pubKey.VerifySignature(msg, sig)) @@ -75,7 +74,7 @@ func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { // This function creates a private and public key in the underlying libraries format. // The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes - priv, _ := underlyingSecp256k1.PrivKeyFromBytes(privKeyBytes[:]) + priv, _ := underlyingsecp256k1.PrivKeyFromBytes(privKeyBytes[:]) // this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes, // pads the bytes from the left with zero bytes. Therefore these two functions composed // result in the identity function on privKeyBytes, hence the following equality check @@ -86,8 +85,8 @@ func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { } func TestGenPrivKeySecp256k1(t *testing.T) { - // curve oder N - N := underlyingSecp256k1.S256().N + // curve order N + n := underlyingsecp256k1.S256().N tests := []struct { name string secret []byte @@ -109,8 +108,8 @@ func TestGenPrivKeySecp256k1(t *testing.T) { require.NotNil(t, gotPrivKey) // interpret as a big.Int and make sure it is a valid field element: fe := new(big.Int).SetBytes(gotPrivKey[:]) - require.True(t, fe.Cmp(N) < 0) - require.True(t, fe.Sign() > 0) + require.Less(t, fe.Cmp(n), 0) + require.Greater(t, fe.Sign(), 0) }) } } diff --git a/crypto/sr25519/batch.go b/crypto/sr25519/batch.go index 6c07747d68d..05b71dc6334 100644 --- a/crypto/sr25519/batch.go +++ b/crypto/sr25519/batch.go @@ -1,6 +1,7 @@ package sr25519 import ( + "errors" "fmt" "github.com/oasisprotocol/curve25519-voi/primitives/sr25519" @@ -10,6 +11,36 @@ import ( var _ crypto.BatchVerifier = &BatchVerifier{} +// ErrInvalidKey represents an error that could occur as a result of +// using an invalid private or public key. It wraps errors that could +// arise due to failures in serialization or the use of an incorrect +// key, i.e., uninitialised or not sr25519. +type ErrInvalidKey struct { + Err error +} + +func (e ErrInvalidKey) Error() string { + return fmt.Sprintf("sr25519: invalid public key: %v", e.Err) +} + +func (e ErrInvalidKey) Unwrap() error { + return e.Err +} + +// ErrInvalidSignature wraps an error that could occur as a result of +// generating an invalid signature. +type ErrInvalidSignature struct { + Err error +} + +func (e ErrInvalidSignature) Error() string { + return fmt.Sprintf("sr25519: invalid signature: %v", e.Err) +} + +func (e ErrInvalidSignature) Unwrap() error { + return e.Err +} + // BatchVerifier implements batch verification for sr25519. type BatchVerifier struct { *sr25519.BatchVerifier @@ -22,17 +53,17 @@ func NewBatchVerifier() crypto.BatchVerifier { func (b *BatchVerifier) Add(key crypto.PubKey, msg, signature []byte) error { pk, ok := key.(PubKey) if !ok { - return fmt.Errorf("sr25519: pubkey is not sr25519") + return ErrInvalidKey{Err: errors.New("sr25519: pubkey is not sr25519")} } var srpk sr25519.PublicKey if err := srpk.UnmarshalBinary(pk); err != nil { - return fmt.Errorf("sr25519: invalid public key: %w", err) + return ErrInvalidKey{Err: err} } var sig sr25519.Signature if err := sig.UnmarshalBinary(signature); err != nil { - return fmt.Errorf("sr25519: unable to decode signature: %w", err) + return ErrInvalidSignature{Err: err} } st := signingCtx.NewTranscriptBytes(msg) diff --git a/crypto/sr25519/privkey.go b/crypto/sr25519/privkey.go index 9bea7d3eeb3..1013520c5e4 100644 --- a/crypto/sr25519/privkey.go +++ b/crypto/sr25519/privkey.go @@ -2,6 +2,7 @@ package sr25519 import ( "encoding/json" + "errors" "fmt" "io" @@ -40,19 +41,25 @@ func (privKey PrivKey) Bytes() []byte { // Sign produces a signature on the provided message. func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { if privKey.kp == nil { - return nil, fmt.Errorf("sr25519: uninitialized private key") + return nil, ErrInvalidKey{ + Err: errors.New("sr25519: uninitialized private key"), + } } st := signingCtx.NewTranscriptBytes(msg) sig, err := privKey.kp.Sign(crypto.CReader(), st) if err != nil { - return nil, fmt.Errorf("sr25519: failed to sign message: %w", err) + return nil, ErrInvalidSignature{ + Err: fmt.Errorf("sr25519: failed to sign message: %w", err), + } } sigBytes, err := sig.MarshalBinary() if err != nil { - return nil, fmt.Errorf("sr25519: failed to serialize signature: %w", err) + return nil, ErrInvalidSignature{ + Err: fmt.Errorf("sr25519: failed to serialize signature: %w", err), + } } return sigBytes, nil @@ -81,7 +88,7 @@ func (privKey PrivKey) Equals(other crypto.PrivKey) bool { return false } -func (privKey PrivKey) Type() string { +func (PrivKey) Type() string { return KeyType } @@ -104,7 +111,9 @@ func (privKey *PrivKey) UnmarshalJSON(data []byte) error { var b []byte if err := json.Unmarshal(data, &b); err != nil { - return fmt.Errorf("sr25519: failed to deserialize JSON: %w", err) + return ErrInvalidKey{ + Err: fmt.Errorf("sr25519: failed to deserialize JSON: %w", err), + } } if len(b) == 0 { return nil diff --git a/crypto/sr25519/pubkey.go b/crypto/sr25519/pubkey.go index b25718f9a43..b6eca1acd4f 100644 --- a/crypto/sr25519/pubkey.go +++ b/crypto/sr25519/pubkey.go @@ -65,6 +65,6 @@ func (pubKey PubKey) String() string { return fmt.Sprintf("PubKeySr25519{%X}", []byte(pubKey)) } -func (pubKey PubKey) Type() string { +func (PubKey) Type() string { return KeyType } diff --git a/crypto/sr25519/sr25519_test.go b/crypto/sr25519/sr25519_test.go index b2437be797f..baca16bf2ad 100644 --- a/crypto/sr25519/sr25519_test.go +++ b/crypto/sr25519/sr25519_test.go @@ -18,7 +18,7 @@ func TestSignAndValidateSr25519(t *testing.T) { msg := crypto.CRandBytes(128) sig, err := privKey.Sign(msg) - require.Nil(t, err) + require.NoError(t, err) // Test the signature assert.True(t, pubKey.VerifySignature(msg, sig)) diff --git a/crypto/tmhash/bench_test.go b/crypto/tmhash/bench_test.go new file mode 100644 index 00000000000..1165ec9fdd7 --- /dev/null +++ b/crypto/tmhash/bench_test.go @@ -0,0 +1,52 @@ +package tmhash + +import ( + "bytes" + "crypto/sha256" + "strings" + "testing" +) + +var sink any + +var manySlices = []struct { + name string + in [][]byte + want [32]byte +}{ + { + name: "all empty", + in: [][]byte{[]byte(""), []byte("")}, + want: sha256.Sum256(nil), + }, + { + name: "ax6", + in: [][]byte{[]byte("aaaa"), []byte("😎"), []byte("aaaa")}, + want: sha256.Sum256([]byte("aaaa😎aaaa")), + }, + { + name: "composite joined", + in: [][]byte{bytes.Repeat([]byte("a"), 1<<10), []byte("AA"), bytes.Repeat([]byte("z"), 100)}, + want: sha256.Sum256([]byte(strings.Repeat("a", 1<<10) + "AA" + strings.Repeat("z", 100))), + }, +} + +func BenchmarkSHA256Many(b *testing.B) { + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + for _, tt := range manySlices { + got := SumMany(tt.in[0], tt.in[1:]...) + if !bytes.Equal(got, tt.want[:]) { + b.Fatalf("Outward checksum mismatch for %q\n\tGot: %x\n\tWant: %x", tt.name, got, tt.want) + } + sink = got + } + } + + if sink == nil { + b.Fatal("Benchmark did not run!") + } + + sink = nil +} diff --git a/crypto/tmhash/hash.go b/crypto/tmhash/hash.go index f9b9582420d..5313bf1ccf1 100644 --- a/crypto/tmhash/hash.go +++ b/crypto/tmhash/hash.go @@ -21,7 +21,19 @@ func Sum(bz []byte) []byte { return h[:] } -//------------------------------------------------------------- +// SumMany takes at least 1 byteslice along with a variadic +// number of other byteslices and produces the SHA256 sum from +// hashing them as if they were 1 joined slice. +func SumMany(data []byte, rest ...[]byte) []byte { + h := sha256.New() + h.Write(data) + for _, data := range rest { + h.Write(data) + } + return h.Sum(nil) +} + +// ------------------------------------------------------------- const ( TruncatedSize = 20 @@ -34,6 +46,7 @@ type sha256trunc struct { func (h sha256trunc) Write(p []byte) (n int, err error) { return h.sha256.Write(p) } + func (h sha256trunc) Sum(b []byte) []byte { shasum := h.sha256.Sum(b) return shasum[:TruncatedSize] @@ -43,7 +56,7 @@ func (h sha256trunc) Reset() { h.sha256.Reset() } -func (h sha256trunc) Size() int { +func (sha256trunc) Size() int { return TruncatedSize } diff --git a/crypto/xchacha20poly1305/xchachapoly.go b/crypto/xchacha20poly1305/xchachapoly.go index 2578520a5a0..763d4dbc414 100644 --- a/crypto/xchacha20poly1305/xchachapoly.go +++ b/crypto/xchacha20poly1305/xchachapoly.go @@ -6,12 +6,11 @@ import ( "crypto/cipher" "encoding/binary" "errors" - "fmt" "golang.org/x/crypto/chacha20poly1305" ) -// Implements crypto.AEAD +// Implements crypto.AEAD. type xchacha20poly1305 struct { key [KeySize]byte } @@ -21,12 +20,12 @@ const ( KeySize = 32 // NonceSize is the size of the nonce used with this AEAD, in bytes. NonceSize = 24 - // TagSize is the size added from poly1305 + // TagSize is the size added from poly1305. TagSize = 16 - // MaxPlaintextSize is the max size that can be passed into a single call of Seal + // MaxPlaintextSize is the max size that can be passed into a single call of Seal. MaxPlaintextSize = (1 << 38) - 64 // MaxCiphertextSize is the max size that can be passed into a single call of Open, - // this differs from plaintext size due to the tag + // this differs from plaintext size due to the tag. MaxCiphertextSize = (1 << 38) - 48 // sigma are constants used in xchacha. @@ -37,21 +36,27 @@ const ( sigma3 = uint32(0x6b206574) ) -// New returns a new xchachapoly1305 AEAD +var ( + ErrInvalidKeyLen = errors.New("xchacha20poly1305: bad key length") + ErrInvalidNonceLen = errors.New("xchacha20poly1305: bad nonce length") + ErrInvalidCipherTextLen = errors.New("xchacha20poly1305: ciphertext too large") +) + +// New returns a new xchachapoly1305 AEAD. func New(key []byte) (cipher.AEAD, error) { if len(key) != KeySize { - return nil, errors.New("xchacha20poly1305: bad key length") + return nil, ErrInvalidKeyLen } ret := new(xchacha20poly1305) copy(ret.key[:], key) return ret, nil } -func (c *xchacha20poly1305) NonceSize() int { +func (*xchacha20poly1305) NonceSize() int { return NonceSize } -func (c *xchacha20poly1305) Overhead() int { +func (*xchacha20poly1305) Overhead() int { return TagSize } @@ -81,10 +86,10 @@ func (c *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) [ func (c *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { if len(nonce) != NonceSize { - return nil, fmt.Errorf("xchacha20poly1305: bad nonce length passed to Open") + return nil, ErrInvalidNonceLen } if uint64(len(ciphertext)) > MaxCiphertextSize { - return nil, fmt.Errorf("xchacha20poly1305: ciphertext too large") + return nil, ErrInvalidCipherTextLen } var subKey [KeySize]byte var hNonce [16]byte diff --git a/crypto/xsalsa20symmetric/symmetric.go b/crypto/xsalsa20symmetric/symmetric.go index 20fb42ce295..cfb0466af6e 100644 --- a/crypto/xsalsa20symmetric/symmetric.go +++ b/crypto/xsalsa20symmetric/symmetric.go @@ -11,8 +11,15 @@ import ( // TODO, make this into a struct that implements crypto.Symmetric. -const nonceLen = 24 -const secretLen = 32 +const ( + nonceLen = 24 + secretLen = 32 +) + +var ( + ErrInvalidCiphertextLen = errors.New("xsalsa20symmetric: ciphertext is too short") + ErrCiphertextDecryption = errors.New("xsalsa20symmetric: ciphertext decryption failed") +) // secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) // The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. @@ -38,7 +45,7 @@ func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err e panic(fmt.Sprintf("Secret must be 32 bytes long, got len %v", len(secret))) } if len(ciphertext) <= secretbox.Overhead+nonceLen { - return nil, errors.New("ciphertext is too short") + return nil, ErrInvalidCiphertextLen } nonce := ciphertext[:nonceLen] nonceArr := [nonceLen]byte{} @@ -48,7 +55,7 @@ func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err e plaintext = make([]byte, len(ciphertext)-nonceLen-secretbox.Overhead) _, ok := secretbox.Open(plaintext[:0], ciphertext[nonceLen:], &nonceArr, &secretArr) if !ok { - return nil, errors.New("ciphertext decryption failed") + return nil, ErrCiphertextDecryption } return plaintext, nil } diff --git a/crypto/xsalsa20symmetric/symmetric_test.go b/crypto/xsalsa20symmetric/symmetric_test.go index 7f0da23b391..d252803c02d 100644 --- a/crypto/xsalsa20symmetric/symmetric_test.go +++ b/crypto/xsalsa20symmetric/symmetric_test.go @@ -5,25 +5,22 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/crypto/bcrypt" "github.com/cometbft/cometbft/crypto" ) func TestSimple(t *testing.T) { - plaintext := []byte("sometext") secret := []byte("somesecretoflengththirtytwo===32") ciphertext := EncryptSymmetric(plaintext, secret) plaintext2, err := DecryptSymmetric(ciphertext, secret) - require.Nil(t, err, "%+v", err) + require.NoError(t, err, "%+v", err) assert.Equal(t, plaintext, plaintext2) } func TestSimpleWithKDF(t *testing.T) { - plaintext := []byte("sometext") secretPass := []byte("somesecret") secret, err := bcrypt.GenerateFromPassword(secretPass, 12) @@ -35,6 +32,6 @@ func TestSimpleWithKDF(t *testing.T) { ciphertext := EncryptSymmetric(plaintext, secret) plaintext2, err := DecryptSymmetric(ciphertext, secret) - require.Nil(t, err, "%+v", err) + require.NoError(t, err, "%+v", err) assert.Equal(t, plaintext, plaintext2) } diff --git a/docker-compose.yml b/docker-compose.yml index ee582871976..825dccac171 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,7 @@ services: image: "cometbft/localnode" ports: - "26656-26657:26656-26657" + - "26670:26660" environment: - ID=0 - LOG=${LOG:-cometbft.log} @@ -20,6 +21,7 @@ services: image: "cometbft/localnode" ports: - "26659-26660:26656-26657" + - "26671:26660" environment: - ID=1 - LOG=${LOG:-cometbft.log} @@ -37,6 +39,7 @@ services: - LOG=${LOG:-cometbft.log} ports: - "26661-26662:26656-26657" + - "26672:26660" volumes: - ./build:/cometbft:Z networks: @@ -51,6 +54,7 @@ services: - LOG=${LOG:-cometbft.log} ports: - "26663-26664:26656-26657" + - "26673:26660" volumes: - ./build:/cometbft:Z networks: @@ -63,4 +67,4 @@ networks: ipam: driver: default config: - - subnet: 192.167.10.0/16 + - subnet: 192.167.0.0/16 diff --git a/docs/README.md b/docs/README.md index c13ca2f4ca7..1560a757464 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,14 +16,14 @@ 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/README.md#what-is-cometbft.md). +For more background, see [What is CometBFT?](./explanation/introduction/README.md). -To get started quickly with an example application, see the [quick start guide](guides/quick-start.md). +To get started quickly with an example application, see the [quick start guide](tutorials/quick-start.md). To learn about application development on CometBFT, see the [Application Blockchain Interface](https://github.com/cometbft/cometbft/tree/main/spec/abci). For more details on using CometBFT, see the respective documentation for -[CometBFT internals](core/), [benchmarking and monitoring](tools/), and [network deployments](networks/). +[CometBFT internals](explanation/core/), [benchmarking and monitoring](guides/tools/), and [network deployments](guides/networks/). ## Contribute diff --git a/docs/app-dev/README.md b/docs/app-dev/README.md deleted file mode 100644 index aff0a570ca2..00000000000 --- a/docs/app-dev/README.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -order: false -parent: - order: 3 ---- - -# Apps - -- [Using ABCI-CLI](./abci-cli.md) -- [Getting Started](./getting-started.md) -- [Indexing transactions](./indexing-transactions.md) -- [Application Architecture Guide](./app-architecture.md) diff --git a/docs/architecture/tendermint-core/README.md b/docs/architecture/tendermint-core/README.md deleted file mode 100644 index d1d8c276f34..00000000000 --- a/docs/architecture/tendermint-core/README.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -order: 1 -parent: - order: false ---- - -# Tendermint Core Architecture Decision Records (ADR) - -Here we record all high-level architecture decisions in the Tendermint Core -project. All implemented ADRs in this list naturally affect CometBFT, since -CometBFT is a fork of Tendermint Core as of December 2022. - -This list is currently frozen and kept for reference purposes. To add new ADRs, -please do so for CometBFT [here](../). - -## Table of Contents - -### Implemented - -- [ADR-001: Logging](./adr-001-logging.md) -- [ADR-002: Event-Subscription](./adr-002-event-subscription.md) -- [ADR-003: ABCI-APP-RPC](./adr-003-abci-app-rpc.md) -- [ADR-004: Historical-Validators](./adr-004-historical-validators.md) -- [ADR-005: Consensus-Params](./adr-005-consensus-params.md) -- [ADR-008: Priv-Validator](./adr-008-priv-validator.md) -- [ADR-009: ABCI-Design](./adr-009-ABCI-design.md) -- [ADR-010: Crypto-Changes](./adr-010-crypto-changes.md) -- [ADR-011: Monitoring](./adr-011-monitoring.md) -- [ADR-014: Secp-Malleability](./adr-014-secp-malleability.md) -- [ADR-015: Crypto-Encoding](./adr-015-crypto-encoding.md) -- [ADR-016: Protocol-Versions](./adr-016-protocol-versions.md) -- [ADR-017: Chain-Versions](./adr-017-chain-versions.md) -- [ADR-018: ABCI-Validators](./adr-018-ABCI-Validators.md) -- [ADR-019: Multisigs](./adr-019-multisigs.md) -- [ADR-020: Block-Size](./adr-020-block-size.md) -- [ADR-021: ABCI-Events](./adr-021-abci-events.md) -- [ADR-025: Commit](./adr-025-commit.md) -- [ADR-026: General-Merkle-Proof](./adr-026-general-merkle-proof.md) -- [ADR-033: Pubsub](./adr-033-pubsub.md) -- [ADR-034: Priv-Validator-File-Structure](./adr-034-priv-validator-file-structure.md) -- [ADR-043: Blockchain-RiRi-Org](./adr-043-blockchain-riri-org.md) -- [ADR-044: Lite-Client-With-Weak-Subjectivity](./adr-044-lite-client-with-weak-subjectivity.md) -- [ADR-046: Light-Client-Implementation](./adr-046-light-client-implementation.md) -- [ADR-047: Handling-Evidence-From-Light-Client](./adr-047-handling-evidence-from-light-client.md) -- [ADR-051: Double-Signing-Risk-Reduction](./adr-051-double-signing-risk-reduction.md) -- [ADR-052: Tendermint-Mode](./adr-052-tendermint-mode.md) -- [ADR-053: State-Sync-Prototype](./adr-053-state-sync-prototype.md) -- [ADR-054: Crypto-Encoding-2](./adr-054-crypto-encoding-2.md) -- [ADR-055: Protobuf-Design](./adr-055-protobuf-design.md) -- [ADR-056: Light-Client-Amnesia-Attacks](./adr-056-light-client-amnesia-attacks.md) -- [ADR-059: Evidence-Composition-and-Lifecycle](./adr-059-evidence-composition-and-lifecycle.md) -- [ADR-065: Custom Event Indexing](./adr-065-custom-event-indexing.md) -- [ADR-066: E2E-Testing](./adr-066-e2e-testing.md) -- [ADR-072: Restore Requests for Comments](./adr-072-request-for-comments.md) -- [ADR-076: Combine Spec and Tendermint Repositories](./adr-076-combine-spec-repo.md) -- [ADR-077: Configurable Block Retention](./adr-077-block-retention.md) -- [ADR-078: Non-zero Genesis](./adr-078-nonzero-genesis.md) - -### Accepted - -- [ADR-006: Trust-Metric](./adr-006-trust-metric.md) -- [ADR-024: Sign-Bytes](./adr-024-sign-bytes.md) -- [ADR-039: Peer-Behaviour](./adr-039-peer-behaviour.md) -- [ADR-063: Privval-gRPC](./adr-063-privval-grpc.md) -- [ADR-067: Mempool Refactor](./adr-067-mempool-refactor.md) -- [ADR-071: Proposer-Based Timestamps](./adr-071-proposer-based-timestamps.md) -- [ADR-075: RPC Event Subscription Interface](./adr-075-rpc-subscription.md) -- [ADR-079: Ed25519 Verification](./adr-079-ed25519-verification.md) -- [ADR-081: Protocol Buffers Management](./adr-081-protobuf-mgmt.md) - -### Deprecated - -- [ADR-035: Documentation](./adr-035-documentation.md) - -### Rejected - -- [ADR-023: ABCI-Propose-tx](./adr-023-ABCI-propose-tx.md) -- [ADR-029: Check-Tx-Consensus](./adr-029-check-tx-consensus.md) -- [ADR-058: Event-Hashing](./adr-058-event-hashing.md) - -### Proposed - -- [ADR-007: Trust-Metric-Usage](./adr-007-trust-metric-usage.md) -- [ADR-012: Peer-Transport](./adr-012-peer-transport.md) -- [ADR-013: Symmetric-Crypto](./adr-013-symmetric-crypto.md) -- [ADR-022: ABCI-Errors](./adr-022-abci-errors.md) -- [ADR-030: Consensus-Refactor](./adr-030-consensus-refactor.md) -- [ADR-036: Empty Blocks via ABCI](./adr-036-empty-blocks-abci.md) -- [ADR-037: Deliver-Block](./adr-037-deliver-block.md) -- [ADR-038: Non-Zero-Start-Height](./adr-038-non-zero-start-height.md) -- [ADR-040: Blockchain Reactor Refactor](./adr-040-blockchain-reactor-refactor.md) -- [ADR-041: Proposer-Selection-via-ABCI](./adr-041-proposer-selection-via-abci.md) -- [ADR-042: State Sync Design](./adr-042-state-sync.md) -- [ADR-045: ABCI-Evidence](./adr-045-abci-evidence.md) -- [ADR-050: Improved Trusted Peering](./adr-050-improved-trusted-peering.md) -- [ADR-057: RPC](./adr-057-RPC.md) -- [ADR-060: Go-API-Stability](./adr-060-go-api-stability.md) -- [ADR-061: P2P-Refactor-Scope](./adr-061-p2p-refactor-scope.md) -- [ADR-062: P2P-Architecture](./adr-062-p2p-architecture.md) -- [ADR-064: Batch Verification](./adr-064-batch-verification.md) -- [ADR-068: Reverse-Sync](./adr-068-reverse-sync.md) -- [ADR-069: Node Initialization](./adr-069-flexible-node-initialization.md) -- [ADR-073: Adopt LibP2P](./adr-073-libp2p.md) -- [ADR-074: Migrate Timeout Parameters to Consensus Parameters](./adr-074-timeout-params.md) -- [ADR-080: Reverse Sync](./adr-080-reverse-sync.md) diff --git a/docs/core/README.md b/docs/core/README.md deleted file mode 100644 index 26cb7a40607..00000000000 --- a/docs/core/README.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -order: 1 -parent: - title: Core - order: 4 ---- - -# Overview - -This section dives into the internals of the CometBFT's implementation. - -- [Using CometBFT](./using-cometbft.md) -- [Configuration](./configuration.md) -- [Running in Production](./running-in-production.md) -- [Metrics](./metrics.md) -- [Validators](./validators.md) -- [Subscribing to events](./subscription.md) -- [Block Structure](./block-structure.md) -- [RPC](./rpc.md) -- [Block Sync](./block-sync.md) -- [State Sync](./state-sync.md) -- [Mempool](./mempool.md) -- [Light Client](./light-client.md) diff --git a/docs/core/block-structure.md b/docs/core/block-structure.md deleted file mode 100644 index a422aa9cd9a..00000000000 --- a/docs/core/block-structure.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -order: 8 ---- - -# Block Structure - -The CometBFT consensus engine records all agreements by a -supermajority of nodes into a blockchain, which is replicated among all -nodes. This blockchain is accessible via various RPC endpoints, mainly -`/block?height=` to get the full block, as well as -`/blockchain?minHeight=_&maxHeight=_` to get a list of headers. But what -exactly is stored in these blocks? - -The [specification](https://github.com/cometbft/cometbft/blob/main/spec/core/data_structures.md) contains a detailed description of each component - that's the best place to get started. - -To dig deeper, check out the [types package documentation](https://godoc.org/github.com/cometbft/cometbft/types). diff --git a/docs/core/mempool.md b/docs/core/mempool.md deleted file mode 100644 index 8dd96878196..00000000000 --- a/docs/core/mempool.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -order: 12 ---- - -# Mempool - -## Transaction ordering - -Currently, there's no ordering of transactions other than the order they've -arrived (via RPC or from other nodes). - -So the only way to specify the order is to send them to a single node. - -valA: - -- `tx1` -- `tx2` -- `tx3` - -If the transactions are split up across different nodes, there's no way to -ensure they are processed in the expected order. - -valA: - -- `tx1` -- `tx2` - -valB: - -- `tx3` - -If valB is the proposer, the order might be: - -- `tx3` -- `tx1` -- `tx2` - -If valA is the proposer, the order might be: - -- `tx1` -- `tx2` -- `tx3` - -That said, if the transactions contain some internal value, like an -order/nonce/sequence number, the application can reject transactions that are -out of order. So if a node receives `tx3`, then `tx1`, it can reject `tx3` and then -accept `tx1`. The sender can then retry sending `tx3`, which should probably be -rejected until the node has seen `tx2`. diff --git a/docs/explanation/README.md b/docs/explanation/README.md new file mode 100644 index 00000000000..905a72eeff9 --- /dev/null +++ b/docs/explanation/README.md @@ -0,0 +1,27 @@ +--- +order: 1 +title: CometBFT Explained +description: Explanation +parent: + order: 1 +--- + +# CometBFT Explained + +## The comprehensive guide to understanding CometBFT + +This section is designed to provide you with a comprehensive understanding of the core +concepts that underpin CometBFT. You will delve into the block structure, explore the +light client, gain insights into mempool, and learn about state sync, among other essential +concepts. + +This section also includes information about the new Data Companion gRPC endpoints +that allow external applications to access data from the node and manage data pruning. +This allows storage optimization and node performance by keeping only necessary data. + +By the end of this section, you will have a firm grasp of the fundamental +principles that make CometBFT a powerful technology in the realm of distributed systems. + +- [Introduction](./introduction/README.md) +- [Core Concepts](./core/README.md) +- [Data Companion](./data-companion/README.md) diff --git a/docs/explanation/core/README.md b/docs/explanation/core/README.md new file mode 100644 index 00000000000..2512adc18be --- /dev/null +++ b/docs/explanation/core/README.md @@ -0,0 +1,23 @@ +--- +order: 1 +parent: + title: Core + order: 4 +--- + +# Overview + +This section dives into the internals of the CometBFT's implementation. + +- [Using CometBFT](using-cometbft.md) +- [Configuration](configuration.md) +- [Running in Production](running-in-production.md) +- [Metrics](metrics.md) +- [Validators](validators.md) +- [Subscribing to events](subscription.md) +- [Block Structure](block-structure.md) +- [RPC](rpc.md) +- [Block Sync](block-sync.md) +- [State Sync](state-sync.md) +- [Mempool](mempool.md) +- [Light Client](light-client.md) diff --git a/docs/explanation/core/block-structure.md b/docs/explanation/core/block-structure.md new file mode 100644 index 00000000000..dc6819be20a --- /dev/null +++ b/docs/explanation/core/block-structure.md @@ -0,0 +1,19 @@ +--- +order: 8 +--- + +# Block Structure + +The CometBFT consensus engine records all agreements by a 2/3+ of nodes +into a blockchain, which is replicated among all nodes. This blockchain is +accessible via various RPC endpoints, mainly `/block?height=` to get the full +block, as well as `/blockchain?minHeight=_&maxHeight=_` to get a list of +headers. But what exactly is stored in these blocks? + +The [specification][data_structures] contains a detailed description of each +component - that's the best place to get started. + +To dig deeper, check out the [types package documentation][types]. + +[data_structures]: https://github.com/cometbft/cometbft/blob/main/spec/core/data_structures.md +[types]: https://pkg.go.dev/github.com/cometbft/cometbft/types diff --git a/docs/core/block-sync.md b/docs/explanation/core/block-sync.md similarity index 100% rename from docs/core/block-sync.md rename to docs/explanation/core/block-sync.md diff --git a/docs/core/configuration.md b/docs/explanation/core/configuration.md similarity index 51% rename from docs/core/configuration.md rename to docs/explanation/core/configuration.md index 63c8e723ea8..2edc95b1155 100644 --- a/docs/core/configuration.md +++ b/docs/explanation/core/configuration.md @@ -11,7 +11,7 @@ further below are intended for advance power users. ## Options -The default configuration file create by `cometbft init` has all +The default configuration file created by `cometbft init` has all the parameters set with their default values. It will look something like the file below, however, double check by inspecting the `config.toml` created with your version of `cometbft` installed: @@ -25,6 +25,10 @@ like the file below, however, double check by inspecting the # "$HOME/.cometbft" by default, but could be changed via $CMTHOME env variable # or --home cmd flag. +# The version of the CometBFT binary that created or +# last modified the config file. Do not modify this. +version = "1.0.0-dev" + ####################################################################### ### Main Base Config Options ### ####################################################################### @@ -34,34 +38,34 @@ like the file below, however, double check by inspecting the proxy_app = "tcp://127.0.0.1:26658" # A custom human readable name for this node -moniker = "anonymous" +moniker = "thinkpad" -# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb -# * goleveldb (github.com/syndtr/goleveldb - most popular implementation) -# - pure go +# Database backend: goleveldb | rocksdb | badgerdb | pebbledb +# * goleveldb (github.com/syndtr/goleveldb) +# - UNMAINTAINED # - stable -# * cleveldb (uses levigo wrapper) -# - fast -# - requires gcc -# - use cleveldb build tag (go build -tags cleveldb) -# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt) -# - EXPERIMENTAL -# - may be faster is some use-cases (random reads - indexer) -# - use boltdb build tag (go build -tags boltdb) -# * rocksdb (uses github.com/tecbot/gorocksdb) +# - pure go +# * rocksdb (uses github.com/linxGnu/grocksdb) # - EXPERIMENTAL # - requires gcc # - use rocksdb build tag (go build -tags rocksdb) # * badgerdb (uses github.com/dgraph-io/badger) # - EXPERIMENTAL +# - stable +# - pure go # - use badgerdb build tag (go build -tags badgerdb) +# * pebbledb (uses github.com/cockroachdb/pebble) +# - EXPERIMENTAL +# - stable +# - pure go +# - use pebbledb build tag (go build -tags pebbledb) db_backend = "goleveldb" # Database directory db_dir = "data" # Output level for logging, including package level options -log_level = "main:info,state:info,statesync:info,*:error" +log_level = "info" # Output format: 'plain' (colored text) or 'json' log_format = "plain" @@ -115,24 +119,10 @@ cors_allowed_methods = ["HEAD", "GET", "POST", ] # A list of non simple headers the client is allowed to use with cross-domain requests cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ] -# TCP or UNIX socket address for the gRPC server to listen on -# NOTE: This server only supports /broadcast_tx_commit -grpc_laddr = "" - -# Maximum number of simultaneous connections. -# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections -# If you want to accept a larger number than the default, make sure -# you increase your OS limits. -# 0 - unlimited. -# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} -# 1024 - 40 - 10 - 50 = 924 = ~900 -grpc_max_open_connections = 900 - # Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool unsafe = false # Maximum number of simultaneous connections (including WebSocket). -# Does not include gRPC connections. See grpc_max_open_connections # If you want to accept a larger number than the default, make sure # you increase your OS limits. # 0 - unlimited. @@ -140,16 +130,43 @@ unsafe = false # 1024 - 40 - 10 - 50 = 924 = ~900 max_open_connections = 900 -# Maximum number of unique clientIDs that can /subscribe +# Maximum number of unique clientIDs that can /subscribe. # If you're using /broadcast_tx_commit, set to the estimated maximum number # of broadcast_tx_commit calls per block. max_subscription_clients = 100 -# Maximum number of unique queries a given client can /subscribe to -# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to -# the estimated # maximum number of broadcast_tx_commit calls per block. +# Maximum number of unique queries a given client can /subscribe to. +# If you're using /broadcast_tx_commit, set to the estimated maximum number +# of broadcast_tx_commit calls per block. max_subscriptions_per_client = 5 +# Experimental parameter to specify the maximum number of events a node will +# buffer, per subscription, before returning an error and closing the +# subscription. Must be set to at least 100, but higher values will accommodate +# higher event throughput rates (and will use more memory). +experimental_subscription_buffer_size = 200 + +# Experimental parameter to specify the maximum number of RPC responses that +# can be buffered per WebSocket client. If clients cannot read from the +# WebSocket endpoint fast enough, they will be disconnected, so increasing this +# parameter may reduce the chances of them being disconnected (but will cause +# the node to use more memory). +# +# Must be at least the same as "experimental_subscription_buffer_size", +# otherwise connections could be dropped unnecessarily. This value should +# ideally be somewhat higher than "experimental_subscription_buffer_size" to +# accommodate non-subscription-related RPC responses. +experimental_websocket_write_buffer_size = 200 + +# If a WebSocket client cannot read fast enough, at present we may +# silently drop events instead of generating an error or disconnecting the +# client. +# +# Enabling this experimental parameter will cause the WebSocket connection to +# be closed instead if it cannot read fast enough, allowing for greater +# predictability in subscription behavior. +experimental_close_on_slow_client = false + # How long to wait for a tx to be committed during /broadcast_tx_commit. # WARNING: Using a value larger than 10s will result in increasing the # global HTTP write timeout, which applies to all connections and endpoints. @@ -180,6 +197,66 @@ tls_key_file = "" # pprof listen address (https://golang.org/pkg/net/http/pprof) pprof_laddr = "" +####################################################### +### gRPC Server Configuration Options ### +####################################################### + +# +# Note that the gRPC server is exposed unauthenticated. It is critical that +# this server not be exposed directly to the public internet. If this service +# must be accessed via the public internet, please ensure that appropriate +# precautions are taken (e.g. fronting with a reverse proxy like nginx with TLS +# termination and authentication, using DDoS protection services like +# CloudFlare, etc.). +# + +[grpc] + +# TCP or UNIX socket address for the RPC server to listen on. If not specified, +# the gRPC server will be disabled. +laddr = "" + +# +# Each gRPC service can be turned on/off, and in some cases configured, +# individually. If the gRPC server is not enabled, all individual services' +# configurations are ignored. +# + +# The gRPC version service provides version information about the node and the +# protocols it uses. +[grpc.version_service] +enabled = true + +# The gRPC block service returns block information +[grpc.block_service] +enabled = true + +# The gRPC block results service returns block results for a given height. If no height +# is given, it will return the block results from the latest height. +[grpc.block_results_service] +enabled = true + +# +# Configuration for privileged gRPC endpoints, which should **never** be exposed +# to the public internet. +# +[grpc.privileged] +# The host/port on which to expose privileged gRPC endpoints. +laddr = "" + +# +# Configuration specifically for the gRPC pruning service, which is considered a +# privileged service. +# +[grpc.privileged.pruning_service] + +# Only controls whether the pruning service is accessible via the gRPC API - not +# whether a previously set pruning service retain height is honored by the +# node. See the [storage.pruning] section for control over pruning. +# +# Disabled by default. +enabled = false + ####################################################### ### P2P Configuration Options ### ####################################################### @@ -188,10 +265,9 @@ pprof_laddr = "" # Address to listen for incoming connections laddr = "tcp://0.0.0.0:26656" -# Address to advertise to peers for them to dial -# If empty, will use the same port as the laddr, -# and will introspect on the listener or use UPnP -# to figure out the address. +# Address to advertise to peers for them to dial. If empty, will use the same +# port as the laddr, and will introspect on the listener to figure out the +# address. IP and port are required. Example: 159.89.10.97:26656 external_address = "" # Comma separated list of seed nodes to connect to @@ -200,9 +276,6 @@ seeds = "" # Comma separated list of nodes to keep persistent connections to persistent_peers = "" -# UPNP port forwarding -upnp = false - # Path to address book addr_book_file = "config/addrbook.json" @@ -254,21 +327,51 @@ handshake_timeout = "20s" dial_timeout = "3s" ####################################################### -### Mempool Configurattion Option ### +### Mempool Configuration Options ### ####################################################### [mempool] +# The type of mempool for this node to use. +# +# Possible types: +# - "flood" : concurrent linked list mempool with flooding gossip protocol +# (default) +# - "nop" : nop-mempool (short for no operation; the ABCI app is responsible +# for storing, disseminating and proposing txs). "create_empty_blocks=false" is +# not supported. +type = "flood" + +# recheck (default: true) defines whether CometBFT should recheck the +# validity for all remaining transaction in the mempool after a block. +# Since a block affects the application state, some transactions in the +# mempool may become invalid. If this does not apply to your application, +# you can disable rechecking. recheck = true + +# broadcast (default: true) defines whether the mempool should relay +# transactions to other peers. Setting this to false will stop the mempool +# from relaying transactions to other peers until they are included in a +# block. In other words, if Broadcast is disabled, only the peer you send +# the tx to will see it until it is included in a block. broadcast = true + +# wal_dir (default: "") configures the location of the Write Ahead Log +# (WAL) for the mempool. The WAL is disabled by default. To enable, set +# wal_dir to where you want the WAL to be written (e.g. +# "data/mempool.wal"). wal_dir = "" # Maximum number of transactions in the mempool size = 5000 -# Limit the total size of all txs in the mempool. -# This only accounts for raw transactions (e.g. given 1MB transactions and -# max_txs_bytes=5MB, mempool will only accept 5 transactions). -max_txs_bytes = 1073741824 +# Maximum size in bytes of a single transaction accepted into the mempool. +max_tx_bytes = 1048576 + +# The maximum size in bytes of all transactions stored in the mempool. +# This is the raw, total transaction size. For example, given 1MB +# transactions and a 5MB maximum mempool byte size, the mempool will +# only accept five transactions. +max_txs_bytes = 67108864 # Size of the cache (used to filter transactions we saw earlier) in transactions cache_size = 10000 @@ -278,14 +381,20 @@ cache_size = 10000 # again in the future. keep-invalid-txs-in-cache = false -# Maximum size of a single transaction. -# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes}. -max_tx_bytes = 1048576 - -# Maximum size of a batch of transactions to send to a peer -# Including space needed by encoding (one varint per transaction). -# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796 -max_batch_bytes = 10485760 +# Experimental parameters to limit gossiping txs to up to the specified number of peers. +# We use two independent upper values for persistent and non-persistent peers. +# Unconditional peers are not affected by this feature. +# If we are connected to more than the specified number of persistent peers, only send txs to +# ExperimentalMaxGossipConnectionsToPersistentPeers of them. If one of those +# persistent peers disconnects, activate another persistent peer. +# Similarly for non-persistent peers, with an upper limit of +# ExperimentalMaxGossipConnectionsToNonPersistentPeers. +# If set to 0, the feature is disabled for the corresponding group of peers, that is, the +# number of active connections to that group of peers is not bounded. +# For non-persistent peers, if enabled, a value of 10 is recommended based on experimental +# performance results using the default P2P configuration. +experimental_max_gossip_connections_to_persistent_peers = 0 +experimental_max_gossip_connections_to_non_persistent_peers = 0 ####################################################### ### State Sync Configuration Options ### @@ -307,19 +416,29 @@ enable = false rpc_servers = "" trust_height = 0 trust_hash = "" -trust_period = "0s" +trust_period = "168h0m0s" + +# Time to spend discovering snapshots before initiating a restore. +discovery_time = "15s" # Temporary directory for state sync snapshot chunks, defaults to the OS tempdir (typically /tmp). # Will create a new, randomly named directory within, and remove it when done. temp_dir = "" +# The timeout duration before re-requesting a chunk, possibly from a different +# peer (default: 1 minute). +chunk_request_timeout = "10s" + +# The number of concurrent chunk fetchers to run (default: 1). +chunk_fetchers = "4" + ####################################################### ### Block Sync Configuration Options ### ####################################################### [blocksync] # Block Sync version to use: -# +# # In v0.37, v1 and v2 of the block sync protocols were deprecated. # Please use v0 instead. # @@ -365,8 +484,90 @@ create_empty_blocks_interval = "0s" # Reactor sleep duration parameters peer_gossip_sleep_duration = "100ms" +peer_gossip_intraloop_sleep_duration = "0s" peer_query_maj23_sleep_duration = "2s" +####################################################### +### Storage Configuration Options ### +####################################################### +[storage] + +# Set to true to discard ABCI responses from the state store, which can save a +# considerable amount of disk space. Set to false to ensure ABCI responses are +# persisted. ABCI responses are required for /block_results RPC queries, and to +# reindex events in the command-line tool. +discard_abci_responses = false + +# The representation of keys in the database. +# The current representation of keys in Comet's stores is considered to be v1 +# Users can experiment with a different layout by setting this field to v2. +# Note that this is an experimental feature and switching back from v2 to v1 +# is not supported by CometBFT. +# If the database was initially created with v1, it is necessary to migrate the DB +# before switching to v2. The migration is not done automatically. +# v1 - the legacy layout existing in Comet prior to v1. +# v2 - Order preserving representation ordering entries by height. +# We used a command to migrate from v1 to v2 in our tests. The command is used +# purely for experimental purposes but can be used as a starting point for experimentation +# https://github.com/cometbft/cometbft/blob/migrate_db/cmd/cometbft/commands/migrate_db.go +# compiling Comet at this branch and running migrate-db --home PATH_TO_CMT_HOME will transform the +# db. +experimental_db_key_layout = "v1" + +# Set to true to discard ABCI responses from the state store, which can save a +# considerable amount of disk space. Set to false to ensure ABCI responses are +# persisted. ABCI responses are required for /block_results RPC queries, and to +# reindex events in the command-line tool. +discard_abci_responses = false + +# If set to true, CometBFT will force compaction to happen for databases that support this feature. +# and save on storage space. Setting this to true is most benefits when used in combination +# with pruning as it will physically delete the entries marked for deletion. +# false by default (forcing compaction is disabled). +compact = false + +# To avoid forcing compaction every time, this parameter instructs CometBFT to wait +# the given amount of blocks to be pruned before triggering compaction. +# It should be tuned depending on the number of items. If your retain height is 1 block, +# it is too much of an overhead to try compaction every block. But it should also not be a very +# large multiple of your retain height as it might occur bigger overheads. +compaction_interval = "1000" + +# Hash of the Genesis file (as hex string), passed to CometBFT via the command line. +# If this hash mismatches the hash that CometBFT computes on the genesis file, +# the node is not able to boot. +genesis_hash = "" + +[storage.pruning] + +# The time period between automated background pruning operations. +interval = "10s" + +# +# Storage pruning configuration relating only to the data companion. +# +[storage.pruning.data_companion] + +# Whether automatic pruning respects values set by the data companion. Disabled +# by default. All other parameters in this section are ignored when this is +# disabled. +# +# If disabled, only the application retain height will influence block pruning +# (but not block results pruning). Only enabling this at a later stage will +# potentially mean that blocks below the application-set retain height at the +# time will not be available to the data companion. +enabled = false + +# The initial value for the data companion block retain height if the data +# companion has not yet explicitly set one. If the data companion has already +# set a block retain height, this is ignored. +initial_block_retain_height = 0 + +# The initial value for the data companion block results retain height if the +# data companion has not yet explicitly set one. If the data companion has +# already set a block results retain height, this is ignored. +initial_block_results_retain_height = 0 + ####################################################### ### Transaction Indexer Configuration Options ### ####################################################### @@ -381,8 +582,14 @@ peer_query_maj23_sleep_duration = "2s" # 1) "null" # 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). # - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed. +# 3) "psql" - the indexer services backed by PostgreSQL. +# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed. indexer = "kv" +# The PostgreSQL connection configuration, the connection format: +# postgresql://:@:/? +psql-conn = "" + ####################################################### ### Instrumentation Configuration Options ### ####################################################### @@ -404,7 +611,6 @@ max_open_connections = 3 # Instrumentation namespace namespace = "cometbft" - ``` ## Empty blocks VS no empty blocks @@ -417,7 +623,7 @@ the delay between blocks by changing the `timeout_commit`. E.g. `timeout_commit ### create_empty_blocks = false -In this setting, blocks are created when transactions received. +In this setting, blocks are created when transactions are received. Note after the block H, CometBFT creates something we call a "proof block" (only if the application hash changed) H+1. The reason for this is to support @@ -463,14 +669,83 @@ matter what is `timeout_commit`. Here's a brief summary of the timeouts: -- `timeout_propose` = how long we wait for a proposal block before prevoting nil -- `timeout_propose_delta` = how much `timeout_propose` increases with each round -- `timeout_prevote` = how long we wait after receiving +2/3 prevotes for +- `timeout_propose` = how long a validator should wait for a proposal block before prevoting nil +- `timeout_propose_delta` = how much `timeout_propose` increases with each round +- `timeout_prevote` = how long a validator should wait after receiving +2/3 prevotes for anything (ie. not a single block or nil) - `timeout_prevote_delta` = how much the `timeout_prevote` increases with each round -- `timeout_precommit` = how long we wait after receiving +2/3 precommits for +- `timeout_precommit` = how long a validator should wait after receiving +2/3 precommits for anything (ie. not a single block or nil) - `timeout_precommit_delta` = how much the `timeout_precommit` increases with each round -- `timeout_commit` = how long we wait after committing a block, before starting +- `timeout_commit` = how long a validator should wait after committing a block, before starting on the new height (this gives us a chance to receive some more precommits, even though we already have +2/3) + +### The adverse effect of using inconsistent `timeout_propose` in a network + +Here's an interesting question. What happens if a particular validator sets a +very small `timeout_propose`, as compared to the rest of the network? + +Imagine there are only two validators in your network: Alice and Bob. Bob sets +`timeout_propose` to 0s. Alice uses the default value of 3s. Let's say they +both have an equal voting power. Given the proposer selection algorithm is a +weighted round-robin, you may expect Alice and Bob to take turns proposing +blocks, and the result like: + +``` +#1 block - Alice +#2 block - Bob +#3 block - Alice +#4 block - Bob +... +``` + +What happens in reality is, however, a little bit different: + +``` +#1 block - Bob +#2 block - Bob +#3 block - Bob +#4 block - Bob +``` + +That's because Bob doesn't wait for a proposal from Alice (prevotes `nil`). +This leaves Alice no chances to commit a block. Note that every block Bob +creates needs a vote from Alice to constitute 2/3+. Bob always gets one because +Alice has `timeout_propose` set to 3s. Alice never gets one because Bob has it +set to 0s. + +Imagine now there are ten geographically distributed validators. One of them +(Bob) sets `timeout_propose` to 0s. Others have it set to 3s. Now, Bob won't be +able to move with his own speed because it still needs 2/3 votes of the other +validators and it takes time to propagate those. I.e., the network moves with +the speed of time to accumulate 2/3+ of votes (prevotes & precommits), not with +the speed of the fastest proposer. + +> Isn't block production determined by voting power? + +If it were determined solely by voting power, it wouldn't be possible to ensure +liveness. Timeouts exist because the network can't rely on a single proposer +being available and must move on if such is not responding. + +> How can we address situations where someone arbitrarily adjusts their block +> production time to gain an advantage? + +The impact shown above is negligible in a decentralized network with enough +decentralization. + +### The adverse effect of using inconsistent `timeout_commit` in a network + +Let's look at the same scenario as before. There are ten geographically +distributed validators. One of them (Bob) sets `timeout_commit` to 0s. Others +have it set to 1s (the default value). Now, Bob will be the fastest producer +because he doesn't wait for additional precommits after creating a block. If +waiting for precommits (`timeout_commit`) is not incentivized, Bob will accrue +more rewards compared to the other 9 validators. + +This is because Bob has the advantage of broadcasting its proposal early (1 +second earlier than the others). But it also makes it possible for Bob to miss +a proposal from another validator and prevote `nil` due to him starting +`timeout_propose` earlier. I.e., if Bob's `timeout_commit` is too low comparing +to other validators, then he might miss some proposals and get slashed for +inactivity. diff --git a/docs/core/how-to-read-logs.md b/docs/explanation/core/how-to-read-logs.md similarity index 94% rename from docs/core/how-to-read-logs.md rename to docs/explanation/core/how-to-read-logs.md index ba064952f77..f42fe49c9bc 100644 --- a/docs/core/how-to-read-logs.md +++ b/docs/explanation/core/how-to-read-logs.md @@ -24,16 +24,13 @@ I[10-04|13:54:27.368] ABCI Replay Blocks module=consen I[10-04|13:54:27.368] Completed ABCI Handshake - CometBFT and App are synced module=consensus appHeight=90 appHash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD ``` -After that, we start a few more things like the event switch, reactors, -and perform UPNP discover in order to detect the IP address. +After that, we start a few more things like the event switch and reactors. ```sh I[10-04|13:54:27.374] Starting EventSwitch module=types impl=EventSwitch I[10-04|13:54:27.375] This node is a validator module=consensus I[10-04|13:54:27.379] Starting Node module=main impl=Node I[10-04|13:54:27.381] Local listener module=p2p ip=:: port=26656 -I[10-04|13:54:27.382] Getting UPNP external address module=p2p -I[10-04|13:54:30.386] Could not perform UPNP discover module=p2p err="write udp4 0.0.0.0:38238->239.255.255.250:1900: i/o timeout" I[10-04|13:54:30.386] Starting DefaultListener module=p2p impl=Listener(@10.0.2.15:26656) I[10-04|13:54:30.387] Starting P2P Switch module=p2p impl="P2P Switch" I[10-04|13:54:30.387] Starting MempoolReactor module=mempool impl=MempoolReactor @@ -114,7 +111,7 @@ I[10-04|13:54:30.410] Recheck txs module=mempoo Here is the list of modules you may encounter in CometBFT's log and a little overview what they do. -- `abci-client` As mentioned in [Application Development Guide](../app-dev/abci-cli.md), CometBFT acts as an ABCI +- `abci-client` As mentioned in [Application Development Guide](../../guides/app-dev/abci-cli.md), CometBFT acts as an ABCI client with respect to the application and maintains 3 connections: mempool, consensus and query. The code used by CometBFT can be found [here](https://github.com/cometbft/cometbft/blob/main/abci/client). @@ -129,13 +126,13 @@ little overview what they do. found [here](https://github.com/cometbft/cometbft/blob/main/types/events.go). You can subscribe to them by calling `subscribe` RPC method. Refer - to [RPC docs](./rpc.md) for additional information. + to [RPC docs](rpc.md) for additional information. - `mempool` Mempool module handles all incoming transactions, whenever they are coming from peers or the application. - `p2p` Provides an abstraction around peer-to-peer communication. For more details, please check out the [README](https://github.com/cometbft/cometbft/blob/main/p2p/README.md). -- `rpc` [CometBFT's RPC](./rpc.md). +- `rpc` [CometBFT's RPC](rpc.md). - `rpc-server` RPC server. For implementation details, please read the [doc.go](https://github.com/cometbft/cometbft/blob/main/rpc/jsonrpc/doc.go). - `state` Represents the latest state and execution submodule, which diff --git a/docs/core/light-client.md b/docs/explanation/core/light-client.md similarity index 100% rename from docs/core/light-client.md rename to docs/explanation/core/light-client.md diff --git a/docs/explanation/core/mempool.md b/docs/explanation/core/mempool.md new file mode 100644 index 00000000000..f38668ca18c --- /dev/null +++ b/docs/explanation/core/mempool.md @@ -0,0 +1,103 @@ +--- +order: 12 +--- + +# Mempool + +A mempool (a contraction of memory and pool) is a node’s data structure for +storing information on uncommitted transactions. It acts as a sort of waiting +room for transactions that have not yet been committed. + +CometBFT currently supports two types of mempools: `flood` and `nop`. + +## 1. Flood + +The `flood` mempool stores transactions in a concurrent linked list. When a new +transaction is received, it first checks if there's a space for it (`size` and +`max_txs_bytes` config options) and that it's not too big (`max_tx_bytes` config +option). Then, it checks if this transaction has already been seen before by using +an LRU cache (`cache_size` regulates the cache's size). If all checks pass and +the transaction is not in the cache (meaning it's new), the ABCI +[`CheckTxAsync`][1] method is called. The ABCI application validates the +transaction using its own rules. + +If the transaction is deemed valid by the ABCI application, it's added to the linked list. + +The mempool's name (`flood`) comes from the dissemination mechanism. When a new +transaction is added to the linked list, the mempool sends it to all connected +peers. Peers themselves gossip this transaction to their peers and so on. One +can say that each transaction "floods" the network, hence the name `flood`. + +Note there are experimental config options +`experimental_max_gossip_connections_to_persistent_peers` and +`experimental_max_gossip_connections_to_non_persistent_peers` to limit the +number of peers a transaction is broadcasted to. Also, you can turn off +broadcasting with `broadcast` config option. + +After each committed block, CometBFT rechecks all uncommitted transactions (can +be disabled with the `recheck` config option) by repeatedly calling the ABCI +`CheckTxAsync`. + +### Transaction ordering + +Currently, there's no ordering of transactions other than the order they've +arrived (via RPC or from other nodes). + +So the only way to specify the order is to send them to a single node. + +valA: + +- `tx1` +- `tx2` +- `tx3` + +If the transactions are split up across different nodes, there's no way to +ensure they are processed in the expected order. + +valA: + +- `tx1` +- `tx2` + +valB: + +- `tx3` + +If valB is the proposer, the order might be: + +- `tx3` +- `tx1` +- `tx2` + +If valA is the proposer, the order might be: + +- `tx1` +- `tx2` +- `tx3` + +That said, if the transactions contain some internal value, like an +order/nonce/sequence number, the application can reject transactions that are +out of order. So if a node receives `tx3`, then `tx1`, it can reject `tx3` and then +accept `tx1`. The sender can then retry sending `tx3`, which should probably be +rejected until the node has seen `tx2`. + +## 2. Nop + +`nop` (short for no operation) mempool is used when the ABCI application developer wants to +build their own mempool. When `type = "nop"`, transactions are not stored anywhere +and are not gossiped to other peers using the P2P network. + +Submitting a transaction via the existing RPC methods (`BroadcastTxSync`, +`BroadcastTxAsync`, and `BroadcastTxCommit`) will always result in an error. + +Because there's no way for the consensus to know if transactions are available +to be committed, the node will always create blocks, which can be empty +sometimes. Using `consensus.create_empty_blocks=false` is prohibited in such +cases. + +The ABCI application becomes responsible for storing, disseminating, and +proposing transactions using [`PrepareProposal`][2]. The concrete design is up +to the ABCI application developers. + +[1]: ../../../spec/abci/abci++_methods.md#checktx +[2]: ../../../spec/abci/abci++_methods.md#prepareproposal diff --git a/docs/core/metrics.md b/docs/explanation/core/metrics.md similarity index 85% rename from docs/core/metrics.md rename to docs/explanation/core/metrics.md index 71cc8d2093b..d41796a554f 100644 --- a/docs/core/metrics.md +++ b/docs/explanation/core/metrics.md @@ -24,9 +24,9 @@ The following metrics are available: | blocksync\_syncing | Gauge | | Either 0 (not block syncing) or 1 (syncing) | | consensus\_height | Gauge | | Height of the chain | | consensus\_validators | Gauge | | Number of validators | -| consensus\_validators\_power | Gauge | | Total voting power of all validators | -| consensus\_validator\_power | Gauge | | Voting power of the node if in the validator set | -| consensus\_validator\_last\_signed\_height | Gauge | | Last height the node signed a block, if the node is a validator | +| consensus\_validators\_power | Gauge | validator\_address | Total voting power of all validators | +| consensus\_validator\_power | Gauge | validator\_address | Voting power of the node if in the validator set | +| consensus\_validator\_last\_signed\_height | Gauge | validator\_address | Last height the node signed a block, if the node is a validator | | consensus\_validator\_missed\_blocks | Gauge | | Total amount of blocks missed for the node, if the node is a validator | | consensus\_missing\_validators | Gauge | | Number of validators who did not sign | | consensus\_missing\_validators\_power | Gauge | | Total voting power of the missing validators | @@ -39,16 +39,19 @@ The following metrics are available: | consensus\_block\_parts | Counter | peer\_id | Number of blockparts transmitted by peer | | consensus\_latest\_block\_height | Gauge | | /status sync\_info number | | consensus\_block\_size\_bytes | Gauge | | Block size in bytes | -| consensus\_step\_duration | Histogram | step | Histogram of durations for each step in the consensus protocol | -| consensus\_round\_duration | Histogram | | Histogram of durations for all the rounds that have occurred since the process started | +| consensus\_step\_duration\_seconds | Histogram | step | Histogram of durations for each step in the consensus protocol | +| consensus\_round\_duration\_seconds | Histogram | | Histogram of durations for all the rounds that have occurred since the process started | | consensus\_block\_gossip\_parts\_received | Counter | matches\_current | Number of block parts received by the node | -| consensus\_quorum\_prevote\_delay | Gauge | | Interval in seconds between the proposal timestamp and the timestamp of the earliest prevote that achieved a quorum | -| consensus\_full\_prevote\_delay | Gauge | | Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted | +| consensus\_quorum\_prevote\_delay | Gauge | proposer\_address | Interval in seconds between the proposal timestamp and the timestamp of the earliest prevote that achieved a quorum | +| consensus\_full\_prevote\_delay | Gauge | proposer\_address | Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted | | consensus\_vote\_extension\_receive\_count | Counter | status | Number of vote extensions received | | consensus\_proposal\_receive\_count | Counter | status | Total number of proposals received by the node since process start | | consensus\_proposal\_create\_count | Counter | | Total number of proposals created by the node since process start | | consensus\_round\_voting\_power\_percent | Gauge | vote\_type | A value between 0 and 1.0 representing the percentage of the total voting power per vote type received within a round | | consensus\_late\_votes | Counter | vote\_type | Number of votes received by the node since process start that correspond to earlier heights and rounds than this node is currently in. | +| consensus\_duplicate\_vote | Counter | | Number of times we received a duplicate vote. | +| consensus\_duplicate\_block\_part | Counter | | Number of times we received a duplicate block part. | +| consensus\_proposal\_timestamp\_difference | Histogram | is\_timely | Difference between the timestamp in the proposal message and the local time of the validator at the time it received the message. | | p2p\_message\_send\_bytes\_total | Counter | message\_type | Number of bytes sent to all peers per message type | | p2p\_message\_receive\_bytes\_total | Counter | message\_type | Number of bytes received from all peers per message type | | p2p\_peers | Gauge | | Number of peers node's connected to | @@ -61,7 +64,7 @@ The following metrics are available: | mempool\_tx\_size\_bytes | Histogram | | Transaction sizes in bytes | | mempool\_failed\_txs | Counter | | Number of failed transactions | | mempool\_recheck\_times | Counter | | Number of transactions rechecked in the mempool | -| state\_block\_processing\_time | Histogram | | Time between BeginBlock and EndBlock in ms | +| state\_block\_processing\_time | Histogram | | Time spent processing FinalizeBlock in ms | | state\_consensus\_param\_updates | Counter | | Number of consensus parameter updates returned by the application since process start | | state\_validator\_set\_updates | Counter | | Number of validator set updates returned by the application since process start | | statesync\_syncing | Gauge | | Either 0 (not state syncing) or 1 (syncing) | diff --git a/docs/explanation/core/proposer-based-timestamps.md b/docs/explanation/core/proposer-based-timestamps.md new file mode 100644 index 00000000000..10d12b18378 --- /dev/null +++ b/docs/explanation/core/proposer-based-timestamps.md @@ -0,0 +1,265 @@ +--- +order: 14 +--- + +# Proposer-Based Timestamp (PBTS) + +This document overviews the Proposer-Based Timestamp (PBTS) +algorithm introduced in CometBFT version v1.0. +It outlines the core functionality of the algorithm and details the consensus +parameters that govern its operation. + +## Overview + +The PBTS algorithm defines a way for a blockchain to create block +timestamps that are within a reasonable bound of the validators' clocks on +the network. +It replaces the BFT Time algorithm for timestamp calculation and assignment, which computes the +timestamp of a block using the timestamps aggregated from precommit messages. + +### Block Timestamps + +Each block produced by CometBFT contains a timestamp, represented by the `Time` +field of the block's `Header`. + +The timestamp of each block is expected to be a meaningful representation of time that is +useful for the protocols and applications built on top of CometBFT. +The following protocols and application features require a reliable source of time: + +* Light Clients [rely on correspondence between their known time][light-client-verification] and the block time for block verification. +* Evidence expiration is determined [either in terms of heights or in terms of time][evidence-verification]. +* Unbonding of staked assets in the Cosmos Hub [occurs after a period of 21 + days](https://github.com/cosmos/governance/blob/master/params-change/Staking.md#unbondingtime). +* IBC packets can use either a [timestamp or a height to timeout packet + delivery](https://ibc.cosmos.network/v8/ibc/light-clients/updates-and-misbehaviour?_highlight=time#checkformisbehaviour). + +### Enabling PBTS + +The PBTS algorithm is **not enabled by default** in CometBFT v1.0. + +If a network upgrades to CometBFT v1.0, it will still use the BFT Time +algorithm until PBTS is enabled. +The same applies to new networks that do not change the default values for +consensus parameters in the genesis file. + +Enabling PBTS requires configuring the [consensus parameters](#consensus-parameters) +that govern the operation of the algorithm. +There are two `SynchronyParams`, `Precision` and `MessageDelay`, used to +validate block timestamps, as described in the following. +And a `FeatureParams.PbtsEnableHeight` that defines the height from which PBTS +is adopted. + +### Selecting a Timestamp + +When a validator creates a new block, it reads the time from its local clock +and uses this reading as the timestamp for the block. +The proposer of a block is thus free to select the block timestamp, but this +timestamp must be validated by other nodes in the network. + +### Validating Timestamps + +When each validator on the network receives a proposed block, it performs a +series of checks to ensure that the block can be considered valid as a +candidate to be the next block in the chain. +If the block is considered invalid, the validator issues a `nil` prevote, +signaling to the rest of the network that the proposed block is not valid. + +The PBTS algorithm performs a validity check on the timestamp of proposed +blocks. +This only applies to the first time at which a block is proposed. +If the same block is re-proposed in a future round because it was deemed valid +by the network, this check is not performed. +Refer to the PBTS specification for more details. + +When a validator receives a proposal for a new block, it ensures that the timestamp in +the proposal is within a bound of the validator's local clock. +For that it uses `Precision` and `MessageDelay` consensus parameters, +which are the same across all nodes for a given height. +Specifically, the algorithm checks that the proposed block's timestamp is +no more than `Precision` greater than the node's local clock +(i.e., not in the future) +and no less than `MessageDelay + Precision` behind the node's local clock +(i.e., not too far in the past). +If the proposed block's timestamp is within the window of acceptable +timestamps, the timestamp is considered **timely**. +If the block timestamp is **not timely**, the validator rejects the proposed block by +issuing a `nil` prevote. + +### Clock Synchronization + +The PBTS algorithm requires the clocks of the validators in the network to be +within `Precision` of each other. In practice, this means that validators +should periodically synchronize their clocks, e.g. to a reliable NTP server. +Validators whose clocks drift too far away from the rest of the network will no +longer propose blocks with valid timestamps. Additionally, they will not consider +the timestamps of blocks proposed by their peers to be valid either. + + +## Consensus Parameters + +The functionality of the PBTS algorithm is governed by two consensus +parameters: the synchronous parameters `Precision` and `MessageDelay`. +An additional consensus parameter `PbtsEnableHeight` is used to enable PBTS +when instantiating a new network or when upgrading an existing a network that +uses BFT Time. + +Consensus parameters are configured through the genesis file, for new chains, or by the ABCI application, for new and existing chains, and are the same +across all nodes in the network at any given height. + +### `SynchronyParams.Precision` + +The `Precision` parameter configures the acceptable upper-bound of clock drift +among all of the validators in the network. +Any two validators are expected to have clocks that differ by at most +`Precision` at any given instant. + +The `Precision` parameter is of [`time.Duration`](https://pkg.go.dev/time#Duration) type. + +Networks should choose a `Precision` that is large enough to represent the +worst-case for the clock drift among all participants. +Due to the [leap second events](https://github.com/tendermint/tendermint/issues/7724), +it is recommended to set `Precision` to at least `500ms`. + +### `SynchronyParams.MessageDelay` + +The `MessageDelay` parameter configures the acceptable upper-bound for the +end-to-end delay for transmitting a `Proposal` message from the proposer to +_all_ validators in the network. + +The `MessageDelay` parameter is of [`time.Duration`](https://pkg.go.dev/time#Duration) type. + +Networks should choose a `MessageDelay` that is large enough to represent the +delay for a `Proposal` message to reach all participants. +As `Proposal` messages are fixed-size, this delay should not depend, a priori, +on the size of proposed blocks. +But it does depend on the number of nodes in the network, the latency of their +connections, and the level of congestion in the network. + +### `FeatureParams.PbtsEnableHeight` + +The `PbtsEnableHeight` parameter configures the first height at which the PBTS +algorithm should be adopted for generating and validating block timestamps in a network. + +The `PbtsEnableHeight` parameter is an integer. + +While `PbtsEnableHeight` is set to `0`, the network will adopt the legacy BFT +Time algorithm. + +When `PbtsEnableHeight` is set to a height `H > 0`, the network will switch to +the PBTS algorithm from height `H` on. +The network will still adopt the legacy BFT Time algorithm to produce block +timestamps until height `H - 1`, and to validate block timestamps produced in +heights up to `H - 1`. +The enable height `H` must be a future height when it is configured, namely it +can only be set to a height that is larger than the current blockchain height. + +Once `PbtsEnableHeight` is set and the PBTS algorithm is enabled (i.e., from height +`PbtsEnableHeight`), it is not possible to return to the legacy BFT Time algorithm. +The switch to PBTS is therefore irreversible. + +Finally, if `PbtsEnableHeight` is set to `InitialHeight` in the genesis file or by the +ABCI `InitChain` method, the network will adopt PBTS from the initial +height. This is the recommended setup for new chains. + + +## Important Notes + +When configuring a network to adopt the PBTS algorithm, the following steps must be considered: + +1. Make sure that the clocks of validators are [synchronized](#clock-synchronization) **before** enabling PBTS. +1. Make sure that the configured value for [`SynchronyParams.Precision`](#synchronyparamsprecision) is + reasonable. +1. Make sure that the configured value for [`SynchronyParams.MessageDelay`](#synchronyparamsmessagedelay) is + reasonable and large enough to reflect the maximum expected delay for messages in the network. + Setting this parameter to a small value may impact the progress of the + network, namely blocks may take very long to be committed. + - An approach to define this parameter is to observe the latency for + fixed-size messages (e.g., `Vote` and `Proposal`) over time and define an + empirical distribution of message delays. + Then pick as value for the `MessageDelay` parameter, a high percentile of + this distribution (e.g., the 99th or 99.9th percentiles). +1. Make sure that the block times **currently** produced by the network do not + differ too much from real time. + This is specially relevant when block times produced by BFT time are in the + future, with respect to real time. + +### Adaptive MessageDelay + +Observation 3. is important because a network that sets +[`SynchronyParams.MessageDelay`](#synchronyparamsmessagedelay) +to a small value is likely to suffer from long block latencies +and even, in extreme cases, from the complete halt of the network. +By a small value here we mean a message delay that is not enough for an important +portion of the validators to receive the `Proposal` message broadcast by the +proposer of a round within the configured message delay. +If the subset of validators that are unlikely to receive the proposal within the +configured `SynchronyParams.MessageDelay` hold more than 1/3 of the total +voting power of the network, the network could stop producing blocks +indefinitely. + +To prevent the network from halting due to the configuration of a small value +for `SynchronyParams.MessageDelay`, we have introduced the concept of +[adaptive synchronous parameters](https://github.com/cometbft/cometbft/issues/2184). +In summary, this means that the synchrony parameters adopted to verify whether +a proposal timestamp is timely are relaxed as more rounds are required to +commit a block. +The maximum message delay for round 0 is still the configured +`SynchronyParams.MessageDelay`; most blocks are committed in round 0, so there +are no changes for the regular case. +From round 1, the maximum message delay adopted by PBTS slowly increases, at a +rate of 10% per round. +As a result, the adopted maximum message delay will eventually converge to the +actual message delay observed in the network. + +While this solution prevents the network from halting, it still delays the +commit of a block by several rounds. +For example, if the configured `SynchronyParams.MessageDelay` is 0.5s but an +important portion of nodes regularly receive the `Proposal` message after 1s, +between 7 and 8 rounds will be necessary to commit a block. +This is an important performance penalty that network operators must avoid at +all costs. Upon noticing this problem, as the network will not halt because of this, +network operators can agree to increase the value of `SynchronyParams.MessageDelay` +in order to fix the problem. + +### BFT Times in the future + +Observation 4. is important because, with the adoption of PBTS, block times are +expected to converge to values that bear resemblance to real time. +At the same time, the property of monotonicity of block times is guaranteed by both BFT +Time and PBTS. +This means that proposers using PBTS will **wait** until the time they read +from their local clocks becomes bigger than the time of the last committed +block before proposing a new block. + +As a result, if the time of the last block produced using BFT Time is too far in +the future, then the first block produced using PBTS will take very long to be +committed: the time it takes for the clock of the proposer to reach the time of +the previously committed block. +To prevent this from happening, first, follow recommendation 1., i.e., synchronize +the validators' clocks. +Then wait until the block times produced by BFT Time converge to values that do +not differ too much from real time. +This may take a long time, because in BFT Time if the value a validator reads +from its local clock is smaller than the time of the previous block, then the +time it sets to a new block will be the time of the previous block plus `1ms`. +It may take a while, but block times will eventually converge to real time. + +## See Also + +* [Block Time specification][block-time-spec]: overview of block timestamps properties. +* [Consensus parameters][consensus-parameters]: list of consensus parameters, their usage and validation. +* [PBTS specification][pbts-spec]: formal specification and all of the details of the PBTS algorithm. +* [BFT Time specification][bft-time-spec]: all details of the legacy BFT Time algorithm to compute block times. +* [Proposer-Based Timestamps Runbook][pbts-runbook]: a guide for diagnosing and + fix issues related to clock synchronization and the configuration of the + `SynchronyParams` consensus parameters adopted by PBTS. + +[pbts-spec]: https://github.com/cometbft/cometbft/blob/main/spec/consensus/proposer-based-timestamp/README.md +[bft-time-spec]: https://github.com/cometbft/cometbft/blob/main/spec/consensus/bft-time.md +[block-time-spec]: https://github.com/cometbft/cometbft/blob/main/spec/consensus/time.md +[pbts-runbook]: ../../guides/tools/proposer-based-timestamps-runbook.md + +[consensus-parameters]: https://github.com/cometbft/cometbft/blob/main/spec/abci/abci%2B%2B_app_requirements.md#consensus-parameters + +[light-client-verification]: https://github.com/cometbft/cometbft/blob/main/spec/light-client/verification/README.md#failure-model +[evidence-verification]: https://github.com/cometbft/cometbft/blob/main/spec/consensus/evidence.md#verification diff --git a/docs/core/rpc.md b/docs/explanation/core/rpc.md similarity index 100% rename from docs/core/rpc.md rename to docs/explanation/core/rpc.md diff --git a/docs/core/running-in-production.md b/docs/explanation/core/running-in-production.md similarity index 91% rename from docs/core/running-in-production.md rename to docs/explanation/core/running-in-production.md index beaee33056e..1eab150a5ae 100644 --- a/docs/core/running-in-production.md +++ b/docs/explanation/core/running-in-production.md @@ -8,29 +8,28 @@ order: 4 By default, CometBFT uses the `syndtr/goleveldb` package for its in-process key-value database. If you want maximal performance, it may be best to install -the real C-implementation of LevelDB and compile CometBFT to use that using -`make build COMETBFT_BUILD_OPTIONS=cleveldb`. See the [install +RocksDB and compile CometBFT to use that using +`make build COMETBFT_BUILD_OPTIONS=rocksdb`. See the [install instructions](../introduction/install.md) for details. CometBFT keeps multiple distinct databases in the `$CMTHOME/data`: - `blockstore.db`: Keeps the entire blockchain - stores blocks, - block commits, and block meta data, each indexed by height. Used to sync new + block commits, and block metadata, each indexed by height. Used to sync new peers. - `evidence.db`: Stores all verified evidence of misbehavior. -- `state.db`: Stores the current blockchain state (ie. height, validators, +- `state.db`: Stores the current blockchain state (i.e. height, validators, consensus params). Only grows if consensus params or validators change. Also used to temporarily store intermediate results during block processing. -- `tx_index.db`: Indexes txs (and their results) by tx hash and by DeliverTx result events. +- `tx_index.db`: Indexes transactions and by tx hash and height. The tx results are indexed if they are added to the `FinalizeBlock` response in the application. -By default, CometBFT will only index txs by their hash and height, not by their DeliverTx -result events. See [indexing transactions](../app-dev/indexing-transactions.md) for -details. +> By default, CometBFT will only index transactions by their hash and height, if you want the result events to be indexed, see [indexing transactions](../../guides/app-dev/indexing-transactions.md#adding-events) for +for details. Applications can expose block pruning strategies to the node operator. Please read the documentation of your application to find out more details. -Applications can use [state sync](./state-sync.md) to help nodes bootstrap quickly. +Applications can use [state sync](state-sync.md) to help nodes bootstrap quickly. ## Logging @@ -38,7 +37,7 @@ Default logging level (`log_level = "main:info,state:info,statesync:info,*:error normal operation mode. Read [this post](https://blog.cosmos.network/one-of-the-exciting-new-features-in-0-10-0-release-is-smart-log-level-flag-e2506b4ab756) for details on how to configure `log_level` config variable. Some of the -modules can be found [here](./how-to-read-logs.md#list-of-modules). If +modules can be found [here](how-to-read-logs.md#list-of-modules). If you're trying to debug CometBFT or asked to provide logs with debug logging level, you can do so by running CometBFT with `--log_level="*:debug"`. @@ -62,12 +61,12 @@ If your `consensus.wal` is corrupted, see [below](#wal-corruption). ### Mempool WAL -The `mempool.wal` logs all incoming txs before running CheckTx, but is +The `mempool.wal` logs all incoming transactions before running CheckTx, but is otherwise not used in any programmatic way. It's just a kind of manual safe guard. Note the mempool provides no durability guarantees - a tx sent to one or many nodes may never make it into the blockchain if those nodes crash before being able to -propose it. Clients must monitor their txs by subscribing over websockets, -polling for them, or using `/broadcast_tx_commit`. In the worst case, txs can be +propose it. Clients must monitor their transactions by subscribing over websockets, +polling for them, or using `/broadcast_tx_commit`. In the worst case, transactions can be resent from the mempool WAL manually. For the above reasons, the `mempool.wal` is disabled by default. To enable, set @@ -76,7 +75,7 @@ For the above reasons, the `mempool.wal` is disabled by default. To enable, set ## DoS Exposure and Mitigation -Validators are supposed to setup [Sentry Node Architecture](./validators.md) +Validators are supposed to setup [Sentry Node Architecture](validators.md) to prevent Denial-of-Service attacks. ### P2P @@ -129,7 +128,7 @@ for more information. ## Debugging CometBFT If you ever have to debug CometBFT, the first thing you should probably do is -check out the logs. See [How to read logs](./how-to-read-logs.md), where we +check out the logs. See [How to read logs](how-to-read-logs.md), where we explain what certain log statements mean. If, after skimming through the logs, things are not clear still, the next thing @@ -154,7 +153,7 @@ just the votes seen at the current height. If, after consulting with the logs and above endpoints, you still have no idea what's happening, consider using `cometbft debug kill` sub-command. This command will scrap all the available info and kill the process. See -[Debugging](../tools/debugging.md) for the exact format. +[Debugging](../../guides/tools/debugging.md) for the exact format. You can inspect the resulting archive yourself or create an issue on [Github](https://github.com/cometbft/cometbft). Before opening an issue @@ -171,10 +170,10 @@ Other useful endpoints include mentioned earlier `/status`, `/net_info` and `/validators`. CometBFT also can report and serve Prometheus metrics. See -[Metrics](./metrics.md). +[Metrics](metrics.md). `cometbft debug dump` sub-command can be used to periodically dump useful -information into an archive. See [Debugging](../tools/debugging.md) for more +information into an archive. See [Debugging](../../guides/tools/debugging.md) for more information. ## What happens when my app dies @@ -359,7 +358,7 @@ applications, setting it to true is not a problem. - `consensus.peer_gossip_sleep_duration` You can try to reduce the time your node sleeps before checking if -theres something to send its peers. +there's something to send its peers. - `consensus.timeout_commit` diff --git a/docs/core/state-sync.md b/docs/explanation/core/state-sync.md similarity index 96% rename from docs/core/state-sync.md rename to docs/explanation/core/state-sync.md index 0f477302e29..7f5c5433d2e 100644 --- a/docs/core/state-sync.md +++ b/docs/explanation/core/state-sync.md @@ -30,7 +30,7 @@ The next information you will need to acquire it through publicly exposed RPC's - `trust_period`: Trust period is the period in which headers can be verified. > :warning: This value should be significantly smaller than the unbonding period. -If you are relying on publicly exposed RPC's to get the need information, you can use `curl`. +If you are relying on publicly exposed RPC's to get the need information, you can use `curl` and [`jq`][jq]. Example: @@ -46,3 +46,5 @@ The response will be: "hash": "188F4F36CBCD2C91B57509BBF231C777E79B52EE3E0D90D06B1A25EB16E6E23D" } ``` + +[jq]: https://jqlang.github.io/jq/ diff --git a/docs/core/subscription.md b/docs/explanation/core/subscription.md similarity index 59% rename from docs/core/subscription.md rename to docs/explanation/core/subscription.md index 96d455e54eb..33049fccbe6 100644 --- a/docs/core/subscription.md +++ b/docs/explanation/core/subscription.md @@ -14,9 +14,11 @@ To connect to a node via websocket from the CLI, you can use a tool such as [wscat](https://github.com/websockets/wscat) and run: ```sh -wscat ws://127.0.0.1:26657/websocket +wscat -c ws://127.0.0.1:26657/websocket ``` +NOTE: If your node's RPC endpoint is TLS-enabled, utilize the scheme `wss` instead of `ws`. + You can subscribe to any of the events above by calling the `subscribe` RPC method via Websocket along with a valid query. @@ -34,9 +36,28 @@ method via Websocket along with a valid query. Check out [API docs](https://docs.cometbft.com/main/rpc/) for more information on query syntax and other options. -You can also use tags, given you had included them into DeliverTx +You can also use tags, given you had included them into FinalizeBlock response, to query transaction results. See [Indexing -transactions](../app-dev/indexing-transactions.md) for details. +transactions](../../guides/app-dev/indexing-transactions.md#adding-events) for details. + +## Query parameter and event type restrictions + +While CometBFT imposes no restrictions on the application with regards to the type of +the event output, there are several considerations that need to be taken into account +when querying events with numeric values. + +- Queries convert all numeric event values to `big.Float` , provided by `math/big`. Integers +are converted into a float with a precision equal to the number of bits needed +to represent this integer. This is done to avoid precision loss for big integers when they +are converted with the default precision (`64`). +- When comparing two values, if either one of them is a float, the other one will be represented +as a big float. Integers are again parsed as big floats with a precision equal to the number +of bits required to represent them. +- As with all floating point comparisons, comparing floats with decimal values can lead to imprecise +results. +- Queries cannot include negative numbers + +Prior to version `v0.38.x`, floats were not supported as query parameters. ## ValidatorSetUpdates diff --git a/docs/core/using-cometbft.md b/docs/explanation/core/using-cometbft.md similarity index 97% rename from docs/core/using-cometbft.md rename to docs/explanation/core/using-cometbft.md index 258f20fc2c1..06df62ddef5 100644 --- a/docs/core/using-cometbft.md +++ b/docs/explanation/core/using-cometbft.md @@ -92,8 +92,8 @@ definition](https://github.com/cometbft/cometbft/blob/main/types/genesis.go)). "initial_height": "0", "consensus_params": { "block": { - "max_bytes": "22020096", - "max_gas": "-1", + "max_bytes": "4194304", + "max_gas": "10000000", }, "evidence": { "max_age_num_blocks": "100000", @@ -130,7 +130,7 @@ cometbft node ``` By default, CometBFT will try to connect to an ABCI application on -`127.0.0.1:26658`. If you have the `kvstore` ABCI app installed, run it in +`tcp://127.0.0.1:26658`. If you have the `kvstore` ABCI app installed, run it in another window. If you don't, kill CometBFT and run an in-process version of the `kvstore` app: @@ -139,8 +139,8 @@ cometbft node --proxy_app=kvstore ``` After a few seconds, you should see blocks start streaming in. Note that blocks -are produced regularly, even if there are no transactions. See _No Empty -Blocks_, below, to modify this setting. +are produced regularly, even if there are no transactions. See [No Empty +Blocks](#no-empty-blocks), below, to modify this setting. CometBFT supports in-process versions of the `counter`, `kvstore`, and `noop` apps that ship as examples with `abci-cli`. It's easy to compile your app @@ -248,7 +248,7 @@ address book files. ## Configuration CometBFT uses a `config.toml` for configuration. For details, see [the -config specification](./configuration.md). +config specification](configuration.md). Notable options include the socket address of the application (`proxy_app`), the listening address of the CometBFT peer @@ -338,7 +338,7 @@ Note the mempool does not provide strong guarantees - just because a tx passed CheckTx (ie. was accepted into the mempool), doesn't mean it will be committed, as nodes with the tx in their mempool may crash before they get to propose. For more information, see the [mempool -write-ahead-log](./running-in-production.md#mempool-wal) +write-ahead-log](running-in-production.md#mempool-wal) ## CometBFT Networks @@ -552,7 +552,7 @@ failing, you need at least four validator nodes (e.g., 2/3). Updating validators in a live network is supported but must be explicitly programmed by the application developer. See the [application -developers guide](../app-dev/abci-cli.md) for more details. +developers guide](../../guides/app-dev/abci-cli.md) for more details. ### Local Network diff --git a/docs/core/validators.md b/docs/explanation/core/validators.md similarity index 84% rename from docs/core/validators.md rename to docs/explanation/core/validators.md index 34f99290856..631600367b5 100644 --- a/docs/core/validators.md +++ b/docs/explanation/core/validators.md @@ -10,14 +10,13 @@ _votes_ which contain cryptographic signatures signed by each validator's private key. Some Proof-of-Stake consensus algorithms aim to create a "completely" -decentralized system where all stakeholders (even those who are not -always available online) participate in the committing of blocks. -CometBFT has a different approach to block creation. Validators are -expected to be online, and the set of validators is permissioned/curated -by some external process. Proof-of-stake is not required, but can be -implemented on top of CometBFT consensus. That is, validators may be -required to post collateral on-chain, off-chain, or may not be required -to post any collateral at all. +decentralized system where all stakeholders (even those who are not always +available online) participate in the committing of blocks. CometBFT has a +different approach to block creation. Validators are expected to be online, and +the set of validators is permissioned/curated by the ABCI application. +Proof-of-stake is not required, but can be implemented on top of CometBFT +consensus. That is, validators may be required to post collateral on-chain, +off-chain, or may not be required to post any collateral at all. Validators have a cryptographic key-pair and an associated amount of "voting power". Voting power need not be the same. @@ -26,8 +25,8 @@ Validators have a cryptographic key-pair and an associated amount of There are two ways to become validator. -1. They can be pre-established in the [genesis state](./using-cometbft.md#genesis) -2. The ABCI app responds to the EndBlock message with changes to the +1. They can be pre-established in the [genesis state](using-cometbft.md#genesis) +2. The ABCI app responds to the FinalizeBlock message with changes to the existing validator set. ## Setting up a Validator @@ -36,7 +35,7 @@ When setting up a validator there are countless ways to configure your setup. Th ### Network Layout -![ALT Network Layout](../imgs/sentry_layout.png) +![ALT Network Layout](../../imgs/sentry_layout.png) The diagram is based on AWS, other cloud providers will have similar solutions to design a solution. Running nodes is not limited to cloud providers, you can run nodes on bare metal systems as well. The architecture will be the same no matter which setup you decide to go with. @@ -50,7 +49,7 @@ A more persistent solution (not detailed on the diagram) is to have multiple dir ### Local Configuration -![ALT Local Configuration](../imgs/sentry_local_config.png) +![ALT Local Configuration](../../imgs/sentry_local_config.png) The validator will only talk to the sentry that are provided, the sentry nodes will communicate to the validator via a secret connection and the rest of the network through a normal connection. The sentry nodes do have the option of communicating with each other as well. @@ -100,16 +99,3 @@ More Information can be found at these links: Protecting a validator's consensus key is the most important factor to take in when designing your setup. The key that a validator is given upon creation of the node is called a consensus key, it has to be online at all times in order to vote on blocks. It is **not recommended** to merely hold your private key in the default json file (`priv_validator_key.json`). Fortunately, the [Interchain Foundation](https://interchain.io) has worked with a team to build a key management server for validators. You can find documentation on how to use it [here](https://github.com/iqlusioninc/tmkms), it is used extensively in production. You are not limited to using this tool, there are also [HSMs](https://safenet.gemalto.com/data-encryption/hardware-security-modules-hsms/), there is not a recommended HSM. Currently CometBFT uses [Ed25519](https://ed25519.cr.yp.to/) keys which are widely supported across the security sector and HSMs. - -## Committing a Block - -> **+2/3 is short for "more than 2/3"** - -A block is committed when +2/3 of the validator set sign -[precommit votes](https://github.com/cometbft/cometbft/blob/main/spec/core/data_structures.md#vote) -for that block at the same `round`. -The +2/3 set of precommit votes is called a -[commit](https://github.com/cometbft/cometbft/blob/main/spec/core/data_structures.md#commit). -While any +2/3 set of precommits for the same block at the same height&round can serve as -validation, the canonical commit is included in the next block (see -[LastCommit](https://github.com/cometbft/cometbft/blob/main/spec/core/data_structures.md#block)). diff --git a/docs/explanation/data-companion/README.md b/docs/explanation/data-companion/README.md new file mode 100644 index 00000000000..32f97388942 --- /dev/null +++ b/docs/explanation/data-companion/README.md @@ -0,0 +1,12 @@ +--- +order: false +parent: + title: Data Companion + order: 6 +--- + +# Guides + +- [Introduction](intro.md) +- [gRPC services](grpc.md) +- [Pruning service](pruning.md) diff --git a/docs/explanation/data-companion/grpc.md b/docs/explanation/data-companion/grpc.md new file mode 100644 index 00000000000..b34d0d3ae4a --- /dev/null +++ b/docs/explanation/data-companion/grpc.md @@ -0,0 +1,216 @@ +--- +order: 1 +parent: + title: gRPC services + order: 2 +--- + + +# Fetching data from the node + +One of the most important steps to create a Data Companion service is to extract the necessary data from the node. +Fortunately, CometBFT provides gRPC endpoints that allow you to fetch the data, such as `version`, `block` and +`block results`. + +This documentation aims to provide a detailed explanation of CometBFT's gRPC services that can be used to retrieve +the data you need. + +## Enabling the gRPC services + +To utilize the gRPC services, it's necessary to enable them in CometBFT's configuration settings. + +In the `[gRPC]` section of the configuration: +``` +####################################################### +### gRPC Server Configuration Options ### +####################################################### + +# +# Note that the gRPC server is exposed unauthenticated. It is critical that +# this server not be exposed directly to the public internet. If this service +# must be accessed via the public internet, please ensure that appropriate +# precautions are taken (e.g. fronting with a reverse proxy like nginx with TLS +# termination and authentication, using DDoS protection services like +# CloudFlare, etc.). +# + +[grpc] +``` + +Add the address for the non-privileged (regular) services, for example: + +``` +# TCP or UNIX socket address for the RPC server to listen on. If not specified, +# the gRPC server will be disabled. +laddr = "tcp://0.0.0.0:26090" +``` + +The non-privileged gRPC endpoint is **enabled by default**. Each individual service exposed in this endpoint can be disabled +or enabled individually. For example, to enable the `Version` service, in the `[grpc.version_service]` section, ensure +that the `enabled` property is set to `true`: + +``` +# +# Each gRPC service can be turned on/off, and in some cases configured, +# individually. If the gRPC server is not enabled, all individual services' +# configurations are ignored. +# + +# The gRPC version service provides version information about the node and the +# protocols it uses. +[grpc.version_service] +enabled = true +``` + +Do the same thing for the `block_service` and the `block_results_service` to enable them. + +``` +# The gRPC block service returns block information +[grpc.block_service] +enabled = true + +# The gRPC block results service returns block results for a given height. If no height +# is given, it will return the block results from the latest height. +[grpc.block_results_service] +enabled = true +``` + +## Fetching **Block** data + +In order to retrieve `block` data using the gRPC block service, ensure the service is enabled as described in the section above. + +Once the service has been enabled, the Golang gRPC client provided by CometBFT can be utilized to retrieve data from the node. + +This client code is a convenient option for retrieving data, as it allows for requests to be sent and responses to be +managed in a more idiomatic manner. However, if necessary and desired, the protobuf client can also be used directly. + +Here is an example code to retrieve a block by its height: +``` +import ( + "github.com/cometbft/cometbft/rpc/grpc/client" +) + +ctx := context.Background() + +// Service Client +addr := "0.0.0.0:26090" +conn, err := client.New(ctx, addr, client.WithInsecure()) +if err != nil { + // Do something with the error +} + +block, err := conn.GetBlockByHeight(ctx, height) +if err != nil { + // Do something with the error +} else { + // Do something with the `block` +} + +``` + +## Fetching **Block Results** data + +To fetch `block results` you can use a similar code as the previous one but just invoking the method to that retrieves +block results. + +Here's an example: +``` +blockResults, err := conn.GetBlockResults(ctx, height) +if err != nil { + // Do something with the error +} else { + // Do something with the `blockResults` +} + +``` + +## Latest height streaming + +There is a new way to subscribe to a stream of new blocks with the Block service. Previously, you could connect and +subscribe to new block events using websockets through the RPC service. + +One of the advantages of the new streaming service is that it allows you to opt for the latest height subscription. +This way, the gRPC endpoint will not have to transfer entire blocks to keep you updated. Instead, you can fetch the +blocks at the desired pace through the `GetBlockByHeight` method. + +To receive the latest height from the stream, you need to call the method that returns the receive-only channel and then +watch for messages that come through the channel. The message sent on the channel is a `LatestHeightResult` struct. + +``` +// LatestHeightResult type used in GetLatestResult and send to the client +// via a channel +type LatestHeightResult struct { + Height int64 + Error error +} +``` + +Once you get a message, you can check the `Height` field for the latest height (assuming the `Error` field is nil) + +Here's an example: +``` +import ( +"github.com/cometbft/cometbft/rpc/grpc/client" +) + +ctx := context.Background() + +// Service Client +addr := "0.0.0.0:26090" +conn, err := client.New(ctx, addr, client.WithInsecure()) +if err != nil { + // Do something with the error +} + +stream, err := conn.GetLatestHeight(ctx) +if err != nil { + // Do something with the error +} + +for { + select { + case <- ctx.Done(): + return + case latestHeight, ok := <-stream: + if ok { + if latestHeight.Error != nil { + // Do something with error + } else { + // Latest Height -> latestHeight.Height + } + } else { + return + } + } +} +``` + +The ability to monitor new blocks is attractive as it unlocks avenues for creating dynamic pipelines and ingesting services +via the producer-consumer pattern. + +For instance, upon receiving a notification about a fresh block, one can activate a method to retrieve block data and +save it in a database. Subsequently, the node can set a retain height, allowing for data pruning. + +## Storing the fetched data + +In the Data Companion workflow, the second step involves saving the data retrieved from a blockchain onto an external +storage medium, such as a database. This external storage medium is important because it allows the data to be accessed +and utilized by custom web services that can serve the blockchain data in a more efficient way. + +When choosing a database, evaluate your specific needs, including data size, user access, and budget. +For example, the [RPC Companion](https://github.com/cometbft/rpc-companion) uses Postgresql as a starting point, but there +are many other options to consider. Choose a database that meets your needs and helps you achieve your objectives. + +Before proceeding to the next step, it is crucial to verify that the data has been correctly stored in the external database. +Once you have confirmed that the data has been successfully stored externally, you can proceed to update the new "retain_height" +information. This update will allow the node to prune the information that is now stored externally. + +## Pruning the node data + +In order to successfully execute the Data Companion workflow, the third step entails utilizing the newly introduced +gRPC pruning service API to set certain retain height values on the node. The pruning service allows the data companion +to effectively influence the pruning of blocks and state, ABCI results (if enabled), block indexer data and transaction +indexer data on the node. + +For a comprehensive understanding of the pruning service, please see the document +[Pruning service](pruning.md). diff --git a/docs/explanation/data-companion/intro.md b/docs/explanation/data-companion/intro.md new file mode 100644 index 00000000000..eba44b7b303 --- /dev/null +++ b/docs/explanation/data-companion/intro.md @@ -0,0 +1,26 @@ +--- +order: 1 +parent: + title: Introduction + order: 1 +--- + +# Introduction + +A proposal was made in +[ADR-101](https://github.com/cometbft/cometbft/blob/thane/adr-084-data-companion-pull-api/docs/architecture/adr-101-data-companion-pull-api.md) +to introduce new gRPC endpoints that can be used by an external application to fetch data from the node and to control +which data is pruned by the node. + +The Data Companion pruning service allows users to keep only the necessary data on the node, +enabling more efficient storage management and improved performance of the node. With this new service, users can have +greater control over their pruning mechanism and therefore better ability to optimize the node's storage. + +The new pruning service allows granular control of what can be pruned such as blocks and state, ABCI results (if enabled), block +indexer data and transaction indexer data. + +By also using the new gRPC services, it's possible now to retrieve data from the node, such as `block` and `block results` +in a more efficient way. + +The [gRPC services](grpc.md) document provides practical information and insights that will guide you through the +process of using these services in order to create a Data Companion service. diff --git a/docs/explanation/data-companion/pruning.md b/docs/explanation/data-companion/pruning.md new file mode 100644 index 00000000000..467e50ed397 --- /dev/null +++ b/docs/explanation/data-companion/pruning.md @@ -0,0 +1,338 @@ +--- +order: 1 +parent: + title: Pruning Service + order: 3 +--- + +# Pruning data via the pruning service + +CometBFT employs a sophisticated pruning logic to eliminate unnecessary data and reduce storage requirements. + +This document covers use cases where the pruning process on a CometBFT node can be influenced via the Data Companion +pruning service API. + +CometBFT provides a privileged gRPC endpoint for the pruning service. This privileged endpoint is distinct from the +non-privileged (regular) gRPC endpoint and requires separate configuration and activation. These "privileged" services +have the ability to manipulate the storage on the node. + +Therefore, **only operators who have privileged access to the server should be allowed to use them**. + +## Privileged Services configuration + +CometBFT provides "privileged" services which are not intended to be exposed to the public-facing Internet. + +The privileged services offered by CometBFT can modify the data stored in the node, and hence, it's essential to keep +them off by default to avoid any unintended modifications. + +However, when required, these services can be activated to set and retrieve a retained height, which can influence +the pruning mechanism on the node. + +To be able to use the privileged gRPC services, they should be enabled through CometBFT's configuration. + +The first step is to set the address for the privileged service, for example: +``` +# +# Configuration for privileged gRPC endpoints, which should **never** be exposed +# to the public internet. +# +[grpc.privileged] +# The host/port on which to expose privileged gRPC endpoints. +laddr = "tcp://0.0.0.0:26091" +``` + +In the `[grpc.privileged.pruning_service]` section, ensure the value `enabled` is set to `true` + +``` +# +# Configuration specifically for the gRPC pruning service, which is considered a +# privileged service. +# +[grpc.privileged.pruning_service] + +# Only controls whether the pruning service is accessible via the gRPC API - not +# whether a previously set pruning service retain height is honored by the +# node. See the [storage.pruning] section for control over pruning. +# +# Disabled by default. +enabled = true +``` + +## Pruning configuration + +Ensure that the data companion pruning is enabled in the configuration to allow the data companion to influence the +node pruning mechanism. + +In the `[storage.pruning.data_companion]` section of the CometBFT's configuration +file, the property `enabled` should be set to `true`: + +``` +[storage.pruning.data_companion] + +# Whether automatic pruning respects values set by the data companion. Disabled +# by default. All other parameters in this section are ignored when this is +# disabled. +# +# If disabled, only the application retain height will influence block pruning +# (but not block results pruning). Only enabling this at a later stage will +# potentially mean that blocks below the application-set retain height at the +# time will not be available to the data companion. +enabled = true +``` + +In order to avoid unwanted pruning of data when the data companion is activated, it is possible to define the initial +retain height for block and block results in the configuration file. This configuration ensures that the necessary data +is retained and not removed in an undesirable way. + +For example, you can change the values in this part of the configuration: +``` +# The initial value for the data companion block retain height if the data +# companion has not yet explicitly set one. If the data companion has already +# set a block retain height, this is ignored. +initial_block_retain_height = 0 + +# The initial value for the data companion block results retain height if the +# data companion has not yet explicitly set one. If the data companion has +# already set a block results retain height, this is ignored. +initial_block_results_retain_height = 10 +``` + +## Retain Height + +One important concept that can affect the pruning of nodes is the `retain height`. The retain height determines the specific +height from which the data can be safely deleted from the node's storage. By considering the retain height, +nodes can effectively manage their storage usage and ensure that they are only retaining the data that is necessary for +their operations. This is important because storage space is a finite resource and nodes with limited storage space may +struggle to keep up with the growth of the blockchain. + +## Pruning Blocks + +The pruning service uses the "block retain height" parameter to specify the height to which the node will +preserve blocks. It is important to note that this parameter differs from the application block retain height, which +the application sets in response to ABCI commit messages. + +> NOTE: In order to set the block retain height on the node, you have to enable the privileged services endpoint and the +pruning service in the configuration as described in section above. + +Once the services are enabled, you can use the Golang client provided by CometBFT to invoke the method that sets the block retain height. + +Here is an example code: +``` + +import ( + "github.com/cometbft/cometbft/rpc/grpc/client/privileged" +) + +ctx := context.Background() + +// Privileged Service Client +addr := "0.0.0.0:26091" +conn, err := privileged.New(ctx, addr, privileged.WithInsecure()) +if err != nil { + // Do something with the error +} + +err := conn.SetBlockRetainHeight(ctx, height) +if err != nil { + // Do something with the error +} +``` + +If you need to check what is the current value for the `Block Retain Height` you can use another method. + +Here's an example: +``` +retainHeight, err := conn.GetBlockRetainHeight(ctx) +if err != nil { + // Do something with the error +} else { + // Do something with + // `retainHeight.App` + // `retainHeight.PruningService` +} +``` + +Retaining data is crucial to data management, and the application has complete control over the application retain height. +The operator can monitor the application retain height with `GetBlockRetainHeight`, which returns a `RetainHeights` +structure with both the block retain height and the application retain height (as shown in the code above). + +It's worth noting that at any given point in time, the node will only accept the lowest retain height. +If you try to set the `Block Retain Height` to a value that is lower to what is currently stored in the node, an error will +be returned informing that. + +By default, both the application retain height and the data companion retain height are set to zero. This is done to prevent +either one of them from prematurely pruning the data while the other has not indicated that it's okay to do so. + +In essence, the node will preserve blocks up to the lowest value between data companion block retain height and the application +block retain height. This way, data can be reliably preserved and maintained for the necessary amount of time, ensuring +that it is not lost or prematurely deleted. + +## Pruning Block Results + +The "block results retain height" pruning parameter determines the height up to which the node will keep block results. +By retaining block results to a certain height, the node can efficiently manage its storage and optimize its performance. + +> NOTE: In order to set the block results retain height on the node, you have to enable the privileged services endpoint and the +pruning service in the configuration as described in the section above. + +Once the services are enabled, you can use the Golang client provided by CometBFT to invoke the method that sets the block results retain height. + +Here is an example code: +``` + +import ( + "github.com/cometbft/cometbft/rpc/grpc/client/privileged" +) + +ctx := context.Background() + +// Privileged Service Client +addr := "0.0.0.0:26091" +conn, err := privileged.New(ctx, addr, privileged.WithInsecure()) +if err != nil { + // Do something with the error +} + +err := conn.SetBlockResultsRetainHeight(ctx, height) +if err != nil { + // Do something with the error +} + +``` + +> NOTE: If you try to set the `Block Results Retain Height` to a value that is lower to what is currently stored in the node, an error will +be returned informing that. + +If you need to check what is the current value for the `Block Results Retain Height` you can use another method. + +Here's an example: +``` +retainHeight, err := conn.GetBlockResultsRetainHeight(ctx) +if err != nil { + // Do something with the error +} else { + // Do something with the `retainHeight` value +} + +``` + +> NOTE: Please note that if the `discard_abci_responses` in the `[storage]` section of the configuration file is set to `true`, then +block results are **not stored** on the node and the `Block Results Retain Height` will be ignored. In order to have block +results pruned the value should be set to `false` (default) + +``` +####################################################### +### Storage Configuration Options ### +####################################################### +[storage] + +# Set to true to discard ABCI responses from the state store, which can save a +# considerable amount of disk space. Set to false to ensure ABCI responses are +# persisted. ABCI responses are required for /block_results RPC queries, and to +# reindex events in the command-line tool. +discard_abci_responses = false +``` + +## Pruning Block Indexed Data + +The "block indexer retain height" pruning parameter determines the height up to which the node will keep block indexed data. + +> NOTE: In order to set the block indexer retain height on the node, you have to enable the privileged services endpoint and the +pruning service in the configuration as described in the section above. + +Once the services are enabled, you can use the Golang client provided by CometBFT to invoke the method that sets the block +indexer retain height. + +Here is an example code: +``` + +import ( +"github.com/cometbft/cometbft/rpc/grpc/client/privileged" +) + +ctx := context.Background() + +// Privileged Service Client +addr := "0.0.0.0:26091" +conn, err := privileged.New(ctx, addr, privileged.WithInsecure()) +if err != nil { + // Do something with the error +} + +err := conn.SetBlockIndexerRetainHeight(ctx, height) +if err != nil { + // Do something with the error +} + +``` + +> NOTE: If you try to set the `Block Indexer Retain Height` to a value that is lower to what is currently stored in the node, an error will +be returned informing that. + +If you need to check what is the current value for the `Block Indexer Retain Height` you can use another method. + +Here's an example: +``` +retainHeight, err := conn.GetBlockIndexerRetainHeight(ctx) +if err != nil { + // Do something with the error +} else { + // Do something with the `retainHeight` value +} + +``` + +## Pruning Transaction Indexed Data + +The "tx indexer retain height" pruning parameter determines the height up to which the node will keep transaction indexed data. + +> NOTE: In order to set the tx indexer retain height on the node, you have to enable the privileged services endpoint and the +pruning service in the configuration as described in the section above. + +Once the services are enabled, you can use the Golang client provided by CometBFT to invoke the method that sets the tx +indexer retain height. + +Here is an example code: +``` + +import ( +"github.com/cometbft/cometbft/rpc/grpc/client/privileged" +) + +ctx := context.Background() + +// Privileged Service Client +addr := "0.0.0.0:26091" +conn, err := privileged.New(ctx, addr, privileged.WithInsecure()) +if err != nil { + // Do something with the error +} + +err := conn.SetTxIndexerRetainHeight(ctx, height) +if err != nil { + // Do something with the error +} + +``` + +> NOTE: If you try to set the `Tx Indexer Retain Height` to a value that is lower to what is currently stored in the node, an error will +be returned informing that. + +If you need to check what is the current value for the `Tx Indexer Retain Height` you can use another method. + +Here's an example: +``` +retainHeight, err := conn.GetTxIndexerRetainHeight(ctx) +if err != nil { + // Do something with the error +} else { + // Do something with the `retainHeight` value +} + +``` + +## Conclusion + +Utilizing the pruning service can unlock remarkable benefits for your node. Whether used with a Data Companion service +or as a standalone solution, it can greatly enhance the pruning mechanism on your node, leading to significant cost +savings in node operation. diff --git a/docs/introduction/README.md b/docs/explanation/introduction/README.md similarity index 94% rename from docs/introduction/README.md rename to docs/explanation/introduction/README.md index 1c2b5850b38..b3179b50163 100644 --- a/docs/introduction/README.md +++ b/docs/explanation/introduction/README.md @@ -193,17 +193,16 @@ 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 +The **FinalizeBlock** message is the work horse of the application. Each +transaction in the blockchain is finalized within 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 +**FinalizeBlock** message against the current state, application protocol, +and the cryptographic credentials of the transaction. FinalizeBlock only +prepares the update to be made and does not change the state of the application. +The state change is actually committed in a later stage i.e. in commit phase. + +The **CheckTx** message is used 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 @@ -220,17 +219,17 @@ 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. +CometBFT creates four 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, one for creating snapshots of the +application state, and one more for querying the application state. It's probably evident that application 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) +![abci](../../imgs/abci.png) ## A Note on Determinism @@ -265,7 +264,7 @@ 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) +![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 diff --git a/docs/guides/README.md b/docs/guides/README.md index b563396313a..16a37f131ed 100644 --- a/docs/guides/README.md +++ b/docs/guides/README.md @@ -1,12 +1,22 @@ --- -order: false +order: 2 +title: CometBFT How-to Guides +description: How-to Guides parent: - order: 2 + order: 1 --- -# Guides +# How-To 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) +CometBFT How-To Guides is a resource center that provides users with comprehensive guides +on how to develop applications, use essential tools, and run networks powered by the +CometBFT consensus algorithm. The guides are suitable for developers, system administrators, +and blockchain enthusiasts who want to gain practical skills and knowledge in distributed +systems and blockchain technology using CometBFT. + +The CometBFT How-To Guides are designed to provide step-by-step instructions and practical +examples to help users acquire real-world experience while learning. + +- [Application Development](./app-dev/README.md) +- [Tools](./tools/README.md) +- [Running Networks](./networks/README.md) diff --git a/docs/guides/app-dev/README.md b/docs/guides/app-dev/README.md new file mode 100644 index 00000000000..abde0fc08bc --- /dev/null +++ b/docs/guides/app-dev/README.md @@ -0,0 +1,12 @@ +--- +order: false +parent: + order: 3 +--- + +# Apps + +- [Using ABCI-CLI](abci-cli.md) +- [Getting Started](getting-started.md) +- [Indexing transactions](indexing-transactions.md) +- [Application Architecture Guide](app-architecture.md) diff --git a/docs/app-dev/abci-cli.md b/docs/guides/app-dev/abci-cli.md similarity index 79% rename from docs/app-dev/abci-cli.md rename to docs/guides/app-dev/abci-cli.md index 17aa4f2bf2e..c38da3372e7 100644 --- a/docs/app-dev/abci-cli.md +++ b/docs/guides/app-dev/abci-cli.md @@ -1,5 +1,5 @@ --- -order: 2 +order: 3 --- # Using ABCI-CLI @@ -62,51 +62,10 @@ The most important messages are `deliver_tx`, `check_tx`, and `commit`, but there are others for convenience, configuration, and information purposes. -We'll start a kvstore application, which was installed at the same time -as `abci-cli` above. The kvstore just stores transactions in a merkle -tree. Its code can be found -[here](https://github.com/cometbft/cometbft/blob/main/abci/cmd/abci-cli/abci-cli.go) -and looks like the following: - -```go -func cmdKVStore(cmd *cobra.Command, args []string) error { - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Create the application - in memory or persisted to disk - var app types.Application - if flagPersist == "" { - var err error - flagPersist, err = os.MkdirTemp("", "persistent_kvstore_tmp") - if err != nil { - return err - } - } - app = kvstore.NewPersistentKVStoreApplication(flagPersist) - app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) - - // Start the listener - srv, err := server.NewServer(flagAddress, flagAbci, app) - if err != nil { - return err - } - srv.SetLogger(logger.With("module", "abci-server")) - if err := srv.Start(); err != nil { - return err - } - - // Stop upon receiving SIGTERM or CTRL-C. - tmos.TrapSignal(logger, func() { - // Cleanup - if err := srv.Stop(); err != nil { - logger.Error("Error while stopping server", "err", err) - } - }) - - // Run forever. - select {} -} - -``` +We'll start a kvstore application, which was installed at the same time as +`abci-cli` above. The kvstore just stores transactions in a Merkle tree. Its +code can be found +[here](https://github.com/cometbft/cometbft/blob/main/abci/example/kvstore/kvstore.go). Start the application by running: @@ -184,11 +143,11 @@ Try running these commands: > process_proposal "abc==456" -> code: OK --> status: REJECT +-> status: PROCESS_PROPOSAL_STATUS_REJECT > process_proposal "abc=123" -> code: OK --> status: ACCEPT +-> status: PROCESS_PROPOSAL_STATUS_ACCEPT > finalize_block "abc=123" -> code: OK @@ -240,11 +199,11 @@ You could put the commands in a file and run Note that the `abci-cli` is designed strictly for testing and debugging. In a real deployment, the role of sending messages is taken by CometBFT, which -connects to the app using three separate connections, each with its own +connects to the app using four separate connections, each with its own pattern of messages. For examples of running an ABCI app with CometBFT, see the -[getting started guide](./getting-started.md). +[getting started guide](getting-started.md). ## Bounties diff --git a/docs/app-dev/app-architecture.md b/docs/guides/app-dev/app-architecture.md similarity index 96% rename from docs/app-dev/app-architecture.md rename to docs/guides/app-dev/app-architecture.md index 97ebf502cf2..a8b4fd41603 100644 --- a/docs/app-dev/app-architecture.md +++ b/docs/guides/app-dev/app-architecture.md @@ -1,5 +1,5 @@ --- -order: 3 +order: 4 --- # Application Architecture Guide @@ -51,5 +51,5 @@ See the following for more extensive documentation: - [Interchain Standard for the Light-Client REST API](https://github.com/cosmos/cosmos-sdk/pull/1617) (legacy/deprecated) - [CometBFT RPC Docs](https://docs.cometbft.com/main/rpc/) -- [CometBFT in Production](../core/running-in-production.md) +- [CometBFT in Production](../../explanation/core/running-in-production.md) - [ABCI spec](https://github.com/cometbft/cometbft/tree/main/spec/abci) diff --git a/docs/app-dev/getting-started.md b/docs/guides/app-dev/getting-started.md similarity index 95% rename from docs/app-dev/getting-started.md rename to docs/guides/app-dev/getting-started.md index 94076287224..d576f5b52a0 100644 --- a/docs/app-dev/getting-started.md +++ b/docs/guides/app-dev/getting-started.md @@ -1,5 +1,5 @@ --- -order: 1 +order: 2 --- # Getting Started @@ -11,7 +11,7 @@ application you want to run. So, to run a complete blockchain that does something useful, you must start two programs: one is CometBFT, the other is your application, which can be written in any programming language. Recall from [the intro to -ABCI](../introduction/what-is-cometbft.md#abci-overview) that CometBFT +ABCI](../explanation/introduction/what-is-cometbft.md#abci-overview) that CometBFT handles all the p2p and consensus stuff, and just forwards transactions to the application when they need to be validated, or when they're ready to be executed and committed. @@ -92,7 +92,7 @@ abci-cli kvstore In another terminal, we can start CometBFT. You should already have the CometBFT binary installed. If not, follow the steps from -[here](../introduction/install.md). If you have never run CometBFT +[here](../explanation/introduction/install.md). If you have never run CometBFT before, use: ```sh @@ -103,7 +103,7 @@ cometbft node If you have used CometBFT, you may want to reset the data for a new blockchain by running `cometbft unsafe-reset-all`. Then you can run `cometbft node` to start CometBFT, and connect to the app. For more -details, see [the guide on using CometBFT](../core/using-cometbft.md). +details, see [the guide on using CometBFT](../../explanation/core/using-cometbft.md). You should see CometBFT making blocks! We can get the status of our CometBFT node as follows: diff --git a/docs/app-dev/indexing-transactions.md b/docs/guides/app-dev/indexing-transactions.md similarity index 87% rename from docs/app-dev/indexing-transactions.md rename to docs/guides/app-dev/indexing-transactions.md index d6ee4e0ceb7..69f610a3bb1 100644 --- a/docs/app-dev/indexing-transactions.md +++ b/docs/guides/app-dev/indexing-transactions.md @@ -1,12 +1,12 @@ --- -order: 6 +order: 5 --- # Indexing Transactions CometBFT allows you to index transactions and blocks and later query or -subscribe to their results. Transactions are indexed by `ResponseFinalizeBlock.tx_results.events` and -blocks are indexed by `ResponseFinalizeBlock.events`. However, transactions +subscribe to their results. Transactions are indexed by `FinalizeBlockResponse.tx_results.events` and +blocks are indexed by `FinalizeBlockResponse.events`. However, transactions are also indexed by a primary key which includes the transaction hash and maps 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. @@ -14,11 +14,7 @@ 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. +details on `Events`, see the [ABCI][abci-events] documentation. An `Event` has a composite key associated with it. A `compositeKey` is constructed by its type and key separated by a dot. @@ -175,7 +171,7 @@ UTF-8 encoded strings (e.g. "transfer.sender": "Bob", "transfer.recipient": Example: ```go -func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { +func (app *Application) FinalizeBlock(_ context.Context, req *types.FinalizeBlockRequest) (*types.FinalizeBlockResponse, error) { //... tx_results[0] := &types.ExecTxResult{ @@ -219,7 +215,7 @@ func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinal }, }, } - return &types.ResponseFinalizeBlock{TxResults: tx_results, Events: block_events} + return &types.FinalizeBlockResponse{TxResults: tx_results, Events: block_events} } ``` @@ -276,3 +272,14 @@ This behavior was fixed with CometBFT 0.34.26+. However, if the data was indexed Tendermint Core and not re-indexed, that data will be queried as if all the attributes within a height occurred within the same event. +## Event attribute value types + +Users can use anything as an event value. However, if the event attribute value is a number, the following needs to be taken into account: + +- Negative numbers will not be properly retrieved when querying the indexer. +- Event values are converted to big floats (from the `big/math` package). The precision of the floating point number is set to the bit length +of the integer it is supposed to represent, so that there is no loss of information due to insufficient precision. This was not present before CometBFT v0.38.x and all float values were ignored. +- As of CometBFT v0.38.x, queries can contain floating point numbers as well. +- Note that comparing to floats can be imprecise with a high number of decimals. + +[abci-events]: https://github.com/cometbft/cometbft/blob/main/spec/abci/abci++_basic_concepts.md#events diff --git a/docs/guides/go-built-in.md b/docs/guides/go-built-in.md deleted file mode 100644 index c0e780bf95c..00000000000 --- a/docs/guides/go-built-in.md +++ /dev/null @@ -1,799 +0,0 @@ ---- -order: 2 ---- - -# Creating a built-in application in Go - -## Guide Assumptions - -This guide is designed for beginners who want to get started with a CometBFT -application from scratch. It does not assume that you have any prior -experience with CometBFT. - -CometBFT is a service that provides a Byzantine Fault Tolerant consensus engine -for state-machine replication. The replicated state-machine, or "application", can be written -in any language that can send and receive protocol buffer messages in a client-server model. -Applications written in Go can also use CometBFT as a library and run the service in the same -process as the application. - -By following along this tutorial you will create a CometBFT application called kvstore, -a (very) simple distributed BFT key-value store. -The application will be written in Go and -some understanding of the Go programming language is expected. -If you have never written Go, you may want to go through [Learn X in Y minutes -Where X=Go](https://learnxinyminutes.com/docs/go/) first, to familiarize -yourself with the syntax. - -Note: Please use the latest released version of this guide and of CometBFT. -We strongly advise against using unreleased commits for your development. - -### Built-in app vs external app - -On the one hand, to get maximum performance you can run your application in -the same process as the CometBFT, as long as your application is written in Go. -[Cosmos SDK](https://github.com/cosmos/cosmos-sdk) is written -this way. -This is the approach followed in this tutorial. - -On the other hand, having a separate application might give you better security -guarantees as two processes would be communicating via established binary protocol. -CometBFT will not have access to application's state. -If that is the way you wish to proceed, use the [Creating an application in Go](./go.md) guide instead of this one. - - -## 1.1 Installing Go - -Verify that you have the latest version of Go installed (refer to the [official guide for installing Go](https://golang.org/doc/install)): - -```bash -$ go version -go version go1.20.1 darwin/amd64 -``` - -## 1.2 Creating a new Go project - -We'll start by creating a new Go project. - -```bash -mkdir kvstore -``` - -Inside the example directory, create a `main.go` file with the following content: - -```go -package main - -import ( - "fmt" -) - -func main() { - fmt.Println("Hello, CometBFT") -} -``` - -When run, this should print "Hello, CometBFT" to the standard output. - -```bash -cd kvstore -$ go run main.go -Hello, CometBFT -``` - -We are going to use [Go modules](https://github.com/golang/go/wiki/Modules) for -dependency management, so let's start by including a dependency on the latest version of -CometBFT, `v0.37.0` in this example. - -```bash -go mod init kvstore -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`. -The go.mod file should look similar to: - -```go -module github.com/me/example - -go 1.20 - -require ( - github.com/cometbft/cometbft v0.37.0 -) -``` - -As you write the kvstore application, you can rebuild the binary by -pulling any new dependencies and recompiling it. - -```sh -go get -go build -``` - -## 1.3 Writing a CometBFT application - -CometBFT communicates with the application through the Application -BlockChain Interface (ABCI). The messages exchanged through the interface are -defined in the ABCI [protobuf -file](https://github.com/cometbft/cometbft/blob/v0.37.x/proto/tendermint/abci/types.proto). - -We begin by creating the basic scaffolding for an ABCI application by -creating a new type, `KVStoreApplication`, which implements the -methods defined by the `abcitypes.Application` interface. - -Create a file called `app.go` with the following contents: - -```go -package main - -import ( - abcitypes "github.com/cometbft/cometbft/abci/types" -) - -type KVStoreApplication struct{} - -var _ abcitypes.Application = (*KVStoreApplication)(nil) - -func NewKVStoreApplication() *KVStoreApplication { - return &KVStoreApplication{} -} - -func (app *KVStoreApplication) Info(info abcitypes.RequestInfo) abcitypes.ResponseInfo { - return abcitypes.ResponseInfo{} -} - -func (app *KVStoreApplication) Query(query abcitypes.RequestQuery) abcitypes.ResponseQuery { - return abcitypes.ResponseQuery{} -} - -func (app *KVStoreApplication) CheckTx(tx abcitypes.RequestCheckTx) abcitypes.ResponseCheckTx { - return abcitypes.ResponseCheckTx{} -} - -func (app *KVStoreApplication) InitChain(chain abcitypes.RequestInitChain) abcitypes.ResponseInitChain { - return abcitypes.ResponseInitChain{} -} - -func (app *KVStoreApplication) PrepareProposal(proposal abcitypes.RequestPrepareProposal) abcitypes.ResponsePrepareProposal { - return abcitypes.ResponsePrepareProposal{} -} - -func (app *KVStoreApplication) ProcessProposal(proposal abcitypes.RequestProcessProposal) abcitypes.ResponseProcessProposal { - return abcitypes.ResponseProcessProposal{} -} - -func (app *KVStoreApplication) BeginBlock(block abcitypes.RequestBeginBlock) abcitypes.ResponseBeginBlock { - return abcitypes.ResponseBeginBlock{} -} - -func (app *KVStoreApplication) DeliverTx(tx abcitypes.RequestDeliverTx) abcitypes.ResponseDeliverTx { - return abcitypes.ResponseDeliverTx{} -} - -func (app *KVStoreApplication) EndBlock(block abcitypes.RequestEndBlock) abcitypes.ResponseEndBlock { - return abcitypes.ResponseEndBlock{} -} - -func (app *KVStoreApplication) Commit() abcitypes.ResponseCommit { - return abcitypes.ResponseCommit{} -} - -func (app *KVStoreApplication) ListSnapshots(snapshots abcitypes.RequestListSnapshots) abcitypes.ResponseListSnapshots { - return abcitypes.ResponseListSnapshots{} -} - -func (app *KVStoreApplication) OfferSnapshot(snapshot abcitypes.RequestOfferSnapshot) abcitypes.ResponseOfferSnapshot { - return abcitypes.ResponseOfferSnapshot{} -} - -func (app *KVStoreApplication) LoadSnapshotChunk(chunk abcitypes.RequestLoadSnapshotChunk) abcitypes.ResponseLoadSnapshotChunk { - return abcitypes.ResponseLoadSnapshotChunk{} -} - -func (app *KVStoreApplication) ApplySnapshotChunk(chunk abcitypes.RequestApplySnapshotChunk) abcitypes.ResponseApplySnapshotChunk { - return abcitypes.ResponseApplySnapshotChunk{} -} -``` - -The types used here are defined in the CometBFT library and were added as a dependency -to the project when you ran `go get`. If your IDE is not recognizing the types, go ahead and run the command again. - -```bash -go get github.com/cometbft/cometbft@v0.37.0 -``` - -Now go back to the `main.go` and modify the `main` function so it matches the following, -where an instance of the `KVStoreApplication` type is created. - -```go -func main() { - fmt.Println("Hello, CometBFT") - - _ = NewKVStoreApplication() -} -``` - -You can recompile and run the application now by running `go get` and `go build`, but it does -not do anything. -So let's revisit the code adding the logic needed to implement our minimal key/value store -and to start it along with the CometBFT Service. - - -### 1.3.1 Add a persistent data store - -Our application will need to write its state out to persistent storage so that it -can stop and start without losing all of its data. - -For this tutorial, we will use [BadgerDB](https://github.com/dgraph-io/badger), a -fast embedded key-value store. - -First, add Badger as a dependency of your go module using the `go get` command: - -`go get github.com/dgraph-io/badger/v3` - -Next, let's update the application and its constructor to receive a handle to the database, as follows: - -```go -type KVStoreApplication struct { - db *badger.DB - onGoingBlock *badger.Txn -} - -var _ abcitypes.Application = (*KVStoreApplication)(nil) - -func NewKVStoreApplication(db *badger.DB) *KVStoreApplication { - return &KVStoreApplication{db: db} -} -``` - -The `onGoingBlock` keeps track of the Badger transaction that will update the application's state when a block -is completed. Don't worry about it for now, we'll get to that later. - -Next, update the `import` stanza at the top to include the Badger library: - -```go -import( - "github.com/dgraph-io/badger/v3" - abcitypes "github.com/cometbft/cometbft/abci/types" -) -``` - -Finally, update the `main.go` file to invoke the updated constructor: - -```go - _ = NewKVStoreApplication(nil) -``` - -### 1.3.2 CheckTx - -When CometBFT receives a new transaction from a client, or from another full node, -CometBFT asks the application if the transaction is acceptable, using the `CheckTx` method. -Invalid transactions will not be shared with other nodes and will not become part of any blocks and, therefore, will not be executed by the application. - -In our application, a transaction is a string with the form `key=value`, indicating a key and value to write to the store. - -The most basic validation check we can perform is to check if the transaction conforms to the `key=value` pattern. -For that, let's add the following helper method to app.go: - -```go -func (app *KVStoreApplication) isValid(tx []byte) uint32 { - // check format - parts := bytes.Split(tx, []byte("=")) - if len(parts) != 2 { - return 1 - } - - return 0 -} -``` - -Now you can rewrite the `CheckTx` method to use the helper function: - -```go -func (app *KVStoreApplication) CheckTx(req abcitypes.RequestCheckTx) abcitypes.ResponseCheckTx { - code := app.isValid(req.Tx) - return abcitypes.ResponseCheckTx{Code: code} -} -``` - -While this `CheckTx` is simple and only validates that the transaction is well-formed, -it is very common for `CheckTx` to make more complex use of the state of an application. -For example, you may refuse to overwrite an existing value, or you can associate -versions to the key/value pairs and allow the caller to specify a version to -perform a conditional update. - -Depending on the checks and on the conditions violated, the function may return -different values, but any response with a non-zero code will be considered invalid -by CometBFT. Our `CheckTx` logic returns 0 to CometBFT when a transaction passes -its validation checks. The specific value of the code is meaningless to CometBFT. -Non-zero codes are logged by CometBFT so applications can provide more specific -information on why the transaction was rejected. - -Note that `CheckTx` does not execute the transaction, it only verifies that the transaction could be executed. We do not know yet if the rest of the network has agreed to accept this transaction into a block. - - -Finally, make sure to add the bytes package to the `import` stanza at the top of `app.go`: - -```go -import( - "bytes" - - "github.com/dgraph-io/badger/v3" - abcitypes "github.com/cometbft/cometbft/abci/types" -) -``` - - -### 1.3.3 BeginBlock -> DeliverTx -> EndBlock -> Commit - -When the CometBFT consensus engine has decided on the block, the block is transferred to the -application over three ABCI method calls: `BeginBlock`, `DeliverTx`, and `EndBlock`. - -- `BeginBlock` is called once to indicate to the application that it is about to -receive a block. -- `DeliverTx` is called repeatedly, once for each application transaction that was included in the block. -- `EndBlock` is called once to indicate to the application that no more transactions -will be delivered to the application within this block. - -Note that, to implement these calls in our application we're going to make use of Badger's -transaction mechanism. We will always refer to these as Badger transactions, not to -confuse them with the transactions included in the blocks delivered by CometBFT, -the _application transactions_. - -First, let's create a new Badger transaction during `BeginBlock`. All application transactions in the -current block will be executed within this Badger transaction. -Then, return informing CometBFT that the application is ready to receive application transactions: - -```go -func (app *KVStoreApplication) BeginBlock(req abcitypes.RequestBeginBlock) abcitypes.ResponseBeginBlock { - app.onGoingBlock = app.db.NewTransaction(true) - return abcitypes.ResponseBeginBlock{} -} -``` - -Next, let's modify `DeliverTx` to add the `key` and `value` to the database transaction every time our application -receives a new application transaction through `RequestDeliverTx`. - -```go -func (app *KVStoreApplication) DeliverTx(req abcitypes.RequestDeliverTx) abcitypes.ResponseDeliverTx { - if code := app.isValid(req.Tx); code != 0 { - return abcitypes.ResponseDeliverTx{Code: code} - } - - parts := bytes.SplitN(req.Tx, []byte("="), 2) - key, value := parts[0], parts[1] - - if err := app.onGoingBlock.Set(key, value); err != nil { - log.Panicf("Error writing to database, unable to execute tx: %v", err) - } - - return abcitypes.ResponseDeliverTx{Code: 0} -} -``` - -Note that we check the validity of the transaction _again_ during `DeliverTx`. -Transactions are not guaranteed to be valid when they are delivered to an -application, even if they were valid when they were proposed. -This can happen if the application state is used to determine transaction -validity. Application state may have changed between the initial execution of `CheckTx` -and the transaction delivery in `DeliverTx` in a way that rendered the transaction -no longer valid. - -`EndBlock` is called to inform the application that the full block has been delivered -and give the application a chance to perform any other computation needed, before the -effects of the transactions become permanent. - -Note that `EndBlock` **cannot** yet commit the Badger transaction we were building -in during `DeliverTx`. -Since other methods, such as `Query`, rely on a consistent view of the application's -state, the application should only update its state by committing the Badger transactions -when the full block has been delivered and the `Commit` method is invoked. - -The `Commit` method tells the application to make permanent the effects of -the application transactions. -Let's update the method to terminate the pending Badger transaction and -persist the resulting state: - -```go -func (app *KVStoreApplication) Commit() abcitypes.ResponseCommit { - if err := app.onGoingBlock.Commit(); err != nil { - log.Panicf("Error writing to database, unable to commit block: %v", err) - } - return abcitypes.ResponseCommit{Data: []byte{}} -} -``` - -Finally, make sure to add the log library to the `import` stanza as well: - -```go -import ( - "bytes" - "log" - - "github.com/dgraph-io/badger/v3" - abcitypes "github.com/cometbft/cometbft/abci/types" -) -``` - -You may have noticed that the application we are writing will crash if it receives -an unexpected error from the Badger database during the `DeliverTx` or `Commit` methods. -This is not an accident. If the application received an error from the database, there -is no deterministic way for it to make progress so the only safe option is to terminate. - -### 1.3.4 Query - -When a client tries to read some information from the `kvstore`, the request will be -handled in the `Query` method. To do this, let's rewrite the `Query` method in `app.go`: - -```go -func (app *KVStoreApplication) Query(req abcitypes.RequestQuery) abcitypes.ResponseQuery { - resp := abcitypes.ResponseQuery{Key: req.Data} - - dbErr := app.db.View(func(txn *badger.Txn) error { - item, err := txn.Get(req.Data) - if err != nil { - if err != badger.ErrKeyNotFound { - return err - } - resp.Log = "key does not exist" - return nil - } - - return item.Value(func(val []byte) error { - resp.Log = "exists" - resp.Value = val - return nil - }) - }) - if dbErr != nil { - log.Panicf("Error reading database, unable to execute query: %v", dbErr) - } - return resp -} -``` - -Since it reads only committed data from the store, transactions that are part of a block -that is being processed are not reflected in the query result. - -### 1.3.5 PrepareProposal and ProcessProposal - -`PrepareProposal` and `ProcessProposal` are methods introduced in CometBFT v0.37.0 -to give the application more control over the construction and processing of transaction blocks. - -When CometBFT sees that valid transactions (validated through `CheckTx`) are available to be -included in blocks, it groups some of these transactions and then gives the application a chance -to modify the group by invoking `PrepareProposal`. - -The application is free to modify the group before returning from the call, as long as the resulting set -does not use more bytes than `RequestPrepareProposal.max_tx_bytes' -For example, the application may reorder, add, or even remove transactions from the group to improve the -execution of the block once accepted. -In the following code, the application simply returns the unmodified group of transactions: - -```go -func (app *KVStoreApplication) PrepareProposal(proposal abcitypes.RequestPrepareProposal) abcitypes.ResponsePrepareProposal { - return abcitypes.ResponsePrepareProposal{Txs: proposal.Txs} -} -``` - -Once a proposed block is received by a node, the proposal is passed to the application to give -its blessing before voting to accept the proposal. - -This mechanism may be used for different reasons, for example to deal with blocks manipulated -by malicious nodes, in which case the block should not be considered valid. -The following code simply accepts all proposals: - -```go -func (app *KVStoreApplication) ProcessProposal(proposal abcitypes.RequestProcessProposal) abcitypes.ResponseProcessProposal { - return abcitypes.ResponseProcessProposal{Status: abcitypes.ResponseProcessProposal_ACCEPT} -} -``` - -## 1.4 Starting an application and a CometBFT instance in the same process - -Now that we have the basic functionality of our application in place, let's put it all together inside of our main.go file. - -Change the contents of your `main.go` file to the following. - -```go -package main - -import ( - "flag" - "fmt" - "github.com/cometbft/cometbft/p2p" - "github.com/cometbft/cometbft/privval" - "github.com/cometbft/cometbft/proxy" - "log" - "os" - "os/signal" - "path/filepath" - "syscall" - - "github.com/dgraph-io/badger/v3" - "github.com/spf13/viper" - cfg "github.com/cometbft/cometbft/config" - cmtflags "github.com/cometbft/cometbft/libs/cli/flags" - cmtlog "github.com/cometbft/cometbft/libs/log" - nm "github.com/cometbft/cometbft/node" -) - -var homeDir string - -func init() { - flag.StringVar(&homeDir, "cmt-home", "", "Path to the CometBFT config directory (if empty, uses $HOME/.cometbft)") -} - -func main() { - flag.Parse() - if homeDir == "" { - homeDir = os.ExpandEnv("$HOME/.cometbft") - } - config := cfg.DefaultConfig() - - config.SetRoot(homeDir) - - viper.SetConfigFile(fmt.Sprintf("%s/%s", homeDir, "config/config.toml")) - if err := viper.ReadInConfig(); err != nil { - log.Fatalf("Reading config: %v", err) - } - if err := viper.Unmarshal(config); err != nil { - log.Fatalf("Decoding config: %v", err) - } - if err := config.ValidateBasic(); err != nil { - log.Fatalf("Invalid configuration data: %v", err) - } - - dbPath := filepath.Join(homeDir, "badger") - db, err := badger.Open(badger.DefaultOptions(dbPath)) - if err != nil { - log.Fatalf("Opening database: %v", err) - } - defer func() { - if err := db.Close(); err != nil { - log.Printf("Closing database: %v", err) - } - }() - - app := NewKVStoreApplication(db) - - pv := privval.LoadFilePV( - config.PrivValidatorKeyFile(), - config.PrivValidatorStateFile(), - ) - - nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) - if err != nil { - log.Fatalf("failed to load node's key: %v", err) - } - - logger := cmtlog.NewTMLogger(cmtlog.NewSyncWriter(os.Stdout)) - logger, err = cmtflags.ParseLogLevel(config.LogLevel, logger, cfg.DefaultLogLevel) - if err != nil { - log.Fatalf("failed to parse log level: %v", err) - } - - node, err := nm.NewNode( - config, - pv, - nodeKey, - proxy.NewLocalClientCreator(app), - nm.DefaultGenesisDocProviderFunc(config), - nm.DefaultDBProvider, - nm.DefaultMetricsProvider(config.Instrumentation), - logger) - - if err != nil { - log.Fatalf("Creating node: %v", err) - } - - node.Start() - defer func() { - node.Stop() - node.Wait() - }() - - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - <-c -} -``` - -This is a huge blob of code, so let's break it down into pieces. - -First, we use [viper](https://github.com/spf13/viper) to load the CometBFT configuration files, which we will generate later: - - -```go - config := cfg.DefaultValidatorConfig() - - config.SetRoot(homeDir) - - viper.SetConfigFile(fmt.Sprintf("%s/%s", homeDir, "config/config.toml")) - if err := viper.ReadInConfig(); err != nil { - log.Fatalf("Reading config: %v", err) - } - if err := viper.Unmarshal(config); err != nil { - log.Fatalf("Decoding config: %v", err) - } - if err := config.ValidateBasic(); err != nil { - log.Fatalf("Invalid configuration data: %v", err) - } -``` - -Next, we initialize the Badger database and create an app instance. - -```go - dbPath := filepath.Join(homeDir, "badger") - db, err := badger.Open(badger.DefaultOptions(dbPath)) - if err != nil { - log.Fatalf("Opening database: %v", err) - } - defer func() { - if err := db.Close(); err != nil { - log.Fatalf("Closing database: %v", err) - } - }() - - app := NewKVStoreApplication(db) -``` - -We use `FilePV`, which is a private validator (i.e. thing which signs consensus -messages). Normally, you would use `SignerRemote` to connect to an external -[HSM](https://kb.certus.one/hsm.html). - -```go - pv := privval.LoadFilePV( - config.PrivValidatorKeyFile(), - config.PrivValidatorStateFile(), - ) -``` - -`nodeKey` is needed to identify the node in a p2p network. - -```go - nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) - if err != nil { - return nil, fmt.Errorf("failed to load node's key: %w", err) - } -``` - -Now we have everything set up to run the CometBFT node. We construct -a node by passing it the configuration, the logger, a handle to our application and -the genesis information: - -```go - node, err := nm.NewNode( - config, - pv, - nodeKey, - proxy.NewLocalClientCreator(app), - nm.DefaultGenesisDocProviderFunc(config), - nm.DefaultDBProvider, - nm.DefaultMetricsProvider(config.Instrumentation), - logger) - - if err != nil { - log.Fatalf("Creating node: %v", err) - } -``` - -Finally, we start the node, i.e., the CometBFT service inside our application: - -```go - node.Start() - defer func() { - node.Stop() - node.Wait() - }() -``` - -The additional logic at the end of the file allows the program to catch SIGTERM. This means that the node can shut down gracefully when an operator tries to kill the program: - -```go - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - <-c -``` - -## 1.5 Initializing and Running - -Our application is almost ready to run, but first we'll need to populate the CometBFT configuration files. -The following command will create a `cometbft-home` directory in your project and add a basic set of configuration files in `cometbft-home/config/`. -For more information on what these files contain see [the configuration documentation](https://github.com/cometbft/cometbft/blob/v0.37.x/docs/core/configuration.md). - -From the root of your project, run: - -```bash -go run github.com/cometbft/cometbft/cmd/cometbft@v0.37.0 init --home /tmp/cometbft-home -``` - -You should see an output similar to the following: - -```bash -I[2022-11-09|09:06:34.444] Generated private validator module=main keyFile=/tmp/cometbft-home/config/priv_validator_key.json stateFile=/tmp/cometbft-home/data/priv_validator_state.json -I[2022-11-09|09:06:34.444] Generated node key module=main path=/tmp/cometbft-home/config/node_key.json -I[2022-11-09|09:06:34.444] Generated genesis file module=main path=/tmp/cometbft-home/config/genesis.json -``` - -Now rebuild the app: - -```bash -go build -mod=mod # use -mod=mod to automatically refresh the dependencies -``` - -Everything is now in place to run your application. Run: - -```bash -./kvstore -cmt-home /tmp/cometbft-home -``` - -The application will start and you should see a continuous output starting with: - -```bash -badger 2022/11/09 09:08:50 INFO: All 0 tables opened in 0s -badger 2022/11/09 09:08:50 INFO: Discard stats nextEmptySlot: 0 -badger 2022/11/09 09:08:50 INFO: Set nextTxnTs to 0 -I[2022-11-09|09:08:50.085] service start module=proxy msg="Starting multiAppConn service" impl=multiAppConn -I[2022-11-09|09:08:50.085] service start module=abci-client connection=query msg="Starting localClient service" impl=localClient -I[2022-11-09|09:08:50.085] service start module=abci-client connection=snapshot msg="Starting localClient service" impl=localClient -... -``` - -More importantly, the application using CometBFT is producing blocks 🎉🎉 and you can see this reflected in the log output in lines like this: - -```bash -I[2022-11-09|09:08:52.147] received proposal module=consensus proposal="Proposal{2/0 (F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C:1:C73D3D1273F2, -1) AD19AE292A45 @ 2022-11-09T12:08:52.143393Z}" -I[2022-11-09|09:08:52.152] received complete proposal block module=consensus height=2 hash=F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C -I[2022-11-09|09:08:52.160] finalizing commit of block module=consensus height=2 hash=F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C root= num_txs=0 -I[2022-11-09|09:08:52.167] executed block module=state height=2 num_valid_txs=0 num_invalid_txs=0 -I[2022-11-09|09:08:52.171] committed state module=state height=2 num_txs=0 app_hash= -``` - -The blocks, as you can see from the `num_valid_txs=0` part, are empty, but let's remedy that next. - -## 1.6 Using the application - -Let's try submitting a transaction to our new application. -Open another terminal window and run the following curl command: - - -```bash -curl -s 'localhost:26657/broadcast_tx_commit?tx="cometbft=rocks"' -``` - -If everything went well, you should see a response indicating which height the -transaction was included in the blockchain. - -Finally, let's make sure that transaction really was persisted by the application. -Run the following command: - -```bash -curl -s 'localhost:26657/abci_query?data="cometbft"' -``` - -Let's examine the response object that this request returns. -The request returns a `json` object with a `key` and `value` field set. - -```json -... - "key": "dGVuZGVybWludA==", - "value": "cm9ja3M=", -... -``` - -Those values don't look like the `key` and `value` we sent to CometBFT. -What's going on here? - -The response contains a `base64` encoded representation of the data we submitted. -To get the original value out of this data, we can use the `base64` command line utility: - -```bash -echo cm9ja3M=" | base64 -d -``` - -## Outro - -I hope everything went smoothly and your first, but hopefully not the last, -CometBFT application is up and running. If not, please [open an issue on -Github](https://github.com/cometbft/cometbft/issues/new/choose). diff --git a/docs/guides/go.md b/docs/guides/go.md deleted file mode 100644 index 3edb91691e2..00000000000 --- a/docs/guides/go.md +++ /dev/null @@ -1,715 +0,0 @@ ---- -order: 1 ---- - -# Creating an application in Go - -## Guide Assumptions - -This guide is designed for beginners who want to get started with a CometBFT -application from scratch. It does not assume that you have any prior -experience with CometBFT. - -CometBFT is a service that provides a Byzantine Fault Tolerant consensus engine -for state-machine replication. The replicated state-machine, or "application", can be written -in any language that can send and receive protocol buffer messages in a client-server model. -Applications written in Go can also use CometBFT as a library and run the service in the same -process as the application. - -By following along this tutorial you will create a CometBFT application called kvstore, -a (very) simple distributed BFT key-value store. -The application will be written in Go and -some understanding of the Go programming language is expected. -If you have never written Go, you may want to go through [Learn X in Y minutes -Where X=Go](https://learnxinyminutes.com/docs/go/) first, to familiarize -yourself with the syntax. - -Note: Please use the latest released version of this guide and of CometBFT. -We strongly advise against using unreleased commits for your development. - -### Built-in app vs external app - -On the one hand, to get maximum performance you can run your application in -the same process as the CometBFT, as long as your application is written in Go. -[Cosmos SDK](https://github.com/cosmos/cosmos-sdk) is written -this way. -If that is the way you wish to proceed, use the [Creating a built-in application in Go](./go-built-in.md) guide instead of this one. - -On the other hand, having a separate application might give you better security -guarantees as two processes would be communicating via established binary protocol. -CometBFT will not have access to application's state. -This is the approach followed in this tutorial. - -## 1.1 Installing Go - -Verify that you have the latest version of Go installed (refer to the [official guide for installing Go](https://golang.org/doc/install)): - -```bash -$ go version -go version go1.20.1 darwin/amd64 -``` - -## 1.2 Creating a new Go project - -We'll start by creating a new Go project. - -```bash -mkdir kvstore -``` - -Inside the example directory, create a `main.go` file with the following content: - -```go -package main - -import ( - "fmt" -) - -func main() { - fmt.Println("Hello, CometBFT") -} -``` - -When run, this should print "Hello, CometBFT" to the standard output. - -```bash -cd kvstore -$ go run main.go -Hello, CometBFT -``` - -We are going to use [Go modules](https://github.com/golang/go/wiki/Modules) for -dependency management, so let's start by including a dependency on the latest version of -CometBFT, `v0.37.0` in this example. - -```bash -go mod init kvstore -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`. -The go.mod file should look similar to: - -```go -module github.com/me/example - -go 1.20 - -require ( - github.com/cometbft/cometbft v0.37.0 -) -``` - -As you write the kvstore application, you can rebuild the binary by -pulling any new dependencies and recompiling it. - -```sh -go get -go build -``` - - -## 1.3 Writing a CometBFT application - -CometBFT communicates with the application through the Application -BlockChain Interface (ABCI). The messages exchanged through the interface are -defined in the ABCI [protobuf -file](https://github.com/cometbft/cometbft/blob/v0.37.x/proto/tendermint/abci/types.proto). - -We begin by creating the basic scaffolding for an ABCI application by -creating a new type, `KVStoreApplication`, which implements the -methods defined by the `abcitypes.Application` interface. - -Create a file called `app.go` with the following contents: - -```go -package main - -import ( - abcitypes "github.com/cometbft/cometbft/abci/types" -) - -type KVStoreApplication struct{} - -var _ abcitypes.Application = (*KVStoreApplication)(nil) - -func NewKVStoreApplication() *KVStoreApplication { - return &KVStoreApplication{} -} - -func (app *KVStoreApplication) Info(info abcitypes.RequestInfo) abcitypes.ResponseInfo { - return abcitypes.ResponseInfo{} -} - -func (app *KVStoreApplication) Query(query abcitypes.RequestQuery) abcitypes.ResponseQuery { - return abcitypes.ResponseQuery{} -} - -func (app *KVStoreApplication) CheckTx(tx abcitypes.RequestCheckTx) abcitypes.ResponseCheckTx { - return abcitypes.ResponseCheckTx{} -} - -func (app *KVStoreApplication) InitChain(chain abcitypes.RequestInitChain) abcitypes.ResponseInitChain { - return abcitypes.ResponseInitChain{} -} - -func (app *KVStoreApplication) PrepareProposal(proposal abcitypes.RequestPrepareProposal) abcitypes.ResponsePrepareProposal { - return abcitypes.ResponsePrepareProposal{} -} - -func (app *KVStoreApplication) ProcessProposal(proposal abcitypes.RequestProcessProposal) abcitypes.ResponseProcessProposal { - return abcitypes.ResponseProcessProposal{} -} - -func (app *KVStoreApplication) BeginBlock(block abcitypes.RequestBeginBlock) abcitypes.ResponseBeginBlock { - return abcitypes.ResponseBeginBlock{} -} - -func (app *KVStoreApplication) DeliverTx(tx abcitypes.RequestDeliverTx) abcitypes.ResponseDeliverTx { - return abcitypes.ResponseDeliverTx{} -} - -func (app *KVStoreApplication) EndBlock(block abcitypes.RequestEndBlock) abcitypes.ResponseEndBlock { - return abcitypes.ResponseEndBlock{} -} - -func (app *KVStoreApplication) Commit() abcitypes.ResponseCommit { - return abcitypes.ResponseCommit{} -} - -func (app *KVStoreApplication) ListSnapshots(snapshots abcitypes.RequestListSnapshots) abcitypes.ResponseListSnapshots { - return abcitypes.ResponseListSnapshots{} -} - -func (app *KVStoreApplication) OfferSnapshot(snapshot abcitypes.RequestOfferSnapshot) abcitypes.ResponseOfferSnapshot { - return abcitypes.ResponseOfferSnapshot{} -} - -func (app *KVStoreApplication) LoadSnapshotChunk(chunk abcitypes.RequestLoadSnapshotChunk) abcitypes.ResponseLoadSnapshotChunk { - return abcitypes.ResponseLoadSnapshotChunk{} -} - -func (app *KVStoreApplication) ApplySnapshotChunk(chunk abcitypes.RequestApplySnapshotChunk) abcitypes.ResponseApplySnapshotChunk { - return abcitypes.ResponseApplySnapshotChunk{} -} -``` - -The types used here are defined in the CometBFT library and were added as a dependency -to the project when you ran `go get`. If your IDE is not recognizing the types, go ahead and run the command again. - -```bash -go get github.com/cometbft/cometbft@v0.37.0 -``` - -Now go back to the `main.go` and modify the `main` function so it matches the following, -where an instance of the `KVStoreApplication` type is created. - -```go -func main() { - fmt.Println("Hello, CometBFT") - - _ = NewKVStoreApplication() -} -``` - -You can recompile and run the application now by running `go get` and `go build`, but it does -not do anything. -So let's revisit the code adding the logic needed to implement our minimal key/value store -and to start it along with the CometBFT Service. - - -### 1.3.1 Add a persistent data store - -Our application will need to write its state out to persistent storage so that it -can stop and start without losing all of its data. - -For this tutorial, we will use [BadgerDB](https://github.com/dgraph-io/badger), a -a fast embedded key-value store. - -First, add Badger as a dependency of your go module using the `go get` command: - -`go get github.com/dgraph-io/badger/v3` - -Next, let's update the application and its constructor to receive a handle to the database, as follows: - -```go -type KVStoreApplication struct { - db *badger.DB - onGoingBlock *badger.Txn -} - -var _ abcitypes.Application = (*KVStoreApplication)(nil) - -func NewKVStoreApplication(db *badger.DB) *KVStoreApplication { - return &KVStoreApplication{db: db} -} -``` - -The `onGoingBlock` keeps track of the Badger transaction that will update the application's state when a block -is completed. Don't worry about it for now, we'll get to that later. - -Next, update the `import` stanza at the top to include the Badger library: - -```go -import( - "github.com/dgraph-io/badger/v3" - abcitypes "github.com/cometbft/cometbft/abci/types" -) -``` - -Finally, update the `main.go` file to invoke the updated constructor: - -```go - _ = NewKVStoreApplication(nil) -``` - -### 1.3.2 CheckTx - -When CometBFT receives a new transaction from a client, or from another full node, -CometBFT asks the application if the transaction is acceptable, using the `CheckTx` method. -Invalid transactions will not be shared with other nodes and will not become part of any blocks and, therefore, will not be executed by the application. - -In our application, a transaction is a string with the form `key=value`, indicating a key and value to write to the store. - -The most basic validation check we can perform is to check if the transaction conforms to the `key=value` pattern. -For that, let's add the following helper method to app.go: - -```go -func (app *KVStoreApplication) isValid(tx []byte) uint32 { - // check format - parts := bytes.Split(tx, []byte("=")) - if len(parts) != 2 { - return 1 - } - - return 0 -} -``` - -Now you can rewrite the `CheckTx` method to use the helper function: - -```go -func (app *KVStoreApplication) CheckTx(req abcitypes.RequestCheckTx) abcitypes.ResponseCheckTx { - code := app.isValid(req.Tx) - return abcitypes.ResponseCheckTx{Code: code} -} -``` - -While this `CheckTx` is simple and only validates that the transaction is well-formed, -it is very common for `CheckTx` to make more complex use of the state of an application. -For example, you may refuse to overwrite an existing value, or you can associate -versions to the key/value pairs and allow the caller to specify a version to -perform a conditional update. - -Depending on the checks and on the conditions violated, the function may return -different values, but any response with a non-zero code will be considered invalid -by CometBFT. Our `CheckTx` logic returns 0 to CometBFT when a transaction passes -its validation checks. The specific value of the code is meaningless to CometBFT. -Non-zero codes are logged by CometBFT so applications can provide more specific -information on why the transaction was rejected. - -Note that `CheckTx` does not execute the transaction, it only verifies that that the transaction could be executed. We do not know yet if the rest of the network has agreed to accept this transaction into a block. - - -Finally, make sure to add the bytes package to the `import` stanza at the top of `app.go`: - -```go -import( - "bytes" - - "github.com/dgraph-io/badger/v3" - abcitypes "github.com/cometbft/cometbft/abci/types" -) -``` - - -### 1.3.3 BeginBlock -> DeliverTx -> EndBlock -> Commit - -When the CometBFT consensus engine has decided on the block, the block is transferred to the -application over three ABCI method calls: `BeginBlock`, `DeliverTx`, and `EndBlock`. - -- `BeginBlock` is called once to indicate to the application that it is about to -receive a block. -- `DeliverTx` is called repeatedly, once for each application transaction that was included in the block. -- `EndBlock` is called once to indicate to the application that no more transactions -will be delivered to the application in within this block. - -Note that, to implement these calls in our application we're going to make use of Badger's -transaction mechanism. We will always refer to these as Badger transactions, not to -confuse them with the transactions included in the blocks delivered by CometBFT, -the _application transactions_. - -First, let's create a new Badger transaction during `BeginBlock`. All application transactions in the -current block will be executed within this Badger transaction. -Then, return informing CometBFT that the application is ready to receive application transactions: - -```go -func (app *KVStoreApplication) BeginBlock(req abcitypes.RequestBeginBlock) abcitypes.ResponseBeginBlock { - app.onGoingBlock = app.db.NewTransaction(true) - return abcitypes.ResponseBeginBlock{} -} -``` - -Next, let's modify `DeliverTx` to add the `key` and `value` to the database transaction every time our application -receives a new application transaction through `RequestDeliverTx`. - -```go -func (app *KVStoreApplication) DeliverTx(req abcitypes.RequestDeliverTx) abcitypes.ResponseDeliverTx { - if code := app.isValid(req.Tx); code != 0 { - return abcitypes.ResponseDeliverTx{Code: code} - } - - parts := bytes.SplitN(req.Tx, []byte("="), 2) - key, value := parts[0], parts[1] - - if err := app.onGoingBlock.Set(key, value); err != nil { - log.Panicf("Error writing to database, unable to execute tx: %v", err) - } - - return abcitypes.ResponseDeliverTx{Code: 0} -} -``` - -Note that we check the validity of the transaction _again_ during `DeliverTx`. -Transactions are not guaranteed to be valid when they are delivered to an -application, even if they were valid when they were proposed. -This can happen if the application state is used to determine transaction -validity. Application state may have changed between the initial execution of `CheckTx` -and the transaction delivery in `DeliverTx` in a way that rendered the transaction -no longer valid. - -`EndBlock` is called to inform the application that the full block has been delivered -and give the application a chance to perform any other computation needed, before the -effects of the transactions become permanent. - -Note that `EndBlock` **cannot** yet commit the Badger transaction we were building -in during `DeliverTx`. -Since other methods, such as `Query`, rely on a consistent view of the application's -state, the application should only update its state by committing the Badger transactions -when the full block has been delivered and the `Commit` method is invoked. - -The `Commit` method tells the application to make permanent the effects of -the application transactions. -Let's update the method to terminate the pending Badger transaction and -persist the resulting state: - -```go -func (app *KVStoreApplication) Commit() abcitypes.ResponseCommit { - if err := app.onGoingBlock.Commit(); err != nil { - log.Panicf("Error writing to database, unable to commit block: %v", err) - } - return abcitypes.ResponseCommit{Data: []byte{}} -} -``` - -Finally, make sure to add the log library to the `import` stanza as well: - -```go -import ( - "bytes" - "log" - - "github.com/dgraph-io/badger/v3" - abcitypes "github.com/cometbft/cometbft/abci/types" -) -``` - -You may have noticed that the application we are writing will crash if it receives -an unexpected error from the Badger database during the `DeliverTx` or `Commit` methods. -This is not an accident. If the application received an error from the database, there -is no deterministic way for it to make progress so the only safe option is to terminate. - -### 1.3.4 Query - -When a client tries to read some information from the `kvstore`, the request will be -handled in the `Query` method. To do this, let's rewrite the `Query` method in `app.go`: - -```go -func (app *KVStoreApplication) Query(req abcitypes.RequestQuery) abcitypes.ResponseQuery { - resp := abcitypes.ResponseQuery{Key: req.Data} - - dbErr := app.db.View(func(txn *badger.Txn) error { - item, err := txn.Get(req.Data) - if err != nil { - if err != badger.ErrKeyNotFound { - return err - } - resp.Log = "key does not exist" - return nil - } - - return item.Value(func(val []byte) error { - resp.Log = "exists" - resp.Value = val - return nil - }) - }) - if dbErr != nil { - log.Panicf("Error reading database, unable to execute query: %v", dbErr) - } - return resp -} -``` - -Since it reads only committed data from the store, transactions that are part of a block -that is being processed are not reflected in the query result. - -### 1.3.5 PrepareProposal and ProcessProposal - -`PrepareProposal` and `ProcessProposal` are methods introduced in CometBFT v0.37.0 -to give the application more control over the construction and processing of transaction blocks. - -When CometBFT sees that valid transactions (validated through `CheckTx`) are available to be -included in blocks, it groups some of these transactions and then gives the application a chance -to modify the group by invoking `PrepareProposal`. - -The application is free to modify the group before returning from the call, as long as the resulting set -does not use more bytes than `RequestPrepareProposal.max_tx_bytes' -For example, the application may reorder, add, or even remove transactions from the group to improve the -execution of the block once accepted. -In the following code, the application simply returns the unmodified group of transactions: - -```go -func (app *KVStoreApplication) PrepareProposal(proposal abcitypes.RequestPrepareProposal) abcitypes.ResponsePrepareProposal { - return abcitypes.ResponsePrepareProposal{Txs: proposal.Txs} -} -``` - -Once a proposed block is received by a node, the proposal is passed to the application to give -its blessing before voting to accept the proposal. - -This mechanism may be used for different reasons, for example to deal with blocks manipulated -by malicious nodes, in which case the block should not be considered valid. -The following code simply accepts all proposals: - -```go -func (app *KVStoreApplication) ProcessProposal(proposal abcitypes.RequestProcessProposal) abcitypes.ResponseProcessProposal { - return abcitypes.ResponseProcessProposal{Status: abcitypes.ResponseProcessProposal_ACCEPT} -} -``` - -## 1.4 Starting an application and a CometBFT instance - -Now that we have the basic functionality of our application in place, let's put it all together inside of our `main.go` file. - -Change the contents of your `main.go` file to the following. - -```go -package main - -import ( - "flag" - "fmt" - abciserver "github.com/cometbft/cometbft/abci/server" - "log" - "os" - "os/signal" - "path/filepath" - "syscall" - - "github.com/dgraph-io/badger/v3" - cmtlog "github.com/cometbft/cometbft/libs/log" -) - -var homeDir string -var socketAddr string - -func init() { - flag.StringVar(&homeDir, "kv-home", "", "Path to the kvstore directory (if empty, uses $HOME/.kvstore)") - flag.StringVar(&socketAddr, "socket-addr", "unix://example.sock", "Unix domain socket address (if empty, uses \"unix://example.sock\"") -} - -func main() { - flag.Parse() - if homeDir == "" { - homeDir = os.ExpandEnv("$HOME/.kvstore") - } - - dbPath := filepath.Join(homeDir, "badger") - db, err := badger.Open(badger.DefaultOptions(dbPath)) - if err != nil { - log.Fatalf("Opening database: %v", err) - } - defer func() { - if err := db.Close(); err != nil { - log.Fatalf("Closing database: %v", err) - } - }() - - app := NewKVStoreApplication(db) - - logger := cmtlog.NewTMLogger(cmtlog.NewSyncWriter(os.Stdout)) - - server := abciserver.NewSocketServer(socketAddr, app) - server.SetLogger(logger) - - if err := server.Start(); err != nil { - fmt.Fprintf(os.Stderr, "error starting socket server: %v", err) - os.Exit(1) - } - defer server.Stop() - - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - <-c -} -``` - -This is a huge blob of code, so let's break it down into pieces. - -First, we initialize the Badger database and create an app instance: - -```go - dbPath := filepath.Join(homeDir, "badger") - db, err := badger.Open(badger.DefaultOptions(dbPath)) - if err != nil { - log.Fatalf("Opening database: %v", err) - } - defer func() { - if err := db.Close(); err != nil { - log.Fatalf("Closing database: %v", err) - } - }() - - app := NewKVStoreApplication(db) -``` - -Then we start the ABCI server and add some signal handling to gracefully stop -it upon receiving SIGTERM or Ctrl-C. CometBFT will act as a client, -which connects to our server and send us transactions and other messages. - -```go - server := abciserver.NewSocketServer(socketAddr, app) - server.SetLogger(logger) - - if err := server.Start(); err != nil { - fmt.Fprintf(os.Stderr, "error starting socket server: %v", err) - os.Exit(1) - } - defer server.Stop() - - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - <-c -``` - -## 1.5 Initializing and Running - -Our application is almost ready to run, but first we'll need to populate the CometBFT configuration files. -The following command will create a `cometbft-home` directory in your project and add a basic set of configuration files in `cometbft-home/config/`. -For more information on what these files contain see [the configuration documentation](https://github.com/cometbft/cometbft/blob/v0.37.x/docs/core/configuration.md). - -From the root of your project, run: - -```bash -go run github.com/cometbft/cometbft/cmd/cometbft@v0.37.0 init --home /tmp/cometbft-home -``` - -You should see an output similar to the following: - -```bash -I[2022-11-09|09:06:34.444] Generated private validator module=main keyFile=/tmp/cometbft-home/config/priv_validator_key.json stateFile=/tmp/cometbft-home/data/priv_validator_state.json -I[2022-11-09|09:06:34.444] Generated node key module=main path=/tmp/cometbft-home/config/node_key.json -I[2022-11-09|09:06:34.444] Generated genesis file module=main path=/tmp/cometbft-home/config/genesis.json -``` - -Now rebuild the app: - -```bash -go build -mod=mod # use -mod=mod to automatically refresh the dependencies -``` - -Everything is now in place to run your application. Run: - -```bash -./kvstore -kv-home /tmp/badger-home -``` - -The application will start and you should see an output similar to the following: - -```bash -badger 2022/11/09 17:01:28 INFO: All 0 tables opened in 0s -badger 2022/11/09 17:01:28 INFO: Discard stats nextEmptySlot: 0 -badger 2022/11/09 17:01:28 INFO: Set nextTxnTs to 0 -I[2022-11-09|17:01:28.726] service start msg="Starting ABCIServer service" impl=ABCIServer -I[2022-11-09|17:01:28.726] Waiting for new connection... -``` - -Then we need to start CometBFT service and point it to our application. -Open a new terminal window and cd to the same folder where the app is running. -Then execute the following command: - -```bash -go run github.com/cometbft/cometbft/cmd/cometbft@v0.37.0 node --home /tmp/cometbft-home --proxy_app=unix://example.sock -``` - -This should start the full node and connect to our ABCI application, which will be -reflected in the application output. - -```sh -I[2022-11-09|17:07:08.124] service start msg="Starting ABCIServer service" impl=ABCIServer -I[2022-11-09|17:07:08.124] Waiting for new connection... -I[2022-11-09|17:08:12.702] Accepted a new connection -I[2022-11-09|17:08:12.703] Waiting for new connection... -I[2022-11-09|17:08:12.703] Accepted a new connection -I[2022-11-09|17:08:12.703] Waiting for new connection... -``` - -Also, the application using CometBFT Core is producing blocks 🎉🎉 and you can see this reflected in the log output of the service in lines like this: - -```bash -I[2022-11-09|09:08:52.147] received proposal module=consensus proposal="Proposal{2/0 (F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C:1:C73D3D1273F2, -1) AD19AE292A45 @ 2022-11-09T12:08:52.143393Z}" -I[2022-11-09|09:08:52.152] received complete proposal block module=consensus height=2 hash=F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C -I[2022-11-09|09:08:52.160] finalizing commit of block module=consensus height=2 hash=F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C root= num_txs=0 -I[2022-11-09|09:08:52.167] executed block module=state height=2 num_valid_txs=0 num_invalid_txs=0 -I[2022-11-09|09:08:52.171] committed state module=state height=2 num_txs=0 app_hash= -``` - -The blocks, as you can see from the `num_valid_txs=0` part, are empty, but let's remedy that next. - -## 1.6 Using the application - -Let's try submitting a transaction to our new application. -Open another terminal window and run the following curl command: - - -```bash -curl -s 'localhost:26657/broadcast_tx_commit?tx="cometbft=rocks"' -``` - -If everything went well, you should see a response indicating which height the -transaction was included in the blockchain. - -Finally, let's make sure that transaction really was persisted by the application. -Run the following command: - -```bash -curl -s 'localhost:26657/abci_query?data="cometbft"' -``` - -Let's examine the response object that this request returns. -The request returns a `json` object with a `key` and `value` field set. - -```json -... - "key": "dGVuZGVybWludA==", - "value": "cm9ja3M=", -... -``` - -Those values don't look like the `key` and `value` we sent to CometBFT. -What's going on here? - -The response contains a `base64` encoded representation of the data we submitted. -To get the original value out of this data, we can use the `base64` command line utility: - -```bash -echo cm9ja3M=" | base64 -d -``` - -## Outro - -I hope everything went smoothly and your first, but hopefully not the last, -CometBFT application is up and running. If not, please [open an issue on -Github](https://github.com/cometbft/cometbft/issues/new/choose). diff --git a/docs/networks/README.md b/docs/guides/networks/README.md similarity index 67% rename from docs/networks/README.md rename to docs/guides/networks/README.md index ceea235985d..caeb3a682ba 100644 --- a/docs/networks/README.md +++ b/docs/guides/networks/README.md @@ -7,7 +7,7 @@ parent: # Overview -Use [Docker Compose](./docker-compose.md) to spin up CometBFT testnets on your +Use [Docker Compose](docker-compose.md) to spin up CometBFT testnets on your local machine. See the `cometbft testnet --help` command for more help initializing testnets. diff --git a/docs/networks/docker-compose.md b/docs/guides/networks/docker-compose.md similarity index 96% rename from docs/networks/docker-compose.md rename to docs/guides/networks/docker-compose.md index 9d99ff65f35..8a1cdea5487 100644 --- a/docs/networks/docker-compose.md +++ b/docs/guides/networks/docker-compose.md @@ -8,7 +8,7 @@ With Docker Compose, you can spin up local testnets with a single command. ## Requirements -1. [Install CometBFT](../introduction/install.md) +1. [Install CometBFT](../../tutorials/install.md) 2. [Install docker](https://docs.docker.com/engine/installation/) 3. [Install docker-compose](https://docs.docker.com/compose/install/) @@ -59,7 +59,7 @@ calling the `cometbft testnet` command. The `./build` directory is mounted to the `/cometbft` mount point to attach the binary and config files to the container. -To change the number of validators / non-validators change the `localnet-start` Makefile target [here](../../Makefile): +To change the number of validators / non-validators change the `localnet-start` Makefile target [here](../../../Makefile): ```makefile localnet-start: localnet-stop @@ -87,7 +87,7 @@ Adding 4 more nodes is required in order to fully utilize the config files that ipv4_address: 192.167.10.5 # bump the final digit by 1 for every node ``` -Before running it, don't forget to cleanup the old files: +Before running it, don't forget to clean up the old files: ```sh # Clear the build folder @@ -145,7 +145,7 @@ To use your own ABCI applications with 4-node setup edit the [docker-compose.yam ``` -Override the [command](https://github.com/cometbft/cometbft/blob/main/networks/local/localnode/Dockerfile#L11) in each node to connect to it's ABCI. +Override the [command](https://github.com/cometbft/cometbft/blob/main/networks/local/localnode/Dockerfile#L11) in each node to connect to its ABCI. ```yml node0: diff --git a/docs/tools/README.md b/docs/guides/tools/README.md similarity index 52% rename from docs/tools/README.md rename to docs/guides/tools/README.md index de29e17f122..068b927ffa5 100644 --- a/docs/tools/README.md +++ b/docs/guides/tools/README.md @@ -2,19 +2,19 @@ order: 1 parent: title: Tools - order: 6 + order: 5 --- # Overview CometBFT has some tools that are associated with it for: -- [Debugging](./debugging.md) +- [Debugging](debugging.md) - [Benchmarking](#benchmarking) ## Benchmarking -- +- -`tm-load-test` is a distributed load testing tool (and framework) for load +`cometbft-load-test` is a distributed load testing tool (and framework) for load testing CometBFT networks. diff --git a/docs/tools/debugging.md b/docs/guides/tools/debugging.md similarity index 100% rename from docs/tools/debugging.md rename to docs/guides/tools/debugging.md diff --git a/docs/guides/tools/proposer-based-timestamps-runbook.md b/docs/guides/tools/proposer-based-timestamps-runbook.md new file mode 100644 index 00000000000..4ce6d1d9397 --- /dev/null +++ b/docs/guides/tools/proposer-based-timestamps-runbook.md @@ -0,0 +1,263 @@ +--- +order: 3 +--- + +# Proposer-Based Timestamps Runbook + +From version `v1.0`, CometBFT has new constraints for the timestamps included +in produced blocks. + +The new constraints mean that validators may fail to produce valid blocks, +which causes other validators to issue `nil` prevotes, thus rejecting the +proposed block, depending on the configuration of the validator's local clock. + +## What is this document for? + +This document provides a set of actionable steps for application developers and +node operators to diagnose and fix issues related to clock synchronization and +configuration of the [`SynchronyParams`](../../explanation/core/proposer-based-timestamps.md#consensus-parameters) +consensus parameters. + +Use this runbook if you observe that validators are frequently voting `nil` for a block that the rest +of the network votes for, or if validators are frequently producing block proposals +that are rejected by the rest of the network. + +## Requirements + +To use this runbook, you must be running a node that has the [Prometheus metrics endpoint enabled](../../explanation/core/metrics.md) +and the [RPC endpoint](../../explanation/core/rpc.md) enabled and accessible. + +It is strongly recommended to also run a Prometheus metrics collector to gather and +analyze metrics from the CometBFT node. + +## Debugging a Single Node + +If you observe that a single validator is frequently failing to produce blocks or +voting `nil` for proposals that other validators vote for and suspect it may be +related to clock synchronization, use the following steps to debug and correct the issue. + +### Check Timely Metric + +CometBFT exposes a histogram metric with the difference between the timestamp in the proposal +and the time read from the node's local clock when the proposal is received. + +The histogram exposes multiple metrics on the Prometheus `/metrics` endpoint called + +* `consensus_proposal_timestamp_difference_bucket` +* `consensus_proposal_timestamp_difference_sum` +* `consensus_proposal_timestamp_difference_count` + +Each metric is also labeled with the key `is_timely`, which can have a value of +`true` or `false`. +When `is_timely="true"`, the timestamp in the proposal was accepted by the node. +When `is_timely="false"`, the timestamp in the proposal was rejected by the node +that, as result, has prevoted `nil` for the proposal. + +#### From the Prometheus Collector UI + +If you are running a Prometheus collector, navigate to the query web interface and select the 'Graph' tab. + +Issue a query for the following: + +``` +consensus_proposal_timestamp_difference_count{is_timely="false"} / +consensus_proposal_timestamp_difference_count{is_timely="true"} +``` + +This query will graph the ratio of proposals the node considered timely to those it +considered untimely. If the ratio is increasing, it means that your node is consistently +seeing more proposals that are far from its local clock. If this is the case, you should +check to make sure your local clock is properly synchronized to NTP. + +#### From the `/metrics` url + +If you are not running a Prometheus collector, navigate to the `/metrics` endpoint +exposed on the Prometheus metrics port with `curl` or a browser. + +Search for the `consensus_proposal_timestamp_difference_count` metrics. +This metric is labeled with `is_timely`. Investigate the value of +`consensus_proposal_timestamp_difference_count` where `is_timely="false"` +and where `is_timely="true"`. Refresh the endpoint and observe if the value of `is_timely="false"` +is growing. + +If you observe that `is_timely="false"` is growing, it means that your node is consistently +seeing proposals that are far from its local clock. If this is the case, you should check +to make sure your local clock is properly synchronized to NTP. + +## Debugging a Network + +If you observe that a network is frequently failing to produce blocks and suspect +it may be related to clock synchronization, use the following steps to debug and correct the issue. + +### Check Prevote Message Delay + +CometBFT exposes metrics that help determine how synchronized the clocks on a network are. + +These metrics are visible on the Prometheus `/metrics` endpoint and are called: + +* `consensus_quorum_prevote_delay` +* `consensus_full_prevote_delay` + +These metrics calculate the difference between the timestamp in the proposal message and +the timestamp of a prevote that was issued during consensus. + +The `consensus_quorum_prevote_delay` metric is the interval in seconds +between the proposal timestamp and the timestamp of the earliest prevote that +achieved a `2/3+` quorum during the prevote step. + +The `consensus_full_prevote_delay` metric is the interval in seconds +between the proposal timestamp and the timestamp of the latest prevote in a round +where 100% of the validators voted. + +#### From the Prometheus Collector UI + +If you are running a Prometheus collector, navigate to the query web interface and select the 'Graph' tab. + +Issue a query for the following: + +``` +sum(consensus_quorum_prevote_delay) by (proposer_address) +``` + +This query will graph the difference in seconds for each proposer on the network. + +If the value is much larger for some proposers, then the issue is likely related to the clock +synchronization of their nodes. Contact those proposers and ensure that their nodes +are properly connected to NTP using the steps for [Debugging a Single Node](#debugging-a-single-node). + +If the value is relatively similar for all proposers you should next compare this +value to the `SynchronyParams` values for the network. Continue to the +[Checking Sychrony](#checking-synchronyparams) steps. + +#### From the `/metrics` url + +If you are not running a Prometheus collector, navigate to the `/metrics` endpoint +exposed on the Prometheus metrics port. + +Search for the `consensus_quorum_prevote_delay` metric. There will be one +entry of this metric for each `proposer_address`. If the value of this metric is +much larger for some proposers, then the issue is likely related to synchronization of their +nodes with NTP. Contact those proposers and ensure that their nodes are properly connected +to NTP using the steps for [Debugging a Single Node](#debugging-a-single-node). + +If the values are relatively similar for all proposers, +you'll need to compare this value to the `SynchronyParams` for the network. Continue +to the [Checking Sychrony](#checking-synchronyparams) steps. + +## Checking Clock Sync + +NTP configuration and tooling is very specific to the operating system and distribution +that your validator node is running. This guide assumes you have `timedatectl` installed with +[`systemd-timesyncd`](https://www.freedesktop.org/software/systemd/man/latest/systemd-timesyncd.service.html), +which provides a simple NTP client, or the more complete +[chrony](https://chrony.tuxfamily.org/), a popular tool for interacting with time +synchronization on Linux distributions. If you are using an operating system or +distribution with a different time synchronization mechanism, please consult the +documentation for your operating system to check the status and re-synchronize the daemon. + +### Check if NTP is Enabled + +```shell +timedatectl +``` + +From the output, ensure that `NTP service` is `active`. If `NTP service` is `inactive`, run: + +```shell +timedatectl set-ntp true +``` + +Re-run the `timedatectl` command and verify that the change has taken effect. + +### Check if Your NTP Daemon is Synchronized + +We provide two examples here, for `chrony` and `timesync`, but these steps +should be adapted if you are using a different daemon. + +If you find that the NTP is not synchronizing, remember to allow NTP traffic +(123/UDP) to your NTP servers. + +#### `chrony` + +Check the status of your `chrony` daemon by running the following command: + +```shell +chronyc tracking +``` + +If the `chrony` daemon is running, you will see output that indicates its current status. +If the `chrony` daemon is not running, restart it and re-run `chronyc tracking`. + +The `System time` field of the response should show a value that is much smaller than 100 +milliseconds. + +If the value is very large, restart the `chronyd` daemon. + +#### `timesync` + +If you are using `systemd-timesyncd`, then execute the following command: + +```shell +timedatectl timesync-status --monitor +``` + +If the output indicates an error, restart the service by running + +```shell +timedatectl set-ntp false +timedatectl set-ntp true +``` + +Once running, the output should include a `Packet count`, indicating how many times the protocol +has been executed, and a small `Precision` value. +Observe that this daemon increases the polling interval over time, up to a limit. +You may want to decrease the maximum value of the polling interval by tweaking +the `/etc/systemd/timesyncd.conf` file. + +## Checking SynchronyParams + +To determine the currently configured `SynchronyParams` for your network, issue a +request to your node's RPC endpoint. For a node running locally with the RPC server +exposed on port `26657`, run the following command: + +```shell +curl localhost:26657/consensus_params +``` + +The json output will contain a field named `synchrony`, with the following structure: + +```json +{ + "precision": "500000000", + "message_delay": "3000000000" +} +``` + +The `precision` and `message_delay` values returned are listed in nanoseconds: +In the examples above, the precision is 500ms and the message delay is 3s. +Remember, `consensus_quorum_prevote_delay` is listed in seconds. +If the `consensus_quorum_prevote_delay` value approaches the sum of `precision` and `message_delay`, +then the value selected for these parameters is too small. Your application will +need to be modified to update the `SynchronyParams` to have larger values. + +Note that the `message_delay` adopted by CometBFT +[increases over rounds](../../explanation/core/proposer-based-timestamps.md#adaptive-messagedelay), +so that the chain does not block forever when it is set to an improper value. +However, if the standard `message_delay`, used in round 0, is too small, there +is an important performance impact, and the value of this parameter should be +updated in order to be aligned with actual message delays in the network. + +### Updating SynchronyParams + +The `SynchronyParams` are Consensus Parameters, which means they are the same +for all nodes in the network and are set and updated +by the application running alongside CometBFT. Updates to these parameters must +be passed to the application during the `FinalizeBlock` ABCI method call. + +If the application was built using the CosmosSDK, then these parameters can be updated +programmatically using a governance proposal. For more information, see the +[CosmosSDK documentation](https://docs.cosmos.network/v0.50/build/modules/gov#proposal-submission). + +If the application does not implement a way to update the consensus parameters +programmatically, then the application itself must be updated to do so. More information on updating +the consensus parameters via ABCI can be found in the [FinalizeBlock documentation](https://github.com/cometbft/cometbft/blob/main/spec/abci/abci%2B%2B_methods.md#finalizeblock). diff --git a/docs/imgs/contributing.png b/docs/imgs/contributing.png deleted file mode 100644 index bb4bc6b5f5b..00000000000 Binary files a/docs/imgs/contributing.png and /dev/null differ diff --git a/docs/imgs/light_client_bisection_alg.png b/docs/imgs/light_client_bisection_alg.png index 2a12c7542e5..a960ee69f88 100644 Binary files a/docs/imgs/light_client_bisection_alg.png and b/docs/imgs/light_client_bisection_alg.png differ diff --git a/docs/imgs/sentry_layout.png b/docs/imgs/sentry_layout.png index 240abde18fa..7d7dff44d6d 100644 Binary files a/docs/imgs/sentry_layout.png and b/docs/imgs/sentry_layout.png differ diff --git a/docs/imgs/sentry_local_config.png b/docs/imgs/sentry_local_config.png index 050a6df2fac..4fdb2fe580a 100644 Binary files a/docs/imgs/sentry_local_config.png and b/docs/imgs/sentry_local_config.png differ diff --git a/docs/qa/method.md b/docs/qa/method.md deleted file mode 100644 index 6de0cbcf80c..00000000000 --- a/docs/qa/method.md +++ /dev/null @@ -1,257 +0,0 @@ ---- -order: 1 -parent: - title: Method - order: 1 ---- - -# Method - -This document provides a detailed description of the QA process. -It is intended to be used by engineers reproducing the experimental setup for future tests of CometBFT. - -The (first iteration of the) QA process as described [in the RELEASES.md document][releases] -was applied to version v0.34.x in order to have a set of results acting as benchmarking baseline. -This baseline is then compared with results obtained in later versions. - -Out of the testnet-based test cases described in [the releases document][releases] we focused on two of them: -_200 Node Test_, and _Rotating Nodes Test_. - -[releases]: https://github.com/cometbft/cometbft/blob/main/RELEASES.md#large-scale-testnets - -## Software Dependencies - -### Infrastructure Requirements to Run the Tests - -* An account at Digital Ocean (DO), with a high droplet limit (>202) -* The machine to orchestrate the tests should have the following installed: - * A clone of the [testnet repository][testnet-repo] - * This repository contains all the scripts mentioned in the reminder of this section - * [Digital Ocean CLI][doctl] - * [Terraform CLI][Terraform] - * [Ansible CLI][Ansible] - -[testnet-repo]: https://github.com/cometbft/qa-infra -[Ansible]: https://docs.ansible.com/ansible/latest/index.html -[Terraform]: https://www.terraform.io/docs -[doctl]: https://docs.digitalocean.com/reference/doctl/how-to/install/ - -### Requirements for Result Extraction - -* Matlab or Octave -* [Prometheus][prometheus] server installed -* blockstore DB of one of the full nodes in the testnet -* Prometheus DB - -[prometheus]: https://prometheus.io/ - -## 200 Node Testnet - -### Running the test - -This section explains how the tests were carried out for reproducibility purposes. - -1. [If you haven't done it before] - Follow steps 1-4 of the `README.md` at the top of the testnet repository to configure Terraform, and `doctl`. -2. Copy file `testnets/testnet200.toml` onto `testnet.toml` (do NOT commit this change) -3. Set the variable `VERSION_TAG` in the `Makefile` to the git hash that is to be tested. - * If you are running the base test, which implies an homogeneous network (all nodes are running the same version), - then make sure makefile variable `VERSION2_WEIGHT` is set to 0 - * If you are running a mixed network, set the variable `VERSION_TAG2` to the other version you want deployed - in the network. The, adjust the weight variables `VERSION_WEIGHT` and `VERSION2_WEIGHT` to configure the - desired proportion of nodes running each of the two configured versions. -4. Follow steps 5-10 of the `README.md` to configure and start the 200 node testnet - * WARNING: Do NOT forget to run `make terraform-destroy` as soon as you are done with the tests (see step 9) -5. As a sanity check, connect to the Prometheus node's web interface and check the graph for the `COMETBFT_CONSENSUS_HEIGHT` metric. - All nodes should be increasing their heights. -6. You now need to start the load runner that will produce transaction load - * If you don't know the saturation load of the version you are testing, you need to discover it. - * `ssh` into the `testnet-load-runner`, then copy script `script/200-node-loadscript.sh` and run it from the load runner node. - * Before running it, you need to edit the script to provide the IP address of a full node. - This node will receive all transactions from the load runner node. - * This script will take about 40 mins to run. - * It is running 90-seconds-long experiments in a loop with different loads. - * If you already know the saturation load, you can simply run the test (several times) for 90 seconds with a load somewhat - below saturation: - * set makefile variables `ROTATE_CONNECTIONS`, `ROTATE_TX_RATE`, to values that will produce the desired transaction load. - * set `ROTATE_TOTAL_TIME` to 90 (seconds). - * run "make runload" and wait for it to complete. You may want to run this several times so the data from different runs can be compared. -7. Run `make retrieve-data` to gather all relevant data from the testnet into the orchestrating machine - * Alternatively, you may want to run `make retrieve-prometheus-data` and `make retrieve-blockstore` separately. - The end result will be the same. - * `make retrieve-blockstore` accepts the following values in makefile variable `RETRIEVE_TARGET_HOST` - * `any`: (which is the default) picks up a full node and retrieves the blockstore from that node only. - * `all`: retrieves the blockstore from all full nodes; this is extremely slow, and consumes plenty of bandwidth, - so use it with care. - * the name of a particular full node (e.g., `validator01`): retrieves the blockstore from that node only. -8. Verify that the data was collected without errors - * at least one blockstore DB for a CometBFT validator - * the Prometheus database from the Prometheus node - * for extra care, you can run `zip -T` on the `prometheus.zip` file and (one of) the `blockstore.db.zip` file(s) -9. **Run `make terraform-destroy`** - * Don't forget to type `yes`! Otherwise you're in trouble. - -### Result Extraction - -The method for extracting the results described here is highly manual (and exploratory) at this stage. -The CometBFT team should improve it at every iteration to increase the amount of automation. - -#### Steps - -1. Unzip the blockstore into a directory -2. Extract the latency report and the raw latencies for all the experiments. Run these commands from the directory containing the blockstore - * ```bash - mkdir results - go run github.com/cometbft/cometbft/test/loadtime/cmd/report@f1aaa436d --database-type goleveldb --data-dir ./ > results/report.txt` - go run github.com/cometbft/cometbft/test/loadtime/cmd/report@f1aaa436d --database-type goleveldb --data-dir ./ --csv results/raw.csv` - ``` -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 - ```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 - * This effectively creates a table where rows are a particular tx rate and columns are a particular number of websocket connections. -5. Extract the raw latencies from file `raw.csv` using the following bash loop. This creates a `.csv` file and a `.dat` file per experiment. - The format of the `.dat` files is amenable to loading them as matrices in Octave. - * Adapt the values of the for loop variables according to the experiments that you ran (check `report.txt`). - * Adapt `report*.txt` to the files you produced in step 3. - - ```bash - uuids=($(cat report01.txt report02.txt report04.txt | grep '^Experiment ID: ' | awk '{ print $3 }')) - c=1 - rm -f *.dat - for i in 01 02 04; do - for j in 0025 0050 0100 0200; do - echo $i $j $c "${uuids[$c]}" - filename=c${i}_r${j} - grep ${uuids[$c]} raw.csv > ${filename}.csv - cat ${filename}.csv | tr , ' ' | awk '{ print $2, $3 }' >> ${filename}.dat - c=$(expr $c + 1) - done - done - ``` - -6. Enter Octave -7. Load all `.dat` files generated in step 5 into matrices using this Octave code snippet - - ```octave - conns = { "01"; "02"; "04" }; - rates = { "0025"; "0050"; "0100"; "0200" }; - for i = 1:length(conns) - for j = 1:length(rates) - filename = strcat("c", conns{i}, "_r", rates{j}, ".dat"); - load("-ascii", filename); - endfor - endfor - ``` - -8. Set variable release to the current release undergoing QA - - ```octave - release = "v0.34.x"; - ``` - -9. Generate a plot with all (or some) experiments, where the X axis is the experiment time, - and the y axis is the latency of transactions. - The following snippet plots all experiments. - - ```octave - legends = {}; - hold off; - for i = 1:length(conns) - for j = 1:length(rates) - data_name = strcat("c", conns{i}, "_r", rates{j}); - l = strcat("c=", conns{i}, " r=", rates{j}); - m = eval(data_name); plot((m(:,1) - min(m(:,1))) / 1e+9, m(:,2) / 1e+9, "."); - hold on; - legends(1, end+1) = l; - endfor - endfor - legend(legends, "location", "northeastoutside"); - xlabel("experiment time (s)"); - ylabel("latency (s)"); - t = sprintf("200-node testnet - %s", release); - title(t); - ``` - -10. Consider adjusting the axis, in case you want to compare your results to the baseline, for instance - - ```octave - axis([0, 100, 0, 30], "tic"); - ``` - -11. Use Octave's GUI menu to save the plot (e.g. as `.png`) - -12. Repeat steps 9 and 10 to obtain as many plots as deemed necessary. - -13. To generate a latency vs throughput plot, using the raw CSV file generated - in step 2, follow the instructions for the [`latency_throughput.py`] script. - This plot is useful to visualize the saturation point. - -[`latency_throughput.py`]: ../../scripts/qa/reporting/README.md#Latency-vs-Throughput-Plotting - -14. Alternatively, follow the instructions for the [`latency_plotter.py`] script. - This script generates a series of plots per experiment and configuration that my - help with visualizing Latency vs Throughput variation. - -[`latency_plotter.py`]: ../../scripts/qa/reporting/README.md#Latency-vs-Throughput-Plotting-version-2 - -#### Extracting Prometheus Metrics - -1. Stop the prometheus server if it is running as a service (e.g. a `systemd` unit). -2. Unzip the prometheus database retrieved from the testnet, and move it to replace the - local prometheus database. -3. Start the prometheus server and make sure no error logs appear at start up. -4. Identify the time window you want to plot in your graphs. -5. Execute the [`prometheus_plotter.py`] script for the time window. - -[`prometheus_plotter.py`]: ../../scripts/qa/reporting/README.md#prometheus-metrics - -## Rotating Node Testnet - -### Running the test - -This section explains how the tests were carried out for reproducibility purposes. - -1. [If you haven't done it before] - Follow steps 1-4 of the `README.md` at the top of the testnet repository to configure Terraform, and `doctl`. -2. Copy file `testnet_rotating.toml` onto `testnet.toml` (do NOT commit this change) -3. Set variable `VERSION_TAG` to the git hash that is to be tested. -4. Run `make terraform-apply EPHEMERAL_SIZE=25` - * WARNING: Do NOT forget to run `make terraform-destroy` as soon as you are done with the tests -5. Follow steps 6-10 of the `README.md` to configure and start the "stable" part of the rotating node testnet -6. As a sanity check, connect to the Prometheus node's web interface and check the graph for the `tendermint_consensus_height` metric. - All nodes should be increasing their heights. -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](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. -9. When the height of the chain reaches 3000, stop the `make rotate` script -10. When the rotate script has made two iterations (i.e., all ephemeral nodes have caught up twice) - after height 3000 was reached, stop `make rotate` -11. Run `make retrieve-data` to gather all relevant data from the testnet into the orchestrating machine -12. Verify that the data was collected without errors - * at least one blockstore DB for a CometBFT validator - * the Prometheus database from the Prometheus node - * for extra care, you can run `zip -T` on the `prometheus.zip` file and (one of) the `blockstore.db.zip` file(s) -13. **Run `make terraform-destroy`** - -Steps 8 to 10 are highly manual at the moment and will be improved in next iterations. - -### Result Extraction - -In order to obtain a latency plot, follow the instructions above for the 200 node experiment, but: - -* The `results.txt` file contains only one experiment -* Therefore, no need for any `for` loops - -As for prometheus, the same method as for the 200 node experiment can be applied. diff --git a/docs/references/README.md b/docs/references/README.md new file mode 100644 index 00000000000..fbc78d6544b --- /dev/null +++ b/docs/references/README.md @@ -0,0 +1,97 @@ +--- +order: 4 +title: CometBFT Reference Documentation +description: References +parent: + order: 1 +--- + +# Reference Documentation + +Welcome to the CometBFT Reference Documentation, a comprehensive resource for essential information and +standards related to CometBFT. + +In this documentation, you'll find valuable references in three key areas: + +## Architecture Decision Records (ADRs) + +[Architecture Decision Records (ADRs)](./architecture/README.md) provide a structured approach to documenting key architectural +decisions made during the development of CometBFT. These records help us maintain transparency, +share knowledge, and ensure that architectural choices align with CometBFT's goals and constraints. + +### What You'll Find in ADRs: + +- Clear explanations of architectural decisions. +- The context and background that led to each decision. +- Rationale for choosing a particular solution. +- Any associated risks and trade-offs. +- Decision status and tracking for ongoing changes. + +Browse the ADRs to gain insights into the architectural decisions that shape CometBFT. + +## Quality Assurance (QA) Documents + +[Quality Assurance (QA)](./qa/README.md) Documents are the foundation of the commitment to delivering a high-quality CometBFT +implementation. These standards guide the testing processes, quality control measures, and best practices +to ensure that CometBFT meets and exceeds industry benchmarks. + +### What You'll Find in QA: + +- Testing methodologies and strategies. +- Documentation on test plans and test cases. + +Explore the QA documents to understand the testing methods to ensure the quality and performance of CometBFT. + +## Configuration Manual + +The [Configuration Manual](./config/README.md) is a reference manual describing CometBFT configuration options. +It details all configuration files deployed and includes examples and best practices to ensure that +CometBFT is deployed with a proper configuration. + +### What You'll Find in the Configuration Manual: + +- Documentation of each configuration option. +- Examples for real-world use-cases. + +Explore the Configuration Manual to understand the different options of CometBFT to ensure a high-performing deployment. + +## Request for Comments (RFCs) + +[Request for Comments (RFCs)](./rfc/README.md) documents serve as a platform for open and collaborative discussions on proposed +changes, new features, and improvements within CometBFT. RFCs encourage cross-team communication +and feedback, ensuring that decisions are well-informed and aligned with CometBFT's goals. + +### What You'll Find in RFCs: + +- Proposals for changes or enhancements. +- Technical details and specifications. +- Discussions and feedback from team members. +- Status updates and implementation progress. + +Engage with RFCs to participate in shaping the direction of CometBFT, share your insights, +and contribute to its continuous evolution. + +## Storage + +[Storage](./storage/README.md) references comprise findings from storage sub-systems +(eg block store, state store) improvements in CometBFT. + +### What You'll Find in Storage: + +- Prior improvements efforts and reports that documents those efforts +- The testing methodology used to improve storage footprint and performance in Comet +- Conclusions and potential future work + +Explore the Storage references to get a deeper understanding of prior work and future plans in these +sub-systems of CometBFT. + +## Explore CometBFT References + +The CometBFT Reference Documentation empowers you with knowledge and information that enhances +your understanding of CometBFT's architecture, quality assurance, and ongoing improvements. +Whether you're a chain developer, application developer, or simply interested in CometBFT, +you'll find valuable insights and documentation here. + +Feel free to explore the sections on ADRs, QA Standards, and RFCs to access the resources you need. +We are committed to transparency, collaboration, and excellence, and this documentation reflects +our dedication to those principles. diff --git a/docs/architecture/README.md b/docs/references/architecture/README.md similarity index 58% rename from docs/architecture/README.md rename to docs/references/architecture/README.md index 2dde6df4597..d54a1d8ce32 100644 --- a/docs/architecture/README.md +++ b/docs/references/architecture/README.md @@ -21,7 +21,7 @@ provide: - References - Changelog -To create a new ADR, please use the [ADR template](./adr-template.md). +To create a new ADR, please use the [ADR template](adr-template.md). Note the distinction between an ADR and a spec. An ADR provides the context, intuition, reasoning, and justification for a change in architecture, or for the @@ -44,9 +44,24 @@ numbering our ADRs from 100 onwards. ### Accepted +- [ADR-101: Data companion pull API](adr-101-data-companion-pull-api.md) +- [ADR-102: RPC Companion](adr-102-rpc-companion.md) +- [ADR-103: Protobuf definition versioning](adr-103-proto-versioning.md) +- [ADR-104: State sync from local snapshot](adr-104-out-of-band-state-sync.md) +- [ADR-105: Refactor list of senders in mempool](adr-105-refactor-mempool-senders.md) +- [ADR-106: gRPC API](adr-106-grpc-api) +- [ADR-107: Rename protobuf versions of 0.x releases to pre-v1 betas](adr-107-betaize-proto-versions.md) +- [ADR-109: Reduce CometBFT Go API Surface Area](adr-109-reduce-go-api-surface.md) +- [ADR-111: `nop` Mempool](adr-111-nop-mempool.md) +- [ADR-112: Proposer-Based Timestamps](adr-112-proposer-based-timestamps.md) + ### Implemented +- [ADR-108: E2E tests for CometBFT's behaviour in respect to ABCI 1.0.](adr-108-e2e-abci++.md) + ### Deprecated ### Rejected +- [ADR-100: Data companion push API](adr-100-data-companion-push-api.md) +- [ADR-110: Remote mempool](adr-110-remote-mempool.md) diff --git a/docs/references/architecture/adr-100-data-companion-push-api.md b/docs/references/architecture/adr-100-data-companion-push-api.md new file mode 100644 index 00000000000..5e04b3595b3 --- /dev/null +++ b/docs/references/architecture/adr-100-data-companion-push-api.md @@ -0,0 +1,514 @@ +# ADR 100: Data Companion Push API + +## Changelog + +- 2023-05-03: Mark as rejected in favour of ADR-101 (@thanethomson) +- 2023-04-04: Update based on review feedback (@thanethomson) +- 2023-02-28: Renumber from 082 to 100 (@thanethomson) +- 2022-01-05: Sync requirements with those of [ADR 101][adr-101] (@thanethomson) +- 2022-12-18: Renamed proposal to "Data Companion Push API" (@thanethomson) +- 2022-11-26: Clarify user stories and alternatives, allow for selective + publishing of data via the companion API, buffer on disk instead of in memory + (@thanethomson) +- 2022-09-10: First draft (@thanethomson) + +## Status + +Rejected + +## Context + +At present, CometBFT handles a mixture of application- and consensus-related +concerns, which results in code bloat and scope creep into territory that should +technically be taken care of by the application. Some major examples of this +right now are **event and block execution result data**, with CometBFT being +responsible for: + +1. Storing event/execution result data. + 1. For some applications, this results in dramatic storage growth, leading to + high operational costs for operators, as application-specific pruning is + not feasible to implement within the consensus engine. + 2. Storing application-specific data also means that multiple underlying + databases need to be supported (via [cometbft-db]) in order to cater to + different applications' needs, which substantially increases the project's + maintenance costs and complexity. +2. Facilitating complex querying of this data, including providing real-time + notifications of complex updates. + 1. This has resulted in needing to provide query mechanisms such as + `/block_search` and `/tx_search`, which are not really optimal to provide + via some of the databases supported by cometbft-db, and therefore result + in problems like [\#517]. + 2. This has also resulted in having to maintain multiple indexers and our own + custom, database-independent indexing scheme, and having to turn down + users' requests for even more indexers that would work better for their + use cases, since this imposes a substantial maintenance burden on the core + team. + 3. The current (somewhat unreliable) event subscription implementation can + cause back-pressure into consensus and affect IBC relayer stability (see + [\#6729] and [\#7156]) + +Ultimately the core team, whose focus is providing a high quality consensus +engine, has finite resources. Having to take care of both consensus- and +application-related concerns means that neither will be taken care of +effectively. + +It then starts to become clearer that, in order to address these problems in the +long run, event and execution results data need to be handled in application +territory. But what does the trajectory look like to facilitate this evolution +over time? + +### Roadmap + +This ADR proposes the following path to eventually separating these concerns: + +1. Provide an API explicitly dedicated to facilitating offloading of this data + to a **single data companion** ("sidecar") service - this is the focus of + this ADR. The primary function of such a companion is effectively to act as + an _ingest_ of sorts, translating block and block result data (including + events) into application-specific data. **Single** is emphasized here, as we + anticipate that attaching more than one companion service to a node may slow + it down and affect its operations. +2. Provide a reference implementation of a data companion which facilitates + offering most of the current RPC endpoints from a service _external_ to the + node. Beyond serving as an example for the community as to how to implement a + data companion, this will potentially: + 1. Allow for horizontal scalability of the RPC independently of the + associated full node, reducing operational costs for operators who want to + provide RPC services for their user base (who, in some cases, have to run + multiple full nodes in order to facilitate a highly available RPC + service). + 2. Address some of the problems outlined in [RFC-006][rfc-006] relating to + event subscription. + 3. Address more general problems in the RPC, such as its inherent + susceptibility to DDoS attacks. +3. Once the community has mostly migrated to using this data companion API, we + can mark many of the node-based RPC endpoints as deprecated, and eventually + remove them from the node. +4. In parallel, start an effort to design a future where event and execution + result data are handled exclusively in the application domain. Once these + changes are ready to be rolled out, the ingest components of data companions + are the only parts of the ecosystem that will need to be migrated to interact + directly with the application instead of the node (e.g. by way of RPC + endpoints exposed by the application, instead of the consensus engine). +5. Once the ingests are migrated to rely on the application, it will be safe to + entirely remove any notion of event data storage and retrieval, as well as + indexing from the consensus engine, dramatically simplifying the consensus + engine. + +## Alternative Approaches + +1. One clear alternative to this would be the approach outlined in [ADR + 075][adr-075] (specifically, implementing it in isolation). This approach: + + 1. Still leaves CometBFT responsible for maintaining a query interface and + event indexing functionality, increasing the long-term maintenance burden of, + and the possibility of feature sprawl in, that subsystem. To overcome this, + we could remove the query interface altogether and just always publish all + data. + 2. Only keeps track of a sliding window of events (and does so in-memory), and + so does not provide reliable guaranteed delivery of this data. Even just + persisting this data will not solve this problem: if we prioritize + continued operation of the node over guaranteed delivery of this data, we + may eventually run out of disk storage. So here we would need to persist the + data _and_ we would need to panic if the sliding window of events fills up. + 3. Allows for multiple consumers. While desirable from typical web services, + CometBFT is a consensus engine and, as such, we should prioritize consensus + over providing similar guarantees to a scalable RPC interface (especially + since we know this does not scale, and if such a job could just be + outsourced). If we have a single consumer, we can easily automatically prune + data that was already sent. We could overcome this by limiting the API to a + single consumer and single event window. + + Making the requisite modifications to ADR-075 basically converges on the + solution outlined in this ADR, except that ADR-075 publishes data via JSON over + HTTP while this solution proposes gRPC. + + Technically, however, ADR-075 is orthogonal to the solution proposed in this + ADR, and could be implemented as part of an "RPC companion" to provide better + delivery guarantees to subscribers. + +2. Another alternative is proposed in [ADR 101][adr-101], which has the same + requirements as this proposed approach, except it implements a "pull" model + instead. + +3. We could pick a database that provides real-time notifications of inserts to + consumers and just dump the requisite data into that database. Consumers + would then need to connect to that database, listen for updates, and then + transform/process the data as needed. + + This approach could also inevitably lead to feature sprawl in people wanting + us to support multiple different databases. It is also not clear which + database would be the best option here, as that would most likely be + influenced by integrators' use cases. + + Beyond this, if we exclusively support one database but integrators needed + another for their use case, they would be forced to perform some kind of + continuous ETL operation to transfer the data from the one database to the + other, potentially doubling their storage capacity requirements and therefore + their storage-related costs. This would also increase pruning complexity. + +## Decision + +> TODO(thane) + +## Detailed Design + +The model proposed in this ADR is one where the node is a client, and the data +companion is a server. This model is inverted in ADR-101 (the "pull" companion). +The model in this ADR provides strong guarantees as to reliable delivery, but +also potentially facilitates halting of consensus if the interaction with the +companion is unreliable. + +The model proposed in ADR-101 offers much weaker delivery guarantees, allowing +the companion to lag significantly behind consensus, but offers the greatest +potential uptime for the consensus engine. + +### Use Cases + +1. Integrators could provide standalone RPC services that would be able to scale + independently of the CometBFT node. They would also be able to present the + data in whatever format and by whichever protocol they want. +2. Block explorers could make use of this data to provide real-time information + about the blockchain. +3. IBC relayer nodes could use this data to filter and store only the data they + need to facilitate relaying without putting additional pressure on the + consensus engine (until such time that a decision is made on whether to + continue providing event data from CometBFT). + +### Requirements + +1. A node _must_ support at most one data companion. + +2. All or part of the following data _must_ be obtainable by the companion: + 1. Committed block data + 2. Block execution results (including event data) for blocks that have been + committed + +3. The companion _must_ be able to establish the earliest height for which the + node has all of the requisite data. + +4. The API _must_ be (or be able to be) appropriately shielded from untrusted + consumers and abuse. Note that the companion is considered a **trusted** + consumer of this API. Critical control facets of the API (e.g. those that + influence the node's pruning mechanisms) _must_ be implemented in such a way + as to eliminate the possibility of accidentally exposing those endpoints to + the public internet unprotected. + +5. The node _must_ know, by way of signals from the companion, which heights' + associated data are safe to automatically prune. + +6. The API _must_ be opt-in. When off or not in use, it _should_ have no impact + on system performance. + +7. It _must_ not slow down consensus operations without halting the node. + +8. It _must_ not cause unbounded memory growth. + +9. It _must_ provide one or more ways for operators to control storage growth. + +10. It _must_ provide insight to operators (e.g. by way of logs/metrics) to + assist in dealing with possible failure modes. + +### Entity Relationships + +The following simple diagram shows the proposed relationships between +CometBFT, a socket-based ABCI application, and the proposed data companion +service. + +```mermaid +flowchart RL + comet[CometBFT] + companion[Data Companion] + app[ABCI App] + + comet --> app + comet --> companion +``` + +As can be seen in this diagram, CometBFT (client) connects out to both the ABCI +application (server) and data companion service (server) based on the CometBFT +node's configuration. + +The fact that CometBFT connects out to the companion service instead of the +other way around provides a natural constraint on the number of consumers of the +API. This also implies that the data companion is a trusted external service, +just like an ABCI application, as it would need to be configured within the +CometBFT configuration file. + +### gRPC API + +The following gRPC API is proposed: + +```protobuf +import "tendermint/abci/types.proto"; +import "tendermint/types/block.proto"; + +// DataCompanionService allows CometBFT to publish certain data generated by +// the consensus engine to a single external consumer with specific reliability +// guarantees. +// +// Note that implementers of this service must take into account the possibility +// that CometBFT may re-send data that was previously sent. Therefore +// the service should simply ignore previously seen data instead of responding +// with errors to ensure correct functioning of the node, as responding with an +// error is taken as a signal to CometBFT that it must crash and await +// operator intervention. +service DataCompanionService { + // BlockCommitted is called after a block has been committed. This method is + // also called on CometBFT startup to ensure that the service received the + // last committed block, in case there was previously a transport failure. + // + // If an error is returned, CometBFT will crash. + rpc BlockCommitted(BlockCommittedRequest) returns (BlockCommittedResponse) {} +} + +// BlockCommittedRequest contains at least the data for the block that was just +// committed. If enabled, it also contains the ABCI FinalizeBlock response data +// related to the block in this request. +message BlockCommittedRequest { + // The block data for the block that was just committed. + tendermint.types.Block block = 1; + // The FinalizeBlockResponse related to the block in this request. This + // field is optional, depending on the CometBFT node's configuration. + optional tendermint.abci.FinalizeBlockResponse finalize_block_response = 2; +} + +// BlockCommittedResponse is either empty upon success, or returns one or more +// errors. Note that returning any errors here will cause CometBFT to crash. +message BlockCommittedResponse { + // If an error occurred during the companion's processing of the request. + optional Error error = 1; +} + +// Error can be one of several different types of errors. +message Error { + oneof error { + UnexpectedBlockError unexpected_block_err = 1; + UnexpectedFieldError unexpected_field_err = 2; + ExpectedFieldError expected_field_err = 3; + } +} + +// UnexpectedBlockError is returned by the server when CometBFT sent it a +// block that is ahead of the block expected by the server. +message UnexpectedBlockError { + // The height of the block expected by the server. + int64 expected_height = 1; +} + +// UnexpectedFieldError is returned by the server when CometBFT sent it a +// message containing an unexpected field. For instance, if the companion +// expects only the `block` field but not `finalize_block_response`, but somehow +// the companion receives a value for `finalize_block_response`, it should +// return this error because it indicates that either CometBFT or the data +// companion are most likely incorrectly configured. +message UnexpectedFieldError { + // The name of the field whose value was expected to be empty, but was not. + string field_name = 1; +} + +// ExpectedFieldError is returned by the server when CometBFT sent it a +// message containing an empty field value for a field it was expecting to be +// populated. If this occurs, it indicates that either CometBFT or the data +// companion are most likely incorrectly configured. +message ExpectedFieldError { + // The name of the field whose value was expected to be populated, but was + // empty. + string field_name = 1; +} +``` + +### Request Buffering + +In order to ensure reliable delivery, while also catering for intermittent +faults, we should facilitate buffering of data destined for the companion +service. This data would need to be stored on disk to ensure that CometBFT +could attempt to resubmit all unsubmitted data upon CometBFT startup. + +At present, this data is already stored on disk, and so practically we would +need to implement some form of background pruning mechanism to remove the data +we know has been shared with the companion service. + +In order to not allow disk storage to grow unbounded, _and_ ensure that we do +not lose any critical data, we need to impose some kind of limit on the number +of requests we will buffer before crashing the CometBFT node. In case there is +manual intervention needed to restore the companion service, CometBFT should +attempt to flush this buffer upon startup before continuing normal operations. + +### Crash Recovery + +In order to ensure that the companion has the latest data, if CometBFT does not +have confirmation that the companion has received the data for a particular +height, it should resend all data from the last height for which it has +confirmation. + +An example where the companion saves all data up to and including height 10, but +crashes before confirming receipt of data for height 11: + +```mermaid +sequenceDiagram + participant N as Node + participant C as Companion + + N->>+C: BlockCommittedRequest (height = 10) + C->>-N: BlockCommittedResponse (error = nil) + N->>N: Save prune height as 10 + + N->>C: BlockCommittedRequest (height = 11) + break Node or companion crashes + N-->C: Node and companion recover + end + + N->>+C: BlockCommittedRequest (height = 11) + C->>-N: BlockCommittedResponse (error = nil) + N->>N: Save prune height as 11 +``` + +In such a case, it is possible for the companion to receive the same height's +data multiple times (at-least-once delivery). It is up to the companion to +handle this correctly. + +### Configuration + +The following configuration file update is proposed to support the data +companion API. + +```toml +[data_companion] +# By default, the data companion service interaction is disabled. It is +# recommended that this only be enabled on full nodes and not validators so as +# to minimize the possibility of network instability. +enabled = false + +# Address at which the gRPC companion service server is hosted. It is +# recommended that this companion service be co-located at least within the same +# data center as the CometBFT node to reduce the risk of network latencies +# interfering in node operation. +addr = "http://localhost:26659" + +# Controls the BlockCommitted gRPC call. +[data_companion.block_committed] +# Enable the BlockCommitted gRPC call. Only relevant if the data companion is +# enabled. +enabled = true +# Additional fields to publish in each BlockCommittedRequest sent to the +# companion. Available options: +# - "finalize_block_response": Also publish the FinalizeBlock response related +# to the block in the BlockCommittedRequest. +additionally_publish = ["finalize_block_response"] +``` + +### Monitoring + +To monitor the health of the interaction between CometBFT and the companion +service, the following additional Prometheus metrics are proposed: + +- `data_companion_send_time` - A gauge that indicates the maximum time, in + milliseconds, taken to send a single request to the companion service take + from a rolling window of tracked send times (e.g. the maximum send time over + the past minute). +- `data_companion_send_bytes` - A counter indicating the number of bytes sent to + the data companion since node startup. +- `data_companion_buffer_size` - A gauge indicating the number of requests + currently being buffered on disk on behalf of the companion service for each + kind of request. +- `data_companion_buffer_size_bytes` - A gauge indicating how much data is being + buffered by CometBFT on disk, in bytes, on behalf of the companion service, + for each kind of request. + +## Implications + +1. We will be able to mark the following RPC APIs as deprecated and schedule + them for removal in a future release: + 1. The [WebSocket subscription API][websocket-api] + 2. [`/tx_search`] + 3. [`/block_search`] + 4. [`/block_results`] + + We may eventually be able to remove the [`/broadcast_tx_commit`] endpoint, + but this is often useful during debugging and development, so we may want to + keep it around. + +2. We will be able to remove all event indexing from CometBFT once we remove + the above APIs. + +3. Depending on the implementation approach chosen, we will still need to store + some quantity of data not critical to consensus. This data can automatically + be pruned once CometBFT has successfully transmitted it to the companion + service. + +### Release Strategy + +As captured in the [requirements](#requirements), we should be able to release +this as an additive, opt-in change, thereby not impacting existing APIs. This +way we can evolve this API until such time that consumers are satisfied with +removal of the old APIs mentioned in [implications](#implications). + +## Follow-Up Work + +If implemented, we should consider releasing our own RPC companion server with +easy deployment instructions for people to test it out and compare the +performance with directly connecting to the CometBFT node. + +This RPC companion server could easily implement an interface like that outlined +in [ADR-075](adr-075), providing the same HTTP- and cursor-based subscription +mechanism, but storing data to and pulling data from a different database (e.g. +PostgreSQL). + +## Consequences + +### Positive + +- Integrators can expose CometBFT data in whatever format/protocol they want + (e.g. JSON-RPC or gRPC). +- Integrators can index data in whatever way suits them best. +- All users eventually benefit from faster changes to CometBFT because the core + team has less, and less complex, code to maintain (implementing this ADR would + add more code in the short-term, but would pave the way for significant + reductions in complexity in future). +- Can be rolled out as experimental and opt-in in a non-breaking way. +- The broad nature of what the API publishes lends itself to reasonable + long-term stability. + +### Negative + +- Keeping existing CometBFT functionality would involve operators having to + run an additional process, which increases operational complexity. +- It is unclear at present as to the impact of the requirement to publish large + quantities of block/result data on the speed of block execution. This should + be quantified in production networks as soon as this feature can be rolled out + as experimental. If the impact is meaningful, we should either remove the + feature or develop mitigation strategies (e.g. allowing for queries to be + specified via the configuration file, or supporting a specific subset of use + cases' data). +- Requires a reasonable amount of coordination work across a number of + stakeholders across the ecosystem in order to ensure their use cases are + addressed effectively and people have enough opportunity to migrate. + +### Neutral + +## References + +- [\#6729]: Tendermint emits events over WebSocket faster than any clients can + pull them if tx includes many events +- [\#7156]: Tracking: PubSub performance and UX improvements +- [RFC 003: Taxonomy of potential performance issues in Tendermint][rfc-003] +- [RFC 006: Event Subscription][rfc-006] +- [\#7471] Deterministic Events +- [ADR 075: RPC Event Subscription Interface][adr-075] + +[cometbft-db]: https://github.com/cometbft/cometbft-db +[\#517]: https://github.com/cometbft/cometbft/issues/517 +[\#6729]: https://github.com/tendermint/tendermint/issues/6729 +[\#7156]: https://github.com/tendermint/tendermint/issues/7156 +[PostgreSQL indexer]: https://github.com/tendermint/tendermint/blob/0f45086c5fd79ba47ab0270944258a27ccfc6cc3/state/indexer/sink/psql/psql.go +[\#7471]: https://github.com/tendermint/tendermint/issues/7471 +[rfc-003]: ../rfc/tendermint-core/rfc-003-performance-questions.md +[rfc-006]: ../rfc/tendermint-core/rfc-006-event-subscription.md +[adr-075]: tendermint-core/adr-075-rpc-subscription.md +[websocket-api]: https://docs.cometbft.com/v0.34/rpc/#/Websocket +[`/tx_search`]: https://docs.cometbft.com/v0.34/rpc/#/Info/tx_search +[`/block_search`]: https://docs.cometbft.com/v0.34/rpc/#/Info/block_search +[`/broadcast_tx_commit`]: https://docs.cometbft.com/v0.34/rpc/#/Tx/broadcast_tx_commit +[`/block_results`]: https://docs.cometbft.com/v0.34/rpc/#/Info/block_results +[adr-101]: https://github.com/cometbft/tendermint/pull/82 diff --git a/docs/references/architecture/adr-101-data-companion-pull-api.md b/docs/references/architecture/adr-101-data-companion-pull-api.md new file mode 100644 index 00000000000..b941ae5b54f --- /dev/null +++ b/docs/references/architecture/adr-101-data-companion-pull-api.md @@ -0,0 +1,472 @@ +# ADR 101: Data Companion Pull API + +## Changelog + +- 2023-05-03: Update based on synchronous feedback from team (@thanethomson) +- 2023-04-04: Update based on review feedback (@thanethomson) +- 2023-02-28: Renumber from 084 to 101 (@thanethomson) +- 2022-12-18: First draft (@thanethomson) + +## Status + +Accepted + +## Context + +See the [context for the Data Companion Push API (ADR-100)][adr-100-context]. + +The primary novelty introduced in this ADR is effectively a new gRPC API +that allows an external application to influence which data the node prunes. +Otherwise, existing and planned RPC interfaces (such as the planned gRPC +interface) in addition to this pruning API should, in theory, deliver the same +kind of value as the solution proposed in ADR-100. + +Even though the pruning API could be useful to operators outside the context of +the usage of a data companion (e.g. it could provide operators with more control +over node pruning behaviour), it is presented as part of the data companion +discussion to illustrate its initial intended use case. + +## Alternative Approaches + +[ADR-100][adr-100], as well as the [alternatives][adr-100-alt] outlined in +ADR-100, are all alternative approaches. + +## Decision + +To implement ADR-101 instead of ADR-100. + +## Detailed Design + +The model proposed in this ADR inverts that proposed in ADR-100, with the node +being the server and the data companion being the client. Here, the companion +"pulls" data from the node. + +This provides much weaker data delivery guarantees than the "push" model of +ADR-100. In this "pull" model, the companion can lag behind consensus, but the +node does not crash if the companion is unavailable. + +### Requirements + +The requirements for ADR-101 are the same as the [requirements for +ADR-100][adr-100-req]. + +### Entity Relationships + +The following model shows the proposed relationships between CometBFT, a +socket-based ABCI application, and the proposed data companion service. + +```mermaid +flowchart RL + comet[CometBFT] + companion[Data Companion] + app[ABCI App] + + comet --> app + companion --> comet +``` + +In this diagram, it is evident that CometBFT (as a client) connects out to the +ABCI application (a server), and the companion (a client) connects to the +CometBFT node (a server). + +### Pruning Behaviour + +Two parameters are proposed as a necessary part of the pruning API: + +- **Pruning service block retain height**, which influences the height to which + the node will retain blocks. This is different to the **application block + retain height**, which is set by the application in its response to each ABCI + `Commit` message. + + The node will prune blocks to whichever is lower between the pruning service + and application block retain heights. + +- **Pruning service block results retain height**, which influences the height + to which the node will retain block results. + +These parameters need to be durable (i.e. stored on disk). + +### gRPC API + +At the time of this writing, it is proposed that CometBFT implement a full gRPC +interface ([\#81]). As such, we have several options when it comes to +implementing the data companion pull API: + +1. Extend the proposed gRPC API from [\#81] to simply provide the additional + data companion-specific endpoints. In order to meet the + [requirements](#requirements), however, some of the endpoints will have to be + protected by default. This is simpler for clients to interact with though, + because they only need to interact with a single endpoint for all of their + needs. +2. Implement a separate gRPC API on a different port to the standard gRPC + interface. This allows for a clearer distinction between the standard and + data companion-specific gRPC interfaces, but complicates the server and + client interaction models. + +Due to past experience of operators exposing _all_ RPC endpoints on a specific +port to the public internet, option 2 will be chosen here to minimize the +chances of this happening in future, even though it offers a slightly more +complicated experience for operators. + +#### Block Service + +The following `BlockService` will be implemented as part of [\#81], regardless +of whether or not this ADR is implemented. This API, therefore, needs to be more +generally useful than just for the purposes of the data companion. The minimal +API to support a data companion, however, is presented in this ADR. + +```protobuf +syntax = "proto3"; + +package tendermint.services.block.v1; + +import "tendermint/abci/types.proto"; +import "tendermint/types/types.proto"; +import "tendermint/types/block.proto"; + +// BlockService provides information about blocks. +service BlockService { + // GetLatestHeight returns a stream of the latest block heights committed by + // the network. This is a long-lived stream that is only terminated by the + // server if an error occurs. The caller is expected to handle such + // disconnections and automatically reconnect. + rpc GetLatestHeight(GetLatestHeightRequest) returns (stream GetLatestHeightResponse) {} + + // GetByHeight attempts to retrieve the block at a particular height. + rpc GetByHeight(GetByHeightRequest) returns (GetByHeightResponse) {} +} + +message GetLatestHeightRequest {} + +// GetLatestHeightResponse provides the height of the latest committed block. +message GetLatestHeightResponse { + // The height of the latest committed block. Will be 0 if no data has been + // committed yet. + uint64 height = 1; +} + +message GetByHeightRequest { + // The height of the block to get. Set to 0 to return the latest block. + uint64 height = 1; +} + +message GetByHeightResponse { + // The ID associated with the relevant block. + tendermint.types.BlockID block_id = 1; + // Block data for the requested height. + tendermint.types.Block block = 2; +} +``` + +#### Block Results Service + +The following `BlockResultsService` service is proposed _separately_ to the +`BlockService`. There are several reasons as to why there are two separate gRPC +services to meet the companion's needs as opposed to just one: + +1. The quantity of data stored by each is application-dependent, and coalescing + the two types of data could impose significant overhead in some cases (this + is primarily a justification for having separate RPC calls for each type of + data). +2. Operators can enable/disable these services independently of one another. +3. The existing JSON-RPC API distinguishes between endpoints providing these two + types of data (`/block` and `/block_results`), so users are already + accustomed to this distinction. +4. Eventually, when we no longer need to store block results at all, we can + simply deprecate the `BlockResultsService` without affecting clients who rely + on `BlockService`. + +```protobuf +syntax = "proto3"; + +package tendermint.services.block_results.v1; + +// BlockResultsService provides information about the execution results for +// specific blocks. +service BlockResultsService { + // GetByHeight attempts to retrieve the execution results associated with a + // block of a certain height. + rpc GetByHeight(GetByHeightRequest) returns (GetByHeightResponse) {} +} + +message GetByHeightRequest { + // The height of the block whose results are to be retrieved. Set to 0 to + // return the latest block's results. + uint64 height = 1; +} + +message GetByHeightResponse { + // The height associated with the block results. + uint64 height = 1; + + // The contents of the FinalizeBlock response, which contain block execution + // results. + tendermint.abci.ResponseFinalizeBlock finalize_block_response = 2; +} +``` + +#### Pruning Service + +This gRPC service is the only novel service proposed in this ADR, and +effectively gives a single external caller (e.g. a data companion) a say in how +the node prunes its data. + +```protobuf +syntax = "proto3"; + +package tendermint.services.pruning.v1; + +// PruningService provides privileged access to specialized pruning +// functionality on the CometBFT node to help control node storage. +service PruningService { + // SetBlockRetainHeightRequest indicates to the node that it can safely + // prune all block data up to the specified retain height. + // + // The lower of this retain height and that set by the application in its + // Commit response will be used by the node to determine which heights' data + // can be pruned. + rpc SetBlockRetainHeight(SetBlockRetainHeightRequest) returns (SetBlockRetainHeightResponse); + + // GetBlockRetainHeight returns information about the retain height + // parameters used by the node to influence block retention/pruning. + rpc GetBlockRetainHeight(GetBlockRetainHeightRequest) returns (GetBlockRetainHeightResponse); + + // SetBlockResultsRetainHeightRequest indicates to the node that it can + // safely prune all block results data up to the specified height. + // + // The node will always store the block results for the latest height to + // help facilitate crash recovery. + rpc SetBlockResultsRetainHeight(SetBlockResultsRetainHeightRequest) returns (SetBlockResultsRetainHeightResponse); + + // GetBlockResultsRetainHeight returns information about the retain height + // parameters used by the node to influence block results retention/pruning. + rpc GetBlockResultsRetainHeight(GetBlockResultsRetainHeightRequest) returns (GetBlockResultsRetainHeightResponse); +} + +message SetBlockRetainHeightRequest { + uint64 height = 1; +} + +message SetBlockRetainHeightResponse {} + +message GetBlockRetainHeightRequest {} + +message GetBlockRetainHeightResponse { + // The retain height set by the application. + uint64 app_retain_height = 1; + + // The retain height set via the pruning service (e.g. by the data + // companion) specifically for blocks. + uint64 pruning_service_retain_height = 2; +} + +message SetBlockResultsRetainHeightRequest { + uint64 height = 1; +} + +message SetBlockResultsRetainHeightResponse {} + +message GetBlockResultsRetainHeightRequest {} + +message GetBlockResultsRetainHeightResponse { + // The retain height set by the pruning service (e.g. by the data + // companion) specifically for block results. + uint64 pruning_service_retain_height = 1; +} +``` + +##### Indexer pruning service + +This gRPC service can be used to instruct CometBFT to prune the transaction and +block events indexed by CometBFT. + +To support this, the above described pruning service is extended as follows: + +```protobuf + +// PruningService provides privileged access to specialized pruning +// functionality on the CometBFT node to help control node storage. +service PruningService { + + + // SetTxIndexerRetainHeightRequest indicates to the node that it can safely + // prune all tx indices up to the specified retain height. + rpc SetTxIndexerRetainHeight(SetTxIndexerRetainHeightRequest) returns (SetTxIndexerRetainHeightResponse); + + // GetTxIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence TxIndexer pruning + rpc GetTxIndexerRetainHeight(GetTxIndexerRetainHeightRequest) returns (GetTxIndexerRetainHeightResponse); + + // SetBlockIndexerRetainHeightRequest indicates to the node that it can safely + // prune all block indices up to the specified retain height. + rpc SetBlockIndexerRetainHeight(SetBlockIndexerRetainHeightRequest) returns (SetBlockIndexerRetainHeightResponse); + + // GetBlockIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence BlockIndexer pruning + rpc GetBlockIndexerRetainHeight(GetBlockIndexerRetainHeightRequest) returns (GetBlockIndexerRetainHeightResponse); + + +} + +message SetTxIndexerRetainHeightRequest { + uint64 height = 1; +} + +message SetTxIndexerRetainHeightResponse {} + +message GetTxIndexerRetainHeightRequest {} + +message GetTxIndexerRetainHeightResponse { + uint64 height = 1; +} + +message SetBlockIndexerRetainHeightRequest { + uint64 height = 1; +} + +message SetBlockIndexerRetainHeightResponse {} + +message GetBlockIndexerRetainHeightRequest {} + +message GetBlockIndexerRetainHeightResponse { + uint64 height = 1; +} + +``` + +With this API design, it is technically possible for an integrator to attach +multiple data companions to the node, but only one of their retain heights will +be considered by the node. + +### Configuration + +The following configuration file (`config.toml`) update is proposed to support the data +companion API. + +```toml +[storage] + +# +# Storage pruning configuration relating only to the data companion. +# +[storage.pruning.data_companion] + +# Whether automatic pruning respects values set by the data companion. Disabled +# by default. All other parameters in this section are ignored when this is +# disabled. +# +# If disabled, only the application retain height will influence block pruning +# (but not block results pruning). Only enabling this at a later stage will +# potentially mean that blocks below the application-set retain height at the +# time will not be available to the data companion. +enabled = false + +# The initial value for the data companion block retain height if the data +# companion has not yet explicitly set one. If the data companion has already +# set a block retain height, this is ignored. +initial_block_retain_height = 0 + +# The initial value for the data companion block results retain height if the +# data companion has not yet explicitly set one. If the data companion has +# already set a block results retain height, this is ignored. +initial_block_results_retain_height = 0 + +# +# This is the envisaged configuration section for the gRPC API that will be +# introduced as part of https://github.com/cometbft/cometbft/issues/81 +# (Still a WIP) +# +[grpc] + +# The host/port on which to expose non-privileged gRPC endpoints. +laddr = "tcp://localhost:26654" + +# +# Configuration for privileged gRPC endpoints, which should **never** be exposed +# to the public internet. +# +[grpc.privileged] +# The host/port on which to expose privileged gRPC endpoints. +laddr = "tcp://localhost:26655" + +# +# Configuration specifically for the gRPC pruning service, which is considered a +# privileged service. +# +[grpc.privileged.pruning_service] + +# Only controls whether the pruning service is accessible via the gRPC API - not +# whether a previously set pruning service retain height is honoured by the +# node. That is controlled by settings in the [storage.pruning] section. +# +# Disabled by default. +enabled = false +``` + +### Metrics + +The following metrics are proposed to be added to monitor the health of the +interaction between a node and its data companion: + +- `pruning_service_block_retain_height` - The current block retain height as + requested by the pruning service. +- `pruning_service_block_results_retain_height` - The current block results + retain height as requested by the pruning service. +- `application_block_retain_height` - The current block retain height as set by + the application. +- `block_store_base_height` - The actual base height of the block store, which + is influenced by the application and pruning service block retain heights. +- `abci_results_base_height` - The actual base height of stored block results, + which is influenced by the pruning service block results retain height. +- `block_indexer_retain_height` - The current block indexer retain height + requested by the pruning service. +- `tx_indexer_retain_height` - The current tx indexer retain height + requested by the pruning service. +- `block_indexer_base_height` - The minimum height at which we have block events + (should demonstrate the effects of pruning the block indexer) +- `tx_indexer_base_height` - The minimum height at which we have transaction events + (should demonstrate the effects of pruning the tx indexer) + +Other metrics may be proposed as part of the non-privileged gRPC API that could +assist operators in understanding the health of the interaction with the data +companion, but only if the data companion is the exclusive user of those APIs. + +## Consequences + +### Positive + +- Facilitates offloading of data to an external service, which can be scaled + independently of the node + - Potentially reduces load on the node itself + - Paves the way for eventually reducing the surface area of a node's exposed + APIs +- Allows the data companion more leeway in reading the data it needs than the + approach in [ADR 100][adr-100] +- Simpler implementation and fewer changes within the node than [ADR + 100][adr-100] + +### Negative + +- Increases system complexity slightly in the short-term +- If data companions are not correctly implemented and deployed (e.g. if a + companion is attached to the same storage as the node, and/or if its retain + height signalling is poorly handled), this could result in substantially + increased storage usage + +### Neutral + +- Expands the overall API surface area of a node in the short-term + +## References + +- [ADR 100 - Data Companion Push API][adr-100] +- [\#81 - rpc: Add gRPC support][\#81] +- [Documentation on current implementation of ADR-101][dc-docs] + +[adr-100-context]: adr-100-data-companion-push-api.md#context +[adr-100]: adr-100-data-companion-push-api.md +[adr-100-req]: adr-100-data-companion-push-api.md#requirements +[adr-100-alt]: adr-100-data-companion-push-api.md#alternative-approaches +[\#81]: https://github.com/cometbft/cometbft/issues/81 +[abci-commit]: ../../../spec/abci/abci++_methods.md#commit +[dc-docs]: https://github.com/cometbft/cometbft/tree/main/docs/data-companion diff --git a/docs/references/architecture/adr-102-rpc-companion.md b/docs/references/architecture/adr-102-rpc-companion.md new file mode 100644 index 00000000000..334c11ab6c7 --- /dev/null +++ b/docs/references/architecture/adr-102-rpc-companion.md @@ -0,0 +1,352 @@ +# ADR-102: RPC Companion + +## Changelog + +- 2022-03-27: First draft (@andynog) +- 2024-03-19: Update ADR information (@andynog) +- 2024-03-25: Final updates before publishing (@andynog) + +## Status + +Accepted + +[Tracking issue](https://github.com/cometbft/cometbft/issues/707) + +## Context + +This solution can run as a sidecar, a separate process that runs concurrently with the full node. However, the RPC +Companion is optional, meaning that the full node will still provide RPC services that can be queried if operators +don't want to run an RPC Companion service. + +This ADR provides a reference implementation of a system that can be used to offload queryable data from a CometBFT +full node to a database and offer a service exposing the same JSON-RPC methods on an endpoint as the regular JSON-RPC +methods of a CometBFT node endpoint. This makes it easier for integrators of RPC clients, such as client libraries and +applications, to switch to this RPC Companion with as little effort as possible. + +This architecture also makes it possible to scale horizontally the querying capacity of a full node by running multiple +copies of the RPC Companion server instances that can be behind a scalable load-balancer (e.g., Cloudflare), which makes +it possible to serve the data in a more scalable way. + +One of the benefits of utilizing an RPC Companion is that it enables data indexing on external storage, leading to +improved performance compared to the internal indexer of CometBFT. The internal indexer of CometBFT has certain +limitations and might not be suitable for specific application use cases. + +## Alternative Approaches + +The Data Companion Pull API concept, identified as [[ADR-101]](adr-101-data-companion-pull-api.md), is a novel idea. As it gains popularity and acceptance, +users are expected to develop their own versions of it to meet their specific requirements. The RPC Companion is the +initial implementation of a Data Companion that can serve as a model for others to follow. + +## Decision + +TBD + +## Detailed Design + +### Requirements + +The target audience for this solution are operators and integrators that want to alleviate the load on their nodes by offloading +the queryable data requests to the **RPC Companion**. + +This solution shall meet the following requirements in order to provide real benefits to these users. + +The **RPC Companion** solution shall: + +1. Provide an **[Ingest Service](#ingest-service)** implemented as a data companion that can pull data from a CometBFT node and store it on +its own storage (database) +2. Provide a storage ([Database](#database)) that can persist the data using a [database schema](#database-schema) that +can store information that was fetched from the full node. +3. Do not force breaking changes to the existing RPC. +4. Ensure the responses returned by the RPC Companion v1 endpoint is wire compatible with the existing CometBFT +JSON-RPC endpoint. +5. Implement tests to verify backwards compatibility. + +### [RPC Endpoint](#rpc-endpoint) + +The RPC Companion endpoint will be the same as the CometBFT JSON-RPC endpoint but with a `/v1` appended to it. The RPC +Companion endpoint can be hosted on a different URL and might also use a different port than the default CometBFT RPC +port (e.g. `26657`) as shown below. + +For example, suppose these are the URLs for each RPC endpoint: + +CometBFT RPC -> `http://cosmos.host:26657` + +RPC Companion -> `http://rpc-companion.host:8080/v1` + +To make a request for a `block` at height `5` using the CometBFT JSON-RPC endpoint: + + curl --header "Content-Type: application/json" --request POST --data '{"method": "block", "params": ["5"], "id": 1}' http://cosmos.host:26657 + +To make the same request to the RPC Companion endpoint: + + curl --header "Content-Type: application/json" --request POST --data '{"method": "block", "params": ["5"], "id": 1}' http://rpc-companion.host:8080/v1 + +> Note that only the URL and port changes between these two `curl` commands + +The RPC Companion will accept JSON-RPC requests, the same way as the CometBFT JSON-RPC endpoint does. + +The RPC Companion endpoint methods listed in the following table should be implemented first as they are straightforward +and less complex. + +| **JSON-RPC method** | **JSON-RPC Parameters** | **Description** | **Notes** | +|---------------------|----------------------------------------|-------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `abci_info` | | Get information about the application | This method will return the same response structure as the equivalent CometBFT method. It will return the latest information stored in its database that was retrieved from the full node. | +| `block` | * height | Get block at a specified height | This method will return the same response structure as the equivalent CometBFT method. The data retrieved from the companion database for a particular block will have to be properly serialized into the `block` struct in order to be returned as a response. | +| `block_by_hash` | * hash | Get block by its hash | This method will return the same response structure as the equivalent CometBFT method. | +| `block_results` | * height | Get block results at a specified height | This method will return the same response structure as the equivalent CometBFT method. The data retrieved from the companion database for a particular block result will have to be properly serialized into the `ResultsBlockResults` struct in order to be returned as a response. | +| `blockchain` | * minHeight
* maxHeight | Get blocks in a specified height range | This method will return the same response structure as the equivalent CometBFT method. The data retrieved from the companion database will include one or more blocks. | +| `commit` | * height | Get commit results at a specified height | This method will return the same response structure as the equivalent CometBFT method. | +| `consensus_params` | * height | Get consensus parameters at a specified height | This method will return the same response structure as the equivalent CometBFT method. | +| `header` | * height | Get header at a specified height | This method will return the same response structure as the equivalent CometBFT method. | +| `header_by_hash` | * hash | Get header by its hash | This method will return the same response structure as the equivalent CometBFT method. | +| `health` | | Get node health | This method basically only returns an empty response. This can be used to test if the server RPC is up. While this on CometBFT is used to return a response if the full node is up, when using the companion service this will return an `OK` status if the companion service is up. | +| `tx` | * hash
* prove | Get a transaction by its hash | This method will return the same response structure as the equivalent CometBFT method. | +| `validators` | * height
* page
* per_page | Get validator set at a specified height | This method will return the same response structure as the equivalent CometBFT method. | + +The following methods can also be implemented, but might require some additional effort and complexity to be implemented. +These are mostly the ones that provide `search` and `query` functionalities. These methods will proxy the request to the +full node. Since they are not dependent on data retrieval from the RPC Companion database they should just act as proxies +to the full node. In the future, it might be possible to implement these methods in the RPC Companion if the database +stores all the information required to be indexed and the queries specified in the JSON-RPC methods can be translated into +SQL statements to return the queried data from the database. + +| **JSON-RPC method** | **JSON-RPC Parameters** | **Description** | **Notes** | +|---------------------|----------------------------------------------------------------------|----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `abci_query` | * path
* data
* height
* prove | Query information from the application | This method will return the same response structure as the equivalent CometBFT method. The RPC companion service will have to implement a proper abci parameter to sql query translation. | +| `block_search` | * query
* page
* per_page
* order_by | Query information about a block | This method will return the same response structure as the equivalent CometBFT method. The RPC companion service will have to implement a proper query parameter to sql query translation. | +| `tx_search` | * query
* page
* per_page
* prove
* order_by | Query information about transactions | This method will return the same response structure as the equivalent CometBFT method. The RPC companion service will have to implement a proper query parameter to sql query translation. | + +The following methods will proxy the requests through the RPC Companion endpoint to the full node to ensure that clients don't need to implement a routing logic for methods that would not be available in the RPC Companion endpoint. + +> The `/broadcast_tx_*` methods might need some additional logic for proxying since some of them have different asynchronicity patterns. + +| **JSON-RPC method** | *JSON-RPC Parameters** | **Description** | **Notes** | Proxy | +|------------------------|------------------------|-------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------| +| `broadcast_evidence` | * evidence | Broadcast evidence of the misbehavior | The evidence parameter is in JSON format | yes | +| `broadcast_tx_async` | * tx | Broadcast a transaction | Returns right away with no response | yes | +| `broadcast_tx_sync` | * tx | Broadcast a transaction | Returns with the response from CheckTx | yes | +| `broadcast_tx_commit` | * tx | Broadcast a transaction | Returns with the responses from CheckTx and DeliverTx | yes | +| `check_tx` | * tx | Check a transaction | Checks a transaction without executing it | yes | +| `consensus_state` | | Gets consensus state | The consensus state will not be stored in the RPC companion database so it should proxy the request to the full node | yes | +| `dump_consensus_state` | | Gets the full consensus state | The consensus state will not be stored in the RPC companion database so it should proxy the request to the full node | yes | +| `genesis` | | Gets the genesis information | The RPC companion service can proxy the genesis request to the full node. If there are use cases that serving the genesis from the RPC companion service (no proxy) is desirable then it can be implemented as method | yes | +| `net_info` | | Gets network information | The request should proxy to the full node since the RPC companion database will not store network information | yes | +| `unconfirmed_txs` | * limit | Gets the list of unconfirmed transactions | The request should proxy to the full node since the RPC companion database will not store unconfirmed transactions information | yes | +| `num_unconfirmed_txs` | | Gets data about unconfirmed transactions | The request should proxy to the full node since the RPC companion database will not store unconfirmed transactions information | yes | +| `status` | | Gets node status | The request should proxy to the full node since the RPC companion database will not store node status information | yes | + +> NOTE: The RPC Companion should not implement logic to store data in its database that can modify state in the blockchain such as +the `broadcast_tx_*` methods. These requests will proxy to the full node as outlined above. + +### High-level architecture + +![High-level architecture](images/adr-102-architecture.jpeg) + +This diagram shows all the required components for a full RPC Companion solution. The solution implementation contains +many parts and each one is described below: + +### [Ingest Service](#ingest-service) + +The **Ingest Service** pulls the data from the full node JSON-RPC endpoint and stores the information retrieved in +the RPC Companion database. + +The **Ingest Service** should run as a "singleton" which means only one instance of this service +should be fetching the information from the CometBFT full node. + +Currently, the Data Companion Pull APIs offer gRPC services to retrieve `Block` and `BlockResults`. These can be used +to pull the data from the server. + +The **Ingest Service** can influence the pruning of `Blocks` and `BlockResults` on the full node via a [pruning service](https://docs.cometbft.com/v1.0/explanation/data-companion/pruning). +Once the Ingest Service pulls the data from the full node and is able to process it, and it gets an acknowledgement from +the database that the data was inserted, the **Ingest Service** can communicate with the full node notifying it that +a specific height has been processed and set the processed height as the `retain height` on the full node signaling +this way to the node that this height can be pruned. + +If the **Ingest Service** becomes unavailable (e.g. stops), then it should resume synchronization with the full node when it is back online. +The **Ingest Service** should query the full node for the last `retain height` and the **Ingest Service** should request +and process all the heights missing on the database until it catches up with the full node latest height. + +In case the **Ingest Service** becomes unavailable for a long time and there are several heights to be synchronized, it is +important for the **Ingest Service** to do it in a throttled way (in short intervals) to prevent the server to become overloaded. + +### [Database](#database) + +The database stores the data retrieved from the full node and provides this data for the RPC server instance. + +It is proposed that the relational database [PostgreSQL](https://www.postgresql.org/) be used in order to support +the [RPC server instance](#rpc-instance) scalability + +Also, using a relational database will also provide more flexibility when implementing a future RPC Companion `/v2` +endpoint that can return data in different forms and database indexes might also be leveraged in order to boost the +query responses performance. + +The data needs to be available both for the Ingest Service (database writes) and the RPC server instance (database reads) +and these services might be running from different machines so an embedded database is not recommended in this case +since accessing the data remotely might not be optimal for an embedded key-value database. Also since the RPC might have +many server instances (or processes) running that will need to retrieve data concurrently it is recommended to use +a well-known robust database engine that can support such a load. + +Also, PostgreSQL supports ACID transactions, which is important to provide more guarantees that the data was successfully +inserted in the database and that an acknowledgement can be sent back to the Ingest Service to notify the +full node to prune the inserted data. Supporting ACID transactions can also ensure that there are no partial reads +(return data that was partially written to the database), avoiding that readers access incomplete or inconsistent data. + +#### [Database Schema](#database-schema) + +Implementing this solution comes with a challenge - designing a database schema that can facilitate return responses +equivalent to the existing CometBFT JSON-RPC endpoint. However, the schema should also be flexible enough to return +customized responses in the future. + +Since the RPC Companion stores the information in a relational database, there are opportunities to better structure and +normalize the data in the future. For example, here is the schema definition for a table to persist a `Block` data +structure in the PostgreSQL database: + +```sql +-- TABLE: comet.v1.block + +DROP TABLE IF EXISTS comet.v1.block CASCADE; + +CREATE TABLE comet.v1.block +( + height comet.uint64 NOT NULL, + data bytea NOT NULL, + CONSTRAINT block_pkey PRIMARY KEY (height) +); +``` + +It's important to add a version to the table (e.g `v1`) to ensure schema changes can be supported + +> Note that only the height is stored as structure data. More data field can be normalized and stored in individual fields, +but trying to normalize the CometBFT data structures into a database schema should be only performed if there's a need to +do so (e.g. search for information and using the field as a query parameter). + +##### Data types + +This solution utilizes PostgreSQL's built-in data types to implement a data schema in the database. By using a relational +database, it is possible to normalize the data structures, which can lead to significant storage savings. However, +it's important to note that normalizing the schema too much can make it complex to retrieve a specific dataset due to +the need for data joins. As a result, it's crucial to exercise caution when over-normalizing the schema. + +Also, when normalizing, it is important to ensure the referential integrity is not violated since this can cause issues +to the clients consuming the data. + +In order to accurately ensure the database is storing the full node data types properly, the database implements +custom data types (`domains` in PostgreSQL). + +For example, PostgreSQL doesn't have an unsigned `uint8`, `uint32`, `uint64` datatype, therefore in order to support +this in the database, you can use a `domain`, which is a base type with additional constraints: + +```sql +-- DOMAIN: comet.uint8 + +DO $$ BEGIN +CREATE DOMAIN comet.uint8 AS numeric; + +ALTER DOMAIN comet.uint8 + ADD CONSTRAINT value_max CHECK (VALUE <= '255'::numeric); + +ALTER DOMAIN comet.uint8 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- DOMAIN: comet.uint32 + +DO $$ BEGIN +CREATE DOMAIN comet.uint32 AS numeric; + +ALTER DOMAIN comet.uint32 + ADD CONSTRAINT value_max CHECK (VALUE <= '4294967295'::numeric); + +ALTER DOMAIN comet.uint32 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- DOMAIN: comet.uint64 + +DO $$ BEGIN +CREATE DOMAIN comet.uint64 + AS numeric; + +ALTER DOMAIN comet.uint64 OWNER TO postgres; + +ALTER DOMAIN comet.uint64 + ADD CONSTRAINT value_max CHECK (VALUE <= '18446744073709551615'::numeric); + +ALTER DOMAIN comet.uint64 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +``` + +##### Schema migration + +Another point to consider is when the data structures change across CometBFT releases. + +A potential solution for this scenario is to find a way in the database that can support "versioning" of data structures. +For example, let's assume there's a `Block` structure, let's call it `v1`. If in the future there's a need to modify +this structure that is not compatible with the previous data structure, then the database would support a `v2` schema +for `ResultBlock` and an `index` table could determine the criteria on which data structure should be used for inserting +or querying data. + +### [RPC server instance](#rpc-instance) + +The **RPC server instance** is a node that runs the RPC API process for the data companion. This server instance provides +an RPC API (`/v1`) with the same JSON-RPC methods of the full node JSON-RPC endpoint. The RPC Companion service will expose +the same JSON-RPC methods and will accept the same request types and return wire compatible responses (should match the +same response as the equivalent full node JSON-RPC endpoint). + +The **RPC server instance**, when serving a particular request, retrieves the required data from the database in order to +fulfill the request. The data should be serialized in a way that makes it wire compatible with the CometBFT JSON-RPC endpoint. + +It is possible to integrate a caching layer as part of the RPC server instance solution. Caching can be useful for queries +that are idempotent, which means they produce the same result regardless of how many times they are executed. There are +various caching solutions available, either off-the-shelf or custom-built, that can be added to the RPC server instance +logic. However, implementing a caching solution is not within the scope of this ADR. + +The RPC service endpoints from the server instances should be exposed through an external load-balancer service such +as Cloudflare or AWS ELB, or a server running its own load balancer mechanism (e.g. nginx). + +The RPC clients should make requests to the **RPC Companion** server instances through this load balancer for scalability +reasons. + +The **RPC server instance** will also implement logic to proxy requests to the full node. It should properly handle +the proxy requests and responses from the full node. + +The **RPC Companion** endpoint should support the `https` protocol in order to support a secure endpoint access. It's recommended that +the `https` support is provided by the load balancer. + +## Consequences + +### Positive + +- The **RPC Companion** can be more scalable and consequently provide a higher query throughput. +- Less backpressure on the full node that is running consensus. +- Possibility for future additional custom endpoints (e.g a `/v2`) with additional methods not available in the `/v1` endpoint. +- Can act as a basis for users to create better and faster indexers solutions. +- Possibility to turn off indexing on the full node if the data can be offloaded to an external data storage that supports +indexing. + +### Negative + +- Additional infrastructure complexity to set up and maintain. +- Additional infrastructure costs if using a load balanced setup for the RPC service endpoint (multiple nodes) and a fail-over +database setup (master/replica) + +### Neutral + +- Optional feature, users will only use it if their use case requires such solution +- No privacy / security issues should arise since the data returned by the **RPC Companion** will be the same +as the current RPC. + +## References + +- [ADR-101: Data Companions Pull API](adr-101-data-companion-pull-api.md) +- [Data Companion Guide - CometBFT documentation](https://docs.cometbft.com/v1.0/explanation/data-companion/) +- [RPC Companion - Reference Implementation](https://github.com/cometbft/rpc-companion) + + diff --git a/docs/references/architecture/adr-103-proto-versioning.md b/docs/references/architecture/adr-103-proto-versioning.md new file mode 100644 index 00000000000..3dfa2328270 --- /dev/null +++ b/docs/references/architecture/adr-103-proto-versioning.md @@ -0,0 +1,142 @@ +# ADR 103: Protobuf definition versioning + +## Changelog + +- 2023-04-27: First draft (@thanethomson) + +## Status + +Accepted + +## Context + +In CometBFT v0.34 through v0.38, the Protocol Buffers definitions in the `proto` +folder are organized in a relatively flat structure and evolve over time in +major releases of CometBFT. + +For integrators who may want to interact with nodes running different versions +of CometBFT, this means that, when consuming those Protobuf definitions, they +need to clone the CometBFT repository and check out the definitions for each and +every major version they want to support. It also means that they need to +manually diff the types to get a precise sense of what changed between CometBFT +releases. Moreover, the differences obtained with the manual diff are often +undocumented. + +We hypothesize that, if we had to version our Protobuf definitions according to +[Buf's style guide][buf-style], we could simplify integration efforts with +CometBFT in the long run. Adopting such a practice would also introduce a new +level of rigour into the way CometBFT Protobuf definitions are managed, allowing +for better expectation management with integrators. It would also allow the core +team to make better use of Protobuf-related tooling (such as Buf) in enforcing +standards, conventions and versioning practices in an automated way. + +Some context is captured in [\#95] and the issues/PRs to which it links. + +## Alternative Approaches + +1. The main alternative here is to do nothing and keep our existing Protobuf + definition approach, which suffers from the issues captured in the + [Context](#context) section. +2. Version our Protobuf definitions, as per this ADR. The primary drawback of + introducing versioning is that it represents a substantial breaking change. + Within this approach, there are two alternative policies that @mzabaluev has + proposed: + 1. **Conservative**, recommended by Buf: Do not create new versions when + making non-breaking changes to Protobuf message definitions, such as + adding a new field. The upside to this approach is that non-breaking + changes can be made in non-breaking releases of CometBFT, but the downside + is that some code generators, such as [prost] for Rust, cannot generate + non-breaking code from these non-breaking changes. + 2. **Sensitive**: Create a new version of a Protobuf message definition any + time anything changes, including adding a new field. The upside to this + approach is that generated code in languages like Rust is additive and + non-breaking, but the downside is that non-breaking Protobuf changes can + only be released in new, breaking versions of CometBFT. + +## Decision + +From team discussion, it was decided to adopt versioning, using the **sensitive +versioning** policy. + +## Detailed Design + +### Implementation + +In order to implement Protobuf definition versioning, it is recommended to bring +all of the Protobuf definitions for all currently maintained major CometBFT +releases thus far (v0.34, v0.37 and v0.38 as of the time of writing this ADR) +into `main`, implementing versioning for each major version's definitions. + +For example, the v0.34 Protobuf definitions would be brought to `main` as `v1` +(i.e. `proto/tendermint/types/types.proto` would become +`proto/tendermint/types/v1/types.proto`, and the package would change from +`tendermint.types` to `tendermint.types.v1`). + +Then, the v0.37 Protobuf definitions would be brought to `main`, and only where +changes were made according to our **sensitive** versioning policy would we +create new types (e.g. `proto/tendermint/types/params.proto` from v0.37 would +become `proto/tendermint/types/v2/params.proto` and the package would change +from `tendermint.types` to `tendermint.types.v2`). + +### Minimizing breaking impact + +Changing the type URLs of Protobuf message types (e.g. `tendermint.types.Block` +becoming `tendermint.types.v1.Block`), is considered a breaking change because, +in some cases, integrators may be serializing structures into Protobuf +`Any`-typed fields. When doing so, the URL of the type being serialized is also +embedded in the encoded message. + +In order to minimize the impact of this breaking change, it is proposed to keep +type definitions in the `proto` folder that are _wire-compatible_ with the +_latest_ versioned types, but that are unversioned (e.g. exposing +`tendermint.types.Block`, which would be wire-compatible with +`tendermint.types.v1.Block`). + +Internally, however, CometBFT would make use of types generated from the +versioned Protobuf types only. + +This would facilitate a transition period for integrators who depend on the old +type URL structure, and would allow for a grace period to upgrade to use the +versioned type definitions. + +### Ergonomics of generated code + +One of the challenges associated with this change is that usage of the generated +Go code becomes more difficult for the core team. This is because all generated +code will also have version suffixes in package paths, meaning that the core +team needs to know exactly which versions of which messages are relevant to the +current release when wiring them up. + +A simple way of mitigating the impact here is to introduce type aliases for the +latest versions of generated types, and make use of these aliases internally. + +### Rollout strategy + +The current recommended strategy to roll out this change is to accumulate all +incremental changes on a **feature branch**, which can then be targeted to a +specific release. At present, it is envisaged that CometBFT v0.39 or v0.40 will +introduce these changes, but this could change based on negotiation with +stakeholders. + +## Consequences + +### Positive + +- Protobuf definitions that are wire-compatible with all versions of CometBFT + will be able to be packaged together +- The combined Protobuf definitions could be uploaded to the Buf registry for + easy consumption by integrators +- Changes to Protobuf definitions will be more obvious and explicit to + integrators + +### Negative + +- While some of the short-term impact of this change can be mitigated, + ultimately this is a substantial breaking change for some integrators who + depend on the type URLs of the Protobuf definitions +- Requires slightly more maintenance than not versioning the types if type + aliases need to be maintained for generated code + +[\#95]: https://github.com/cometbft/cometbft/issues/95 +[buf-style]: https://buf.build/docs/best-practices/style-guide/ +[prost]: https://github.com/tokio-rs/prost/ diff --git a/docs/references/architecture/adr-104-out-of-band-state-sync.md b/docs/references/architecture/adr-104-out-of-band-state-sync.md new file mode 100644 index 00000000000..d8ef8c9502b --- /dev/null +++ b/docs/references/architecture/adr-104-out-of-band-state-sync.md @@ -0,0 +1,466 @@ +# ADR 104: State sync from local application snapshot + +## Changelog + +- 2023-05-05: Initial Draft (@cason) +- 2023-24-05: Added description of SDK-based & a CometBFT based solution (@jmalicevic) + +## Status + +Accepted + +## Context + +1. What is state sync? + +From CometBFT v0.34, synchronizing a fresh node with the rest of the network +can benefit from [state sync][state-sync], a protocol for discovering, +fetching, and installing application snapshots. +State sync is able to rapidly bootstrap a node by installing a relatively +recent state machine snapshot, instead of replaying all historical blocks. + +2. What is the problem? + +With the widespread adoption of state sync to bootstrap nodes, however, +what should be one of its strengths - the ability to discover and fetch +application snapshots from peers in the p2p network - has turned out to be one +of its weaknesses. +In fact, while downloading recent snapshots is very convenient for new nodes +(clients of the protocol), providing snapshots to multiple peers (as servers of +the protocol) is _bandwidth-consuming_, especially without a clear incentive for +node operators to provide this service. +As a result, the number of nodes in production CometBFT networks offering the +state sync service (i.e., servers offering snapshots) has been limited, which +has rendered the service _fragile_ (from the client's point of view). In other words, it is very +hard to find a node with _good_ snapshots, leading nodes to often block during sync up. + +3. High level idea behind the solution + +This ADR stems from the observation that state sync is more than a protocol to +discover and fetch snapshots from peers in the network. +In fact, in addition to installing a snapshot, state sync also checks the +consistency of the installed application state with the state (`appHash`) +recorded on the blockchain at the same height, and bootstraps CometBFT's block +store and state store accordingly. +As a result, once state sync is completed the node can safely switch to Block +sync and/or Consensus to catch up with the latest state of the network. + +The purpose of this ADR is to provide node operators with more flexibility in +defining how or where state sync should look for application snapshots. +More precisely, it enables state sync to support the bootstrap of nodes from +application snapshots obtained _out-of-band_ by operators, available to the +node _locally_. +Applications dump snapshots into an exportable format, which can be then obtained +by the operators and placed on the syncing node. The node can then sync locally +without transferring snapshots via the network. +The goal is to provide an alternative to the mechanism currently adopted by +state sync, discovering and fetching application snapshots from peers in the +network, in order to address the above mentioned limitations, while preserving +most of state sync's operation. + +The ADR presents two solutions: + +1. The first solution is implemented by the application and was proposed and +implemented by the Cosmos SDK (PR [#16067][sdk-pr2] and [#16061][sdk-pr1] ). This ADR describes the solution +in a general way, proividing guidelines to non-SDK based applications if they wish +to implement their own local state sync. +2. The second part of the ADR proposes a more general solution, that uses ABCI +to achieve the same behavior provided by the SDK's solution. + + +## Alternative Approaches + +### Strengthen p2p-based state sync + +This ADR proposes a workaround for some limitations of the existing state sync +protocol, briefly summarized above. A more comprehensive and sustainable +long-term solution would require addressing such limitations, by improving the +current p2p based state sync solution. + +From a protocol design point of view, probably the major limitation of state +sync is the lack of mechanisms to incentivize and reward established nodes that +provide "good" (updated and consistent) snapshots to peers. +The existing protocol is essentially altruistic: it assumes that established +nodes will support the bootstrap of fresh nodes without receiving anything in +return, other than having new peers joining their network. + +From an operational point of view, the design of the p2p layer should take into +consideration the fact that not every node in the network is a "good" state +sync server. Fresh nodes, which need support for bootstrapping, should then be +able to discover peers in the network that are able or willing to provide +application snapshots. +The implementation of this feature would require a more complex content-based +peer discovery mechanism. + +However, while relevant, strengthening p2p-based state sync should be seen as +_orthogonal_ to the solution proposed in this ADR, which should have relevant use +cases even for an enhanced version of state sync. + +### Manual application state transfer + +The proposed [ADR 083][adr083]/[ADR 103][adr103] inspired the discussions that +led to this ADR. At first glance, their proposal might look identical to the +solution discussed here. The main distinction is that these previous proposals do not +involve installing application _snapshots_, but rely on node operators to +manually synchronize the application _state_. + +More precisely, their proposal is to +"_allow applications to start with a bootstrapped state_ +(i.e., the application has already a state before the node is started) +_alongside an empty CometBFT instance_ +(i.e., the node's block store is empty and the state store is at genesis state) +_using a subsystem of the state sync protocol_". + +Starting from an "empty CometBFT instance" is a requirement for running state +sync, which is maintained in the current proposal. +The mentioned "subsystem of the state sync protocol" is the light client, +responsible for verifying the application state and for bootstrapping +CometBFT's block store and state store accordingly. + +The distinction, therefore, lies in the way which the state of the application +from a running node is transferred to the new node to be bootstrapped. +Instead of relying on application snapshots, produced by the application but +handled by state sync, [ADR 083][adr083]/[ADR 103][adr103] assumes that node +operators are able to manually synchronize the application state from a running +node (it might be necessary to stop it) to a not-yet-started fresh node. + +The main limitation of the approach in [ADR 083][adr083]/[ADR 103][adr103] +is that it relies on the ability of node +operators to properly synchronize the application state between two nodes. +While experienced node operators are likely able to perform this operation in a +proper way, we have to consider a broader set of users and emphasize that it is +an operation susceptible to errors. Operators need to know the format of the +application's stored state, export the state properly and guarantee consistency. That is, +they have to make sure that nobody is trying to read the exported state while they are +exporting it. +Furthermore, it is an operation that is, by definition, application-specific: +applications are free to manage their state as they see fit, and this includes +how and where the state is persisted. +Node operators would therefore need to know the specifics of each application +in order to adopt this solution. + + +## Decision + +State sync should support the bootstrap of new nodes from application snapshots +available locally. Implementing this option does not mean that networked State sync +should be removed, but not both should be enabled at the same time. + +In other words, the following operation should be, in general terms, possible: + +1. When configuring a new node, operators should be able to define where (e.g., + a local file system location) the client side of state sync should look for + application snapshots to install or restore; +2. Operators should be able to instruct the server side of State sync on a + running node to export application snapshots, when they are available, + to a given location (e.g., at the local file system); +3. It is up to node operators to transfer application snapshots produced by the + running node (server side) to the new node (client side) to be bootstrapped + using this new State sync feature. + + + +As Cosmos SDK implemented a solution for all applications using it, and we do not have +non-SDK in production users requesting this feature, at the moment we will not implement the generally applicable +solution. + +This ADR will outline both the solution implemented by the SDK and a design proposal of a +generally applicable solution, that can be later on picked up and implemented in CometBFT. + +## Detailed Design + +### Application-implemented local state sync + +This section describes the solution to local state sync implemented by the SDK. An application can +chose to implement local state sync differently, or implement only a subset of the functionalities +implemented by the SDK. + +This solution exposes a command line interface enabling a node to manipulate the snapshots +including dumping existing snapshots to an exportable format, loading, restoring and deleting exported snapshots, +as well as a command to bootstrap the node by resetting CometBFT's state and block store. + +The SDK exposes the following commands for snapshot manipulation: + +```script + +delete Delete a snapshot from the local snapshot store +dump Dump the snapshot as portable archive format +export Export app state to snapshot store +list List local snapshots +load Load a snapshot archive file into snapshot store +restore Restore app state from a snapshot stored in the local snapshot store + +``` + +and the following command to bootstrap the state of CometBFT upon installing a snapshot: + +``` script + +comet bootstrap-state Bootstrap the state of CometBFT's state and block store from the + application's state + +``` + +These commands enable the implementation of both the client and server side of statesync. +Namely, a statesync server can use `dump` to create a portable archive format out existing snapshots, +or trigger snapshot creation using `export`. + +The client side, restores the application state from a local snapshot that was previously exported, using +`restore`. Before `restore` can be called, the client has to `load` an archived snapshot into its +local snapshot store. +Upon successful completion of the previous sequence of commands, the state of CometBFT is bootstrapped +using `bootstrap-state` and CometBFT can be launched. + + +There are three prerequisites for this solution to work when a node is syncing: + +1. The application has access to the snapshot store (usually as a separate database used by applications) +2. CometBFT's state and block stores are empty or reset +3. CometBFT is not running while the node is state syncing + +The server side of state sync (snapshot generation and dumping), can be performed while the node is running. +The application has to be careful not to interfere with normal node operations, and to use a snapshot store +and dumping mechanism that will mitigate the risk of requesting snapshots while they are being dumped to an archive format. + +In order to be able to dump or export the snapshots, the application must have access to the snapshot store. + +We describe the main interface expected from the snapshot database and used by the above mentioned CLI commands +for snapshot manipulation. +The interface was derived from the SDK's implementation of local State sync. + +```golang + +// Delete a snapshot for a certain height +func (s *Store) Delete(height uint64, format uint32) error + +// Retrieves a snapshot for a certain height +func (s *Store) Get(height uint64, format uint32) (*Snapshot, error) + +// List recent snapshots, in reverse order (newest first) +func (s *Store) List() ([]*Snapshot, error) + +// Loads a snapshot (both metadata and binary chunks). The chunks must be consumed and closed. +// Returns nil if the snapshot does not exist. +func (s *Store) Load(height uint64, format uint32) (*Snapshot, <-chan io.ReadCloser, error) + +// LoadChunk loads a chunk from disk, or returns nil if it does not exist. The caller must call +// Close() on it when done. +func (s *Store) LoadChunk(height uint64, format, chunk uint32) (io.ReadCloser, error) + +// Save saves a snapshot to disk, returning it. +func (s *Store) Save(height uint64, format uint32, chunks <-chan io.ReadCloser) (*Snapshot, error) + +// PathChunk generates a snapshot chunk path. +func (s *Store) PathChunk(height uint64, format, chunk uint32) string + +``` + +In order to dump a snapshot, an application needs to retrieve all the chunks stored at a certain path. + +#### CometBFT state bootstrap + +In addition to managing snapshots, it is necessary to bootstrap (setup) the state and block store of CometBFT before starting up the node. +Upon a successful start, CometBFT performs block sync and consensus. +At the moment of writing this ADR, there is no command line in CometBFT that supports this, but an [issue][state-bootstrap] +has been opened to address this. +Until it has been resolved, the application developers have to, within their bootstrapping command: + +- Create a state and block store +- Launch a light client to obtain and verify the block header for the snapshot's height. +- Use the light client's `State` to +verify that the `AppHash` on the retrieved block header matches the `AppHash` obtained via +the ABCI `Info` call to the application (the same procedure is performed by the node on startup). +- Use `Commit` to retrieve the last commit for the snapshot's height. +- Save the retrieved values into the state and block stores. + +This code essentially mimics what CometBFT does as part of node setup, once state sync is complete. + + +### CometBFT based local state sync + +Given that snapshot manipulation is entirely application defined, and to avoid pulling this functionality into +CometBFT, we propose a solution using ABCI, that mimics the behaviour described in the previous section. + +On the client side, the main difference between local State sync done by the application and CometBFT is that the +application has to perform the sync offline, in order to properly set up CometBFT's initial state. Furthermore, the +application developer has to manually bootstrap CometBFTs state and block stores. +With support for local State sync, a node can simply load a snapshot from a predefined location and offer it to the application +as is currently done via networked State sync. + +On the server side, without any support for local State sync, an operator has to manually instruct the application +to export the snapshots into a portable format (via `dump`). + +Having support for this within CometBFT, the app can automatically perform this export when taking snapshots. + +In order to support local State sync, the following changes to CometBFT are necessary: + +1. Adding new configuration options to the config file. +2. Introduce a CLI command that can explicitly tell the application to create a snapshot export, in case +operators decide not to generate periodical exports. +3. Extract a snapshot from the exported format. +4. Potentially alter existing ABCI calls to signal to the application that we want to create a snapshot export periodically. +5. Allow reading a snapshot from a compressed format into CometBFT and offer it to the application via +the existing `OfferSnapshot` ABCI call. + + +At a very high level, there are two possible solutions and we will present both: + +1. The application will export snapshots into an exportable format on the server side. When a node syncs up, CometBFT will +send this as a blob of bytes to the application to uncompress and apply the snapshot. + +2. CometBFT creates a snapshot using existing ABCI calls and exports it into a format of our choosing. CometBFT is then in charge of +reading in and parsing the exported snapshot into a snapshot that can be offered to the application via the existing `OfferSnapshot` +and `ApplyChunk` methods. This option does not alter any current APIs and is a good candidate for an initial implementation. + + +#### Config file additions + +```bash +[statesync] +# State syncing from a local snapshot +local_sync=false +# Path to snapshot, will be ignored if local_sync=false +snapshot_load_path="" +# Periodically dump snapshots into archive format (optional) +auto_snapshot_dump=false +# If dumping nodes into archive format, set the path to where the file is dumped +# and the file format +# This can be changed when using a CLI command +snapshot_dump_path="" +snapshot_dump_format="" +``` + +#### *CLI command for application snapshot management* + +CometBFT exposes a CLI command to instruct the application to dump the existing snapshots into an exportable format: + +```bash +dump Dump existing snapshots to exportable file format. +``` + +We could expand the CLI interface to allow for additional operations, similar to the CLI designed for Cosmos SDK. However, +as snapshot generation, dumping and loading a local snapshot would be built into CometBFT, + while the node is running, we do not need to rely on a CLI for this functionality. + +The `dump` command can be implemented in two ways: + +1. Rely on the existing ABCI functions `ListSnapshots` and `LoadChunks` to retrieve the snapshots and chunks from a peer. +This approach requires no change to the current API and is easy to implement. Furthermore, CometBFT has complete control +over the format of the exported snapshot. It does however involve more than one ABCI call and network data transfer. +2. Extend `RequestListSnapshots` with a flag to indicate that we want an exportable snapshot format and extend `ResponseListSnapshot` to return a +path and format of the exported snapshots. + +An improvement to the second option mentioned above would be to add path parameters to the command, + and include the path into `RequestListSnapshots` instructing the application to generate a snapshot export +at a given location. + +A third option is the introduction of a new ABCI call: `ExportSnapshots`, which will have the same effect as option 2 above. + + +#### *Automatic snapshot exporting* + +Applications generate snapshots with a regular cadence (fixed time intervals or heights). The application itself measures the time or number of heights passed since the last snapshot, +and CometBFT has no role in instructing the application when to take snapshots. + +The State sync reactor currently retrieves a list of snapshots from a peer, who obtains these snapshots from the local instance of the application using the ABCI `RequestListSnapshots` call. + +Applications can thus themselves be in charge of dumping the snapshots into a given file format, the same way they generate snapshots. + If `auto_snapshot_dump` is true, +CometBFT instructs the application to export the snapshots periodically. + +An alternative solution is that CometBFT, itself, using the implementation of the `dump` command, whichever +is chosen at the time, creates or asks the application to create snapshot exports. This is not forcing the +application to create a snapshot at the time of he request, rather *dumps* existing snapshots into +an exportable file format. + +**Export file consistency** + +The same caveat of making sure the file into which the snapshot is exported is not corrupted by concurrent reads and writes applies here as well. If we decide to simply export +snapshots into a compressed file, we need to make sure that we do not return files that with ongoing writes. +An alternative is for CometBFT to provide a Snapshot export store with snapshot isolation. This store would essentially be pruned as soon as a new snapshot is written, +thus not taking too much more space. + +If it is the application that exports the snapshots, it is something the application developer has to be aware of. + +#### Syncing a node using local snapshots + +On startup, if `local_sync` is set to `true`, CometBFT will look for an existing snapshot at the path +given by the operator. If a snapshot is available, it will be loaded and state restored as if it came from a peer in the current implementation. + +Note that, if it is not CometBFT that created the snapshot export from the data retrieved via ABCI (a combination of `ListSnapshots` and `LoadChunks`), +CometBFT might not be aware of how the snapshot was exported, and needs to ask the application to restore the snapshot. + +If a snapshot was created using option 1 (by CometBFT) from the previous section, or the export format is known to CometBFT (like `tar, gzip` etc.), +CometBFT can extract the snapshot itself, and offer it to the application via `RequestOfferSnapshot` without any API changes. + +If CometBFT is **not** the one who created the exported file, we introduce a new ABCI call `UnpackSnapshot` +to send the exported snapshot as a blob of bytes to the application, which uncompresses it, installs it +and responds whether the snapshot is accepted (as in `OfferSnapshot`) and the chunks application has passed (as in `LoadChunk`). + + +* **Request**: + + | Name | Type | Description | Field Number | + |-----------------|---------|---------------------------------------------|--------------| + | exportedSnapshot| [] byte | Snapshot export created by the application. | 1 | + + Commit signals the application to persist application state. It takes no parameters. + +* **Response**: + + | Name | Type | Description | Field Number | + |--------------------|-------------------------------------------------------- |----------------------------------------|--------------| + | result | [Result](../../../spec/abci/abci++_methods.md#result) | The result of the snapshot offer. | 1 | + | resultChunk | ResultC | The result of applying the chunks. | 2 | + +```proto + enum ResultC { + UNKNOWN = 0; // Unknown result, abort all snapshot restoration + ACCEPT = 1; // The chunks were accepted. + ABORT = 2; // Abort snapshot restoration, and don't try any other snapshots. + RETRY_SNAPSHOT = 3; // Restart this snapshot from `OfferSnapshot`, reusing chunks unless instructed otherwise. + REJECT_SNAPSHOT = 4; // Reject this snapshot, try a different one. + } +``` + +Unlike networked state sync, we do not re-fetch individual chunks, thus if the application of a chunk fails, then the application of the whole snapshot fails. + +## Consequences + +Adding the support for a node to sync up using a local snapshot can speed up the syncing process, especially as +network based State sync has proven to be fragile. + +### Positive + +- There is a possibility to implement this in a non-breaking manner: providing an alternative and complementary + implementation for State sync +- Node operators will not need to use workarounds to make State sync to download + application snapshots from specific nodes in the network, in particular from + nodes that are controlled by the same operators + +### Negative + +- Implementing additional ABCI functions is API breaking and might not be backwards compatible. + +### Neutral + +- Additional complexity, with additional parameters for State sync's + configuration and the bootstrap of a node +- Additional complexity, with the possible addition of a CLI command to save + application snapshots to the file system + +## References + +- [State sync][state-sync] description, as part of ABCI++ spec +- Original issue on Tendermint Core repository: [statesync: bootstrap node with state obtained out-of-band #4642][original-issue] +- Original solution on Tendermint Core repository: [ADR 083: Supporting out of band state sync #9651][adr083] +- Original proposal ported to CometBFT repository: [ADR 103: Local State Sync Support][adr103] +- SDK's implementation of local state sync: [local snapshot store management][sdk-pr2] and [CometBFT state bootstrap][sdk-pr1] + +[state-sync]: https://github.com/cometbft/cometbft/blob/main/spec/abci/abci%2B%2B_app_requirements.md#state-sync +[original-issue]: https://github.com/tendermint/tendermint/issues/4642 +[adr083]: https://github.com/tendermint/tendermint/pull/9651 +[adr103]: https://github.com/cometbft/cometbft/pull/729 +[state-bootstrap]: https://github.com/cometbft/cometbft/issues/884 +[sdk-pr1]: https://github.com/cosmos/cosmos-sdk/pull/16061 +[sdk-pr2]: https://github.com/cosmos/cosmos-sdk/pull/16067 diff --git a/docs/references/architecture/adr-105-refactor-mempool-senders.md b/docs/references/architecture/adr-105-refactor-mempool-senders.md new file mode 100644 index 00000000000..cbafa971cbc --- /dev/null +++ b/docs/references/architecture/adr-105-refactor-mempool-senders.md @@ -0,0 +1,183 @@ +# ADR 105: Refactor list of senders in mempool + +## Changelog + +- 2023-07-19: Choose callbacks option and mark as accepted (@hvanz) +- 2023-07-10: Add callback alternative (@hvanz) +- 2023-06-26: Initial draft (@hvanz) + +## Status + +Accepted + +## Context + +Before adding a transaction to the mempool or deciding to keep it in the mempool after a block execution, we need to send a `CheckTx` message +to the application for validating the transaction. There are [two variants][CheckTxType] of +this message, distinguished by the value in message field `type`: +- `CheckTxType_New` is for transactions that need to be validated before adding +it to the mempool. +- `CheckTxType_Recheck` is for transactions that are in the mempool and need to +be re-validated after committing a block and advancing to the next height. + +The mempool communicates with the ABCI server (that is, the application) by +sending `abci.Request`s through the proxy `AppConnMempool`. The proxy provides a +callback mechanism for handling `abci.Response`s. The current mempool +implementation `CListMempool` (also called v0) utilizes this mechanism for +`Recheck` transactions but not for `New` transactions. Instead `New` +transactions require an ad-hoc mechanism for each request. + +The reason behind this difference is that for `New` transactions we need to +record the ID of the peer that sent the transaction. However, this information +is not included in `RequestCheckTx` messages. Recording the sender's ID is +necessary for the transaction propagation protocol, which uses the recorded list +of senders to prevent sending the transaction back to these peers, thus avoiding +sending duplicated messages. More importantly, this mechanism serves as the only means +to stop propagating transactions. + +There are two design problems with this implementation. First, there is a +complex pattern for handling callbacks on `New` requests. The following [code +snippet][CheckTxAsync] at the end of the `CheckTx` method, where transactions +received for the first time are processed, demonstrates the issue: +```golang + reqRes, err := mem.proxyAppConn.CheckTxAsync(context.TODO(), &abci.RequestCheckTx{Tx: tx}) + reqRes.SetCallback(mem.reqResCb(tx, txInfo, cb)) +``` +When we send a request for validating a transaction via `CheckTxAsync`, it +returns a `ReqRes` object. To handle the response asynchronously, we set an +ad-hoc callback `reqResCb` on `ReqRes`. This callback is different for each +transaction `tx` because it's parameterized by `tx`, `txInfo` (which essentially +contains the sender ID), and another callback function `cb` provided by the +caller of `CheckTx` to be applied on the response. + +Secondly, the list of senders for each transaction is recorded directly in the +mempool's `txs` data structure. However, the list of senders is an important +component of the propagation protocol and it should be part of the reactor, +while `txs` is part of the implementation of this specific version (v0) of the +mempool. + +In this document, we propose a solution that involves moving the list of senders +from the mempool implementation to the reactor. This change will simplify the +code, establish a more clear separation of the propagation protocol and the data +structure, and allow for future improvements to the mempool as a whole. + +## Detailed Design + +We propose the following changes to the mempool's reactor and the `CListMempool` +implementation. + +- In the `Mempool` interface, change the signature of `CheckTx` from + ``` golang + CheckTx(tx types.Tx, cb func(*abci.ResponseCheckTx), txInfo TxInfo) error + ``` + to + ``` golang + CheckTx(tx types.Tx) (abcicli.ReqRes, error) + ``` + - The returning `ReqRes` object can be used to set and invoke a callback to + handle the response, if needed. + - The callback parameter `cb` is no longer needed. Currently, this is mainly + used by the RPC endpoints `broadcast_tx_sync` and `broadcast_tx_commit`, and + in tests for checking that the response is valid. However, the same + functionality can be obtained with `ReqRes` response. + - `txInfo` contains information about the sender, which is also no longer + needed, as justified by the next point. +- The list of senders for each transaction is currently stored in `mempoolTx`, + the data structure for the entries of `txs`. Move the senders out of + `mempoolTx` to a new map `txSenders` of type `map[types.TxKey]map[uint16]bool` + in the mempool reactor. `txSenders` would map transaction keys to a set of + peer ids (of type `uint16`). Add also a `cmtsync.RWMutex` lock to handle + concurrent accesses to the map. + - This refactoring should not change the fact that the list of senders live as + long as the transactions are in the mempool. When a transaction is received + by the reactor (either via RPC or P2P), we call `CheckTx`. We know whether a + transaction is valid and was included in the mempool by reading the `ReqRes` + response. If this is the case, record the list of senders in `txSenders`. + When a transaction is removed from the mempool, notify the reactor to remove + the list of senders for that transaction, with the channel described below. +- In `CListMempool`, `resCbFirstTime` is the function that handles responses of + type `CheckTxType_New`. Instead of setting it as an ad-hoc callback on each + transaction, we could now call it directly from `globalCb`, where responses of + type `CheckTxType_Recheck` are already being handled. + + +## Alternatives +### Communicating that a transaction was removed from the mempool + +We have identified two approaches for communicating the removal of a transaction +from the mempool to the reactor. + +1. With a channel and an infinite loop in a goroutine. +- In `CListMempool`, introduce a new channel `txsRemoved` of type `chan + types.TxKey` to notify the mempool reactor that a transaction was removed from + the mempool. +- In the mempool reactor, spawn a goroutine to handle incoming transaction keys + from the `txsRemoved` channel. For each key received, update `txSenders`. +- Add methods `TxsRemoved() <-chan types.TxKey` and `EnableTxsRemoved()` to the + `Mempool` interface. +2. With a callback. +- In the mempool reactor's constructor, set a callback function in `CListMempool`. + The callback takes a transaction key as parameter. When invoked, it will + update `txSenders`. +- `CListMempool` stores the callback function as part of its state. When a + transaction is removed from the mempool, the callback is invoked. +- Add a method `SetTxRemovedCallback(cb func(types.TxKey))` to the `Mempool` + interface. + +The channel and goroutine mechanism is the same used by the mempool to notify +the consensus reactor when there are transactions available to be included in a +new block. The advantage of the callback is that it is immediately called when a +transaction is removed, reducing the chances of data races. + +In any case, adding and removing the same transaction from the mempool is +unlikely to happen in parallel. A transaction is removed from the mempool +either: +1. on updating the mempool, when the transaction is included in a block, or +2. when handling a `Recheck` CheckTx response, when the transaction was deemed + invalid by the application. + +In both cases, the transaction will still be in the cache. So, if the same +transaction is received again, it will be discarded by the cache, and thus not +added to the mempool and `txSenders`. + +### Decision + +We have chosen the second option of using a callback because it reduces the +chances of concurrent accesses to the list of senders and it removes the +transaction immediately, keeping the mempool and the list of senders better +synchoronized. + +## Consequences + +The refactoring proposed here does not affect how users and other peers +interact with the mempool. It will only change how transaction metadata is +stored internally. + +### Positive + +- Get rid of the complex design pattern of callbacks for handling + `CheckTxType_New` responses. +- Clear separation of propagation protocol in the reactor and the mempool + implementation. +- Allow for future improvements to both the propagation protocol and the mempool + implementation. + +### Negative + +- If chosen, adding a channel and a goroutine for communicating that a + transaction was removed may increase the concurrency complexity. + +### Neutral + +- We would need to extend the existing tests to cover new scenarios related to + the new data structures and some potential concurrent issues. + +## References + +The trigger for this refactoring was [this comment][comment], where we discussed +improvements to the concurrency in the mempool. + + +[CheckTxType]: https://github.com/cometbft/cometbft/blob/406f8175e352faee381f100ff17fd5c82888646a/proto/tendermint/abci/types.proto#L94-L97 +[CheckTxAsync]: https://github.com/cometbft/cometbft/blob/406f8175e352faee381f100ff17fd5c82888646a/mempool/clist_mempool.go#L269-L273 +[comment]: https://github.com/cometbft/cometbft/pull/895#issuecomment-1584948704 diff --git a/docs/references/architecture/adr-106-grpc-api.md b/docs/references/architecture/adr-106-grpc-api.md new file mode 100644 index 00000000000..c24fc09a581 --- /dev/null +++ b/docs/references/architecture/adr-106-grpc-api.md @@ -0,0 +1,240 @@ +# ADR 106: gRPC API + +## Changelog + +- 2024-03-27: Minor updates based on user feedback and ADR 101 implementation (@andynog) +- 2023-07-04: Expand available endpoints based on user feedback (@thanethomson) +- 2023-05-16: First draft (@thanethomson) + +## Status + +Accepted | Rejected | Deprecated | Superseded by + +Tracking issue: [\#81] + +## Context + +There has been discussion over the years as to which type of RPC interface would +be preferable for Tendermint Core, and now CometBFT, to offer to integrators. +[ADR 057][adr-057] captures some pros and cons of continuing to support the +JSON-RPC API versus implementing a gRPC API. Previously it was decided to remove +the gRPC API from Tendermint Core (see [tendermint/tendermint\#7121] and +[tendermint/tendermint\#9683]). + +After discussion with users, and in considering the implementation of [ADR +101][adr-101] (the data companion pull API), a decision has been taken to +implement a gRPC API _in addition to_ the JSON-RPC API. + +Some services for this gRPC API have already been implemented as part of the [Data Companion Pull API implementation][adr-101-poc], +such as `Block`, `BlockResults` and `Version` services. Also the existing gRPC API (which only provides a +`BroadcastService` with a single method) was removed. These services will be available starting with the CometBFT`v1` release +(there was also a backport to an experimental `v0.38` release) + +It is also envisaged that once it is +feasible to provide the RPC service independently of the node itself (see [ADR +102][adr-102]), the JSON-RPC API on the node itself could eventually be +deprecated and removed. + +## Alternative Approaches + +The primary alternative approach involves continuing to only provide support +for, and potentially evolve, the JSON-RPC API. This API currently exposes many +data types in non-standard and rather complex ways, making it difficult to +implement clients. As per [ADR 075][adr-075], it also does not conform fully to +the JSON-RPC 2.0 specification, further increasing client implementation +complexity. + +## Decision + +Implement gRPC services corresponding to a minimal subset of the currently +exposed [JSON-RPC endpoints][rpc-docs]. This set of services can always be +expanded over time according to user needs, but once released it is hard to +deprecate and remove such APIs. + +## Detailed Design + +### Services + +The initial services to be exposed via gRPC are informed by [Penumbra's +`TendermintProxyService`][penumbra-proxy-svc], as well as the needs of the data +companion API proposed in [ADR 101][adr-101]. Additional services can be rolled +out additively in subsequent releases of CometBFT. + +Services are roughly organized by way of their respective domain. The details of +each service, e.g. request/response types and precise Protobuf definitions, will +be worked out in the implementation. + +- `VersionService` - A simple service that aims to be quite stable over time in + order to be utilized by clients to establish the version of the software with + which they are interacting (e.g. to pre-emptively determine compatibility). + This could technically be part of the `NodeService`, but if the `NodeService` + interface were to be modified, a new version of the service would need to be + created, and all old versions would need to be maintained, since the + `GetVersion` method needs to be quite stable. + - `GetVersion` - Query the version of the software and protocols employed by + the node (e.g. CometBFT, ABCI, block, P2P and application version). +- `NodeService` - Provides information about the node providing the gRPC + interface. + - `GetStatus` - Query the current node status, including node info, public + key, latest block hash, app hash, block height and time. + - `GetHealth` - Lightweight mechanism to query the health of the node. +- `TransactionService` - Facilitates broadcasting and querying of transactions. + - `BroadcastAsync` - Broadcast a transaction asynchronously. Does not wait for + the transaction to be validated via `CheckTx`, nor does it wait for the + transaction to be committed. + - `BroadcastSync` - Broadcast a transaction, but only return once `CheckTx` + has been called on the transaction. Does not wait for the transaction to be + committed. + - `GetByHash` - Fetch a transaction by way of its hash. + - `Search` - Search for transactions with their results. +- `ApplicationService` - Provides a proxy interface through which to access the + application being run by the node (via ABCI). + - `Query` - Submit a query directly to the application via ABCI. +- `BlockService` - Provides information about blocks. + - `GetLatestHeight` - Return a stream of latest block heights as new blocks + are committed to the blockchain. + - `GetByHeight` - Fetch the block associated with a particular height. + - `GetHeaderByHeight` - Fetch the header associated with the block at a + particular height. + - `Search` - Search for blocks by way of block events. +- `BlockResultsService` - Provides information about block execution results. + - `GetBlockResults` - Fetch the block results associated with a particular height. +- `ConsensusService` - Provides information about consensus. + - `GetParams` - Fetch the consensus parameters for a particular height. +- `NetworkService` - Provides information about the blockchain network. + - `GetGenesis` - Fetch paginated genesis data. + - `GetPeers` - Fetch information about the peers to which the node is + connected. + +### Service Versioning + +Every service will be versioned, for example: + +- `VersionService` will have its Protobuf definition under + `cometbft.services.version.v1` +- `NodeService` will have its Protobuf definition under `cometbft.services.node.v1` +- `TransactionService` will have its Protobuf definition under + `cometbft.services.transaction.v1` +- etc. + +The general approach to versioning our Protobuf definitions is captured in [ADR +103][adr-103]. + +### Go API + +#### Server + +The following Go API is proposed for constructing the gRPC server to allow for +ease of construction within the node, and configurability for users who have +forked CometBFT. + +```go +package server + +// Option is any function that allows for configuration of the gRPC server +// during its creation. +type Option func(*serverBuilder) + +// WithVersionService enables the version service on the CometBFT gRPC server. +// +// (Similar methods should be provided for every other service that can be +// exposed via the gRPC interface) +func WithVersionService() Option { + // ... +} + +// WithGRPCOption allows one to specify Google gRPC server options during the +// construction of the CometBFT gRPC server. +func WithGRPCOption(opt grpc.ServerOption) Option { + // ... +} + +// Serve constructs and runs a CometBFT gRPC server using the given listener and +// options. +func Serve(listener net.Listener, opts ...Option) error { + // ... +} +``` + +#### Client + +For convenience, a Go client API should be provided for use within the E2E +testing framework. + +```go +package client + +type Option func(*clientBuilder) + +// Client defines the full client interface for interacting with a CometBFT node +// via its gRPC. +type Client interface { + ApplicationServiceClient + BlockResultsServiceClient + BlockServiceClient + NodeServiceClient + TransactionServiceClient + VersionServiceClient + + // Close the connection to the server. Any subsequent requests will fail. + Close() error +} + +// WithInsecure disables transport security for the underlying client +// connection. +// +// A shortcut for using grpc.WithTransportCredentials and +// insecure.NewCredentials from google.golang.org/grpc. +func WithInsecure() Option { + // ... +} + +// WithGRPCDialOption allows passing lower-level gRPC dial options through to +// the gRPC dialer when creating the client. +func WithGRPCDialOption(opt ggrpc.DialOption) Option { + // ... +} + +// New constructs a client for interacting with a CometBFT node via gRPC. +// +// Makes no assumptions about whether or not to use TLS to connect to the given +// address. To connect to a gRPC server without using TLS, use the WithInsecure +// option. +// +// To connect to a gRPC server with TLS, use the WithGRPCDialOption option with +// the appropriate gRPC credentials configuration. See +// https://pkg.go.dev/google.golang.org/grpc#WithTransportCredentials +func New(ctx context.Context, addr string, opts ...Option) (Client, error) { + // ... +} +``` + +## Consequences + +### Positive + +- Protocol buffers provide a relatively simple, standard way of defining RPC + interfaces across languages. +- gRPC service definitions can be versioned and published via the [Buf Schema + Registry][bsr] (BSR) for easy consumption by integrators. + +### Negative + +- Only programming languages with reasonable gRPC support will be able to + integrate with the gRPC API (although most major languages do have such + support). +- Increases complexity maintaining multiple APIs (gRPC and JSON-RPC) in the short-term (until the JSON-RPC API is definitively extracted and moved outside the node). + +[\#81]: https://github.com/cometbft/cometbft/issues/81 +[\#94]: https://github.com/cometbft/cometbft/issues/94 +[adr-057]: ./tendermint-core/adr-057-RPC.md +[tendermint/tendermint\#7121]: https://github.com/tendermint/tendermint/pull/7121 +[tendermint/tendermint\#9683]: https://github.com/tendermint/tendermint/pull/9683 +[adr-101]: https://github.com/cometbft/cometbft/pull/82 +[adr-101-poc]: https://github.com/cometbft/cometbft/issues/816 +[adr-102]: adr-102-rpc-companion.md +[adr-103]: ./adr-103-proto-versioning.md +[adr-075]: ./tendermint-core/adr-075-rpc-subscription.md +[rpc-docs]: https://docs.cometbft.com/v0.37/rpc/ +[penumbra-proxy-svc]: https://buf.build/penumbra-zone/penumbra/docs/main:penumbra.util.tendermint_proxy.v1 +[bsr]: https://buf.build/explore diff --git a/docs/references/architecture/adr-107-betaize-proto-versions.md b/docs/references/architecture/adr-107-betaize-proto-versions.md new file mode 100644 index 00000000000..e9015d264fb --- /dev/null +++ b/docs/references/architecture/adr-107-betaize-proto-versions.md @@ -0,0 +1,85 @@ +# ADR 107: Rename proto versions preceding 1.0 to pre-v1 betas + +## Changelog + +- 2023-07-11: Initial draft (@mzabaluev) + +## Status + +Accepted + +## Context + +The drive to introduce [protobuf versioning][cometbft#95] resulted in +introducing versioned packages for protobuf definitions corresponding to +each of the major CometBFT releases starting from 0.34. By the upcoming 0.39 +release, some of the packages will get up to `v4`, as the development churn +and the intent to perform code style grooming have resulted in +backward-incompatible changes every time. All this storied history +has not yet been released with semver commitments on [buf schema registry][bsr] +or even merged into the main branch at the time of this writing. + +Efforts to conform to the [buf style guide][buf-style] +(started with [#736][cometbft#736]) have been confined to latter versions +of the proto packages in order to preserve source code compatibility +and ease migration for developers. The earlier packages, therefore, do not +constitute exemplary protobuf material and may even be rejected by a schema +repository linter. + +## Alternative Approaches + +We can do nothing and go ahead with the current versioning rework as per +[ADR 103], which does solve the main problem of managing backward-incompatible +changes in the proto-derived definitions. Come 1.0 release time, we should find +ourselves with a storied collection of versioned protobuf packages going up to +`v4` or `v5` for some packages, where earlier versions refer to pre-1.0 releases +and are in places stylistically bad. + +## Decision + +Rename the current version suffixes to `v1beta1`, `v1beta2`, ..., +with the intent that the definitions in the 1.0 release become `v1`. + +## Detailed Design + +Make the historic status of these protocol versions explicit by renaming +the current suffixes to `v1beta1`, `v1beta2`, and so on. +The protobufs that make it to 1.0 will be consistently placed in new packages +suffixed with `v1`, representing a long-term commitment to maintaining +backward compatibility. + +At the time of this proposal, the changes will only affect the +`feature/proto-update` feature branch, with no impact on users of any releases. +[ADR 103] details the changes caused by the versioning approach in general. + +## Consequences + +### Positive + +The beta versioning clearly denotes developmental status of these early +specifications. By the 1.0 release, the then current set of specifications is +published as a set of packages suffixed with `.v1`, with no confusion about +what constitutes our "v1 protocol". + +### Negative + +No negative consequences expected, at this early stage we still have the +freedom to rename version suffixes as we like. Some extra work, mostly +mechanical renaming, is required to implement the change on the feature branch. + +### Neutral + +The protocol history of the widely deployed 0.x releases will still be present +and consumers can generate usable code from the proto files for those +versions. + +## References + +* [ADR 103]: Protobuf definition versioning +* [cometbft#95], the meta tracking issue. + +[ADR 103]: https://github.com/cometbft/cometbft/blob/main/docs/architecture/adr-103-proto-versioning.md +[cometbft#95]: https://github.com/cometbft/cometbft/issues/95 +[cometbft#736]: https://github.com/cometbft/cometbft/issues/736 +[bsr]: https://buf.build/product/bsr/ +[buf-style]: https://buf.build/docs/best-practices/style-guide diff --git a/docs/references/architecture/adr-108-e2e-abci++.md b/docs/references/architecture/adr-108-e2e-abci++.md new file mode 100644 index 00000000000..c72b5aff0c9 --- /dev/null +++ b/docs/references/architecture/adr-108-e2e-abci++.md @@ -0,0 +1,337 @@ +# ADR 108: E2E tests for CometBFT's behaviour in respect to ABCI 2.0. + +## Changelog +- 2023-08-08: Initial version (@nenadmilosevic95) +- 2023-15-12: Updated to account for grammar changes (@nenadmilosevic95) +- 2024-07-03: Updated to support vote extensions (@nenadmilosevic95) + + +## Context + +ABCI 2.0 defines the interface between the application and CometBFT. A part of the specification is the [ABCI 2.0 grammar](../../../spec/abci/abci%2B%2B_comet_expected_behavior) that describes the sequences of calls that the application can expect from CometBFT. +In order to demonstrate that CometBFT behaves as expected from the viewpoint of the application, we need to test whether CometBFT respects this ABCI 2.0 grammar. To do this, we need to enhance the e2e tests infrastructure. Specifically, we plan to do three things: +- Log every CometBFT's ABCI 2.0 request during the execution. +- Parse the logs post-mortem and extract all ABCI 2.0 requests. +- Check if the set of observed requests respects the ABCI 2.0 grammar. + + +Issue: [353](https://github.com/cometbft/cometbft/issues/353). + + + +## Decision + +### 1) ABCI 2.0 requests logging +The idea was to do this at the Application side. Every time the Application +receives a request, it logs it. + +**Implementation** + +The rationale behind this part of the implementation was to log the request concisely and use the existing structures as much as possible. + +Whenever an ABCI 2.0 request is made, the application will create `abci.Request` (`abci` stands for `"github.com/cometbft/cometbft/abci/types"`) and log it. The example is below. + +```go +func (app *Application) InitChain(_ context.Context, req *abci.InitChainRequest) (*abci.InitChainResponse, error) { + r := &abci.Request{Value: &abci.Request_InitChain{InitChain: &abci.InitChainRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + + ... +} +``` +Notice here that we create an empty `abci.InitChainRequest` object while we can also use the one passed to the `InitChain` function. The reason behind this is that, at the moment, we do not need specific fields of the request; we just need to be able to extract the information about the request type. For this, an empty object of a particular type is enough. + +The `app.logABCIRequest(r)` function is a new function implemented in the same file (`test/e2e/app/app.go`). If the `ABCIRequestsLoggingEnabled` flag is set to `true`, set automatically when ABCI 2.0 tests are enabled, it logs received requests. The full implementation is the following: + +```go +func (app *Application) logABCIRequest(req *abci.Request) error { + if !app.cfg.ABCIRequestsLoggingEnabled { + return nil + } + s, err := GetABCIRequestString(req) + if err != nil { + return err + } + app.logger.Info(s) + return nil +} +``` + +`GetABCIRequestString(req)` is a new method that receives a request and returns its string representation. The implementation and tests for this function and the opposite function `GetABCIRequestFromString(req)` +that returns `abci.Request` from the string are provided in files `test/e2e/app/log_abci.go` and `test/e2e/app/log_abci_test.go`, respectively. To create a string representation of a request, we first marshal the request via `proto.Marshal()` method and then convert received bytes in the string using `base64.StdEncoding.EncodeToString()` method. In addition, we surround the new string with `abci-req` constants so that we can find lines with ABCI 2.0 request more easily. The code of the method is below: + +```go +func GetABCIRequestString(req *abci.Request) (string, error) { + b, err := proto.Marshal(req) + if err != nil { + return "", err + } + reqStr := base64.StdEncoding.EncodeToString(b) + return AbciReq + reqStr + AbciReq, nil +} +``` + +*Note:* At the moment, we are not compressing the marshalled request before converting it to `base64` `string` because we are logging the empty requests that take at most 24 bytes. However, if we decide to log the actual requests in the future, we might want to compress them. Based on a few tests, we observed that the size of a request can go up to 7KB. + +If in the future we want to log another ABCI 2.0 request type, we just need to do the same thing: +create a corresponding `abci.Request` and log it via +`app.logABCIRequest(r)`. + +### 2) Parsing the logs +We need a code that will take the logs from all nodes and collect the ABCI 2.0 requests that were logged by the application. + +**Implementation** + +This logic is implemented inside the `fetchABCIRequests(t *testing.T, nodeName string)` function that resides in `test/e2e/tests/e2e_test.go` file. This function does three things: +- Takes the output of a specific node in the testnet from the moment we launched the testnet until the function is called. The node name is passed as a function parameter. It uses the `docker-compose logs` command. +- Parses the logs line by line and extracts the `abci.Request`, if one exists. The request is received by forwarding each line to the `app.GetABCIRequestFromString(req)` method. +- Returns the array of slices where each slice contains the set of `abci.Request`s logged on that node. Every time a crash happens, a new array element (new slice `[]*abci.Request`) will be created. We know a crash has happened because we log "Application started" every time the application starts. Specifically, we added this log inside `NewApplication()` function in `test/e2e/app/app.go` file. In the end, `fetchABCIRequests()` will return just one slice if the node did not experience any crashes and $n+1$ slices if there were $n$ crashes. The benefit of logging the requests in the previously described way is that now we can use `[]*abci.Request` to store ABCI 2.0 requests of any type. + + + +### 3) ABCI 2.0 grammar checker +The idea here was to find a library that automatically verifies whether a specific execution respects the prescribed grammar. + +**Implementation** + +We found the following library - https://github.com/goccmack/gogll. It generates a GLL or LR(1) parser and an FSA-based lexer for any context-free grammar. What we needed to do is to rewrite [ABCI 2.0 grammar](../../../spec/abci/abci++_comet_expected_behavior.md#valid-method-call-sequences) +using the syntax that the library understands. +The new grammar is below and can be found in `test/e2e/pkg/grammar/abci_grammar.md` file. + +```abnf + +Start : CleanStart | Recovery; + +CleanStart : InitChain ConsensusExec | StateSync ConsensusExec ; +StateSync : StateSyncAttempts SuccessSync | SuccessSync ; +StateSyncAttempts : StateSyncAttempt | StateSyncAttempt StateSyncAttempts ; +StateSyncAttempt : OfferSnapshot ApplyChunks | OfferSnapshot ; +SuccessSync : OfferSnapshot ApplyChunks ; +ApplyChunks : ApplyChunk | ApplyChunk ApplyChunks ; + +Recovery : InitChain ConsensusExec | ConsensusExec ; + +ConsensusExec : ConsensusHeights ; +ConsensusHeights : ConsensusHeight | ConsensusHeight ConsensusHeights ; +ConsensusHeight : ConsensusRounds FinalizeBlock Commit | FinalizeBlock Commit ; +ConsensusRounds : ConsensusRound | ConsensusRound ConsensusRounds ; +ConsensusRound : Proposer | NonProposer ; + +Proposer : GotVotes | ProposerSimple | Extend | GotVotes ProposerSimple | GotVotes Extend | ProposerSimple Extend | GotVotes ProposerSimple Extend ; +ProposerSimple : PrepareProposal | PrepareProposal ProcessProposal ; +NonProposer: GotVotes | ProcessProposal | Extend | GotVotes ProcessProposal | GotVotes Extend | ProcessProposal Extend | GotVotes ProcessProposal Extend ; +Extend : ExtendVote | GotVotes ExtendVote | ExtendVote GotVotes | GotVotes ExtendVote GotVotes ; +GotVotes : GotVote | GotVote GotVotes ; + +InitChain : "init_chain" ; +FinalizeBlock : "finalize_block" ; +Commit : "commit" ; +OfferSnapshot : "offer_snapshot" ; +ApplyChunk : "apply_snapshot_chunk" ; +PrepareProposal : "prepare_proposal" ; +ProcessProposal : "process_proposal" ; +ExtendVote : "extend_vote" ; +GotVote : "verify_vote_extension" ; + +``` + +If you compare this grammar with the original one, you will notice that +`Info` is removed. The reason is that, as explained in the section [CometBFT's expected behaviour](../../../spec/abci/abci++_comet_expected_behavior.md#valid-method-call-sequences), one of the +purposes of the `Info` method is being part of the RPC handling from an external +client. Since this can happen at any time, it complicates the +grammar. +This is not true in other cases, but since the Application does +not know why the `Info` is called, we removed +it totally from the new grammar. The Application is still logging the `Info` +call, but a specific test would need to be written to check whether it happens +at the right moment. + +Moreover, it is worth noticing that the `(inf)` part of the grammar is replaced with the `*`. This results in the new grammar being finite compared to the original, which represents an infinite (omega) grammar. + +The `gogll` library receives the file with the grammar as input, and it generates the corresponding parser and lexer. The actual commands are integrated into `test/e2e/Makefile` and executed when `make grammar-gen` is invoked. +The resulting code is stored inside `test/e2e/pkg/grammar/grammar-auto` directory. + +Apart from this auto-generated code, we implemented `Checker` abstraction +which knows how to use the generated parsers and lexers to verify whether a +specific execution (list of ABCI 2.0 calls logged by the Application while the +testnet was running) respects the ABCI 2.0 grammar. The implementation and tests +for it are inside `test/e2e/pkg/grammar/checker.go` and +`test/e2e/pkg/grammar/checker_test.go`, respectively. + +How the `Checker` works is demonstrated with the test `TestCheckABCIGrammar` +implemented in `test/e2e/tests/abci_test.go` file. + +```go +func TestCheckABCIGrammar(t *testing.T) { + checker := grammar.NewGrammarChecker(grammar.DefaultConfig()) + testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() + if !node.Testnet.ABCITestsEnabled { + return + } + executions, err := fetchABCIRequests(t, node.Name) + require.NoError(t, err) + for i, e := range executions { + isCleanStart := i == 0 + _, err := checker.Verify(e, isCleanStart) + require.NoError(t, err) + } + }) +} + +``` + +Specifically, the test first creates a `Checker` object. Then for each node in the testnet, it collects all requests +logged by this node. Remember here that `fetchABCIRequests()` returns an array of slices(`[]*abci.Request`) where the slice +with index 0 corresponds to the node's `CleanStart` execution, and each additional slice corresponds to the `Recovery` +execution after a specific crash. Each node must have one `CleanStart` execution and the same number of `Recovery` executions +as the number of crashes that happened on this node. If collecting was successful, the test checks whether each execution +respects the ABCI 2.0 +grammar by calling `checker.Verify()` method. If `Verify` returns an error, the specific execution does not respect the +grammar, and the test will fail. + +The tests are executed only if `ABCITestsEnabled` is set to `true`. This is done through the manifest file. Namely, if we +want to test whether CometBFT respects ABCI 2.0 grammar, we would need to enable these tests by adding `abci_tests_enabled = true` in the manifest file of a particular testnet (e.g. `networks/ci.toml`). This will automatically activate logging on the +application side. + +The `Verify()` method is shown below. +```go +func (g *Checker) Verify(reqs []*abci.Request, isCleanStart bool) (bool, error) { + if len(reqs) == 0 { + return false, errors.New("execution with no ABCI calls") + } + fullExecution := g.getExecutionString(reqs) + r := g.filterRequests(reqs) + // Check if the execution is incomplete. + if len(r) == 0 { + return true, nil + } + execution := g.getExecutionString(r) + errors := g.verify(execution, isCleanStart) + if errors == nil { + return true, nil + } + return false, fmt.Errorf("%v\nFull execution:\n%v", g.combineErrors(errors, g.cfg.NumberOfErrorsToShow), g.addHeightNumbersToTheExecution(fullExecution)) +} +``` + +It receives a set of ABCI 2.0 requests and a flag saying whether they represent a `CleanStart` execution or not and does the following things: +- Checks if the execution is an empty execution. +- Filter the requests by calling the method `filterRequests()`. This method will remove all the requests from the set that are not supported by the current version of the grammar. In addition, it will filter the last height by removing all ABCI 2.0 requests after the +last `Commit`. The function `fetchABCIRequests()` can be called in the middle of the height. As a result, the last height may be incomplete and +classified as invalid, even if that is not the reality. The simple example here is that the last +request fetched via `fetchABCIRequests()` is `FinalizeBlock`; however, `Commit` happens after +`fetchABCIRequests()` was invoked. Consequently, the execution +will be considered as faulty because `Commit` is missing, even though the `Commit` +will happen after. This is why if the execution consists of only one incomplete height and function `filterRequests()` returns an empty set of requests, the `Verify()` method considers this execution as valid and returns `true`. +- Generates an execution string by replacing `abci.Request` with the +corresponding terminal from the grammar. This logic is implemented in +`getExecutionString()` function. This function receives a list of `abci.Request` and generates a string where every request +will be replaced with a corresponding terminal. For example, request `r` of type `abci.Request_PrepareProposal` is replaced with the string `prepare_proposal`, the first part of `r`'s string representation. +- Checks if the resulting string with terminals respects the grammar by calling the +`verify()` function. +- Returns true if the execution is valid and an error if that's not the case. An example of an error is below. + +``` +FAIL: TestCheckABCIGrammar/full02 (8.76s) + abci_test.go:24: ABCI grammar verification failed: The error: "Invalid execution: parser was expecting one of [init_chain], got [offer_snapshot] instead." has occurred at height 0. + + Full execution: + 0: offer_snapshot apply_snapshot_chunk finalize_block commit + 1: finalize_block commit + 2: finalize_block commit + 3: finalize_block commit + ... +``` +The error shown above reports an invalid execution. Moreover, it says why it is considered invalid (`init_chain` was missing) and the height of the error. Notice here that the height in the case of `CleanStart` execution corresponds to the actual consensus height, while for the `Recovery` execution, height 0 represents the first height after the crash. Lastly, after the error, the full execution, one height per line, is printed. This part may be optional and handled with a config flag, but we left it like this for now. + +*Note:* The `gogll` parser can return many errors because it returns an error at every point at which the parser fails to parse +a grammar production. Usually, the error of interest is the one that has +parsed the largest number of tokens. This is why, by default, we are printing only the last error; however, this can be configured with the `NumberOfErrorsToShow` field of `Checker`'s config. + +Lastly, we present the `verify()` function since this function is the heart of this code. + +```go +func (g *Checker) verify(execution string, isCleanStart bool) []*Error { + errors := make([]*Error, 0) + lexer := lexer.New([]rune(execution)) + bsrForest, errs := parser.Parse(lexer) + for _, err := range errs { + exp := []string{} + for _, ex := range err.Expected { + exp = append(exp, ex) + } + expectedTokens := strings.Join(exp, ",") + unexpectedToken := err.Token.TypeID() + e := &Error{ + description: fmt.Sprintf("Invalid execution: parser was expecting one of [%v], got [%v] instead.", expectedTokens, unexpectedToken), + height: err.Line - 1, + } + errors = append(errors, e) + } + if len(errors) != 0 { + return errors + } + eType := symbols.NT_Recovery + if isCleanStart { + eType = symbols.NT_CleanStart + } + roots := bsrForest.GetRoots() + for _, r := range roots { + for _, s := range r.Label.Slot().Symbols { + if s == eType { + return nil + } + } + } + e := &Error{ + description: "The execution is not of valid type.", + height: 0, + } + errors = append(errors, e) + return errors +} + +``` + +This function first checks if the specific execution represents a valid execution concerning the ABCI grammar. For this, it uses +the auto-generated parser and lexer. If the execution passes this initial test, it checks whether the execution is of a valid type (`CleanStart` or `Recovery`). Namely, it checks whether the execution is of the type specified with the function's second parameter (`isCleanStart`). + +**Changing the grammar** + +Any modification to the grammar (`test/e2e/pkg/grammar/abci_grammar.md`) requires generating a new parser and lexer. This is done by +going to the `test/e2e/` directory and running: + +```bash +make grammar-gen +``` + +Make sure you commit any changes to the auto-generated code together with the changes to the grammar. + +### Supporting additional ABCI requests + +Here we present all the steps we need to do if we want to support other +ABCI requests in the future: + +- The application needs to log the new request in the same way as we do now. +- We should include the new request to the grammar and generate a new parser and lexer. +- We should add new requests to the list of supported requests. Namely, we should modify the function `isSupportedByGrammar()` in `test/e2e/pkg/grammar/checker.go` to return `true` for the new type of requests. + +## Status + +Implemented. + +To-do list: +- adding the CI workflow to check if make grammar is executed. +- in the future, we might consider whether the logging (actually, tracing) should be done on the e2e application side, or on CometBFT side, so this infra can be reused for MBT-like activities) +## Consequences + +### Positive +- We should be able to check whether CommetBFT respects ABCI 2.0 grammar. +### Negative + +### Neutral + diff --git a/docs/references/architecture/adr-109-reduce-go-api-surface.md b/docs/references/architecture/adr-109-reduce-go-api-surface.md new file mode 100644 index 00000000000..52930c5e7f2 --- /dev/null +++ b/docs/references/architecture/adr-109-reduce-go-api-surface.md @@ -0,0 +1,211 @@ +# ADR 109: Reduce CometBFT Go API Surface Area + +## Changelog + +- 2023-10-09: First draft (@thanethomson) + +## Status + +Accepted ([\#1484]) + +## Context + +At present, the CometBFT codebase is somewhat monolithic, resulting in a very +large Go API surface area. This results in much more difficulty in terms of +changing the Go APIs, since making trivial breaking changes in non-critical +packages requires a major version bump. Doing so ultimately results in much +slower uptake of CometBFT releases and has produced substantial stagnation in +the codebase. + +In order to mitigate this, several changes are proposed: + +1. From when CometBFT v1.0 is released, major version bumps are only made when + state-breaking changes are released. Minor version bumps can result in Go + API-breaking changes (after deprecation warning for a reasonable period of + time, as is customary for the Go standard library). Patch version bumps would + guarantee no breaking changes. +2. Internalize a number of packages that do not need to be externally accessible + along similar lines to that proposed in [ADR 060]. This involves moving these + packages under the `/internal/` path in the repository, making those packages + only accessible to the CometBFT codebase. + +## Alternative Approaches + +The following alternative approaches were considered. + +1. Do nothing. This approach will keep the status quo along with its related + problems. +2. Implement only one or two of the proposed changes. This will result in less + flexibility than implementing all three. +3. Implement [ADR 060] as-is. The context in which ADR 060 was written, however, + has changed, so certain changes need to be made to accommodate the new + context. + +## Decision + +To implement all three approaches, using [ADR 060] as input, but updating +recommendations based on the current context. + +## Detailed Design + +### Versioning + +The Go API stability guarantees provided by the new versioning policy must be +explicitly added to the documentation. + +### Package Internalization + +In order to move certain packages into the `internal` folder, effectively hiding +them from public use, the current package usage by some of the primary CometBFT +users should be considered. This ADR considers the [Cosmos SDK], [IBC Go] and +the [Cosmos Hub]. + +#### Cosmos SDK Imports + +Since the [Cosmos SDK] is one of the primary users of CometBFT, it would make +sense to expose the minimal surface area needed by the Cosmos SDK in CometBFT +v1. Exposing internalized packages at a later stage constitutes a non-breaking +change, whereas internalizing packages later is breaking. + +At the time of this writing, on the `main` branch, the Cosmos SDK imports the +following packages from the CometBFT repository for use at compile/run time and +during testing: + +```bash +> go list -json ./... | jq '.Imports, .TestImports, .XTestImports' | grep cometbft | sort | uniq | tr -d '", ' +github.com/cometbft/cometbft/abci/server +github.com/cometbft/cometbft/abci/types +github.com/cometbft/cometbft/abci/types +github.com/cometbft/cometbft/cmd/cometbft/commands +github.com/cometbft/cometbft/config +github.com/cometbft/cometbft/crypto +github.com/cometbft/cometbft/crypto/ed25519 +github.com/cometbft/cometbft/crypto/encoding +github.com/cometbft/cometbft/crypto/secp256k1 +github.com/cometbft/cometbft/crypto/sr25519 +github.com/cometbft/cometbft/crypto/tmhash +github.com/cometbft/cometbft/libs/bytes +github.com/cometbft/cometbft/libs/cli +github.com/cometbft/cometbft/libs/json +github.com/cometbft/cometbft/libs/log +github.com/cometbft/cometbft/mempool +github.com/cometbft/cometbft/node +github.com/cometbft/cometbft/p2p +github.com/cometbft/cometbft/privval +github.com/cometbft/cometbft/proto/tendermint/crypto +github.com/cometbft/cometbft/proto/tendermint/p2p +github.com/cometbft/cometbft/proto/tendermint/types +github.com/cometbft/cometbft/proto/tendermint/types +github.com/cometbft/cometbft/proto/tendermint/version +github.com/cometbft/cometbft/proxy +github.com/cometbft/cometbft/rpc/client +github.com/cometbft/cometbft/rpc/client/http +github.com/cometbft/cometbft/rpc/client/local +github.com/cometbft/cometbft/rpc/client/mock +github.com/cometbft/cometbft/rpc/core/types +github.com/cometbft/cometbft/rpc/jsonrpc/server +github.com/cometbft/cometbft/types +github.com/cometbft/cometbft/types/time +github.com/cometbft/cometbft/version +``` + +#### Packages used by IBC Go + +[IBC Go] on its `main` branch imports the following packages from CometBFT, +while using CometBFT v0.38.x: + +```bash +> go list -json ./... | jq '.Imports, .TestImports, .XTestImports' | grep cometbft | sort | uniq | tr -d '", ' +github.com/cometbft/cometbft/abci/types +github.com/cometbft/cometbft/config +github.com/cometbft/cometbft/crypto +github.com/cometbft/cometbft/crypto/secp256k1 +github.com/cometbft/cometbft/crypto/tmhash +github.com/cometbft/cometbft/libs/bytes +github.com/cometbft/cometbft/libs/math +github.com/cometbft/cometbft/light +github.com/cometbft/cometbft/proto/tendermint/crypto +github.com/cometbft/cometbft/proto/tendermint/types +github.com/cometbft/cometbft/proto/tendermint/version +github.com/cometbft/cometbft/state +github.com/cometbft/cometbft/types +github.com/cometbft/cometbft/version +``` + +#### Packages used by the Cosmos Hub + +The [Cosmos Hub], at the time of this writing, still uses the CometBFT v0.34.x +series (effectively still using Tendermint Core with the CometBFT alias): + +```bash +> go list -json ./... | jq '.Imports, .TestImports, .XTestImports' | grep 'tendermint/tendermint' | sort | uniq | tr -d '", ' +github.com/tendermint/tendermint/abci/types +github.com/tendermint/tendermint/abci/types +github.com/tendermint/tendermint/config +github.com/tendermint/tendermint/crypto +github.com/tendermint/tendermint/libs/cli +github.com/tendermint/tendermint/libs/json +github.com/tendermint/tendermint/libs/log +github.com/tendermint/tendermint/libs/os +github.com/tendermint/tendermint/libs/rand +github.com/tendermint/tendermint/libs/strings +github.com/tendermint/tendermint/p2p +github.com/tendermint/tendermint/privval +github.com/tendermint/tendermint/proto/tendermint/types +github.com/tendermint/tendermint/proto/tendermint/types +github.com/tendermint/tendermint/rpc/client/http +github.com/tendermint/tendermint/types +github.com/tendermint/tendermint/types/time +``` + +#### Public Package Inventory + +Only the packages from the following table marked as necessary should still +remain publicly exported. All other packages in CometBFT should be moved under +`internal`. + +| Package | Used By | Necessary | Explanation | +|----------------|--------------------------|-----------|-------------| +| `abci` | Cosmos SDK, IBC Go, Gaia | ✅ | | +| `cmd` | Cosmos SDK | ✅ | | +| `config` | Cosmos SDK, IBC Go, Gaia | ✅ | | +| `crypto` | Cosmos SDK, IBC Go, Gaia | ✅ | | +| `libs/bytes` | Cosmos SDK, IBC Go | ✅ | | +| `libs/cli` | Cosmos SDK, Gaia | ✅ | | +| `libs/json` | Cosmos SDK, Gaia | ✅ | | +| `libs/log` | Cosmos SDK, Gaia | ✅ | | +| `libs/math` | IBC Go | ❓ | Necessary for `Fraction` type used by light client, which could be moved into `light` package instead | +| `libs/os` | Gaia | ❌ | Uses `Exit` and `EnsureDir` functions | +| `libs/rand` | Gaia | ❌ | | +| `libs/strings` | Gaia | ❌ | Uses `StringInSlice` function | +| `light` | IBC Go | ✅ | | +| `mempool` | Cosmos SDK | ✅ | | +| `node` | Cosmos SDK | ✅ | | +| `p2p` | Cosmos SDK, Gaia | ✅ | | +| `privval` | Cosmos SDK, Gaia | ✅ | | +| `proto` | Cosmos SDK, IBC Go, Gaia | ✅ | | +| `proxy` | Cosmos SDK | ✅ | | +| `rpc` | Cosmos SDK, Gaia | ✅ | | +| `state` | IBC Go | ❌ | Only uses `TxResultsHash` type to check hash equivalence in test | +| `types` | Cosmos SDK, IBC Go, Gaia | ✅ | | +| `version` | Cosmos SDK, IBC Go | ✅ | | + +## Consequences + +### Positive + +- A smaller, more manageable Go API surface area. +- The team will be able to make internal Go API-breaking changes much quicker. + +### Negative + +- Some users (especially "power users" that make more extensive use of CometBFT + internals) may experience breakages. If absolutely necessary, certain packages + can be moved back out of the `internal` directory in subsequent minor + releases. + +[\#1484]: https://github.com/cometbft/cometbft/issues/1484 +[ADR 060]: tendermint-core/adr-060-go-api-stability.md +[Cosmos SDK]: https://github.com/cosmos/cosmos-sdk/ +[Cosmos Hub]: https://github.com/cosmos/gaia +[IBC Go]: https://github.com/cosmos/ibc-go diff --git a/docs/references/architecture/adr-110-remote-mempool.md b/docs/references/architecture/adr-110-remote-mempool.md new file mode 100644 index 00000000000..93b84480951 --- /dev/null +++ b/docs/references/architecture/adr-110-remote-mempool.md @@ -0,0 +1,362 @@ +# ADR 110: Remote mempool + +## Changelog + +- 2023-11-13: Marked as rejected in favour of ADR 111 (@thanethomson) +- 2023-11-13: Updated with feedback (@thanethomson) +- 2023-11-04: Renamed ADR to "Remote mempool" instead of "External mempool" to + align with gRPC service definition (@thanethomson) +- 2023-11-03: First draft (@thanethomson) + +## Status + +Rejected in favour of ADR 111 + +## Context + +Over time it has become apparent that the generic mempool provided by Tendermint +Core and Comet is not sufficient to meet evolving application needs. In fact, it +appears as though the choice of what kind of mempool to use is inherently +application-specific. The mempool within Comet is also not scalable +independently of Comet, which can become a DoS vector for certain types of +networks (especially those that allow low- or zero-fee transactions). + +As such, and as part of a broader effort to modularize Comet and separate +consensus- and application-related concerns, this ADR proposes a mechanism +whereby Comet can interact with an **external mempool**. This involves +implementing a mempool variant in Comet which is effectively just a client for +an external mempool process or set of processes. + +This approach changes the way that validators obtain transactions, and implies +that full nodes are not necessary as sentries for receiving transactions (in +fact, in this model, full nodes are not intended to interact with the mempool at +all). DDoS mitigation mechanisms, however, are left to those who implement +remote mempools. + +## Alternative Approaches + +The current alternatives considered are: + +1. Do nothing, which does not seem sustainable. +2. Extend ABCI to allow external processes direct access to the P2P layer of the + consensus engine, as per [\#1112]. This, however, is a much more complex + solution that will require more in-depth discussion and design prior to + implementation, as it requires ABCI to allow for _bidirectional_ initiation + of requests. This will also require substantial breaking changes to ABCI + (primarily for remote applications, since a new transport layer will be + required that allows bidirectional initiation of requests, as per [\#1117]). +3. Provide multiple mempool implementations. This does not seem feasible due to + the varying requirements of different applications, including the possibility + that different applications need different types of gossip protocols. It is + unfeasible capacity-wise for the current CometBFT team to maintain different + mempool implementations for specific applications, especially since this + falls outside of the purview of maintaining public goods for the _entire_ + ecosystem as opposed to specific networks. + +## Decision + +N/A + +## Detailed Design + +### High-level architecture + +#### Single-process mempool + +The simplest possible architecture for a Comet validator with an external +mempool is as follows. + +```mermaid +flowchart LR + comet[Comet Validator] + app[Application] + mempool[Mempool] + user[User] + + comet --> app + + comet -- 4. Reap transactions --> mempool + user -- 1. Submit transactions --> app + app -- 2. CheckTx --> app + app -- 3. Publish transactions --> mempool + mempool -- CheckTx --> app +``` + +In this flow: + +1. Users submit transactions directly to some form of RPC in the application. It + is up to operators to secure this RPC endpoint and implement measures to + prevent DDoS attacks. +2. The application validates incoming transactions internally in a similar way + to how `CheckTx` currently works. +3. Transactions that the application deems valid are then sent to the mempool by + the application, e.g. through some form of RPC mechanism. The mempool is then + expected to propagate these transactions to the rest of the network using its + own communication layer, independent of the CometBFT P2P layer. +4. During `PrepareProposal`, a Comet validator will reap transactions from the + mempool by way of an RPC call. + +Additionally, when transactions are received by a remote mempool instance from +foreign remote mempool instances, it is expected that the mempool instance will +send the transaction to the application for validation (similar to how `CheckTx` +currently functions) prior to inclusion. + +#### Scalable mempool + +The recommended high-level architecture for a modular Comet validator with an +externalized, scalable mempool, is as follows. + +```mermaid +flowchart LR + comet[Comet Validator] + app[Application] + mempoolrouter[Mempool Router] + mempool1[Mempool Instance 1] + mempool2[Mempool Instance 2] + mempoolN[Mempool Instance N] + user[User] + + comet --> app + + comet -- 4. Reap transactions --> mempoolrouter + user -- 1. Submit transactions --> app + app -- 2. CheckTx --> app + app -- 3. Publish transactions --> mempoolrouter + + mempoolrouter --> mempool1 + mempoolrouter --> mempool2 + mempoolrouter --> mempoolN + + mempool1 -- CheckTx --> app + mempool2 -- CheckTx --> app + mempoolN -- CheckTx --> app +``` + +Here the interaction is the same as the simple variant discussed earlier, but +instead of interacting directly with the mempool, all interactions are with some +form of routing mechanism. For example, this could be a reverse proxy like nginx +configured to deliver requests to mempool instances in a round-robin fashion. + +This configuration would be application-specific, and would need to be set up +correctly by the operator for the specific application. + +### Configuration + +The following change to the `config.toml` file is envisaged: + +```toml +[mempool] +# The type of mempool for this CometBFT node to use. +# +# Valid types of mempools supported by CometBFT: +# - "local" : Default clist mempool with flooding gossip protocol +# - "remote" : Remote mempool in a separate process +type = "remote" + +# +# Configuration specific to the remote mempool. If mempool.type is not "remote", +# this section will be ignored. +# +# A remote mempool is only usable by a validator node. Turning on the remote +# mempool for a full node will simply disable any mempool-related functionality +# on that full node, and the full node will not interact with any mempool at +# all. +# +[mempool.remote] +# The base URL for the gRPC interface to the remote mempool. +url = "http://localhost:28880" + +# The timeout for reaping (removing) transaction data after a block has been +# committed. +timeout_reap = "1s" + +# The timeout for initiating the TxsAvailable call. +timeout_txs_available = "1s" +``` + +### RPC API + +At the time of this writing, it is recommended to implement a gRPC-based RPC +standard for interacting with the remote mempool (which uses Protobuf encoding +over HTTP/2) because: + +- gRPC, as a standard, is well-established and code generation technologies are + widely available for many different programming languages, allowing mempool + developers more flexibility in how they build those mempools. +- Comet is moving toward making more extensive use of gRPC in future. +- Load balancing technologies for HTTP/2 using reverse proxies such as nginx are + relatively well-established, making routing of requests to scaled-out mempool + clusters relatively straightforward. + +An alternative here would be to implement a RESTful HTTP/3 API (using QUIC), but +HTTP/3 support in reverse proxies is still in its early stages. Such a protocol +can be considered in a future iteration of the interface if it provides +substantial performance/latency benefits. + +The following gRPC API is proposed. + +```protobuf +syntax = "proto3"; +package tendermint.services.remote_mempool.v1; + +// RemoteMempoolService is implemented by a remote mempool instance. A CometBFT +// validator makes use of a client generated from this interface definition to +// interact with the remote mempool. +// +// It is up to the implementer of the remote mempool to define transaction +// submission mechanisms/interfaces. +service RemoteMempoolService { + // Fetch allows a CometBFT validator to obtain the next batch of + // transactions to be included during PrepareProposal when the current node + // is a proposer. + rpc Fetch(FetchRequest) returns (FetchResponse); + + // Remove takes a set of transaction keys and removes the corresponding + // transactions from the mempool. + // + // This will only be called after the block is committed by consensus. + rpc Remove(RemoveRequest) returns (RemoveResponse); + + // TxsAvailable streams notifications back to the client that new + // transactions are available in the mempool. + // + // The mempool is expected to stream a TxsAvailableResponse as it has + // transactions available. A response, however, is only expected in two + // cases: + // + // 1. Once for each newly encountered height (as supplied to the mempool via + // the Remove request). + // + // 2. Upon initiation of the TxsAvailable call. This caters for instances + // where the consensus engine may have failed and restarted. + // + // The consensus engine will only ever make one call to TxsAvailable and + // will attempt to keep the connection alive. + rpc TxsAvailable(TxsAvailableRequest) returns (stream TxsAvailableResponse); +} + +message FetchRequest { + // Fetch as many transactions as possible that cumulatively take up at most + // this number of bytes. Setting this value to -1 implies no limit (this + // implies that the remote mempool is fully in control of this value). + int64 max_bytes = 1; +} + +message FetchResponse { + // Transactions to be included in the proposal. + repeated bytes txs = 1; +} + +message RemoveRequest { + // The current height of the chain. + uint64 height = 1; + + // A list of IDs of transactions to be removed from the mempool. At present + // this is a list of SHA256 hashes of the transactions. + repeated bytes tx_ids = 2; +} + +message RemoveResponse {} + +message TxsAvailableRequest {} + +// TxsAvailableResponse is to be sent once upon initiation of the TxsAvailable +// request, as well as once for each new height, iff new transactions are +// available to be fetched by the consensus engine. +// +// If a TxsAvailableResponse is sent more than once per height, the consensus +// engine is expected to ignore the extra messages. +message TxsAvailableResponse { + // Supplied for informational purposes to the consensus engine to indicate + // the height seen by the mempool during the last call to Remove. + uint64 last_reap_height = 1; +} +``` + +**Notes**: + +- The terminology used in the gRPC interface is different to that used in the + [`Mempool`] interface. The term "reap" technically implies removal from the + mempool, but the [`Mempool`] interface incorrectly uses this term to imply + fetching a batch of transactions. The combination of `Fetch` and `Remove` can + be thought of as a "reap" operation. + +- The gRPC interface purposefully does not facilitate limiting fetched + transactions by gas in an effort to separate consensus- and + application-related concerns (as per [RFC 011]). Should remote mempool + developers want to limit returned transactions by gas, this should be + implemented as part of the configuration of the remote mempool. + +### Impact and properties + +A new mempool that implements the [`Mempool`] interface will be created, and +when enabled it will have the following impacts/properties: + +1. The mempool-related ABCI methods will not be called. +2. The following methods will do nothing: + - `CheckTx`, since transaction validation is assumed to happen prior to + transaction insertion in the mempool. + - `FlushAppConn`, which is only relevant for use via ABCI. + - `RemoveTxByKey`, which is only used in the callback in the context of ABCI. + - `ReapMaxTxs`, which is only used internally and by the `unconfirmed_txs` + RPC endpoint. + - `Flush`, which is only ever used via the `unsafe_flush_mempool` RPC + endpoint. + - `Size` and `SizeBytes`, since these are only used for informational + purposes in the RPC. +3. Reaping of transactions will result in network calls to the remote mempool + instance. +4. The following RPC endpoints will be disabled, returning relevant errors when + users attempt to call them: + - `broadcast_tx_*` + - `unconfirmed_txs` + - `num_unconfirmed_txs` + - `unsafe_flush_mempool` +5. All P2P-based transaction broadcast functionality will be disabled. It will + be up to the mempool developer to implement connectivity to other mempool + instances and the relevant broadcast/gossip mechanisms to disseminate + incoming transactions. + +### Startup and failure modes + +- When a CometBFT-based validator starts up with `mempool.type` set to `remote`, + it will expect to be able to connect to the remote mempool. If it cannot, it + will log an error and continue retrying to connect. + +- When a validator attempts to call any of the `Fetch` or `Remove` methods and + the call fails for whatever reason, it will log an error. + +- It must be kept in mind that transactions will persist in the mempool between + CometBFT node restarts. This implies a different set of assumptions as + compared to when using the default mempool, as when a node fails with the + default mempool, the contents of the mempool are automatically flushed. + +### Rollout plan + +The remote mempool will initially land in CometBFT v1.0, and will potentially be +considered for backporting to the `v0.38.x-experimental` branch. + +## Consequences + +### Positive + +- Application developers can provide their own mempools that live in a separate + process to the validator in which they can implement properties that benefit + their application specifically. +- Transactions can be submitted to processes outside of a validator without + needing to run a full node or sentry, potentially reducing operational costs. +- Separating the mempool out into its own process, if the mempool is built + correctly, can allow it to scale independently of the consensus engine. + +### Negative + +- Application developers would need to potentially build their own mempools, + which involves a substantial amount of effort. +- In some cases, application-specific remote mempools would currently need to + implement their own gossip mechanism (until an interface such as [\#1112] is + available). + +[\#1112]: https://github.com/cometbft/cometbft/discussions/1112 +[\#1117]: https://github.com/cometbft/cometbft/issues/1117 +[`Mempool`]: ../../../mempool/mempool.go +[RFC 011]: ../rfc/tendermint-core/rfc-011-delete-gas.md diff --git a/docs/references/architecture/adr-111-nop-mempool.md b/docs/references/architecture/adr-111-nop-mempool.md new file mode 100644 index 00000000000..234cd5b9c1d --- /dev/null +++ b/docs/references/architecture/adr-111-nop-mempool.md @@ -0,0 +1,324 @@ +# ADR 111: `nop` Mempool + +## Changelog + +- 2023-11-07: First version (@sergio-mena) +- 2023-11-15: Addressed PR comments (@sergio-mena) +- 2023-11-17: Renamed `nil` to `nop` (@melekes) +- 2023-11-20: Mentioned that the app could reuse p2p network in the future (@melekes) +- 2023-11-22: Adapt ADR to implementation (@melekes) + +## Status + +Accepted + +[Tracking issue](https://github.com/cometbft/cometbft/issues/1666) + +## Context + +### Summary + +The current mempool built into CometBFT implements a robust yet somewhat inefficient transaction gossip mechanism. +While the CometBFT team is currently working on more efficient general-purpose transaction gossiping mechanisms, +some users have expressed their desire to manage both the mempool and the transaction dissemination mechanism +outside CometBFT (typically at the application level). + +This ADR proposes a fairly simple way for CometBFT to fulfill this use case without moving away from our current architecture. + +### In the Beginning... + +It is well understood that a dissemination mechanism +(sometimes using _Reliable Broadcast_ [\[HT94\]][HT94] but not necessarily), +is needed in a distributed system implementing State-Machine Replication (SMR). +This is also the case in blockchains. +Early designs such as Bitcoin or Ethereum include an _internal_ component, +responsible for dissemination, called mempool. +Tendermint Core chose to follow the same design given the success +of those early blockchains and, since inception, Tendermint Core and later CometBFT have featured a mempool as an internal piece of its architecture. + + +However, the design of ABCI clearly dividing the application logic (i.e., the appchain) +and the consensus logic that provides SMR semantics to the app is a unique innovation in Cosmos +that sets it apart from Bitcoin, Ethereum, and many others. +This clear separation of concerns entailed many consequences, mostly positive: +it allows CometBFT to be used underneath (currently) tens of different appchains in production +in the Cosmos ecosystem and elsewhere. +But there are other implications for having an internal mempool +in CometBFT: the interaction between the mempool, the application, and the network +becomes more indirect, and thus more complex and hard to understand and operate. + +### ABCI++ Improvements and Remaining Shortcomings + +Before the release of ABCI++, `CheckTx` was the main mechanism the app had at its disposal to influence +what transactions made it to the mempool, and very indirectly what transactions got ultimately proposed in a block. +Since ABCI 1.0 (the first part of ABCI++, shipped in `v0.37.x`), the application has +a more direct say in what is proposed through `PrepareProposal` and `ProcessProposal`. + +This has greatly improved the ability for appchains to influence the contents of the proposed block. +Further, ABCI++ has enabled many new use cases for appchains. However some issues remain with +the current model: + +* We are using the same P2P network for disseminating transactions and consensus-related messages. +* Many mempool parameters are configured on a per-node basis by node operators, + allowing the possibility of inconsistent mempool configuration across the network + with potentially serious scalability effects + (even causing unacceptable performance degradation in some extreme cases). +* The current mempool implementation uses a basic (robust but sub-optimal) flood algorithm + * the CometBFT team is working on improving it as one of our current priorities, + but any improvement we come up with must address the needs of a vast spectrum of applications, + as well as be heavily scaled-tested in various scenarios + (in an attempt to cover the applications' wide spectrum) + * a mempool designed specifically for one particular application + would reduce the search space as its designers can devise it with just their application's + needs in mind. +* The interaction with the application is still somewhat convoluted: + * the application has to decide what logic to implement in `CheckTx`, + what to do with the transaction list coming in `RequestPrepareProposal`, + whether it wants to maintain an app-side mempool (more on this below), and whether or not + to combine the transactions in the app-side mempool with those coming in `RequestPrepareProposal` + * all those combinations are hard to fully understand, as the semantics and guarantees are + often not clear + * when using exclusively an app-mempool (the approach taken in the Cosmos SDK `v0.47.x`) + for populating proposed blocks, with the aim of simplifying the app developers' life, + we still have a suboptimal model where we need to continue using CometBFT's mempool + in order to disseminate the transactions. So, we end up using twice as much memory, + as in-transit transactions need to be kept in both mempools. + +The approach presented in this ADR builds on the app-mempool design released in `v0.47.x` +of the Cosmos SDK, +and briefly discussed in the last bullet point above (see [SDK app-mempool][sdk-app-mempool] for further details of this model). + +In the app-mempool design in Cosmos SDK `v0.47.x` +an unconfirmed transaction must be both in CometBFT's mempool for dissemination and +in the app's mempool so the application can decide how to manage the mempool. +There is no doubt that this approach has numerous advantages. However, it also has some implications that need to be considered: + +* Having every transaction both in CometBFT and in the application is suboptimal in terms of memory. + Additionally, the app developer has to be careful + that the contents of both mempools do not diverge over time + (hence the crucial role `re-CheckTx` plays post-ABCI++). +* The main reason for a transaction needing to be in CometBFT's mempool is + because the design in Cosmos SDK `v0.47.x` does not consider an application + that has its own means of disseminating transactions. + It reuses the peer to peer network underneath CometBFT reactors. +* There is no point in having transactions in CometBFT's mempool if an application implements an ad-hoc design for disseminating transactions. + +This proposal targets this kind of applications: +those that have an ad-hoc mechanism for transaction dissemination that better meets the application requirements. + +The ABCI application could reuse the P2P network once this is exposed via ABCI. +But this will take some time as it needs to be implemented, and has a dependency +on bi-directional ABCI, which is also quite substantial. See +[1](https://github.com/cometbft/cometbft/discussions/1112) and +[2](https://github.com/cometbft/cometbft/discussions/494) discussions. + +We propose to introduce a `nop` (short for no operation) mempool which will effectively act as a stubbed object +internally: + +* it will reject any transaction being locally submitted or gossipped by a peer +* when a _reap_ (as it is currently called) is executed in the mempool, an empty answer will always be returned +* the application running on the proposer validator will add transactions it received + using the appchains's own mechanism via `PrepareProposal`. + +## Alternative Approaches + +These are the alternatives known to date: + +1. Keep the current model. Useful for basic apps, but clearly suboptimal for applications + with their own mechanism to disseminate transactions and particular performance requirements. +2. Provide more efficient general-purpose mempool implementations. + This is an ongoing effort (e.g., [CAT mempool][cat-mempool]), but will take some time, and R&D effort, to come up with + advanced mechanisms -- likely highly configurable and thus complex -- which then will have to be thoroughly tested. +3. A similar approach to this one ([ADR110][adr-110]) whereby the application-specific + mechanism directly interacts with CometBFT via a newly defined gRPC interface. +4. Partially adopting this ADR. There are several possibilities: + * Use the current mempool, disable transaction broadcast in `config.toml`, and accept transactions from users via `BroadcastTX*` RPC methods. + Positive: avoids transaction gossiping; app can reuse the mempool existing in ComeBFT. + Negative: requires clients to know the validators' RPC endpoints (potential security issues). + * Transaction broadcast is disabled in `config.toml`, and have the application always reject transactions in `CheckTx`. + Positive: effectively disables the mempool; does not require modifications to Comet (may be used in `v0.37.x` and `v0.38.x`). + Negative: requires apps to disseminate txs themselves; the setup for this is less straightforward than this ADR's proposal. + +## Decision + +TBD + +## Detailed Design + +What this ADR proposes can already be achieved with an unmodified CometBFT since +`v0.37.x`, albeit with a complex, poor UX (see the last alternative in section +[Alternative Approaches](#alternative-approaches)). The core of this proposal +is to make some internal changes so it is clear an simple for app developers, +thus improving the UX. + +#### `nop` Mempool + +We propose a new mempool implementation, called `nop` Mempool, that effectively disables all mempool functionality +within CometBFT. +The `nop` Mempool implements the `Mempool` interface in a very simple manner: + +* `CheckTx(tx types.Tx) (*abcicli.ReqRes, error)`: returns `nil, ErrNotAllowed` +* `RemoveTxByKey(txKey types.TxKey) error`: returns `ErrNotAllowed` +* `ReapMaxBytesMaxGas(maxBytes, maxGas int64) types.Txs`: returns `nil` +* `ReapMaxTxs(max int) types.Txs`: returns `nil` +* `Lock()`: does nothing +* `Unlock()`: does nothing +* `Update(...) error`: returns `nil` +* `FlushAppConn() error`: returns `nil` +* `Flush()`: does nothing +* `TxsAvailable() <-chan struct{}`: returns `nil` +* `EnableTxsAvailable()`: does nothing +* `SetTxRemovedCallback(cb func(types.TxKey))`: does nothing +* `Size() int` returns 0 +* `SizeBytes() int64` returns 0 + +Upon startup, the `nop` mempool reactor will advertise no channels to the peer-to-peer layer. + +### Configuration + +We propose the following changes to the `config.toml` file: + +```toml +[mempool] +# The type of mempool for this CometBFT node to use. +# +# Valid types of mempools supported by CometBFT: +# - "flood" : clist mempool with flooding gossip protocol (default) +# - "nop" : nop-mempool (app has implemented an alternative tx dissemination mechanism) +type = "nop" +``` + +The config validation logic will be modified to add a new rule that rejects a configuration file +if all of these conditions are met: + +* the mempool is set to `nop` +* `create_empty_blocks`, in `consensus` section, is set to `false`. + +The reason for this extra validity rule is that the `nop`-mempool, as proposed here, +does not support the "do not create empty blocks" functionality. +Here are some considerations on this: + +* The "do not create empty blocks" functionality + * entangles the consensus and mempool reactors + * is hardly used in production by real appchains (to the best of CometBFT team's knowledge) + * its current implementation for the built-in mempool has undesired side-effects + * app hashes currently refer to the previous block, + * and thus it interferes with query provability. +* If needed in the future, this can be supported by extending ABCI, + but we will first need to see a real need for this before committing to changing ABCI + (which has other, higher-impact changes waiting to be prioritized). + +### RPC Calls + +There are no changes needed in the code dealing with RPC. Those RPC paths that call methods of the `Mempool` interface, +will simply be calling the new implementation. + +### Impacted Workflows + +* *Submitting a transaction*. Users are not to submit transactions via CometBFT's RPC. + `BroadcastTx*` RPC methods will fail with a reasonable error and the 501 status code. + The application running on a full node must offer an interface for users to submit new transactions. + It could also be a distinct node (or set of nodes) in the network. + These considerations are exclusively the application's concern in this approach. +* *Time to propose a block*. The consensus reactor will call `ReapMaxBytesMaxGas` which will return a `nil` slice. + `RequestPrepareProposal` will thus contain no transactions. +* *Consensus waiting for transactions to become available*. `TxsAvailable()` returns `nil`. + `cs.handleTxsAvailable()` won't ever be executed. + At any rate, a configuration with the `nop` mempool and `create_empty_blocks` set to `false` + will be rejected in the first place. +* *A new block is decided*. + * When `Update` is called, nothing is done (no decided transaction is removed). + * Locking and unlocking the mempool has no effect. +* *ABCI mempool's connection* + CometBFT will still open a "mempool" connection, even though it won't be used. + This is to avoid doing lots of breaking changes. + +### Impact on Current Release Plans + +The changes needed for this approach, are fairly simple, and the logic is clear. +This might allow us to even deliver it as part of CometBFT `v1` (our next release) +even without a noticeable impact on `v1`'s delivery schedule. + +The CometBFT team (learning from past dramatic events) usually takes a conservative approach +for backporting changes to release branches that have already undergone a full QA cycle +(and thus are in code-freeze mode). +For this reason, although the limited impact of these changes would limit the risks +of backporting to `v0.38.x` and `v0.37.x`, a careful risk/benefit evaluation will +have to be carried out. + +Backporting to `v0.34.x` does not make sense as this version predates the release of `ABCI 1.0`, +so using the `nop` mempool renders CometBFT's operation useless. + +### Config parameter _vs._ application-enforced parameter + +In the current proposal, the parameter selecting the mempool is in `config.toml`. +However, it is not a clear-cut decision. These are the alternatives we see: + +* *Mempool selected in `config.toml` (our current design)*. + This is the way the mempool has always been selected in Tendermint Core and CometBFT, + in those versions where there were more than one mempool to choose from. + As the configuration is in `config.toml`, it is up to the node operators to configure their + nodes consistently, via social consensus. However this cannot be guaranteed. + A network with an inconsistent choice of mempool at different nodes might + result in undesirable side effects, such as peers disconnecting from nodes + that sent them messages via the mempool channel. +* *Mempool selected as a network-wide parameter*. + A way to prevent any inconsistency when selecting the mempool is to move the configuration out of `config.toml` + and have it as a network-wide application-enforced parameter, implemented in the same way as Consensus Params. + The Cosmos community may not be ready for such a rigid, radical change, + even if it eliminates the risk of operators shooting themselves in the foot. + Hence we went currently favor the previous alternative. +* *Mempool selected as a network-wide parameter, but allowing override*. + A third option, half way between the previous two, is to have the mempool selection + as a network-wide parameter, but with a special value called _local-config_ that still + allows an appchain to decide to leave it up to operators to configure it in `config.toml`. + +Ultimately, the "config parameter _vs._ application-enforced parameter" discussion +is a more general one that is applicable to other parameters not related to mempool selection. +In that sense, it is out of the scope of this ADR. + +## Consequences + +### Positive + +- Applications can now find mempool mechanisms that fit better their particular needs: + - Ad-hoc ways to add, remove, merge, reorder, modify, prioritize transactions according + to application needs. + - A way to disseminate transactions (gossip-based or other) to get the submitted transactions + to proposers. The application developers can devise simpler, efficient mechanisms tailored + to their application. + - Back-pressure mechanisms to prevent malicious users from abusing the transaction + dissemination mechanism. +- In this approach, CometBFT's peer-to-peer layer is relieved from managing transaction gossip, freeing up its resources for other reactors such as consensus, evidence, block-sync, or state-sync. +- There is no risk for the operators of a network to provide inconsistent configurations + for some mempool-related parameters. Some of those misconfigurations are known to have caused + serious performance issues in CometBFT's peer to peer network. + Unless, of course, the application-defined transaction dissemination mechanism ends up + allowing similar configuration inconsistencies. +- The interaction between the application and CometBFT at `PrepareProposal` time + is simplified. No transactions are ever provided by CometBFT, + and no transactions can ever be left in the mempool when CometBFT calls `PrepareProposal`: + the application trivially has all the information. +- UX is improved compared to how this can be done prior to this ADR. + +### Negative + +- With the `nop` mempool, it is up to the application to provide users with a way + to submit transactions and deliver those transactions to validators. + This is a considerable endeavor, and more basic appchains may consider it is not worth the hassle. +- There is a risk of wasting resources by those nodes that have a misconfigured + mempool (bandwidth, CPU, memory, etc). If there are TXs submitted (incorrectly) + via CometBFT's RPC, but those TXs are never submitted (correctly via an + app-specific interface) to the App. As those TXs risk being there until the node + is stopped. Moreover, those TXs will be replied & proposed every single block. + App developers will need to keep this in mind and panic on `CheckTx` or + `PrepareProposal` with non-empty list of transactions. +- Optimizing block proposals by only including transaction IDs (e.g. TX hashes) is more difficult. + The ABCI app could do it by submitting TX hashes (rather than TXs themselves) + in `PrepareProposal`, and then having a mechanism for pulling TXs from the + network upon `FinalizeBlock`. + +[sdk-app-mempool]: https://docs.cosmos.network/v0.47/build/building-apps/app-mempool +[adr-110]: https://github.com/cometbft/cometbft/pull/1565 +[HT94]: https://dl.acm.org/doi/book/10.5555/866693 +[cat-mempool]: https://github.com/cometbft/cometbft/pull/1472 \ No newline at end of file diff --git a/docs/references/architecture/adr-112-proposer-based-timestamps.md b/docs/references/architecture/adr-112-proposer-based-timestamps.md new file mode 100644 index 00000000000..93fa5e582f3 --- /dev/null +++ b/docs/references/architecture/adr-112-proposer-based-timestamps.md @@ -0,0 +1,435 @@ +# ADR 112: Proposer-Based Timestamps + +## Changelog + + - July 15 2021: Created by @williambanfield + - Aug 4 2021: Draft completed by @williambanfield + - Aug 5 2021: Draft updated to include data structure changes by @williambanfield + - Aug 20 2021: Language edits completed by @williambanfield + - Oct 25 2021: Update the ADR to match updated spec from @cason by @williambanfield + - Nov 10 2021: Additional language updates by @williambanfield per feedback from @cason + - Feb 2 2022: Synchronize logic for timely with latest version of the spec by @williambanfield + - Feb 1 2024: Renamed to ADR 112 as basis for its adoption ([#1731](https://github.com/cometbft/cometbft/issues/1731)) in CometBFT v1.0 by @cason + - Feb 7 2024: Multiple revisions, fixes, and backwards compatibility discussion by @cason + - Feb 12 2024: More detailed backwards compatibility discussion by @cason + - Feb 22 2024: Consensus parameters for backwards compatibility by @cason + +## Status + +**Accepted** + +## Context + +CometBFT currently provides a monotonically increasing source of time known as [BFT Time][bfttime]. +This mechanism for producing a source of time is reasonably simple. +Each validator adds a timestamp to each `Precommit` message it sends. +The timestamp a correct validator sends is either the validator's current known Unix time or one millisecond greater than the previous block time, depending on which value is greater. +When a block is produced, the proposer chooses the block timestamp as the weighted median of the times in all of the `Precommit` messages the proposer received. +The weighting is defined by the amount of voting power, or stake, each validator has on the network. +This mechanism for producing timestamps is both deterministic and Byzantine fault tolerant. + +This current mechanism for producing timestamps has a few drawbacks. +Validators do not have to agree at all on how close the selected block timestamp is to their own currently known Unix time. +Additionally, any amount of voting power `>1/3` may control the block timestamp. +As a result, it is quite possible that the timestamp is not particularly meaningful. + +These drawbacks present issues in CometBFT. +Timestamps are used by light clients to verify blocks. +Light clients rely on correspondence between their own currently known Unix time and the block timestamp to verify blocks they see. +However, their currently known Unix time may be greatly divergent from the block timestamp as a result of the limitations of `BFT Time`. + +The [Proposer-Based Timestamps specification (PBTS)][pbts-spec] suggests an alternative approach for producing block timestamps that remedies these issues. +Proposer-based timestamps alter the current mechanism for producing block timestamps in two main ways: + +1. The block proposer is amended to offer up its currently known Unix time as the timestamp for the next block instead of the `BFT Time`. +1. Correct validators are assumed to be equipped with synchronized clocks and only approve the proposed block timestamp if it is close enough to their own currently known Unix time. + +The result of these changes is a more meaningful timestamp that cannot be controlled by `<= 2/3` of the validator voting power. +This document outlines the necessary code changes in CometBFT to implement the corresponding [specification][pbts-spec]. + +## Alternative Approaches + +### Remove timestamps altogether + +Computer clocks are bound to skew for a variety of reasons. +Using timestamps in our protocol means either accepting the timestamps as not reliable or impacting the protocol’s liveness guarantees. +This design requires impacting the protocol’s liveness in order to make the timestamps more reliable. +An alternate approach is to remove timestamps altogether from the block protocol. +`BFT Time` is deterministic but may be arbitrarily inaccurate. +However, having a reliable source of time is quite useful for applications and protocols built on top of a blockchain. + +We therefore decided not to remove the timestamp. +Applications often wish for some transactions to occur on a certain day, on a regular period, or after some time following a different event. +All of these require some meaningful representation of agreed upon time. +The following protocols and application features require a reliable source of time: + +* Light Clients [rely on correspondence between their known time](https://github.com/cometbft/cometbft/blob/main/spec/light-client/verification/README.md#failure-model) and the block time for block verification. +* Evidence validity is determined [either in terms of heights or in terms of time](https://github.com/cometbft/cometbft/blob/main/spec/consensus/evidence.md#verification). +* Unbonding of staked assets in the Cosmos Hub [occurs after a period of 21 days](https://github.com/cosmos/governance/blob/ce75de4019b0129f6efcbb0e752cd2cc9e6136d3/params-change/Staking.md#unbondingtime). +* IBC packets can use either a [timestamp or a height to timeout packet delivery](https://docs.cosmos.network/v0.45/ibc/overview.html#acknowledgements) + +Finally, inflation distribution in the Cosmos Hub uses an approximation of time to calculate an annual percentage rate. +This approximation of time is calculated using [block heights with an estimated number of blocks produced in a year](https://github.com/cosmos/governance/blob/master/params-change/Mint.md#blocksperyear). +Proposer-based timestamps will allow this inflation calculation to use a more meaningful and accurate source of time. + +## Decision + +Implement Proposer-Based Timestamps while maintaining backwards compatibility with `BFT Time`. + +## Detailed Design + +### Overview + +Implementing Proposer-Based Timestamps (PBTS) will require a few changes to CometBFT’s code. +These changes will be to the following components: + +* The consensus parameters. +* The `internal/consensus/` package. +* The `internal/state/` package. + +The original version of this document ([ADR 071][original-adr]) dir not +consider that the introduced `PBTS` and the previous method `BFT Time` could +be adopted in the same chain/network. +The [backwards compatibility](#backwards-compatibility) section below was thus +added to address topic. + + + +### Backwards compatibility + +In order to ensure backwards compatibility, PBTS should be enabled using a [consensus parameter](#compatibility-parameters). +The proposed approach is similar to the one adopted to enable vote extensions via +[`VoteExtensionsEnableHeight`](https://github.com/cometbft/cometbft/blob/main/spec/abci/abci++_app_requirements.md#featureparamsvoteextensionsenableheight). + +In summary, the network will migrate from the `BFT Time` method for assigning +and validating timestamps to the new method for assigning and validating +timestamps adopted by `PBTS` from a given, configurable height. +Once `PBTS` is activated, there are no provisions for the network to revert +back to `BFT Time` (see [issue 2063][issue2063]). + +Moreover, when compared to the original ([ADR 071][original-adr]), we will **NOT**: + +- Update `CommitSigs` and `Vote` types, removing the `Timestamp` field +- Remove the `MedianTime` method used by `BFT Time` to produce and validate the block's time +- Remove the `voteTime` method used by `BFT Time` to set timestamps to precommits +- Remove the [validation logic](#current-block-time-validation-logic) used by `BFT Time` + +### New consensus parameters + +The PBTS specification includes some new parameters that must be the same among across all validators. +The set of [consensus parameters](https://github.com/cometbft/cometbft/blob/main/proto/cometbft/types/v1/params.proto#L13) +will be updated to include new fields as follows: + +```diff +type ConsensusParams struct { + Block BlockParams `json:"block"` + Evidence EvidenceParams `json:"evidence"` + Validator ValidatorParams `json:"validator"` + Version VersionParams `json:"version"` + ABCI ABCIParams `json:"abci"` +++ Synchrony SynchronyParams `json:"synchrony"` +++ Feature FeatureParams `json:"feature"` +} +``` + +#### Synchrony parameters + +The `PRECISION` and `MSGDELAY` parameters are used to determine if the proposed timestamp is acceptable. +A validator will only Prevote a proposal if the proposal timestamp is considered `timely`. +A proposal timestamp is considered `timely` if it is within `PRECISION` and `MSGDELAY` of the Unix time known to the validator. +More specifically, the timestamp of a proposal received at `proposalReceiveTime` is `timely` if + + proposalTimestamp - PRECISION ≤ proposalReceiveTime ≤ proposalTimestamp + PRECISION + MSGDELAY + +`PRECISION` and `MSGDELAY` will be added to the consensus synchrony parameters as [durations](https://protobuf.dev/reference/protobuf/google.protobuf/#duration): + +```go +type SynchronyParams struct { + Precision time.Duration `json:"precision,string"` + MessageDelay time.Duration `json:"message_delay,string"` +} +``` + +#### Compatibility parameters + +In order to ensure backwards compatibility, PBTS should be enabled using a consensus parameter: + +```go +type FeatureParams struct { + PbtsEnableHeight int64 `json:"pbts_enable_height"` + ... +} +``` + +The semantics are similar to the ones adopted to enable vote extensions via +[`VoteExtensionsEnableHeight`](https://github.com/cometbft/cometbft/blob/main/spec/abci/abci++_app_requirements.md#abciparamsvoteextensionsenableheight). +The PBTS algorithm is enabled from `FeatureParams.PbtsEnableHeight`, when this +parameter is set to a value greater than zero, and greater to the height at +which it was set. +Until that height, the BFT Time algorithm is used. + +For more discussion of this, see [issue 2197][issue2197]. + + +### Changes to the block proposal step + +#### Proposer selects block timestamp + +CometBFT currently uses the `BFT Time` algorithm to produce the block's `Header.Timestamp`. +The [block production logic](https://github.com/cometbft/cometbft/blob/1f430f51f0e390cd7c789ba9b1e9b35846e34642/internal/state/state.go#L248) +sets the weighted median of the times in the `LastCommit.CommitSigs` as the proposed block's `Header.Timestamp`. +This method will be preserved, but it is only used while operating in `BFT Time` mode. + +In PBTS, the proposer will still set a timestamp into the `Header.Timestamp`. +The timestamp the proposer sets into the `Header` will change depending on whether the block has previously received `2/3+` prevotes in a previous round. +Receiving +2/3 prevotes in a round is frequently referred to as a 'Polka' and we will use this term for simplicity. + +#### Proposal of a block that has not previously received a Polka + +If a proposer is proposing a new block then it will set the Unix time currently known to the proposer into the `Header.Timestamp` field. +The proposer will also set this same timestamp into the `Timestamp` field of the `Proposal` message that it issues. + +#### Re-proposal of a block that has previously received a Polka + +If a proposer is re-proposing a block that has previously received a Polka on the network, then the proposer does not update the `Header.Timestamp` of that block. +Instead, the proposer simply re-proposes the exact same block. +This way, the proposed block has the exact same block ID as the previously proposed block and the nodes that have already received that block do not need to attempt to receive it again. + +The proposer will set the re-proposed block's `Header.Timestamp` as the `Proposal` message's `Timestamp`. + +#### Proposer waits + +Block timestamps must be monotonically increasing. +In `BFT Time`, if a validator’s clock was behind, the [validator added 1 millisecond to the previous block’s time and used that in its vote messages](https://github.com/cometbft/cometbft/blob/1f430f51f0e390cd7c789ba9b1e9b35846e34642/internal/consensus/state.go#L2460). +A goal of adding PBTS is to enforce some degree of clock synchronization, so having a mechanism that completely ignores the Unix time of the validator time no longer works. +Validator clocks will not be perfectly in sync. +Therefore, the proposer’s current known Unix time may be less than the previous block's `Header.Time`. +If the proposer’s current known Unix time is less than the previous block's `Header.Time`, the proposer will sleep until its known Unix time exceeds it. + +This change will require amending the [`defaultDecideProposal`](https://github.com/cometbft/cometbft/blob/1f430f51f0e390cd7c789ba9b1e9b35846e34642/internal/consensus/state.go#L1195) method. +This method should now schedule a timeout that fires when the proposer’s time is greater than the previous block's `Header.Time`. +When the timeout fires, the proposer will finally issue the `Proposal` message. + +### Changes to proposal validation rules + +The rules for validating a proposed block will be modified to implement PBTS. +We will change the validation logic to ensure that a proposal is `timely`. +The `timely` verification is adopted once the node enabled PBTS. + +Per the PBTS spec, `timely` only needs to be checked if a block has not received a Polka in a previous round. +If a block previously received a +2/3 majority of prevotes in a round, then +2/3 of the voting power considered the block's timestamp near enough to their own currently known Unix time in that round. + +The validation logic will be updated to check `timely` for blocks that did not previously receive a Polka in a round. + +#### Timestamp validation when a block has not received a Polka + +The [`POLRound`](https://github.com/cometbft/cometbft/blob/1f430f51f0e390cd7c789ba9b1e9b35846e34642/types/proposal.go#L29) in the `Proposal` message indicates which round the block received a Polka. +A negative value in the `POLRound` field indicates that the block has not previously been proposed on the network. +Therefore the validation logic will check for timely when `POLRound == -1`. + +When a node receives a `Proposal` message, it records it `proposalReceiveTime` as the current Unix time known to the node. +The node will check that the `Proposal.Timestamp` is at most `PRECISION` greater than `proposalReceiveTime`, and at maximum `PRECISION + MSGDELAY` less than `proposalReceiveTime`. +If the timestamp is not within these bounds, the proposed block will not be considered `timely`. +A validator prevotes nil when the proposed block is not considered `timely`. + +Once a full block matching the `Proposal` message is received, the node will also check that the timestamp in the `Header.Timestamp` of the block matches this `Proposal.Timestamp`. +Using the `Proposal.Timestamp` to check `timely` allows for the `MSGDELAY` parameter to be more finely tuned since `Proposal` messages do not change sizes and are therefore faster to gossip than full blocks across the network. + +A node will also check that the proposed timestamp is greater than the timestamp of the block for the previous height. +If the timestamp is not greater than the previous block's timestamp, the block will not be considered valid, which is the same as the current logic. + +#### Timestamp validation when a block has received a Polka + +When a block is re-proposed that has already received a +2/3 majority of `Prevote`s (i.e., a Polka) on the network, the `Proposal` message for the re-proposed block is created with a `POLRound` that is `>= 0`. +A node will not check that the `Proposal` is `timely` if the proposal message has a non-negative `POLRound`. +If the `POLRound` is non-negative, each node (although this is only relevant for validators) will simply ensure that it received the `Prevote` messages for the proposed block in the round indicated by `POLRound`. + +If the node is a validator and it does not receive `Prevote` messages for the proposed block before the proposal timeout, then it will prevote nil. +Validators already check that +2/3 prevotes were seen in `POLRound`, so this does not represent a change to the prevote logic. + +A node will also check that the proposed timestamp is greater than the timestamp of the block for the previous height. +If the timestamp is not greater than the previous block's timestamp, the block will not be considered valid, which is the same as the current logic. + +Additionally, this validation logic can be updated to check that the `Proposal.Timestamp` matches the `Header.Timestamp` of the proposed block, but it is less relevant since checking that votes were received is sufficient to ensure the block timestamp is correct. + +#### Relaxation of the 'Timely' check + +The `Synchrony` parameters, `MessageDelay` and `Precision` provide a means to bound the timestamp of a proposed block. +Selecting values that are too small presents a possible liveness issue for the network. +If a CometBFT network selects a `MessageDelay` parameter that does not accurately reflect the time to broadcast a proposal message to all of the validators on the network, validators will begin rejecting proposals from otherwise correct proposers because these proposals will appear to be too far in the past. + +`MessageDelay` and `Precision` are planned to be configured as `ConsensusParams`. +A very common way to update `ConsensusParams` is by executing a transaction included in a block that specifies new values for them. +However, if the network is unable to produce blocks because of this liveness issue, no such transaction may be executed. +To prevent this dangerous condition, we will add a relaxation mechanism to the `Timely` predicate. + +The chosen solution for this issue is to adopt the configured `MessageDelay` +for the first round (0) of consensus. +Then, as more rounds are needed to commit a value, we increase the +adopted value for `MessageDelay`, at a rate of 10% per additional round. +More precisely, the `MessageDelay(r)` adopted for round `r` of consensus is +given by `MessageDelay(r) = MessageDelay * (1.1)^r`. +Of course, `MessageDelay(0) = MessageDelay`. + +This liveness issue is not as problematic for chains with very small `Precision` values. +Operators can more easily readjust local validator clocks to be more aligned. +Additionally, chains that wish to increase a small `Precision` value can still take advantage of the `MessageDelay` relaxation, waiting for the `MessageDelay` value to grow significantly and issuing proposals with timestamps that are far in the past of their peers. + +For more discussion of this, see [issue 2184][issue2184]. + +### Changes to the prevote step + +Currently, a validator will prevote a proposal in one of three cases: + +* Case 1: Validator has no locked block and receives a valid proposal. +* Case 2: Validator has a locked block and receives a valid proposal matching its locked block. +* Case 3: Validator has a locked block, sees a valid proposal not matching its locked block but sees +2/3 prevotes for the proposal’s block, either in the current round or in a round greater than or equal to the round in which it locked its locked block. + +The only change we will make to the prevote step is to what a validator considers a valid proposal as detailed above. + +### Changes to the precommit step + +The precommit step will not require much modification. +Its proposal validation rules will change in the same ways that validation will change in the prevote step with the exception of the `timely` check: precommit validation will never check that the timestamp is `timely`. + + + +### Changes to the block validation + +To provide a better understanding of the changes needed for timestamp validation, we first detail how timestamp validation works currently with BFT Time, +then presents how it will work with PBTS. + +#### Current block time validation logic + +The [`validateBlock` function](https://github.com/cometbft/cometbft/blob/1f430f51f0e390cd7c789ba9b1e9b35846e34642/internal/state/validation.go#L15) currently [validates the proposed block timestamp in three ways](https://github.com/cometbft/cometbft/blob/1f430f51f0e390cd7c789ba9b1e9b35846e34642/internal/state/validation.go#L116). +First, the validation logic checks that this timestamp is greater than the previous block’s timestamp. + +Second, it validates that the block timestamp is correctly calculated as the weighted median of the timestamps in the [block’s `LastCommit`](https://github.com/cometbft/cometbft/blob/1f430f51f0e390cd7c789ba9b1e9b35846e34642/types/block.go#L49). + +Finally, the validation logic authenticates the timestamps in the `LastCommit.CommitSig`. +The cryptographic signature in each `CommitSig` is created by signing a hash of fields in the block with the voting validator’s private key. +One of the items in this `signedBytes` hash is the timestamp in the `CommitSig`. +To authenticate the `CommitSig` timestamp, the node authenticating votes builds a hash of fields that includes the `CommitSig` timestamp and checks this hash against the signature. +This takes place in the [`VerifyCommit` function](https://github.com/cometbft/cometbft/blob/1f430f51f0e390cd7c789ba9b1e9b35846e34642/types/validation.go#L26). + + + +#### PBTS block time validation + +PBTS does not perform a validation of the timestamp of a block, as part of the `validateBlock` method. +This means that nodes will no longer check that the block time is a weighted median of `LastCommit` timestamps. + +Instead of validating the timestamp of proposed blocks, +PBTS validates the timestamp of the `Proposal` message for a block, as detailed [here](#changes-to-proposal-validation-rules). +Notice that the `Proposal` timestamp must match the proposed block's `Time` field. + +This also means that committed blocks, retrieved from peers via consensus catch-up mechanisms or via block sync, +will not have their timestamps validated, since the timestamp validation is now part of the consensus logic. + + +## Future Improvements + +* Implement BLS signature aggregation. +If we remove the `Timestamp` field from the `Precommit` messages, we are able to aggregate signatures, +as votes for the same block, height and round become identical. + +We have left the removal of the `Timestamp` field of vote messages out for the time being, as it would break the block format and validation +rules (signature verification) and thus may force a hard-fork on chains upgrading to the latest version of CometBFT. +We will remove the timestamps in votes when changing the block format is supported in CometBFT without +requiring a hard-fork (this feature is called [Soft Upgrades](https://github.com/cometbft/cometbft/issues/122)). + +## Consequences + +### Positive + +* `<2/3` of validators can no longer arbitrarily influence block timestamps. +* Block timestamps will have stronger correspondence to real time. +* Improves the reliability of [components](#remove-timestamps-altogether) that rely on block timestamps: + Light Client verification, Evidence validity, Unbonding of staked assets, IBC packet timeouts, inflation distribution, etc. +* It is a step towards enabling BLS signature aggregation. + +### Neutral + +* Alters the liveness requirements for the consensus algorithm. +Liveness now requires that all correct validators have synchronized clocks, with inaccuracy bound by `PRECISION`, +and that end-to-end delays of `PROPOSAL` messages are bound by `MSGDELAY`. + +### Negative + +* May increase the duration of the propose step if there is a large skew between the clocks of the previous proposer and the current proposer. +The clock skew between correct validators is supposed to be bound by `PRECISION`, so this impact is relevant when block times are shorter than `PRECISION`. +* Existing chains that adopt PBTS may have block times far in the future, which may cause the transition height to have a very long duration (to preserve time monotonicity). +The workaround in this case is, first, to synchronize the validators' clocks, then to maintain the legacy operation (using BFT Time), until block times align with real time. +At this point, the transition from BFT Time to PBTS should be smooth. + +## References + +* [PBTS Spec][pbts-spec] +* [BFT Time spec][bfttime] +* [PBTS: support both PBTS and legacy BFT Time #2063][issue2063] +* [PBTS: should synchrony parameters be adaptive? #2184][issue2184] + +[issue2184]: https://github.com/cometbft/cometbft/issues/2184 +[issue2197]: https://github.com/cometbft/cometbft/issues/2197 +[issue2063]: https://github.com/cometbft/cometbft/issues/2063 +[bfttime]: https://github.com/cometbft/cometbft/blob/main/spec/consensus/bft-time.md +[pbts-spec]: https://github.com/cometbft/cometbft/tree/main/spec/consensus/proposer-based-timestamp/README.md +[original-adr]: https://github.com/cometbft/cometbft/blob/main/docs/references/architecture/tendermint-core/adr-071-proposer-based-timestamps.md diff --git a/docs/architecture/adr-template.md b/docs/references/architecture/adr-template.md similarity index 100% rename from docs/architecture/adr-template.md rename to docs/references/architecture/adr-template.md diff --git a/docs/references/architecture/images/adr-102-architecture.jpeg b/docs/references/architecture/images/adr-102-architecture.jpeg new file mode 100644 index 00000000000..dd664f45c3c Binary files /dev/null and b/docs/references/architecture/images/adr-102-architecture.jpeg differ diff --git a/docs/references/architecture/tendermint-core/README.md b/docs/references/architecture/tendermint-core/README.md new file mode 100644 index 00000000000..89de0c19440 --- /dev/null +++ b/docs/references/architecture/tendermint-core/README.md @@ -0,0 +1,105 @@ +--- +order: 1 +parent: + order: false +--- + +# Tendermint Core Architecture Decision Records (ADR) + +Here we record all high-level architecture decisions in the Tendermint Core +project. All implemented ADRs in this list naturally affect CometBFT, since +CometBFT is a fork of Tendermint Core as of December 2022. + +This list is currently frozen and kept for reference purposes. To add new ADRs, +please do so for CometBFT [here](../). + +## Table of Contents + +### Implemented + +- [ADR-001: Logging](adr-001-logging.md) +- [ADR-002: Event-Subscription](adr-002-event-subscription.md) +- [ADR-003: ABCI-APP-RPC](adr-003-abci-app-rpc.md) +- [ADR-004: Historical-Validators](adr-004-historical-validators.md) +- [ADR-005: Consensus-Params](adr-005-consensus-params.md) +- [ADR-008: Priv-Validator](adr-008-priv-validator.md) +- [ADR-009: ABCI-Design](adr-009-ABCI-design.md) +- [ADR-010: Crypto-Changes](adr-010-crypto-changes.md) +- [ADR-011: Monitoring](adr-011-monitoring.md) +- [ADR-014: Secp-Malleability](adr-014-secp-malleability.md) +- [ADR-015: Crypto-Encoding](adr-015-crypto-encoding.md) +- [ADR-016: Protocol-Versions](adr-016-protocol-versions.md) +- [ADR-017: Chain-Versions](adr-017-chain-versions.md) +- [ADR-018: ABCI-Validators](adr-018-ABCI-Validators.md) +- [ADR-019: Multisigs](adr-019-multisigs.md) +- [ADR-020: Block-Size](adr-020-block-size.md) +- [ADR-021: ABCI-Events](adr-021-abci-events.md) +- [ADR-025: Commit](adr-025-commit.md) +- [ADR-026: General-Merkle-Proof](adr-026-general-merkle-proof.md) +- [ADR-033: Pubsub](adr-033-pubsub.md) +- [ADR-034: Priv-Validator-File-Structure](adr-034-priv-validator-file-structure.md) +- [ADR-043: Blockchain-RiRi-Org](adr-043-blockchain-riri-org.md) +- [ADR-044: Lite-Client-With-Weak-Subjectivity](adr-044-lite-client-with-weak-subjectivity.md) +- [ADR-046: Light-Client-Implementation](adr-046-light-client-implementation.md) +- [ADR-047: Handling-Evidence-From-Light-Client](adr-047-handling-evidence-from-light-client.md) +- [ADR-051: Double-Signing-Risk-Reduction](adr-051-double-signing-risk-reduction.md) +- [ADR-052: Tendermint-Mode](adr-052-tendermint-mode.md) +- [ADR-053: State-Sync-Prototype](adr-053-state-sync-prototype.md) +- [ADR-054: Crypto-Encoding-2](adr-054-crypto-encoding-2.md) +- [ADR-055: Protobuf-Design](adr-055-protobuf-design.md) +- [ADR-056: Light-Client-Amnesia-Attacks](adr-056-light-client-amnesia-attacks.md) +- [ADR-059: Evidence-Composition-and-Lifecycle](adr-059-evidence-composition-and-lifecycle.md) +- [ADR-065: Custom Event Indexing](adr-065-custom-event-indexing.md) +- [ADR-066: E2E-Testing](adr-066-e2e-testing.md) +- [ADR-072: Restore Requests for Comments](adr-072-request-for-comments.md) +- [ADR-076: Combine Spec and Tendermint Repositories](adr-076-combine-spec-repo.md) +- [ADR-077: Configurable Block Retention](adr-077-block-retention.md) +- [ADR-078: Non-zero Genesis](adr-078-nonzero-genesis.md) + +### Accepted + +- [ADR-006: Trust-Metric](adr-006-trust-metric.md) +- [ADR-024: Sign-Bytes](adr-024-sign-bytes.md) +- [ADR-039: Peer-Behaviour](adr-039-peer-behaviour.md) +- [ADR-063: Privval-gRPC](adr-063-privval-grpc.md) +- [ADR-067: Mempool Refactor](adr-067-mempool-refactor.md) +- [ADR-071: Proposer-Based Timestamps](adr-071-proposer-based-timestamps.md) +- [ADR-075: RPC Event Subscription Interface](adr-075-rpc-subscription.md) +- [ADR-079: Ed25519 Verification](adr-079-ed25519-verification.md) +- [ADR-081: Protocol Buffers Management](adr-081-protobuf-mgmt.md) + +### Deprecated + +- [ADR-035: Documentation](adr-035-documentation.md) + +### Rejected + +- [ADR-023: ABCI-Propose-tx](adr-023-ABCI-propose-tx.md) +- [ADR-029: Check-Tx-Consensus](adr-029-check-tx-consensus.md) +- [ADR-058: Event-Hashing](adr-058-event-hashing.md) + +### Proposed + +- [ADR-007: Trust-Metric-Usage](adr-007-trust-metric-usage.md) +- [ADR-012: Peer-Transport](adr-012-peer-transport.md) +- [ADR-013: Symmetric-Crypto](adr-013-symmetric-crypto.md) +- [ADR-022: ABCI-Errors](adr-022-abci-errors.md) +- [ADR-030: Consensus-Refactor](adr-030-consensus-refactor.md) +- [ADR-036: Empty Blocks via ABCI](adr-036-empty-blocks-abci.md) +- [ADR-037: Deliver-Block](adr-037-deliver-block.md) +- [ADR-038: Non-Zero-Start-Height](adr-038-non-zero-start-height.md) +- [ADR-040: Blockchain Reactor Refactor](adr-040-blockchain-reactor-refactor.md) +- [ADR-041: Proposer-Selection-via-ABCI](adr-041-proposer-selection-via-abci.md) +- [ADR-042: State Sync Design](adr-042-state-sync.md) +- [ADR-045: ABCI-Evidence](adr-045-abci-evidence.md) +- [ADR-050: Improved Trusted Peering](adr-050-improved-trusted-peering.md) +- [ADR-057: RPC](adr-057-RPC.md) +- [ADR-060: Go-API-Stability](adr-060-go-api-stability.md) +- [ADR-061: P2P-Refactor-Scope](adr-061-p2p-refactor-scope.md) +- [ADR-062: P2P-Architecture](adr-062-p2p-architecture.md) +- [ADR-064: Batch Verification](adr-064-batch-verification.md) +- [ADR-068: Reverse-Sync](adr-068-reverse-sync.md) +- [ADR-069: Node Initialization](adr-069-flexible-node-initialization.md) +- [ADR-073: Adopt LibP2P](adr-073-libp2p.md) +- [ADR-074: Migrate Timeout Parameters to Consensus Parameters](adr-074-timeout-params.md) +- [ADR-080: Reverse Sync](adr-080-reverse-sync.md) diff --git a/docs/architecture/tendermint-core/adr-001-logging.md b/docs/references/architecture/tendermint-core/adr-001-logging.md similarity index 100% rename from docs/architecture/tendermint-core/adr-001-logging.md rename to docs/references/architecture/tendermint-core/adr-001-logging.md diff --git a/docs/architecture/tendermint-core/adr-002-event-subscription.md b/docs/references/architecture/tendermint-core/adr-002-event-subscription.md similarity index 100% rename from docs/architecture/tendermint-core/adr-002-event-subscription.md rename to docs/references/architecture/tendermint-core/adr-002-event-subscription.md diff --git a/docs/architecture/tendermint-core/adr-003-abci-app-rpc.md b/docs/references/architecture/tendermint-core/adr-003-abci-app-rpc.md similarity index 100% rename from docs/architecture/tendermint-core/adr-003-abci-app-rpc.md rename to docs/references/architecture/tendermint-core/adr-003-abci-app-rpc.md diff --git a/docs/architecture/tendermint-core/adr-004-historical-validators.md b/docs/references/architecture/tendermint-core/adr-004-historical-validators.md similarity index 100% rename from docs/architecture/tendermint-core/adr-004-historical-validators.md rename to docs/references/architecture/tendermint-core/adr-004-historical-validators.md diff --git a/docs/architecture/tendermint-core/adr-005-consensus-params.md b/docs/references/architecture/tendermint-core/adr-005-consensus-params.md similarity index 100% rename from docs/architecture/tendermint-core/adr-005-consensus-params.md rename to docs/references/architecture/tendermint-core/adr-005-consensus-params.md diff --git a/docs/architecture/tendermint-core/adr-006-trust-metric.md b/docs/references/architecture/tendermint-core/adr-006-trust-metric.md similarity index 95% rename from docs/architecture/tendermint-core/adr-006-trust-metric.md rename to docs/references/architecture/tendermint-core/adr-006-trust-metric.md index 608978207be..04d4a208dcc 100644 --- a/docs/architecture/tendermint-core/adr-006-trust-metric.md +++ b/docs/references/architecture/tendermint-core/adr-006-trust-metric.md @@ -36,7 +36,7 @@ where _R_[*i*] denotes the raw trust value at time interval _i_ (where _i_ == 0 `H[i] =` ![formula1](img/formula1.png "Weighted Sum Formula") -The weights can be chosen either optimistically or pessimistically. An optimistic weight creates larger weights for newer history data values, while the the pessimistic weight creates larger weights for time intervals with lower scores. The default weights used during the calculation of the history value are optimistic and calculated as _Wk_ = 0.8^_k_, for time interval _k_. With the history value available, we can now finish calculating the integral value: +The weights can be chosen either optimistically or pessimistically. An optimistic weight creates larger weights for newer history data values, while the pessimistic weight creates larger weights for time intervals with lower scores. The default weights used during the calculation of the history value are optimistic and calculated as _Wk_ = 0.8^_k_, for time interval _k_. With the history value available, we can now finish calculating the integral value: ```math (2) Integral Value = b * H[i] @@ -110,7 +110,7 @@ func (tm *TrustMetric) TrustScore() int {} // NewMetric returns a trust metric with the default configuration func NewMetric() *TrustMetric {} -//------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ // For example tm := NewMetric() @@ -148,7 +148,7 @@ func DefaultConfig() TrustMetricConfig {} // NewMetricWithConfig returns a trust metric with a custom configuration func NewMetricWithConfig(tmc TrustMetricConfig) *TrustMetric {} -//------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ // For example config := TrustMetricConfig{ @@ -196,7 +196,7 @@ func (tms *TrustMetricStore) GetPeerTrustMetric(key string) *TrustMetric {} // PeerDisconnected pauses the trust metric associated with the peer identified by the key func (tms *TrustMetricStore) PeerDisconnected(key string) {} -//------------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------------ // For example db := dbm.NewDB("trusthistory", "goleveldb", dirPathStr) diff --git a/docs/architecture/tendermint-core/adr-007-trust-metric-usage.md b/docs/references/architecture/tendermint-core/adr-007-trust-metric-usage.md similarity index 100% rename from docs/architecture/tendermint-core/adr-007-trust-metric-usage.md rename to docs/references/architecture/tendermint-core/adr-007-trust-metric-usage.md diff --git a/docs/architecture/tendermint-core/adr-008-priv-validator.md b/docs/references/architecture/tendermint-core/adr-008-priv-validator.md similarity index 100% rename from docs/architecture/tendermint-core/adr-008-priv-validator.md rename to docs/references/architecture/tendermint-core/adr-008-priv-validator.md diff --git a/docs/architecture/tendermint-core/adr-009-ABCI-design.md b/docs/references/architecture/tendermint-core/adr-009-ABCI-design.md similarity index 99% rename from docs/architecture/tendermint-core/adr-009-ABCI-design.md rename to docs/references/architecture/tendermint-core/adr-009-ABCI-design.md index 3876ffb3de6..fc4592a896e 100644 --- a/docs/architecture/tendermint-core/adr-009-ABCI-design.md +++ b/docs/references/architecture/tendermint-core/adr-009-ABCI-design.md @@ -118,7 +118,7 @@ v1 will: style union types. That said, an Amino v2 will be worked on to improve the performance of the -format and its useability in cryptographic applications. +format and its usability in cryptographic applications. ### PubKey diff --git a/docs/architecture/tendermint-core/adr-010-crypto-changes.md b/docs/references/architecture/tendermint-core/adr-010-crypto-changes.md similarity index 97% rename from docs/architecture/tendermint-core/adr-010-crypto-changes.md rename to docs/references/architecture/tendermint-core/adr-010-crypto-changes.md index 41d15da354f..b4f7055e8ba 100644 --- a/docs/architecture/tendermint-core/adr-010-crypto-changes.md +++ b/docs/references/architecture/tendermint-core/adr-010-crypto-changes.md @@ -4,7 +4,7 @@ Tendermint is a cryptographic protocol that uses and composes a variety of cryptographic primitives. -After nearly 4 years of development, Tendermint has recently undergone multiple security reviews to search for vulnerabilities and to assess the the use and composition of cryptographic primitives. +After nearly 4 years of development, Tendermint has recently undergone multiple security reviews to search for vulnerabilities and to assess the use and composition of cryptographic primitives. ### Hash Functions diff --git a/docs/architecture/tendermint-core/adr-011-monitoring.md b/docs/references/architecture/tendermint-core/adr-011-monitoring.md similarity index 100% rename from docs/architecture/tendermint-core/adr-011-monitoring.md rename to docs/references/architecture/tendermint-core/adr-011-monitoring.md diff --git a/docs/architecture/tendermint-core/adr-012-peer-transport.md b/docs/references/architecture/tendermint-core/adr-012-peer-transport.md similarity index 97% rename from docs/architecture/tendermint-core/adr-012-peer-transport.md rename to docs/references/architecture/tendermint-core/adr-012-peer-transport.md index 1cf4fb80b81..3351a9ff466 100644 --- a/docs/architecture/tendermint-core/adr-012-peer-transport.md +++ b/docs/references/architecture/tendermint-core/adr-012-peer-transport.md @@ -13,7 +13,7 @@ Addresses: - [#2046](https://github.com/tendermint/tendermint/issues/2046) - [#2047](https://github.com/tendermint/tendermint/issues/2047) -First iteraton in [#2067](https://github.com/tendermint/tendermint/issues/2067) +First iteration in [#2067](https://github.com/tendermint/tendermint/issues/2067) ## Decision diff --git a/docs/architecture/tendermint-core/adr-013-symmetric-crypto.md b/docs/references/architecture/tendermint-core/adr-013-symmetric-crypto.md similarity index 95% rename from docs/architecture/tendermint-core/adr-013-symmetric-crypto.md rename to docs/references/architecture/tendermint-core/adr-013-symmetric-crypto.md index 69bfc2f2901..76ee0387e7d 100644 --- a/docs/architecture/tendermint-core/adr-013-symmetric-crypto.md +++ b/docs/references/architecture/tendermint-core/adr-013-symmetric-crypto.md @@ -24,7 +24,7 @@ We currently construct a random nonce, and encrypt the data with it. The returned value is `nonce || encrypted data`. The limitation of this is that does not provide a way to identify which algorithm was used in encryption. -Consequently decryption with multiple algoritms is sub-optimal. +Consequently decryption with multiple algorithms is sub-optimal. (You have to try them all) ## Decision @@ -46,7 +46,7 @@ but I don't really see this as an issue. If there is no error in encryption, Encrypt will return `algo_name || nonce || aead_ciphertext`. `algo_name` should be length prefixed, using standard varuint encoding. -This will be binary data, but thats not a problem considering the nonce and ciphertext are also binary. +This will be binary data, but that's not a problem considering the nonce and ciphertext are also binary. This solution requires a mapping from aead type to name. We can achieve this via reflection. diff --git a/docs/architecture/tendermint-core/adr-014-secp-malleability.md b/docs/references/architecture/tendermint-core/adr-014-secp-malleability.md similarity index 100% rename from docs/architecture/tendermint-core/adr-014-secp-malleability.md rename to docs/references/architecture/tendermint-core/adr-014-secp-malleability.md diff --git a/docs/architecture/tendermint-core/adr-015-crypto-encoding.md b/docs/references/architecture/tendermint-core/adr-015-crypto-encoding.md similarity index 100% rename from docs/architecture/tendermint-core/adr-015-crypto-encoding.md rename to docs/references/architecture/tendermint-core/adr-015-crypto-encoding.md diff --git a/docs/architecture/tendermint-core/adr-016-protocol-versions.md b/docs/references/architecture/tendermint-core/adr-016-protocol-versions.md similarity index 97% rename from docs/architecture/tendermint-core/adr-016-protocol-versions.md rename to docs/references/architecture/tendermint-core/adr-016-protocol-versions.md index e52743e5ca3..e547053cbaa 100644 --- a/docs/architecture/tendermint-core/adr-016-protocol-versions.md +++ b/docs/references/architecture/tendermint-core/adr-016-protocol-versions.md @@ -18,7 +18,7 @@ - 03-08-2018: Updates from discussion with Jae: - ProtocolVersion contains Block/AppVersion, not Current/Next - signal upgrades to Tendermint using EndBlock fields - - dont restrict peer compatibilty by version to simplify syncing old nodes + - dont restrict peer compatibility by version to simplify syncing old nodes - 28-07-2018: Updates from review - split into two ADRs - one for protocol, one for chains - include signalling for upgrades in header @@ -53,7 +53,7 @@ as described below. The BlockVersion defines the core of the blockchain data structures and should change infrequently. -The P2PVersion defines how peers connect and communicate with eachother - it's +The P2PVersion defines how peers connect and communicate with each other - it's not part of the blockchain data structures, but defines the protocols used to build the blockchain. It may change gradually. @@ -227,7 +227,7 @@ BlockVersion is included in both the Header and the NodeInfo. Changing BlockVersion should happen quite infrequently and ideally only for critical upgrades. For now, it is not encoded in ABCI, though it's always -possible to use tags to signal an external process to co-ordinate an upgrade. +possible to use tags to signal an external process to coordinate an upgrade. Note Ethereum has not had to make an upgrade like this (everything has been at state machine level, AFAIK). @@ -268,12 +268,12 @@ help old peers, possibly on older versions, sync the blockchain. We might be tempted to say that we only connect to peers with the same AppVersion and BlockVersion (since these define the consensus critical computations), and a select list of P2PVersions (ie. those compatible with -ours), but then we'd need to make accomodations for connecting to peers with the +ours), but then we'd need to make accommodations for connecting to peers with the right Block/AppVersion for the height they're on. For now, we will connect to peers with any version and restrict compatibility solely based on the ChainID. We leave more restrictive rules on peer -compatibiltiy to a future proposal. +compatibility to a future proposal. ### Future Changes diff --git a/docs/architecture/tendermint-core/adr-017-chain-versions.md b/docs/references/architecture/tendermint-core/adr-017-chain-versions.md similarity index 97% rename from docs/architecture/tendermint-core/adr-017-chain-versions.md rename to docs/references/architecture/tendermint-core/adr-017-chain-versions.md index 7113dbaee76..99360a45e42 100644 --- a/docs/architecture/tendermint-core/adr-017-chain-versions.md +++ b/docs/references/architecture/tendermint-core/adr-017-chain-versions.md @@ -82,7 +82,7 @@ Define `ChainID = TMHASH(ChainDescriptor)`. It's the unique ID of a blockchain. It should be Bech32 encoded when handled by users, eg. with `cosmoschain` prefix. -#### Forks and Uprades +#### Forks and Upgrades When a chain forks or upgrades but continues the same history, it takes a new ChainDescription as follows: @@ -93,7 +93,7 @@ ChainDescription = /x// Where - ChainID is the ChainID from the previous ChainDescription (ie. its hash) -- `x` denotes that a change occured -- `Height` is the height the change occured +- `x` denotes that a change occurred +- `Height` is the height the change occurred - ForkDescription has the same form as ChainDescription but for the fork - this allows forks to specify new versions for tendermint or the app, as well as arbitrary changes to the state or validator set diff --git a/docs/architecture/tendermint-core/adr-018-ABCI-Validators.md b/docs/references/architecture/tendermint-core/adr-018-ABCI-Validators.md similarity index 100% rename from docs/architecture/tendermint-core/adr-018-ABCI-Validators.md rename to docs/references/architecture/tendermint-core/adr-018-ABCI-Validators.md diff --git a/docs/architecture/tendermint-core/adr-019-multisigs.md b/docs/references/architecture/tendermint-core/adr-019-multisigs.md similarity index 98% rename from docs/architecture/tendermint-core/adr-019-multisigs.md rename to docs/references/architecture/tendermint-core/adr-019-multisigs.md index 7fd3aab0acf..31541c328b3 100644 --- a/docs/architecture/tendermint-core/adr-019-multisigs.md +++ b/docs/references/architecture/tendermint-core/adr-019-multisigs.md @@ -19,7 +19,7 @@ This allows for complex conditionals of when to validate a signature. Suppose the set of signers is of size _n_. If we validate a signature if any subgroup of size _k_ signs a message, -this becomes what is commonly reffered to as a _k of n multisig_ in Bitcoin. +this becomes what is commonly referred to as a _k of n multisig_ in Bitcoin. This ADR specifies the encoding standard for general accountable subgroup multisignatures, k of n accountable subgroup multisignatures, and its weighted variant. diff --git a/docs/architecture/tendermint-core/adr-020-block-size.md b/docs/references/architecture/tendermint-core/adr-020-block-size.md similarity index 97% rename from docs/architecture/tendermint-core/adr-020-block-size.md rename to docs/references/architecture/tendermint-core/adr-020-block-size.md index f32ed7ab5c3..764e0085b1b 100644 --- a/docs/architecture/tendermint-core/adr-020-block-size.md +++ b/docs/references/architecture/tendermint-core/adr-020-block-size.md @@ -13,7 +13,7 @@ We currently use MaxTxs to reap txs from the mempool when proposing a block, but enforce MaxBytes when unmarshaling a block, so we could easily propose a -block thats too large to be valid. +block that's too large to be valid. We should just remove MaxTxs all together and stick with MaxBytes, and have a `mempool.ReapMaxBytes`. @@ -26,7 +26,7 @@ We could also consider using a MaxDataBytes instead of or in addition to MaxByte ## MaxBytes vs MaxDataBytes The [PR #3045](https://github.com/tendermint/tendermint/pull/3045) suggested -additional clarity/justification was necessary here, wither respect to the use +additional clarity/justification was necessary here, with respect to the use of MaxDataBytes in addition to, or instead of, MaxBytes. MaxBytes provides a clear limit on the total size of a block that requires no diff --git a/docs/architecture/tendermint-core/adr-021-abci-events.md b/docs/references/architecture/tendermint-core/adr-021-abci-events.md similarity index 100% rename from docs/architecture/tendermint-core/adr-021-abci-events.md rename to docs/references/architecture/tendermint-core/adr-021-abci-events.md diff --git a/docs/architecture/tendermint-core/adr-022-abci-errors.md b/docs/references/architecture/tendermint-core/adr-022-abci-errors.md similarity index 100% rename from docs/architecture/tendermint-core/adr-022-abci-errors.md rename to docs/references/architecture/tendermint-core/adr-022-abci-errors.md diff --git a/docs/architecture/tendermint-core/adr-023-ABCI-propose-tx.md b/docs/references/architecture/tendermint-core/adr-023-ABCI-propose-tx.md similarity index 98% rename from docs/architecture/tendermint-core/adr-023-ABCI-propose-tx.md rename to docs/references/architecture/tendermint-core/adr-023-ABCI-propose-tx.md index af8ea8b8f88..346de1315f0 100644 --- a/docs/architecture/tendermint-core/adr-023-ABCI-propose-tx.md +++ b/docs/references/architecture/tendermint-core/adr-023-ABCI-propose-tx.md @@ -47,7 +47,7 @@ explained in greater detail below. ### Solution 1: App state-based Plasma chain In this work around, the app maintains a `PlasmaStore` with a corresponding -`Keeper`. The PlasmaStore is responsible for maintaing a second, separate +`Keeper`. The PlasmaStore is responsible for maintaining a second, separate blockchain that complies with the MVP specification, including `deposit` blocks and other "internal" transactions. These "virtual" blocks are then broadcasted to the Root Chain. @@ -59,7 +59,7 @@ potentially non-deterministic, as this should not even be done in `Begin/EndBlock`, which may, as a result, break consensus guarantees. Additinoally, this has serious implications for "watchers" - independent third parties, -or even an auxilliary blockchain, responsible for ensuring that blocks recorded +or even an auxiliary blockchain, responsible for ensuring that blocks recorded on the Root Chain are consistent with the Plasma chain's. Since, in this case, the Plasma chain is inconsistent with the canonical one maintained by Tendermint Core, it seems that there exists no compact means of verifying the legitimacy of diff --git a/docs/architecture/tendermint-core/adr-024-sign-bytes.md b/docs/references/architecture/tendermint-core/adr-024-sign-bytes.md similarity index 100% rename from docs/architecture/tendermint-core/adr-024-sign-bytes.md rename to docs/references/architecture/tendermint-core/adr-024-sign-bytes.md diff --git a/docs/architecture/tendermint-core/adr-025-commit.md b/docs/references/architecture/tendermint-core/adr-025-commit.md similarity index 96% rename from docs/architecture/tendermint-core/adr-025-commit.md rename to docs/references/architecture/tendermint-core/adr-025-commit.md index a23d3803f61..e836dfbcbfe 100644 --- a/docs/architecture/tendermint-core/adr-025-commit.md +++ b/docs/references/architecture/tendermint-core/adr-025-commit.md @@ -33,7 +33,7 @@ continue to be used in the consensus reactor and elsewhere. A primary question is what should be included in the `CommitSig` beyond the signature. One current constraint is that we must include a timestamp, since -this is how we calculuate BFT time, though we may be able to change this [in the +this is how we calculate BFT time, though we may be able to change this [in the future](https://github.com/tendermint/tendermint/issues/2840). Other concerns here include: @@ -89,7 +89,7 @@ BFT time [can be mitigated](https://github.com/tendermint/tendermint/issues/2840#issuecomment-529122431). **ValidatorAddress**: we include it in the `CommitSig` for now. While this -does increase the block size unecessarily (20-bytes per validator), it has some ergonomic and debugging advantages: +does increase the block size unnecessarily (20-bytes per validator), it has some ergonomic and debugging advantages: - `Commit` contains everything necessary to reconstruct `[]Vote`, and doesn't depend on additional access to a `ValidatorSet` - Lite clients can check if they know the validators in a commit without diff --git a/docs/architecture/tendermint-core/adr-026-general-merkle-proof.md b/docs/references/architecture/tendermint-core/adr-026-general-merkle-proof.md similarity index 100% rename from docs/architecture/tendermint-core/adr-026-general-merkle-proof.md rename to docs/references/architecture/tendermint-core/adr-026-general-merkle-proof.md diff --git a/docs/architecture/tendermint-core/adr-029-check-tx-consensus.md b/docs/references/architecture/tendermint-core/adr-029-check-tx-consensus.md similarity index 98% rename from docs/architecture/tendermint-core/adr-029-check-tx-consensus.md rename to docs/references/architecture/tendermint-core/adr-029-check-tx-consensus.md index 191a0ec8ed0..52c9571c037 100644 --- a/docs/architecture/tendermint-core/adr-029-check-tx-consensus.md +++ b/docs/references/architecture/tendermint-core/adr-029-check-tx-consensus.md @@ -85,7 +85,7 @@ func (app *CounterApplication) CheckBlock(block types.Request_CheckBlock) types. } ``` -In BeginBlock, the app should restore the state to the orignal state before checking the block: +In BeginBlock, the app should restore the state to the original state before checking the block: ``` func (app *CounterApplication) DeliverTx(tx []byte) types.ResponseDeliverTx { diff --git a/docs/architecture/tendermint-core/adr-030-consensus-refactor.md b/docs/references/architecture/tendermint-core/adr-030-consensus-refactor.md similarity index 98% rename from docs/architecture/tendermint-core/adr-030-consensus-refactor.md rename to docs/references/architecture/tendermint-core/adr-030-consensus-refactor.md index 5c8c3d75431..52beb61ce97 100644 --- a/docs/architecture/tendermint-core/adr-030-consensus-refactor.md +++ b/docs/references/architecture/tendermint-core/adr-030-consensus-refactor.md @@ -4,7 +4,7 @@ One of the biggest challenges this project faces is to proof that the implementations of the specifications are correct, much like we strive to -formaly verify our alogrithms and protocols we should work towards high +formally verify our algorithms and protocols we should work towards high confidence about the correctness of our program code. One of those is the core of Tendermint - Consensus - which currently resides in the `consensus` package. Over time there has been high friction making changes to the package due to the @@ -23,10 +23,10 @@ Addresses: ## Decision To remedy these issues we plan a gradual, non-invasive refactoring of the -`consensus` package. Starting of by isolating the consensus alogrithm into +`consensus` package. Starting of by isolating the consensus algorithm into a pure function and a finite state machine to address the most pressuring issue of lack of confidence. Doing so while leaving the rest of the package in tact -and have follow-up optional changes to improve the sepration of concerns. +and have follow-up optional changes to improve the separation of concerns. ### Implementation changes @@ -111,7 +111,7 @@ func TestConsensusXXX(t *testing.T) { ) for _, e := range events { - sate, msg = Consensus(e.event, state) + state, msg = Consensus(e.event, state) // Test message expectation. if msg != e.want.message { diff --git a/docs/architecture/tendermint-core/adr-033-pubsub.md b/docs/references/architecture/tendermint-core/adr-033-pubsub.md similarity index 100% rename from docs/architecture/tendermint-core/adr-033-pubsub.md rename to docs/references/architecture/tendermint-core/adr-033-pubsub.md diff --git a/docs/architecture/tendermint-core/adr-034-priv-validator-file-structure.md b/docs/references/architecture/tendermint-core/adr-034-priv-validator-file-structure.md similarity index 100% rename from docs/architecture/tendermint-core/adr-034-priv-validator-file-structure.md rename to docs/references/architecture/tendermint-core/adr-034-priv-validator-file-structure.md diff --git a/docs/architecture/tendermint-core/adr-035-documentation.md b/docs/references/architecture/tendermint-core/adr-035-documentation.md similarity index 96% rename from docs/architecture/tendermint-core/adr-035-documentation.md rename to docs/references/architecture/tendermint-core/adr-035-documentation.md index 92cb079168a..e4c5e9e0121 100644 --- a/docs/architecture/tendermint-core/adr-035-documentation.md +++ b/docs/references/architecture/tendermint-core/adr-035-documentation.md @@ -27,7 +27,7 @@ The two points above have been implemented; the `config.js` has a Google Analyti ## Consequences -Because of the organizational seperation between Tendermint & Cosmos, there is a challenge of "what goes where" for certain aspects of documentation. +Because of the organizational separation between Tendermint & Cosmos, there is a challenge of "what goes where" for certain aspects of documentation. ### Positive diff --git a/docs/architecture/tendermint-core/adr-036-empty-blocks-abci.md b/docs/references/architecture/tendermint-core/adr-036-empty-blocks-abci.md similarity index 100% rename from docs/architecture/tendermint-core/adr-036-empty-blocks-abci.md rename to docs/references/architecture/tendermint-core/adr-036-empty-blocks-abci.md diff --git a/docs/architecture/tendermint-core/adr-037-deliver-block.md b/docs/references/architecture/tendermint-core/adr-037-deliver-block.md similarity index 100% rename from docs/architecture/tendermint-core/adr-037-deliver-block.md rename to docs/references/architecture/tendermint-core/adr-037-deliver-block.md diff --git a/docs/architecture/tendermint-core/adr-038-non-zero-start-height.md b/docs/references/architecture/tendermint-core/adr-038-non-zero-start-height.md similarity index 100% rename from docs/architecture/tendermint-core/adr-038-non-zero-start-height.md rename to docs/references/architecture/tendermint-core/adr-038-non-zero-start-height.md diff --git a/docs/architecture/tendermint-core/adr-039-peer-behaviour.md b/docs/references/architecture/tendermint-core/adr-039-peer-behaviour.md similarity index 100% rename from docs/architecture/tendermint-core/adr-039-peer-behaviour.md rename to docs/references/architecture/tendermint-core/adr-039-peer-behaviour.md diff --git a/docs/architecture/tendermint-core/adr-040-blockchain-reactor-refactor.md b/docs/references/architecture/tendermint-core/adr-040-blockchain-reactor-refactor.md similarity index 100% rename from docs/architecture/tendermint-core/adr-040-blockchain-reactor-refactor.md rename to docs/references/architecture/tendermint-core/adr-040-blockchain-reactor-refactor.md diff --git a/docs/architecture/tendermint-core/adr-041-proposer-selection-via-abci.md b/docs/references/architecture/tendermint-core/adr-041-proposer-selection-via-abci.md similarity index 100% rename from docs/architecture/tendermint-core/adr-041-proposer-selection-via-abci.md rename to docs/references/architecture/tendermint-core/adr-041-proposer-selection-via-abci.md diff --git a/docs/architecture/tendermint-core/adr-042-state-sync.md b/docs/references/architecture/tendermint-core/adr-042-state-sync.md similarity index 94% rename from docs/architecture/tendermint-core/adr-042-state-sync.md rename to docs/references/architecture/tendermint-core/adr-042-state-sync.md index a1589318392..32f7ac6f8f7 100644 --- a/docs/architecture/tendermint-core/adr-042-state-sync.md +++ b/docs/references/architecture/tendermint-core/adr-042-state-sync.md @@ -15,7 +15,7 @@ facilitate setting up a new node as quickly as possible. ## Considerations Because Tendermint doesn't know anything about the application state, StateSync will broker messages between nodes and through -the ABCI to an opaque applicaton. The implementation will have multiple +the ABCI to an opaque application. The implementation will have multiple touch points on both the tendermint code base and ABCI application. * A StateSync reactor to facilitate peer communication - Tendermint @@ -60,7 +60,7 @@ optimized for batch read/writes. Additionally the propsosals tend to vary on how they provide safety properties. -**LightClient** Where a client can aquire the merkle root from the block +**LightClient** Where a client can acquire the merkle root from the block headers synchronized from a trusted validator set. Subsets of the application state, called chunks can therefore be validated on receipt to ensure each chunk is part of the merkle root. @@ -85,7 +85,7 @@ happens lazily and in a dynamic way: nodes request key ranges from their peers, and peers respond with some subset of the requested range and with notes on how to request the rest in parallel from other peers. Unlike chunk numbers, keys can be verified directly. And if some keys in the -range are ommitted, proofs for the range will fail to verify. +range are omitted, proofs for the range will fail to verify. This way a node can start by requesting the entire tree from one peer, and that peer can respond with say the first few keys, and the ranges to request from other peers. @@ -100,7 +100,7 @@ design for tendermint was originally tracked in Warp Sync as implemented in OpenEthereum to rapidly download both blocks and state snapshots from peers. Data is carved into ~4MB chunks and snappy compressed. Hashes of snappy compressed chunks are stored in a -manifest file which co-ordinates the state-sync. Obtaining a correct manifest +manifest file which coordinates the state-sync. Obtaining a correct manifest file seems to require an honest majority of peers. This means you may not find out the state is incorrect until you download the whole thing and compare it with a verified block header. @@ -127,19 +127,19 @@ read/write patterns necessitated by serving a snapshot chunk. Specifically, Lazy State Sync performs random reads to the underlying data structure while Eager can optimize for sequential reads. -This distinctin between approaches was demonstrated by Binance's +This distinction between approaches was demonstrated by Binance's [ackratos](https://github.com/ackratos) in their implementation of [Lazy State sync](https://github.com/tendermint/tendermint/pull/3243), The [analysis](https://docs.google.com/document/d/1npGTAa1qxe8EQZ1wG0a0Sip9t5oX2vYZNUDwr_LVRR4/) of the performance, and follow up implementation of [Warp Sync](http://github.com/tendermint/tendermint/pull/3594). -#### Compairing Security Models +#### Comparing Security Models There are several different security models which have been discussed/proposed in the past but generally fall into two categories. Light client validation: In which the node receiving data is expected to -first perform a light client sync and have all the nessesary block +first perform a light client sync and have all the necessary block headers. Within the trusted block header (trusted in terms of from a validator set subject to [weak subjectivity](https://github.com/tendermint/tendermint/pull/3795)) and @@ -169,12 +169,12 @@ giving the block propser enough time to complete the snapshot asynchronousy. ## Proposal: Eager StateSync With Per Chunk Light Client Validation -The conclusion after some concideration of the advantages/disadvances of +The conclusion after some consideration of the advantages/disadvances of eager/lazy and different security models is to produce a state sync which eagerly produces snapshots and uses light client validation. This approach has the performance advantages of pre-computing efficient snapshots which can streamed to new nodes on demand using sequential IO. -Secondly, by using light client validation we cna validate each chunk on +Secondly, by using light client validation we can validate each chunk on receipt and avoid the potential eclipse attack of majority of peer based security. @@ -214,7 +214,7 @@ will need implement: Proposed -## Concequences +## Consequences ### Neutral diff --git a/docs/architecture/tendermint-core/adr-043-blockchain-riri-org.md b/docs/references/architecture/tendermint-core/adr-043-blockchain-riri-org.md similarity index 95% rename from docs/architecture/tendermint-core/adr-043-blockchain-riri-org.md rename to docs/references/architecture/tendermint-core/adr-043-blockchain-riri-org.md index dbe04eeaf9a..f340fabb553 100644 --- a/docs/architecture/tendermint-core/adr-043-blockchain-riri-org.md +++ b/docs/references/architecture/tendermint-core/adr-043-blockchain-riri-org.md @@ -160,7 +160,7 @@ func (r *BlockchainReacor) ioRoutine(ioMesgs chan Message, outMsgs chan Message) case scStatusRequestMessage r.sendStatusRequestToPeer(...) case bcPeerError - r.Swtich.StopPeerForError(msg.src) + r.Switch.StopPeerForError(msg.src) ... ... case bcFinished @@ -173,7 +173,7 @@ func (r *BlockchainReacor) ioRoutine(ioMesgs chan Message, outMsgs chan Message) ### Processor Internals -The processor is responsible for ordering, verifying and executing blocks. The Processor will maintain an internal cursor `height` refering to the last processed block. As a set of blocks arrive unordered, the Processor will check if it has `height+1` necessary to process the next block. The processor also maintains the map `blockPeers` of peers to height, to keep track of which peer provided the block at `height`. `blockPeers` can be used in`handleRemovePeer(...)` to reschedule all unprocessed blocks provided by a peer who has errored. +The processor is responsible for ordering, verifying and executing blocks. The Processor will maintain an internal cursor `height` referring to the last processed block. As a set of blocks arrive unordered, the Processor will check if it has `height+1` necessary to process the next block. The processor also maintains the map `blockPeers` of peers to height, to keep track of which peer provided the block at `height`. `blockPeers` can be used in`handleRemovePeer(...)` to reschedule all unprocessed blocks provided by a peer who has errored. ```go type Processor struct { @@ -384,7 +384,7 @@ Implemented ### Positive - Test become deterministic -- Simulation becomes a-termporal: no need wait for a wall-time timeout +- Simulation becomes a-temporal: no need wait for a wall-time timeout - Peer Selection can be independently tested/simulated - Develop a general approach to refactoring reactors diff --git a/docs/architecture/tendermint-core/adr-044-lite-client-with-weak-subjectivity.md b/docs/references/architecture/tendermint-core/adr-044-lite-client-with-weak-subjectivity.md similarity index 100% rename from docs/architecture/tendermint-core/adr-044-lite-client-with-weak-subjectivity.md rename to docs/references/architecture/tendermint-core/adr-044-lite-client-with-weak-subjectivity.md diff --git a/docs/architecture/tendermint-core/adr-045-abci-evidence.md b/docs/references/architecture/tendermint-core/adr-045-abci-evidence.md similarity index 98% rename from docs/architecture/tendermint-core/adr-045-abci-evidence.md rename to docs/references/architecture/tendermint-core/adr-045-abci-evidence.md index 65a0b688ace..40bf255ab36 100644 --- a/docs/architecture/tendermint-core/adr-045-abci-evidence.md +++ b/docs/references/architecture/tendermint-core/adr-045-abci-evidence.md @@ -46,7 +46,7 @@ Arguments in favor of leaving evidence handling in Tendermint: for the ABCI app to detect it (ie. we don't send all votes we receive during consensus to the app ... ). -2) Amensia attacks can not be easily detected - they require an interactive +2) Amnesia attacks can not be easily detected - they require an interactive protocol among all the validators to submit justification for their past votes. Our best notion of [how to do this currently](https://github.com/tendermint/tendermint/blob/c67154232ca8be8f5c21dff65d154127adc4f7bb/docs/spec/consensus/fork-detection.md) @@ -57,7 +57,7 @@ Arguments in favor of leaving evidence handling in Tendermint: Validators must submit all the votes they saw for the relevant consensus height to justify their precommits. This is quite specific to the Tendermint protocol and may change if the protocol is upgraded. Hence it would be awkward - to co-ordinate this from the app. + to coordinate this from the app. 3) Evidence gossipping is similar to tx gossipping, but it should be higher priority. Since the mempool does not support any notion of priority yet, diff --git a/docs/architecture/tendermint-core/adr-046-light-client-implementation.md b/docs/references/architecture/tendermint-core/adr-046-light-client-implementation.md similarity index 99% rename from docs/architecture/tendermint-core/adr-046-light-client-implementation.md rename to docs/references/architecture/tendermint-core/adr-046-light-client-implementation.md index 15d77373dc3..3d4351ab7e2 100644 --- a/docs/architecture/tendermint-core/adr-046-light-client-implementation.md +++ b/docs/references/architecture/tendermint-core/adr-046-light-client-implementation.md @@ -143,7 +143,7 @@ the recursive version. There are two major reasons: _Fig. 1: Differences between recursive and non-recursive bisections_ -![Fig. 1](./img/adr-046-fig1.png) +![Fig. 1](img/adr-046-fig1.png) Specification of the non-recursive bisection can be found [here](https://github.com/tendermint/spec/blob/zm_non-recursive-verification/spec/consensus/light-client/non-recursive-verification.md). diff --git a/docs/architecture/tendermint-core/adr-047-handling-evidence-from-light-client.md b/docs/references/architecture/tendermint-core/adr-047-handling-evidence-from-light-client.md similarity index 98% rename from docs/architecture/tendermint-core/adr-047-handling-evidence-from-light-client.md rename to docs/references/architecture/tendermint-core/adr-047-handling-evidence-from-light-client.md index b0cac65d82d..dbef4e96ff7 100644 --- a/docs/architecture/tendermint-core/adr-047-handling-evidence-from-light-client.md +++ b/docs/references/architecture/tendermint-core/adr-047-handling-evidence-from-light-client.md @@ -8,7 +8,7 @@ * 14-08-2020: Introduce light traces (listed now as an alternative approach) * 20-08-2020: Light client produces evidence when detected instead of passing to full node * 16-09-2020: Post-implementation revision -* 15-03-2020: Ammends for the case of a forward lunatic attack +* 15-03-2020: Amends for the case of a forward lunatic attack ### Glossary of Terms @@ -100,7 +100,7 @@ of a different hash then trigger the detection process between the primary and t This begins with verification of the witness's header via skipping verification which is run in tande with locating the Light Bifurcation Point -![](./img/light-client-detector.png) +![](img/light-client-detector.png) This is done with: @@ -137,7 +137,7 @@ divergent header of the primary as it is likely, as seen in the example to the r headers where required in order to verify the divergent one. This trace will be used later (as is also described later in this document). -![](./img/bifurcation-point.png) +![](img/bifurcation-point.png) Now, that an attack has been detected, the light client must form evidence to prove it. There are three types of attacks that either the primary or witness could have done to try fool the light client diff --git a/docs/architecture/tendermint-core/adr-050-improved-trusted-peering.md b/docs/references/architecture/tendermint-core/adr-050-improved-trusted-peering.md similarity index 100% rename from docs/architecture/tendermint-core/adr-050-improved-trusted-peering.md rename to docs/references/architecture/tendermint-core/adr-050-improved-trusted-peering.md diff --git a/docs/architecture/tendermint-core/adr-051-double-signing-risk-reduction.md b/docs/references/architecture/tendermint-core/adr-051-double-signing-risk-reduction.md similarity index 100% rename from docs/architecture/tendermint-core/adr-051-double-signing-risk-reduction.md rename to docs/references/architecture/tendermint-core/adr-051-double-signing-risk-reduction.md diff --git a/docs/architecture/tendermint-core/adr-052-tendermint-mode.md b/docs/references/architecture/tendermint-core/adr-052-tendermint-mode.md similarity index 100% rename from docs/architecture/tendermint-core/adr-052-tendermint-mode.md rename to docs/references/architecture/tendermint-core/adr-052-tendermint-mode.md diff --git a/docs/architecture/tendermint-core/adr-053-state-sync-prototype.md b/docs/references/architecture/tendermint-core/adr-053-state-sync-prototype.md similarity index 98% rename from docs/architecture/tendermint-core/adr-053-state-sync-prototype.md rename to docs/references/architecture/tendermint-core/adr-053-state-sync-prototype.md index 2d8c37ad1cb..84e1e1ad220 100644 --- a/docs/architecture/tendermint-core/adr-053-state-sync-prototype.md +++ b/docs/references/architecture/tendermint-core/adr-053-state-sync-prototype.md @@ -2,7 +2,7 @@ State sync is now [merged](https://github.com/tendermint/tendermint/pull/4705). Up-to-date ABCI documentation is [available](https://github.com/tendermint/spec/pull/90), refer to it rather than this ADR for details. -This ADR outlines the plan for an initial state sync prototype, and is subject to change as we gain feedback and experience. It builds on discussions and findings in [ADR-042](./adr-042-state-sync.md), see that for background information. +This ADR outlines the plan for an initial state sync prototype, and is subject to change as we gain feedback and experience. It builds on discussions and findings in [ADR-042](adr-042-state-sync.md), see that for background information. ## Changelog @@ -30,7 +30,7 @@ This ADR outlines the plan for an initial state sync prototype, and is subject t State sync will allow a new node to receive a snapshot of the application state without downloading blocks or going through consensus. This bootstraps the node significantly faster than the current fast sync system, which replays all historical blocks. -Background discussions and justifications are detailed in [ADR-042](./adr-042-state-sync.md). Its recommendations can be summarized as: +Background discussions and justifications are detailed in [ADR-042](adr-042-state-sync.md). Its recommendations can be summarized as: * The application periodically takes full state snapshots (i.e. eager snapshots). @@ -251,4 +251,4 @@ Implemented ## References -* [ADR-042](./adr-042-state-sync.md) and its references +* [ADR-042](adr-042-state-sync.md) and its references diff --git a/docs/architecture/tendermint-core/adr-054-crypto-encoding-2.md b/docs/references/architecture/tendermint-core/adr-054-crypto-encoding-2.md similarity index 88% rename from docs/architecture/tendermint-core/adr-054-crypto-encoding-2.md rename to docs/references/architecture/tendermint-core/adr-054-crypto-encoding-2.md index e58681d155a..998cb503a58 100644 --- a/docs/architecture/tendermint-core/adr-054-crypto-encoding-2.md +++ b/docs/references/architecture/tendermint-core/adr-054-crypto-encoding-2.md @@ -14,7 +14,7 @@ Currently amino encodes keys as ` `. ## Decision Previously Tendermint defined all the key types for use in Tendermint and the Cosmos-SDK. Going forward the Cosmos-SDK will define its own protobuf type for keys. This will allow Tendermint to only define the keys that are being used in the codebase (ed25519). -There is the the opportunity to only define the usage of ed25519 (`bytes`) and not have it be a `oneof`, but this would mean that the `oneof` work is only being postponed to a later date. When using the `oneof` protobuf type we will have to manually switch over the possible key types and then pass them to the interface which is needed. +There is the opportunity to only define the usage of ed25519 (`bytes`) and not have it be a `oneof`, but this would mean that the `oneof` work is only being postponed to a later date. When using the `oneof` protobuf type we will have to manually switch over the possible key types and then pass them to the interface which is needed. The approach that will be taken to minimize headaches for users is one where all encoding of keys will shift to protobuf and where amino encoding is relied on, there will be custom marshal and unmarshal functions. diff --git a/docs/architecture/tendermint-core/adr-055-protobuf-design.md b/docs/references/architecture/tendermint-core/adr-055-protobuf-design.md similarity index 100% rename from docs/architecture/tendermint-core/adr-055-protobuf-design.md rename to docs/references/architecture/tendermint-core/adr-055-protobuf-design.md diff --git a/docs/architecture/tendermint-core/adr-056-light-client-amnesia-attacks.md b/docs/references/architecture/tendermint-core/adr-056-light-client-amnesia-attacks.md similarity index 99% rename from docs/architecture/tendermint-core/adr-056-light-client-amnesia-attacks.md rename to docs/references/architecture/tendermint-core/adr-056-light-client-amnesia-attacks.md index 68ac0f70f80..a4b795c727c 100644 --- a/docs/architecture/tendermint-core/adr-056-light-client-amnesia-attacks.md +++ b/docs/references/architecture/tendermint-core/adr-056-light-client-amnesia-attacks.md @@ -16,7 +16,7 @@ Whilst most created evidence of malicious behavior is self evident such that any The schematic below explains a scenario where an amnesia attack can occur such that two sets of honest nodes, C1 and C2, commit different blocks. -![](./img/tm-amnesia-attack.png) +![](img/tm-amnesia-attack.png) 1. C1 and F send PREVOTE messages for block A. 2. C1 sends PRECOMMIT for round 1 for block A. @@ -140,7 +140,7 @@ type ProofOfLockChange struct { This can be either evidence of +2/3 PREVOTES or PRECOMMITS (either warrants the honest node the right to vote) and is valid, among other checks, so long as the PRECOMMIT vote of the node in V2 came after all the votes in the `ProofOfLockChange` i.e. it received +2/3 votes for a block and then voted for that block thereafter (F is unable to prove this). -In the event that an honest node receives `PotentialAmnesiaEvidence` it will first `ValidateBasic()` and `Verify()` it and then will check if it is among the suspected nodes in the evidence. If so, it will retrieve the `ProofOfLockChange` and combine it with `PotentialAmensiaEvidence` to form `AmensiaEvidence`. All honest nodes that are part of the indicted group will have a time, measured in blocks, equal to `ProofTrialPeriod`, the aforementioned evidence paramter, to gossip their `AmnesiaEvidence` with their `ProofOfLockChange` +In the event that an honest node receives `PotentialAmnesiaEvidence` it will first `ValidateBasic()` and `Verify()` it and then will check if it is among the suspected nodes in the evidence. If so, it will retrieve the `ProofOfLockChange` and combine it with `PotentialAmensiaEvidence` to form `AmensiaEvidence`. All honest nodes that are part of the indicted group will have a time, measured in blocks, equal to `ProofTrialPeriod`, the aforementioned evidence parameter, to gossip their `AmnesiaEvidence` with their `ProofOfLockChange` ```golang type AmnesiaEvidence struct { @@ -163,7 +163,7 @@ When, `state.LastBlockHeight > PotentialAmnesiaEvidence.timestamp + ProofTrialPe Other validators will vote `nil` if: - The Amnesia Evidence is not valid -- The Amensia Evidence is not within their own trial period i.e. too soon. +- The Amnesia Evidence is not within their own trial period i.e. too soon. - They don't have the Amnesia Evidence and it is has an empty polc (each validator needs to run their own trial period of the evidence) - Is of an AmnesiaEvidence that has already been committed to the chain. diff --git a/docs/architecture/tendermint-core/adr-057-RPC.md b/docs/references/architecture/tendermint-core/adr-057-RPC.md similarity index 100% rename from docs/architecture/tendermint-core/adr-057-RPC.md rename to docs/references/architecture/tendermint-core/adr-057-RPC.md diff --git a/docs/architecture/tendermint-core/adr-058-event-hashing.md b/docs/references/architecture/tendermint-core/adr-058-event-hashing.md similarity index 99% rename from docs/architecture/tendermint-core/adr-058-event-hashing.md rename to docs/references/architecture/tendermint-core/adr-058-event-hashing.md index 184b921d5fb..40c80c6c9f7 100644 --- a/docs/architecture/tendermint-core/adr-058-event-hashing.md +++ b/docs/references/architecture/tendermint-core/adr-058-event-hashing.md @@ -109,7 +109,7 @@ and how this ought to ultimately be done by Tendermint.** ## References -- [ADR 021](./adr-021-abci-events.md) +- [ADR 021](adr-021-abci-events.md) - [Indexing transactions](../app-dev/indexing-transactions.md) ## Appendix A. Alternative proposals diff --git a/docs/architecture/tendermint-core/adr-059-evidence-composition-and-lifecycle.md b/docs/references/architecture/tendermint-core/adr-059-evidence-composition-and-lifecycle.md similarity index 99% rename from docs/architecture/tendermint-core/adr-059-evidence-composition-and-lifecycle.md rename to docs/references/architecture/tendermint-core/adr-059-evidence-composition-and-lifecycle.md index 6e0f3f40cce..3030c3d2103 100644 --- a/docs/architecture/tendermint-core/adr-059-evidence-composition-and-lifecycle.md +++ b/docs/references/architecture/tendermint-core/adr-059-evidence-composition-and-lifecycle.md @@ -4,7 +4,7 @@ - 04/09/2020: Initial Draft (Unabridged) - 07/09/2020: First Version -- 13/03/2021: Ammendment to accomodate forward lunatic attack +- 13/03/2021: Amendment to accommodate forward lunatic attack - 29/06/2021: Add information about ABCI specific fields ## Scope @@ -181,7 +181,7 @@ For `LightClientAttack` - Check that the hashes of the conflicting header and the trusted header are different -- In the case of a forward lunatic attack, where the trusted header height is less than the conflicting header height, the node checks that the time of the trusted header is later than the time of conflicting header. This proves that the conflicting header breaks monotonically increasing time. If the node doesn't have a trusted header with a later time then it is unable to validate the evidence for now. +- In the case of a forward lunatic attack, where the trusted header height is less than the conflicting header height, the node checks that the time of the trusted header is later than the time of conflicting header. This proves that the conflicting header breaks monotonically increasing time. If the node doesn't have a trusted header with a later time then it is unable to validate the evidence for now. - Lastly, for each validator, check the look up table to make sure there already isn't evidence against this validator @@ -271,7 +271,7 @@ The ABCI evidence is then sent via the `BlockExecutor` to the application. To summarize, we can see the lifecycle of evidence as such: -![evidence_lifecycle](./img/evidence_lifecycle.png) +![evidence_lifecycle](img/evidence_lifecycle.png) Evidence is first detected and created in the light client and consensus reactor. It is verified and stored as `EvidenceInfo` and gossiped to the evidence pools in other nodes. The consensus reactor later communicates with the evidence pool to either retrieve evidence to be put into a block, or verify the evidence the consensus reactor has retrieved in a block. Lastly when a block is added to the chain, the block executor sends the committed evidence back to the evidence pool so a pointer to the evidence can be stored in the evidence pool and it can update it's height and time. Finally, it turns the committed evidence into ABCI evidence and through the block executor passes the evidence to the application so the application can handle it. diff --git a/docs/architecture/tendermint-core/adr-060-go-api-stability.md b/docs/references/architecture/tendermint-core/adr-060-go-api-stability.md similarity index 97% rename from docs/architecture/tendermint-core/adr-060-go-api-stability.md rename to docs/references/architecture/tendermint-core/adr-060-go-api-stability.md index 31b70e73271..992b2539db2 100644 --- a/docs/architecture/tendermint-core/adr-060-go-api-stability.md +++ b/docs/references/architecture/tendermint-core/adr-060-go-api-stability.md @@ -12,7 +12,7 @@ With the release of Tendermint 1.0 we will adopt [semantic versioning](https://semver.org). One major implication is a guarantee that we will not make backwards-incompatible changes until Tendermint 2.0 (except in pre-release versions). In order to provide this guarantee for our Go API, we must clearly define which of our APIs are public, and what changes are considered backwards-compatible. -Currently, we list packages that we consider public in our [README](https://github.com/tendermint/tendermint#versioning), but since we are still at version 0.x we do not provide any backwards compatiblity guarantees at all. +Currently, we list packages that we consider public in our [README](https://github.com/tendermint/tendermint#versioning), but since we are still at version 0.x we do not provide any backwards compatibility guarantees at all. ### Glossary @@ -54,7 +54,7 @@ When preparing our public API for 1.0, we should keep these principles in mind: - Limit the number of public APIs that we start out with - we can always add new APIs later, but we can't change or remove APIs once they're made public. -- Before an API is made public, do a thorough review of the API to make sure it covers any future needs, can accomodate expected changes, and follows good API design practices. +- Before an API is made public, do a thorough review of the API to make sure it covers any future needs, can accommodate expected changes, and follows good API design practices. The following is the minimum set of public APIs that will be included in 1.0, in some form: @@ -130,7 +130,7 @@ In Go, [almost all API changes are backwards-incompatible](https://blog.golang.o - Widening a numeric type as long as it is a named type (e.g. `type Number int32` can change to `int64`, but not `int8` or `uint32`). -Note that public APIs can expose private types (e.g. via an exported variable, field, or function/method return value), in which case the exported fields and methods on these private types are also part of the public API and covered by its backwards compatiblity guarantees. In general, private types should never be accessible via public APIs unless wrapped in an exported interface. +Note that public APIs can expose private types (e.g. via an exported variable, field, or function/method return value), in which case the exported fields and methods on these private types are also part of the public API and covered by its backwards compatibility guarantees. In general, private types should never be accessible via public APIs unless wrapped in an exported interface. Also note that if we accept, return, export, or embed types from a dependency, we assume the backwards compatibility responsibility for that dependency, and must make sure any dependency upgrades comply with the above constraints. diff --git a/docs/architecture/tendermint-core/adr-061-p2p-refactor-scope.md b/docs/references/architecture/tendermint-core/adr-061-p2p-refactor-scope.md similarity index 94% rename from docs/architecture/tendermint-core/adr-061-p2p-refactor-scope.md rename to docs/references/architecture/tendermint-core/adr-061-p2p-refactor-scope.md index eedff207aee..70b8f914078 100644 --- a/docs/architecture/tendermint-core/adr-061-p2p-refactor-scope.md +++ b/docs/references/architecture/tendermint-core/adr-061-p2p-refactor-scope.md @@ -6,7 +6,7 @@ ## Context -The `p2p` package responsible for peer-to-peer networking is rather old and has a number of weaknesses, including tight coupling, leaky abstractions, lack of tests, DoS vulnerabilites, poor performance, custom protocols, and incorrect behavior. A refactor has been discussed for several years ([#2067](https://github.com/tendermint/tendermint/issues/2067)). +The `p2p` package responsible for peer-to-peer networking is rather old and has a number of weaknesses, including tight coupling, leaky abstractions, lack of tests, DoS vulnerabilities, poor performance, custom protocols, and incorrect behavior. A refactor has been discussed for several years ([#2067](https://github.com/tendermint/tendermint/issues/2067)). Informal Systems are also building a Rust implementation of Tendermint, [Tendermint-rs](https://github.com/informalsystems/tendermint-rs), and plan to implement P2P networking support over the next year. As part of this work, they have requested adopting e.g. [QUIC](https://datatracker.ietf.org/doc/draft-ietf-quic-transport/) as a transport protocol instead of implementing the custom application-level `MConnection` stream multiplexing protocol that Tendermint currently uses. @@ -72,7 +72,7 @@ This phase covers speculative, wide-reaching proposals that are poorly defined a * Adopt LibP2P. [#3696](https://github.com/tendermint/tendermint/issues/3696) * Allow cross-reactor communication, possibly without channels. -* Dynamic channel advertisment, as reactors are enabled/disabled. [#4394](https://github.com/tendermint/tendermint/issues/4394) [#1148](https://github.com/tendermint/tendermint/issues/1148) +* Dynamic channel advertisement, as reactors are enabled/disabled. [#4394](https://github.com/tendermint/tendermint/issues/4394) [#1148](https://github.com/tendermint/tendermint/issues/1148) * Pubsub-style networking topology and pattern. * Support multiple chain IDs in the same network. diff --git a/docs/architecture/tendermint-core/adr-062-p2p-architecture.md b/docs/references/architecture/tendermint-core/adr-062-p2p-architecture.md similarity index 99% rename from docs/architecture/tendermint-core/adr-062-p2p-architecture.md rename to docs/references/architecture/tendermint-core/adr-062-p2p-architecture.md index b2456da46b9..08e31b9b1fc 100644 --- a/docs/architecture/tendermint-core/adr-062-p2p-architecture.md +++ b/docs/references/architecture/tendermint-core/adr-062-p2p-architecture.md @@ -61,7 +61,7 @@ Transports must satisfy the following requirements: * Be connection-oriented, and support both listening for inbound connections and making outbound connections using endpoint addresses. -* Support sending binary messages with distinct channel IDs (although channels and channel IDs are a higher-level application protocol concept explained in the Router section, they are threaded through the transport layer as well for backwards compatibilty with the existing MConnection protocol). +* Support sending binary messages with distinct channel IDs (although channels and channel IDs are a higher-level application protocol concept explained in the Router section, they are threaded through the transport layer as well for backwards compatibility with the existing MConnection protocol). * Exchange the MConnection `NodeInfo` and public key via a node handshake, and possibly encrypt or sign the traffic as appropriate. @@ -599,7 +599,7 @@ Was partially implemented in v0.35 ([#5670](https://github.com/tendermint/tender ### Negative -* Fully implementing the new design as indended is likely to require breaking changes to the P2P protocol at some point, although the initial implementation shouldn't. +* Fully implementing the new design as intended is likely to require breaking changes to the P2P protocol at some point, although the initial implementation shouldn't. * Gradually migrating the existing stack and maintaining backwards-compatibility will be more labor-intensive than simply replacing the entire stack. diff --git a/docs/architecture/tendermint-core/adr-063-privval-grpc.md b/docs/references/architecture/tendermint-core/adr-063-privval-grpc.md similarity index 100% rename from docs/architecture/tendermint-core/adr-063-privval-grpc.md rename to docs/references/architecture/tendermint-core/adr-063-privval-grpc.md diff --git a/docs/architecture/tendermint-core/adr-064-batch-verification.md b/docs/references/architecture/tendermint-core/adr-064-batch-verification.md similarity index 98% rename from docs/architecture/tendermint-core/adr-064-batch-verification.md rename to docs/references/architecture/tendermint-core/adr-064-batch-verification.md index 13bba25e4fe..b017dc7cd50 100644 --- a/docs/architecture/tendermint-core/adr-064-batch-verification.md +++ b/docs/references/architecture/tendermint-core/adr-064-batch-verification.md @@ -33,7 +33,7 @@ type BatchVerifier interface { - `NewBatchVerifier` creates a new verifier. This verifier will be populated with entries to be verified. - `Add` adds an entry to the Verifier. Add accepts a public key and two slice of bytes (signature and message). -- `Verify` verifies all the entires. At the end of Verify if the underlying API does not reset the Verifier to its initial state (empty), it should be done here. This prevents accidentally reusing the verifier with entries from a previous verification. +- `Verify` verifies all the entries. At the end of Verify if the underlying API does not reset the Verifier to its initial state (empty), it should be done here. This prevents accidentally reusing the verifier with entries from a previous verification. Above there is mention of an entry. An entry can be constructed in many ways depending on the needs of the underlying curve. A simple approach would be: diff --git a/docs/architecture/tendermint-core/adr-065-custom-event-indexing.md b/docs/references/architecture/tendermint-core/adr-065-custom-event-indexing.md similarity index 100% rename from docs/architecture/tendermint-core/adr-065-custom-event-indexing.md rename to docs/references/architecture/tendermint-core/adr-065-custom-event-indexing.md diff --git a/docs/architecture/tendermint-core/adr-066-e2e-testing.md b/docs/references/architecture/tendermint-core/adr-066-e2e-testing.md similarity index 99% rename from docs/architecture/tendermint-core/adr-066-e2e-testing.md rename to docs/references/architecture/tendermint-core/adr-066-e2e-testing.md index 528e25238ef..b985fad70ec 100644 --- a/docs/architecture/tendermint-core/adr-066-e2e-testing.md +++ b/docs/references/architecture/tendermint-core/adr-066-e2e-testing.md @@ -75,7 +75,7 @@ Given a test configuration, the test runner has the following stages: - **Setup:** configures the Docker containers and networks, but does not start them. -- **Initialization:** starts the Docker containers, performs fast sync/state sync. Accomodates for different start heights. +- **Initialization:** starts the Docker containers, performs fast sync/state sync. Accommodates for different start heights. - **Perturbation:** adds/removes validators, restarts nodes, perturbs networking, etc - liveness and readiness checked between each operation. diff --git a/docs/architecture/tendermint-core/adr-067-mempool-refactor.md b/docs/references/architecture/tendermint-core/adr-067-mempool-refactor.md similarity index 99% rename from docs/architecture/tendermint-core/adr-067-mempool-refactor.md rename to docs/references/architecture/tendermint-core/adr-067-mempool-refactor.md index d217b1df1ef..6fa51da5488 100644 --- a/docs/architecture/tendermint-core/adr-067-mempool-refactor.md +++ b/docs/references/architecture/tendermint-core/adr-067-mempool-refactor.md @@ -71,7 +71,7 @@ can be addressed in an easy and extensible manner in the future. ### Current Design -![mempool](./img/mempool-v0.jpeg) +![mempool](img/mempool-v0.jpeg) At the core of the `v0` mempool reactor is a concurrent linked-list. This is the primary data structure that contains `Tx` objects that have passed `CheckTx`. diff --git a/docs/architecture/tendermint-core/adr-068-reverse-sync.md b/docs/references/architecture/tendermint-core/adr-068-reverse-sync.md similarity index 98% rename from docs/architecture/tendermint-core/adr-068-reverse-sync.md rename to docs/references/architecture/tendermint-core/adr-068-reverse-sync.md index d7ca5a9162f..ec1985a98d3 100644 --- a/docs/architecture/tendermint-core/adr-068-reverse-sync.md +++ b/docs/references/architecture/tendermint-core/adr-068-reverse-sync.md @@ -36,7 +36,7 @@ Furthermore this allows for a new light client provider which offers the ability ## Detailed Design -This section will focus first on the reverse sync (here we call it `backfill`) mechanism as a standalone protocol and then look to decribe how it integrates within the state sync reactor and how we define the new p2p light client provider. +This section will focus first on the reverse sync (here we call it `backfill`) mechanism as a standalone protocol and then look to describe how it integrates within the state sync reactor and how we define the new p2p light client provider. ```go // Backfill fetches, verifies, and stores necessary history diff --git a/docs/architecture/tendermint-core/adr-069-flexible-node-initialization.md b/docs/references/architecture/tendermint-core/adr-069-flexible-node-initialization.md similarity index 96% rename from docs/architecture/tendermint-core/adr-069-flexible-node-initialization.md rename to docs/references/architecture/tendermint-core/adr-069-flexible-node-initialization.md index 31082b1059b..14cd4213e8d 100644 --- a/docs/architecture/tendermint-core/adr-069-flexible-node-initialization.md +++ b/docs/references/architecture/tendermint-core/adr-069-flexible-node-initialization.md @@ -1,6 +1,6 @@ # ADR 069: Flexible Node Initialization -## Changlog +## Changelog - 2021-06-09: Initial Draft (@tychoish) @@ -12,13 +12,13 @@ Proposed. ## Context -In an effort to support [Go-API-Stability](./adr-060-go-api-stability.md), -during the 0.35 development cycle, we have attempted to reduce the the API +In an effort to support [Go-API-Stability](adr-060-go-api-stability.md), +during the 0.35 development cycle, we have attempted to reduce the API surface area by moving most of the interface of the `node` package into unexported functions, as well as moving the reactors to an `internal` package. Having this coincide with the 0.35 release made a lot of sense because these interfaces were _already_ changing as a result of the `p2p` -[refactor](./adr-061-p2p-refactor-scope.md), so it made sense to think a bit +[refactor](adr-061-p2p-refactor-scope.md), so it made sense to think a bit more about how tendermint exposes this API. While the interfaces of the P2P layer and most of the node package are already @@ -31,7 +31,7 @@ vendor copy of the code. Adding these features requires rather extensive ADR describes a model for changing the way that tendermint nodes initialize, in service of providing this kind of functionality. -We consider node initialization, because the current implemention +We consider node initialization, because the current implementation provides strong connections between all components, as well as between the components of the node and the RPC layer, and being able to think about the interactions of these components will help enable these @@ -41,7 +41,7 @@ features and help define the requirements of the node package. These alternatives are presented to frame the design space and to contextualize the decision in terms of product requirements. These -ideas are not inherently bad, and may even be possible or desireable +ideas are not inherently bad, and may even be possible or desirable in the (distant) future, and merely provide additional context for how we, in the moment came to our decision(s). @@ -265,4 +265,4 @@ described by the following dependency graph makes replacing some of these components more difficult relative to other reactors or components. -![consensus blockchain dependency graph](./img/consensus_blockchain.png) +![consensus blockchain dependency graph](img/consensus_blockchain.png) diff --git a/docs/architecture/tendermint-core/adr-071-proposer-based-timestamps.md b/docs/references/architecture/tendermint-core/adr-071-proposer-based-timestamps.md similarity index 99% rename from docs/architecture/tendermint-core/adr-071-proposer-based-timestamps.md rename to docs/references/architecture/tendermint-core/adr-071-proposer-based-timestamps.md index e17226cce75..2d1fafd7566 100644 --- a/docs/architecture/tendermint-core/adr-071-proposer-based-timestamps.md +++ b/docs/references/architecture/tendermint-core/adr-071-proposer-based-timestamps.md @@ -135,7 +135,7 @@ A validator will only Prevote a proposal if the proposal timestamp is considered A proposal timestamp is considered `timely` if it is within `PRECISION` and `MSGDELAY` of the Unix time known to the validator. More specifically, a proposal timestamp is `timely` if `proposalTimestamp - PRECISION ≤ validatorLocalTime ≤ proposalTimestamp + PRECISION + MSGDELAY`. -Because the `PRECISION` and `MSGDELAY` parameters must be the same across all validators, they will be added to the [consensus parameters](https://github.com/tendermint/tendermint/blob/main/proto/tendermint/types/params.proto#L11) as [durations](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Duration). +Because the `PRECISION` and `MSGDELAY` parameters must be the same across all validators, they will be added to the [consensus parameters](https://github.com/tendermint/tendermint/blob/main/proto/tendermint/types/params.proto#L11) as [durations](https://protobuf.dev/reference/protobuf/google.protobuf/#duration). The consensus parameters will be updated to include this `Synchrony` field as follows: diff --git a/docs/architecture/tendermint-core/adr-072-request-for-comments.md b/docs/references/architecture/tendermint-core/adr-072-request-for-comments.md similarity index 100% rename from docs/architecture/tendermint-core/adr-072-request-for-comments.md rename to docs/references/architecture/tendermint-core/adr-072-request-for-comments.md diff --git a/docs/architecture/tendermint-core/adr-073-libp2p.md b/docs/references/architecture/tendermint-core/adr-073-libp2p.md similarity index 99% rename from docs/architecture/tendermint-core/adr-073-libp2p.md rename to docs/references/architecture/tendermint-core/adr-073-libp2p.md index 080fecbcdf4..549cf64d573 100644 --- a/docs/architecture/tendermint-core/adr-073-libp2p.md +++ b/docs/references/architecture/tendermint-core/adr-073-libp2p.md @@ -230,6 +230,6 @@ the implementation timeline. - [ADR 62: P2P Architecture][adr62] - [P2P Roadmap RFC][rfc] -[adr61]: ./adr-061-p2p-refactor-scope.md -[adr62]: ./adr-062-p2p-architecture.md +[adr61]: adr-061-p2p-refactor-scope.md +[adr62]: adr-062-p2p-architecture.md [rfc]: ../rfc/rfc-000-p2p-roadmap.rst diff --git a/docs/architecture/tendermint-core/adr-074-timeout-params.md b/docs/references/architecture/tendermint-core/adr-074-timeout-params.md similarity index 100% rename from docs/architecture/tendermint-core/adr-074-timeout-params.md rename to docs/references/architecture/tendermint-core/adr-074-timeout-params.md diff --git a/docs/architecture/tendermint-core/adr-075-rpc-subscription.md b/docs/references/architecture/tendermint-core/adr-075-rpc-subscription.md similarity index 98% rename from docs/architecture/tendermint-core/adr-075-rpc-subscription.md rename to docs/references/architecture/tendermint-core/adr-075-rpc-subscription.md index a838f2766a9..8d589c49979 100644 --- a/docs/architecture/tendermint-core/adr-075-rpc-subscription.md +++ b/docs/references/architecture/tendermint-core/adr-075-rpc-subscription.md @@ -308,7 +308,7 @@ type EventParams struct { MaxResults int `json:"max_results"` // Return only items after this cursor. If empty, the limit is just - // before the the beginning of the event log. + // before the beginning of the event log. After string `json:"after"` // Return only items before this cursor. If empty, the limit is just @@ -458,7 +458,7 @@ crashes and connectivity issues: no `before`). 2. If there are more events than the client requested, or if the client needs - to to read older events to recover from a stall or crash, clients will + to read older events to recover from a stall or crash, clients will **page** backward through the event log (by setting `before` and `after`). - While the new API requires explicit polling by the client, it makes better @@ -483,7 +483,7 @@ crashes and connectivity issues: then discard any older than the time window before the latest. To minimize coordination interference between the publisher (the event bus) - and the subcribers (the `events` service handlers), the event log will be + and the subscribers (the `events` service handlers), the event log will be stored as a persistent linear queue with shared structure (a cons list). A single reader-writer mutex will guard the "head" of the queue where new items are published: @@ -516,10 +516,10 @@ crashes and connectivity issues: requires (e.g., reducing to 3/4 of the maximum rather than 1/1). The state of the event log before the publisher acquires the lock: - ![Before publish and pruning](./img/adr-075-log-before.png) + ![Before publish and pruning](img/adr-075-log-before.png) After the publisher has added a new item and pruned old ones: - ![After publish and pruning](./img/adr-075-log-after.png) + ![After publish and pruning](img/adr-075-log-after.png) ### Migration Plan @@ -550,7 +550,7 @@ the new API, to remove a disincentive to upgrading. > disruption for users in the v0.36 cycle, I have decided not to do this for > the first phase. > -> If we wind up pushing this design into v0.37, however, we should re-evaulate +> If we wind up pushing this design into v0.37, however, we should re-evaluate > this partial turn-down of the websocket. ### Future Work diff --git a/docs/architecture/tendermint-core/adr-076-combine-spec-repo.md b/docs/references/architecture/tendermint-core/adr-076-combine-spec-repo.md similarity index 100% rename from docs/architecture/tendermint-core/adr-076-combine-spec-repo.md rename to docs/references/architecture/tendermint-core/adr-076-combine-spec-repo.md diff --git a/docs/architecture/tendermint-core/adr-077-block-retention.md b/docs/references/architecture/tendermint-core/adr-077-block-retention.md similarity index 100% rename from docs/architecture/tendermint-core/adr-077-block-retention.md rename to docs/references/architecture/tendermint-core/adr-077-block-retention.md diff --git a/docs/architecture/tendermint-core/adr-078-nonzero-genesis.md b/docs/references/architecture/tendermint-core/adr-078-nonzero-genesis.md similarity index 100% rename from docs/architecture/tendermint-core/adr-078-nonzero-genesis.md rename to docs/references/architecture/tendermint-core/adr-078-nonzero-genesis.md diff --git a/docs/architecture/tendermint-core/adr-079-ed25519-verification.md b/docs/references/architecture/tendermint-core/adr-079-ed25519-verification.md similarity index 100% rename from docs/architecture/tendermint-core/adr-079-ed25519-verification.md rename to docs/references/architecture/tendermint-core/adr-079-ed25519-verification.md diff --git a/docs/architecture/tendermint-core/adr-080-reverse-sync.md b/docs/references/architecture/tendermint-core/adr-080-reverse-sync.md similarity index 100% rename from docs/architecture/tendermint-core/adr-080-reverse-sync.md rename to docs/references/architecture/tendermint-core/adr-080-reverse-sync.md diff --git a/docs/architecture/tendermint-core/adr-081-protobuf-mgmt.md b/docs/references/architecture/tendermint-core/adr-081-protobuf-mgmt.md similarity index 100% rename from docs/architecture/tendermint-core/adr-081-protobuf-mgmt.md rename to docs/references/architecture/tendermint-core/adr-081-protobuf-mgmt.md diff --git a/docs/architecture/tendermint-core/img/adr-046-fig1.png b/docs/references/architecture/tendermint-core/img/adr-046-fig1.png similarity index 100% rename from docs/architecture/tendermint-core/img/adr-046-fig1.png rename to docs/references/architecture/tendermint-core/img/adr-046-fig1.png diff --git a/docs/architecture/tendermint-core/img/adr-062-architecture.svg b/docs/references/architecture/tendermint-core/img/adr-062-architecture.svg similarity index 100% rename from docs/architecture/tendermint-core/img/adr-062-architecture.svg rename to docs/references/architecture/tendermint-core/img/adr-062-architecture.svg diff --git a/docs/architecture/tendermint-core/img/adr-075-log-after.png b/docs/references/architecture/tendermint-core/img/adr-075-log-after.png similarity index 100% rename from docs/architecture/tendermint-core/img/adr-075-log-after.png rename to docs/references/architecture/tendermint-core/img/adr-075-log-after.png diff --git a/docs/architecture/tendermint-core/img/adr-075-log-before.png b/docs/references/architecture/tendermint-core/img/adr-075-log-before.png similarity index 100% rename from docs/architecture/tendermint-core/img/adr-075-log-before.png rename to docs/references/architecture/tendermint-core/img/adr-075-log-before.png diff --git a/docs/architecture/tendermint-core/img/bc-reactor-refactor.png b/docs/references/architecture/tendermint-core/img/bc-reactor-refactor.png similarity index 100% rename from docs/architecture/tendermint-core/img/bc-reactor-refactor.png rename to docs/references/architecture/tendermint-core/img/bc-reactor-refactor.png diff --git a/docs/architecture/tendermint-core/img/bc-reactor.png b/docs/references/architecture/tendermint-core/img/bc-reactor.png similarity index 100% rename from docs/architecture/tendermint-core/img/bc-reactor.png rename to docs/references/architecture/tendermint-core/img/bc-reactor.png diff --git a/docs/architecture/tendermint-core/img/bifurcation-point.png b/docs/references/architecture/tendermint-core/img/bifurcation-point.png similarity index 100% rename from docs/architecture/tendermint-core/img/bifurcation-point.png rename to docs/references/architecture/tendermint-core/img/bifurcation-point.png diff --git a/docs/architecture/tendermint-core/img/block-retention.png b/docs/references/architecture/tendermint-core/img/block-retention.png similarity index 100% rename from docs/architecture/tendermint-core/img/block-retention.png rename to docs/references/architecture/tendermint-core/img/block-retention.png diff --git a/docs/architecture/tendermint-core/img/blockchain-reactor-v1.png b/docs/references/architecture/tendermint-core/img/blockchain-reactor-v1.png similarity index 100% rename from docs/architecture/tendermint-core/img/blockchain-reactor-v1.png rename to docs/references/architecture/tendermint-core/img/blockchain-reactor-v1.png diff --git a/docs/architecture/tendermint-core/img/blockchain-reactor-v2.png b/docs/references/architecture/tendermint-core/img/blockchain-reactor-v2.png similarity index 100% rename from docs/architecture/tendermint-core/img/blockchain-reactor-v2.png rename to docs/references/architecture/tendermint-core/img/blockchain-reactor-v2.png diff --git a/docs/architecture/tendermint-core/img/blockchain-v2-channels.png b/docs/references/architecture/tendermint-core/img/blockchain-v2-channels.png similarity index 100% rename from docs/architecture/tendermint-core/img/blockchain-v2-channels.png rename to docs/references/architecture/tendermint-core/img/blockchain-v2-channels.png diff --git a/docs/architecture/tendermint-core/img/consensus_blockchain.png b/docs/references/architecture/tendermint-core/img/consensus_blockchain.png similarity index 100% rename from docs/architecture/tendermint-core/img/consensus_blockchain.png rename to docs/references/architecture/tendermint-core/img/consensus_blockchain.png diff --git a/docs/architecture/tendermint-core/img/evidence_lifecycle.png b/docs/references/architecture/tendermint-core/img/evidence_lifecycle.png similarity index 100% rename from docs/architecture/tendermint-core/img/evidence_lifecycle.png rename to docs/references/architecture/tendermint-core/img/evidence_lifecycle.png diff --git a/docs/architecture/tendermint-core/img/formula1.png b/docs/references/architecture/tendermint-core/img/formula1.png similarity index 100% rename from docs/architecture/tendermint-core/img/formula1.png rename to docs/references/architecture/tendermint-core/img/formula1.png diff --git a/docs/architecture/tendermint-core/img/formula2.png b/docs/references/architecture/tendermint-core/img/formula2.png similarity index 100% rename from docs/architecture/tendermint-core/img/formula2.png rename to docs/references/architecture/tendermint-core/img/formula2.png diff --git a/docs/architecture/tendermint-core/img/light-client-detector.png b/docs/references/architecture/tendermint-core/img/light-client-detector.png similarity index 100% rename from docs/architecture/tendermint-core/img/light-client-detector.png rename to docs/references/architecture/tendermint-core/img/light-client-detector.png diff --git a/docs/architecture/tendermint-core/img/mempool-v0.jpeg b/docs/references/architecture/tendermint-core/img/mempool-v0.jpeg similarity index 100% rename from docs/architecture/tendermint-core/img/mempool-v0.jpeg rename to docs/references/architecture/tendermint-core/img/mempool-v0.jpeg diff --git a/docs/architecture/tendermint-core/img/pbts-message.png b/docs/references/architecture/tendermint-core/img/pbts-message.png similarity index 100% rename from docs/architecture/tendermint-core/img/pbts-message.png rename to docs/references/architecture/tendermint-core/img/pbts-message.png diff --git a/docs/architecture/tendermint-core/img/state-sync.png b/docs/references/architecture/tendermint-core/img/state-sync.png similarity index 100% rename from docs/architecture/tendermint-core/img/state-sync.png rename to docs/references/architecture/tendermint-core/img/state-sync.png diff --git a/docs/architecture/tendermint-core/img/tags1.png b/docs/references/architecture/tendermint-core/img/tags1.png similarity index 100% rename from docs/architecture/tendermint-core/img/tags1.png rename to docs/references/architecture/tendermint-core/img/tags1.png diff --git a/docs/architecture/tendermint-core/img/tm-amnesia-attack.png b/docs/references/architecture/tendermint-core/img/tm-amnesia-attack.png similarity index 100% rename from docs/architecture/tendermint-core/img/tm-amnesia-attack.png rename to docs/references/architecture/tendermint-core/img/tm-amnesia-attack.png diff --git a/docs/references/config/README.md b/docs/references/config/README.md new file mode 100644 index 00000000000..c94ed13ddf1 --- /dev/null +++ b/docs/references/config/README.md @@ -0,0 +1,36 @@ +--- +order: 1 +parent: + title: Configuration Manual + description: A comprehensive reference manual for configuring CometBFT + order: false +--- +# CometBFT Configuration Manual + +## Overview +The CometBFT configuration has three distinct parts: +1. The network parameters in [genesis.json](genesis.json.md). +2. The nodeID in [node_key.json](node_key.json.md). +3. The configuration of the node and its services in [config.toml](config.toml.md). + +Validator nodes also require a private/public key-pair to sign consensus messages. + +If a Hardware Security Module (HSM) is not available, CometBFT stores an unencrypted key-pair on the file system in the +[priv_validator_key.json](priv_validator_key.json.md) file and the state of the last block signed in +[priv_validator_state.json](priv_validator_state.json.md). + +## The HOME folder +The CometBFT HOME folder contains all configuration (in the `$HOME/config` folder) for CometBFT as well as all the databases (in the `$HOME/data` folder) +used during execution. + +Path to the folder is defined by these steps: +1. The home folder for CometBFT is read from the `CMTHOME` environment variable. +2. If the variable is undefined, it is assumed the default `$HOME/.cometbft`. +3. The environment variable is overridden by the `--home` command-line parameter. + +By default, all configuration files are stored under the `$CMTHOME/config` directory. +These can be overridden individually for each file in the `config.toml` file, for example to +override the `genesis_file` location change it [here](config.toml.md#genesis_file). + +By default, all databases are stored under the `$CMTHOME/data` directory. +This can be overridden at the [`db_dir`](config.toml.md#db_dir) parameter in the [`config.toml`](config.toml.md) file. diff --git a/docs/references/config/config.toml.md b/docs/references/config/config.toml.md new file mode 100644 index 00000000000..d2f6e5d4e43 --- /dev/null +++ b/docs/references/config/config.toml.md @@ -0,0 +1,2078 @@ +--- +order: 1 +parent: + title: config.toml + description: CometBFT general configuration + order: 3 +--- + + + + + +# config.toml +The `config.toml` file is a standard [TOML](https://toml.io/en/v1.0.0) file that configures the basic functionality +of CometBFT, including the configuration of the reactors. + +All relative paths in the configuration are relative to `$CMTHOME`. +(See [the HOME folder](./README.md#the-home-folder) for more details.) + +## Base configuration +The root table defines generic node settings. It is implemented in a struct called `BaseConfig`, hence the name. + +### version +The version of the CometBFT binary that created or last modified the config file. +```toml +version = "1.0.0" +``` + +| Value type | string | +|:--------------------|:------------------------| +| **Possible values** | semantic version string | +| | `""` | + +This string validates the configuration file for the binary. The string has to be either a +[valid semver](https://semver.org) string or an empty string. In any other case, the binary halts with an +`ERROR: error in config file: invalid version string` error. + +In the future, the code might make restrictions on what version of the file is compatible with what version of the +binary. There is no such check in place right now. Configuration and binary versions are interchangeable. + +### proxy_app +The TCP or UNIX socket of the ABCI application or the name of an example ABCI application compiled in with the CometBFT +library. +```toml +proxy_app = "tcp://127.0.0.1:26658" +``` + +| Value type | string | +|:--------------------|:--------------------------------------------------------| +| **Possible values** | TCP Stream socket (e.g. `"tcp://127.0.0.1:26658"`) | +| | Unix domain socket (e.g. `"unix:///var/run/abci.sock"`) | +| | `"kvstore"` | +| | `"persistent_kvstore"` | +| | `"noop"` | + +When the ABCI application is written in a different language than Golang, (for example the +[Nomic binary](https://github.com/nomic-io/nomic) is written in Rust) the application can open a TCP port or create a +UNIX domain socket to communicate with CometBFT, while CometBFT runs as a separate process. + +IP addresses other than `localhost` (IPv4: `127.0.0.1`, IPv6: `::1`) are strongly discouraged. It has not been tested, and it has strong performance and security implications. +The [abci](#abci) parameter is used in conjunction with this parameter to define the protocol used for communication. + +In other cases (for example in the [Gaia binary](https://github.com/cosmos/gaia)), CometBFT is imported as a library +and the configuration entry is unused. + +For development and testing, the [built-in ABCI application](../../guides/app-dev/abci-cli.md) can be used without additional processes running. + +### moniker +A custom human-readable name for this node. +```toml +moniker = "my.host.name" +``` + +| Value type | string | +|:--------------------|:---------------------------------------------------------| +| **Possible values** | any human-readable string | + +The main use of this entry is to keep track of the different nodes in a local environment. For example, the `/status` RPC +endpoint will return the node moniker in the `.result.moniker` key. + +Monikers do not need to be unique. They are for local administrator use and troubleshooting. + +Nodes on the peer-to-peer network are identified by `nodeID@host:port` as discussed in the +[node_key.json](node_key.json.md) section. + +### db_backend +The chosen database backend for the node. +```toml +db_backend = "goleveldb" +``` + +| Value type | string | dependencies | GitHub | +|:--------------------|:--------------|:--------------|:-------------------------------------------------| +| **Possible values** | `"goleveldb"` | pure Golang | [goleveldb](https://github.com/syndtr/goleveldb) | +| | `"rocksdb"` | requires gcc | [grocksdb](https://github.com/linxGnu/grocksdb) | +| | `"badgerdb"` | pure Golang | [badger](https://github.com/dgraph-io/badger) | +| | `"pebbledb"` | pure Golang | [pebble](https://github.com/cockroachdb/pebble) | + +During the build process, by default, only the `goleveldb` library is built into the binary. +To add support for alternative databases, you need to add them in the build tags. +For example: `go build -tags rocksdb`. + +The RocksDB fork has API changes from the upstream RocksDB implementation. All other databases claim a stable API. + +The CometBFT team tests rely on the GoLevelDB implementation. All other implementations are considered experimental from +a CometBFT perspective. The supported databases are part of the [cometbft-db](https://github.com/cometbft/cometbft-db) library +that CometBFT uses as a common database interface to various databases. + +### db_dir +The directory path where the database is stored. +```toml +db_dir = "data" +``` + +| Value type | string | +|:--------------------|:-------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME` | +| | absolute directory path | + +The default relative path translates to `$CMTHOME/data`. In case `$CMTHOME` is unset, it defaults to +`$HOME/.cometbft/data`. + +### log_level +A comma-separated list of `module:level` pairs that describe the log level of each module. Alternatively, a single word +can be set which will apply that log level to all modules. +```toml +log_level = "info" +``` + +| Value type | string | | +|:---------------|:----------------|----------------------------------------| +| **Modules** | `"main"` | CometBFT main application logs | +| | `"consensus"` | consensus reactor logs | +| | `"p2p"` | p2p reactor logs | +| | `"pex"` | Peer Exchange logs | +| | `"proxy"` | ABCI proxy service (MultiAppConn) logs | +| | `"abci-client"` | ABCI client service logs | +| | `"rpc-server"` | RPC server logs | +| | `"txindex"` | Indexer service logs | +| | `"events"` | Events service logs | +| | `"pubsub"` | PubSub service logs | +| | `"evidence"` | Evidence reactor logs | +| | `"statesync"` | StateSync reactor logs | +| | `"mempool"` | Mempool reactor logs | +| | `"blocksync"` | BlockSync reactor logs | +| | `"state"` | Pruner service logs | +| | `"*"` | All modules | +| **Log levels** | `"debug"` | | +| | `"info"` | | +| | `"error"` | | +| | `"none"` | | + +At the end of a `module:level` list, a default log level can be set for modules with no level set. Use `*` instead of a +module name to set a default log level. The default is `*:info`. + +Examples: + +Set the consensus reactor to `debug` log level and the `p2p` reactor to `none`. Everything else should be set to `error`: +```toml +log_level = "consensus:debug,p2p:none,*:error" +``` +Set RPC server logs to `debug` and leave everything else at `info`: +```toml +log_level = "rpc-server:debug" +``` + +### log_format +Define the output format of the logs. +```toml +log_format = "plain" +``` + +| Value type | string | +|:--------------------|:----------| +| **Possible values** | `"plain"` | +| | `"json"` | + +`plain` provides ANSI color-coded plain-text logs. + +`json` provides JSON objects (one per line, not prettified) using the following (incomplete) schema: +```json +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://cometbft.com/log.schema.json", + "title": "JSON log", + "description": "A log entry in JSON object format", + "type": "object", + "properties": { + "level": { + "description": "log level", + "type": "string" + }, + "ts": { + "description": "timestamp in RFC3339Nano format; the trailing zeroes are removed from the seconds field", + "type": "string" + }, + "_msg": { + "description": "core log message", + "type": "string" + }, + "module": { + "description": "module name that emitted the log", + "type": "string" + }, + "impl": { + "description": "some modules point out specific areas or tasks in log entries", + "type": "string" + }, + "msg": { + "description": "some entries have more granular messages than just the core _msg", + "type": "string" + }, + "height": { + "description": "some entries happen at a specific height", + "type": "integer", + "exclusiveMinimum": 0 + }, + "app_hash": { + "description": "some entries happen at a specific app_hash", + "type": "string" + } + }, + "required": [ "level", "ts", "_msg", "module" ] +} +``` +> Note: The list of properties is not exhaustive. When implementing log parsing, check your logs and update the schema. + + + +### genesis_file +Path to the JSON file containing the initial conditions for a CometBFT blockchain and the initial state of the application (more details [here](./genesis.json.md)). +```toml +genesis_file = "config/genesis.json" +``` + +| Value type | string | +|:--------------------|:------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME` | +| | absolute directory path | + +The default relative path translates to `$CMTHOME/config/genesis.json`. In case `$CMTHOME` is unset, it defaults to +`$HOME/.cometbft/config/genesis.json`. + +### priv_validator_key_file +Path to the JSON file containing the private key to use as a validator in the consensus protocol (more details [here](./priv_validator_key.json.md)). +```toml +priv_validator_key_file = "config/priv_validator_key.json" +``` + +| Value type | string | +|:--------------------|:------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME` | +| | absolute directory path | + +The default relative path translates to `$CMTHOME/config/priv_validator_key.json`. In case `$CMTHOME` is unset, it +defaults to `$HOME/.cometbft/config/priv_validator_key.json`. + + +### priv_validator_state_file +Path to the JSON file containing the last sign state of a validator (more details [here](./priv_validator_state.json.md)). +```toml +priv_validator_state_file = "data/priv_validator_state.json" +``` + +| Value type | string | +|:--------------------|:------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME` | +| | absolute directory path | + +The default relative path translates to `$CMTHOME/data/priv_validator_state.json`. In case `$CMTHOME` is unset, it +defaults to `$HOME/.cometbft/data/priv_validator_state.json`. + +### priv_validator_laddr +TCP or UNIX socket listen address for CometBFT that allows external consensus signing processes to connect. +```toml +priv_validator_laddr = "" +``` + +| Value type | string | +|:--------------------|:-----------------------------------------------------------| +| **Possible values** | TCP Stream socket (e.g. `"tcp://127.0.0.1:26665"`) | +| | Unix domain socket (e.g. `"unix:///var/run/privval.sock"`) | + +When consensus signing is outsourced from CometBFT (typically to a Hardware Security Module, like a +[YubiHSM](https://www.yubico.com/product/yubihsm-2) device), this address is opened by CometBFT for incoming connections +from the signing service. + +Make sure the port is available on the host machine and firewalls allow the signing service to connect to it. + +More information on a supported signing service can be found in the [TMKMS](https://github.com/iqlusioninc/tmkms) +documentation. + +### node_key_file +Path to the JSON file containing the private key to use for node authentication in the p2p protocol (more details [here](./node_key.json.md)). +```toml +node_key_file = "config/node_key.json" +``` + +| Value type | string | +|:--------------------|:------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME` | +| | absolute directory path | + +The default relative path translates to `$CMTHOME/config/node_key.json`. In case `$CMTHOME` is unset, it defaults to +`$HOME/.cometbft/config/node_key.json`. + +### abci +The mechanism used to connect to the ABCI application. +````toml +abci = "socket" +```` + +| Value type | string | +|:--------------------|:-----------| +| **Possible values** | `"socket"` | +| | `"grpc"` | +| | `"" ` | + +This mechanism is used when connecting to the ABCI application over the [proxy_app](#proxy_app) socket. + +### filter_peers +When connecting to a new peer, filter the connection through an ABCI query to decide, if the connection should be kept. +```toml +filter_peers = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +When this setting is `true`, the ABCI application has to implement a query that will allow +the connection to be kept of or dropped. + +This feature will likely be deprecated. + +## RPC Server +These configuration options change the behaviour of the built-in RPC server. + +The RPC server is exposed without any kind of security control or authentication. Do NOT expose this server +on the public Internet without appropriate precautions. Make sure it is secured, load-balanced, etc. + +### rpc.laddr +TCP or UNIX socket address for the RPC server to listen on. +```toml +laddr = "tcp://127.0.0.1:26657" +``` + +| Value type | string | +|:--------------------|:--------------------------------------------------| +| **Possible values** | TCP Stream socket (e.g. `"tcp://127.0.0.1:26657"`) | +| | Unix domain socket (e.g. `"unix:///var/run/rpc.sock"`) | + +The RPC server endpoints have OpenAPI specification definitions through [Swagger UI](../../rpc). + + +Please refer to the [RPC documentation](https://docs.cometbft.com/v1.0/rpc/) for more information. + +### rpc.cors_allowed_origins +A list of origins a cross-domain request can be executed from. +```toml +cors_allowed_origins = [] +``` + +| Value type | array of string | | +|:--------------------|:-------------------------------------------|----------------------| +| **Possible values** | `[]` | disable CORS support | +| | `["*"]` | allow any origin | +| | array of strings containing domain origins | | + +Domain origins are fully qualified domain names with protocol prefixed, for example `"https://cometbft.com"` or +they can contain exactly one wildcard to extend to multiple subdomains, for example: `"https://*.myapis.com"`. + +Example: + +Allow only some subdomains for CORS requests: +```toml +cors_allowed_origins = ["https://www.cometbft.com", "https://*.apis.cometbft.com"] +``` + +### rpc.cors_allowed_methods +A list of methods the client is allowed to use with cross-domain requests. +```toml +cors_allowed_methods = ["HEAD", "GET", "POST", ] +``` + +| Value type | array of string | +|:----------------------------------------|:----------------| +| **Possible string values in the array** | `"HEAD"` | +| | `"GET"` | +| | `"POST"` | + +You can read more about the methods in the +[Mozilla CORS documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). + +### rpc.cors_allowed_headers +A list of headers the client is allowed to use with cross-domain requests. +```toml +cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ] +``` + +| Value type | array of string | +|:----------------------------------------|:---------------------| +| **Possible string values in the array** | `"Accept"` | +| | `"Accept-Language"` | +| | `"Content-Language"` | +| | `"Content-Type"` | +| | `"Range"` | + +The list of possible values are from the [Fetch spec](https://fetch.spec.whatwg.org/#cors-safelisted-request-header) +which defines `Origin` as a forbidden value. Read the +[Mozilla CORS documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) and do your own tests, if you want +to use this parameter. + + + +### rpc.unsafe +Activate unsafe RPC endpoints. +```toml +unsafe = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +| Unsafe RPC endpoints | Description | +|:------------------------|---------------------------------------------------------------------------------------| +| `/dial_seeds` | dials the given seeds (comma-separated id@IP:port) | +| `/dial_peers` | dials the given peers (comma-separated id@IP:port), optionally making them persistent | +| `/unsafe_flush_mempool` | removes all transactions from the mempool | + +Keep this `false` on production systems. + +### rpc.max_open_connections +Maximum number of simultaneous open connections. This includes WebSocket connections. +```toml +max_open_connections = 900 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | > 0 | + +If you want to accept a larger number of connections than the default 900, make sure that you increase the maximum +number of open connections in the operating system. Usually, the `ulimit` command can help with that. + +This value can be estimated by the following calculation: +``` +$(ulimit -Sn) - {p2p.max_num_inbound_peers} - {p2p.max_num_outbound_peers} - {number of WAL, DB and other open files} +``` + +Estimating the number of WAL, DB and other files at `50`, and using the default soft limit of Debian Linux (`1024`): +``` +1024 - 40 - 10 - 50 = 924 (~900) +``` + +Note, that macOS has a default soft limit of `256`. Make sure you calculate this value for the operating system CometBFT +runs on. + +### rpc.max_subscription_clients +Maximum number of unique clientIDs that can subscribe to events at the `/subscribe` RPC endpoint. +```toml +max_subscription_clients = 100 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +### rpc.max_subscriptions_per_client +Maximum number of unique queries a given client can subscribe to at the `/subscribe` RPC endpoint. +```toml +max_subscriptions_per_client = 5 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +### rpc.experimental_subscription_buffer_size +> EXPERIMENTAL parameter! + +Experimental parameter to specify the maximum number of events a node will buffer, per subscription, before returning +an error and closing the subscription. +```toml +experimental_subscription_buffer_size = 200 +``` + +| Value type | integer | +|:--------------------|:----------| +| **Possible values** | >= 100 | + +Higher values will accommodate higher event throughput rates (and will use more memory). + +### rpc.experimental_websocket_write_buffer_size +> EXPERIMENTAL parameter! + +Experimental parameter to specify the maximum number of events that can be buffered per WebSocket client. +```toml +experimental_websocket_write_buffer_size = 200 +``` + +| Value type | integer | +|:--------------------|:------------------------------------------------| +| **Possible values** | >= rpc.experimental_subscription_buffer_size | + +If clients cannot read from the WebSocket endpoint fast enough, they will be disconnected, so increasing this parameter +may reduce the chances of them being disconnected (but will cause the node to use more memory). + +If set lower than `rpc.experimental_subscription_buffer_size`, connections could be dropped unnecessarily. This value +should ideally be somewhat higher to accommodate non-subscription-related RPC responses. + +### rpc.experimental_close_on_slow_client +> EXPERIMENTAL parameter! + +Close the WebSocket client in case it cannot read events fast enough. Allows greater predictability in subscription +behaviour. +```toml +experimental_close_on_slow_client = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +The default behaviour for WebSocket clients is to silently drop events, if they cannot read them fast enough. This does +not cause an error and creates unpredictability. +Enabling this setting creates a predictable outcome by closing the WebSocket connection in case it cannot read events +fast enough. + +### rpc.timeout_broadcast_tx_commit +Timeout waiting for a transaction to be committed when using the `/broadcast_tx_commit` RPC endpoint. +```toml +timeout_broadcast_tx_commit = "10s" +``` + +| Value type | string (duration) | +|:--------------------|:---------------------------| +| **Possible values** | > `"0s"`; <= `"10s"` | + +Using a value larger than `"10s"` will result in increasing the global HTTP write timeout, which applies to all connections +and endpoints. There is an old developer discussion about this [here](https://github.com/tendermint/tendermint/issues/3435). + +> Note: It is generally recommended *not* to use the `broadcast_tx_commit` method in production, and instead prefer `/broadcast_tx_sync`. + +### rpc.max_body_bytes +Maximum size of request body, in bytes. +```toml +max_body_bytes = 1000000 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +### rpc.max_header_bytes +Maximum size of request header, in bytes. +```toml +max_header_bytes = 1048576 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +### rpc.tls_cert_file +TLS certificates file path for HTTPS server use. +```toml +tls_cert_file = "" +``` + +| Value type | string | +|:--------------------|:-------------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME/config` | +| | absolute directory path | +| | `""` | + +The default relative path translates to `$CMTHOME/config`. In case `$CMTHOME` is unset, it defaults to +`$HOME/.cometbft/config`. + +If the certificate is signed by a certificate authority, the certificate file should be the concatenation of the +server certificate, any intermediate certificates, and the Certificate Authority certificate. + +The [rpc.tls_key_file](#rpctls_key_file) property also has to be set with the matching private key. + +If this property is not set, the HTTP protocol will be used by the default server + +### rpc.tls_key_file +TLS private key file path for HTTPS server use. +```toml +tls_key_file = "" +``` + +| Value type | string | +|:--------------------|:-------------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME/config` | +| | absolute directory path | +| | `""` | + +The default relative path translates to `$CMTHOME/config`. In case `$CMTHOME` is unset, it defaults to +`$HOME/.cometbft/config`. + +The [rpc.tls_cert_file](#rpctls_cert_file) property also has to be set with the matching server certificate. + +If this property is not set, the HTTP protocol will be used by the default server + +### rpc.pprof_laddr +Profiling data listen address and port. Without protocol prefix. +```toml +pprof_laddr = "" +``` + +| Value type | string | +|:--------------------|:-----------------------------| +| **Possible values** | IP:port (`"127.0.0.1:6060"`) | +| | :port (`":6060"`) | +| | `""` | + +HTTP is always assumed as the protocol. + +See the Golang [profiling](https://golang.org/pkg/net/http/pprof) documentation for more information. + +## gRPC Server +These configuration options change the behaviour of the built-in gRPC server. + +Each gRPC service can be turned on/off, and in some cases configured, individually. +If the gRPC server is not enabled, all individual services' configurations are ignored. + +The gRPC server is exposed without any kind of security control or authentication. Do NOT expose this server +on the public Internet without appropriate precautions. Make sure it is secured, authenticated, load-balanced, etc. + +### grpc.laddr +TCP or UNIX socket address for the gRPC server to listen on. +```toml +laddr = "" +``` + +| Value type | string | +|:--------------------|:--------------------------------------------------------| +| **Possible values** | TCP Stream socket (e.g. `"tcp://127.0.0.1:26661"`) | +| | Unix domain socket (e.g. `"unix:///var/run/abci.sock"`) | +| | `""` | + +If not specified, the gRPC server will be disabled. + +### grpc.version_service.enabled +The gRPC version service provides version information about the node and the protocols it uses. +```toml +enabled = true +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `true` | +| | `false` | + +If [`grpc.laddr`](#grpcladdr) is empty, this setting is ignored and the service is not enabled. + +### grpc.block_service.enabled +The gRPC block service returns block information. +```toml +enabled = true +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `true` | +| | `false` | + +If [`grpc.laddr`](#grpcladdr) is empty, this setting is ignored and the service is not enabled. + +### grpc.block_results_service.enabled +The gRPC block results service returns block results for a given height. If no height is given, it will return the block +results from the latest height. +```toml +enabled = true +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `true` | +| | `false` | + +If [`grpc.laddr`](#grpcladdr) is empty, this setting is ignored and the service is not enabled. + +### grpc.privileged.laddr +Configuration for privileged gRPC endpoints, which should **never** be exposed to the public internet. +```toml +laddr = "" +``` + +| Value type | string | +|:--------------------|:--------------------------------------------------------| +| **Possible values** | TCP Stream socket (e.g. `"tcp://127.0.0.1:26662"`) | +| | Unix domain socket (e.g. `"unix:///var/run/abci.sock"`) | +| | `""` | + +If not specified, the gRPC privileged endpoints will be disabled. + +### grpc.privileged.pruning_service +Configuration specifically for the gRPC pruning service, which is considered a privileged service. +```toml +enabled = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +Only controls whether the pruning service is accessible via the gRPC API - not whether a previously set pruning service +retain height is honored by the node. See the [storage.pruning](#storagepruninginterval) section for control over pruning. + +If [`grpc.laddr`](#grpcladdr) is empty, this setting is ignored and the service is not enabled. + +## Peer-to-peer + +These configuration options change the behaviour of the peer-to-peer protocol. + +### p2p.laddr + +TCP socket address for the P2P service to listen on and accept connections. +```toml +laddr = "tcp://0.0.0.0:26656" +``` + +| Value type | string | +|:--------------------|:--------------------------------------------------| +| **Possible values** | TCP Stream socket (e.g. `"tcp://0.0.0.0:26657"`) | + +### p2p.external_address + +TCP address that peers should use in order to connect to the node. +This is the address that the node advertises to peers. +If not set, the [`p2p.laddr`](#p2pladdr) is advertised. + +Useful when the node is running on a non-routable address or when the +node does not have the capabilities to figure out its IP public address. +For example, this is useful when running from a cloud service (e.g, AWS, Digital Ocean). +In these scenarios, the public or external address of the node should be set to +`p2p.external_address`, while INADDR_ANY (i.e., `0.0.0.0`) should be used as +the listen address ([`p2p.laddr`](#p2pladdr)). + +```toml +external_address = "" +``` + +| Value type | string | +|:--------------------|:----------------------------| +| **Possible values** | IP:port (`"1.2.3.4:26656"`) | +| | `""` | + +The port has to point to the node's P2P port. + +Example with a node on a NATed non-routable network: +- Node has local or private IP address `10.10.10.10` and uses port `10000` for + P2P communication: set this address as the [listen address](#p2pladdr) (`p2p.laddr`). +- The network gateway has the public IP `1.2.3.4` and we want to use publicly + open port `26656` on the IP address. In this case, a redirection has to be + set up from `1.2.3.4:26656` to `10.10.10.10:1000` in the gateway implementing NAT; +- Or the node has an associated public or external IP `1.2.3.4` + that is mapped to its local or private IP. +- Set `p2p.external_address` to `1.2.3.4:26656`. + +### p2p.seeds + +Comma-separated list of seed nodes. + +```toml +seeds = "" +``` + +| Value type | string (comma-separated list) | +|:----------------------------------|:----------------------------------------| +| **Possible values within commas** | nodeID@IP:port (`"abcd@1.2.3.4:26656"`) | +| | `""` | + +The node will try to connect to any of the configured seed nodes when it needs +addresses of potential peers to connect. + +Example: +```toml +seeds = "abcd@1.2.3.4:26656,deadbeef@5.6.7.8:10000" +``` + +### p2p.persistent_peers + +Comma-separated list of nodes to keep persistent connections to. + +```toml +persistent_peers = "" +``` + +| Value type | string (comma-separated list) | +|:----------------------------------|:----------------------------------------| +| **Possible values within commas** | nodeID@IP:port (`"abcd@1.2.3.4:26656"`) | +| | `""` | + +The node will attempt to establish connections to all configured persistent peers. +This in particular means that persistent peers do not count towards +the configured [`p2p.max_num_outbound_peers`](#p2pmax_num_outbound_peers) +(refer to [issue 1304](https://github.com/cometbft/cometbft/issues/1304) for more details). +Moreover, if a connection to a persistent peer is lost, the node will attempt +reconnecting to that peer. + +Once connected to a persistent peer, the node will request addresses of +potential peers. +This means that when persistent peers are configured the node may not need to +rely on potential peers provided by [seed nodes](#p2pseeds). + +Example: +```toml +persistent_peers = "fedcba@11.22.33.44:26656,beefdead@55.66.77.88:20000" +``` + +### p2p.addr_book_file + +Path to the address book file. + +```toml +addr_book_file = "config/addrbook.json" +``` + +| Value type | string | +|:--------------------|:------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME` | +| | absolute directory path | + +The default relative path translates to `$CMTHOME/config/addrbook.json`. In case `$CMTHOME` is unset, it defaults to +`$HOME/.cometbft/config/addrbook.json`. + +The node periodically persists the content of its address book (addresses of +potential peers and information regarding connected peers) to the address book file. +If the node is started with a non-empty address book file, it may not need to +rely on potential peers provided by [seed nodes](#p2pseeds). + +### p2p.addr_book_strict + +Strict address routability rules disallow non-routable IP addresses in the address book. When `false`, private network +IP addresses are enabled to be stored in the address book and dialed. + +```toml +addr_book_strict = true +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `true` | +| | `false` | + +Set it to `false` for testing on private network. Most production nodes can keep it at `true`. + +### p2p.max_num_inbound_peers + +Maximum number of inbound peers, +that is, peers from which the node accepts connections. + +```toml +max_num_inbound_peers = 40 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +The [`p2p.max_num_inbound_peers`](#p2pmax_num_inbound_peers) and +[`p2p.max_num_outbound_peers`](#p2pmax_num_outbound_peers) values +work together to define how many P2P connections the node will +maintain at maximum capacity. + +Nodes configured as [unconditional peers](#p2punconditional_peer_ids) do not count towards the +configured `p2p.max_num_inbound_peers` limit. + +The connections are bidirectional, so any connection can send or receive messages, blocks, and other data. The separation into +inbound and outbound setting only distinguishes the initial setup of the connection: outbound connections are initiated +by the node while inbound connections are initiated by a remote party. + +Nodes on non-routable networks have to set their gateway to port-forward the P2P port for inbound connections to reach +the node. Inbound connections can be accepted as long as the node has an address accessible from the Internet (using NAT or other methods). +Refer to the [p2p.external_address](#p2pexternal_address) configuration for details. + +### p2p.max_num_outbound_peers + +Maximum number of outbound peers, +that is, peers to which the node dials and establishes connections. + +```toml +max_num_outbound_peers = 10 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +The [`p2p.max_num_inbound_peers`](#p2pmax_num_inbound_peers) and +[`p2p.max_num_outbound_peers`](#p2pmax_num_outbound_peers) values +work together to define how many P2P connections the node will +maintain at maximum capacity. + +The `p2p.max_num_outbound_peers` configuration should be seen as the target +number of outbound connections that a node is expected to establish. +While the maximum configured number of outbound connections is not reached, +the node will attempt to establish connections to potential peers. + +This configuration only has effect if the [PEX reactor](#p2ppex) is enabled. +Nodes configured as [persistent peers](#p2ppersistent_peers) do not count towards the +configured `p2p.max_num_outbound_peers` limit +(refer to [issue 1304](https://github.com/cometbft/cometbft/issues/1304) for more details). + +The connections are bidirectional, so any connection can send or receive messages, blocks, and other data. The separation into +inbound and outbound setting only distinguishes the initial setup of the connection: outbound connections are initiated +by the node while inbound connections are initiated by a remote party. + +Nodes on non-routable networks have to set their gateway to port-forward the P2P port for inbound connections to reach +the node. Outbound connections can only be initiated to peers that have addresses accessible from the Internet (using NAT or other methods). +Refer to the [p2p.external_address](#p2pexternal_address) configuration for details. + +### p2p.unconditional_peer_ids + +List of node IDs that are allowed to connect to the node even when connection limits are exceeded. + +```toml +unconditional_peer_ids = "" +``` + +| Value type | string (comma-separated) | +|:--------------------|:---------------------------------| +| **Possible values** | comma-separated list of node IDs | +| | `""` | + +If a peer listed in this property establishes a connection to the node, it will be accepted even if the +configured [`p2p.max_num_inbound_peers`](#p2pmax_num_inbound_peers) limit was reached. +Peers on this list also do not count towards the +configured [`p2p.max_num_outbound_peers`](#p2pmax_num_outbound_peers) limit. + +Contrary to other settings, only the node ID has to be defined here, not the IP:port of the remote node. + +### p2p.persistent_peers_max_dial_period + +Maximum pause between successive attempts when dialing a persistent peer. + +```toml +persistent_peers_max_dial_period = "0s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +When set to `"0s"`, an exponential backoff is applied when re-dialing the persistent peer over and over. + +### p2p.flush_throttle_timeout + +Time to wait before flushing messages out on a connection. + +```toml +flush_throttle_timeout = "100ms" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0ms"` | + +The flush operation writes any buffered data to the connection. The flush is throttled, so if multiple triggers come in within the +configured timeout, only one flush is executed. + +Setting the value to `0ms` makes flushing messages out on a connection immediate. +While this might reduce latency, it may degrade throughput as batching +outstanding messages is essentially disabled. + +### p2p.max_packet_msg_payload_size + +Maximum size of a packet payload, in bytes. + +```toml +max_packet_msg_payload_size = 1024 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | > 0 | + +Messages exchanged via P2P connections are split into packets. +Packets contain some metadata and message data (payload). +The value configures the maximum size in bytes of the payload +included in a packet. + +### p2p.send_rate + +Rate at which packets can be sent, in bytes/second. + +```toml +send_rate = 5120000 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | > 0 | + +The value represents the amount of packet bytes that can be sent per second +by each P2P connection. + +### p2p.recv_rate + +Rate at which packets can be received, in bytes/second. + +```toml +recv_rate = 5120000 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | > 0 | + +The value represents the amount of packet bytes that can be received per second +by each P2P connection. + +### p2p.pex + +```toml +pex = true +``` + +Enable peer exchange (PEX) reactor. + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `true` | +| | `false` | + +The peer exchange reactor is responsible for exchanging addresses of potential +peers among nodes. +If the PEX reactor is disabled, the node can only connect to +addresses configured as [persistent peers](#p2ppersistent_peers). + +In the [Sentry Node Architecture](https://forum.cosmos.network/t/sentry-node-architecture-overview/454) on the Cosmos Hub, +validator nodes should have the PEX reactor disabled, +as their connections are manually configured via [persistent peers](#p2ppersistent_peers). +Public nodes, such as sentry nodes, should have the PEX reactor enabled, +as this allows them to discover and connect to public peers in the network. + +### p2p.seed_mode + +In seed mode, the node crawls the network and looks for peers. + +```toml +seed_mode = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +In seed mode, the node becomes an online address book. Any incoming connections +can receive a sample of the gathered addresses but no other information (for +example blocks or consensus data) is provided. The node simply disconnects +from the peer after sending the addresses. + +Nodes operating in seed mode should be configured as [seeds](#p2pseeds) for other +nodes in the network. + +The [`p2p.pex`](#p2ppex) option has to be set to `true` for the seed mode to work. + +### p2p.private_peer_ids + +Comma separated list of peer IDs to keep private, they will not be gossiped to other peers. + +```toml +private_peer_ids = "" +``` + +| Value type | string (comma-separated list) | +|:----------------------------------|:----------------------------------| +| **Possible values within commas** | nodeID (`"abcdef0123456789abcd"`) | +| | `""` | + +The addresses with the listed node IDs will not be sent to other peers when the PEX reactor +([`p2p.pex`](#p2ppex)) is enabled. This allows a more granular setting instead of completely disabling the peer exchange +reactor. + +For example, sentry nodes in the +[Sentry Node Architecture](https://forum.cosmos.network/t/sentry-node-architecture-overview/454) on the Cosmos Hub can +use this setting to make sure they do not gossip the node ID of the validator node, while they can still accept node +addresses from the Internet. + +### p2p.allow_duplicate_ip + +Toggle to disable guard against peers connecting from the same IP. + +```toml +allow_duplicate_ip = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +When this setting is set to `true`, multiple connections are allowed from the same IP address (for example, on different +ports). + +### p2p.handshake_timeout + +Timeout duration for protocol handshake (or secret connection negotiation). + +```toml +handshake_timeout = "20s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +This high-level timeout value is applied when the TCP connection has been +established with a peer, and the node and peer are negotiating its upgrade into +a secret authenticated connection. + +The value `"0s"` is undefined, and it can lead to unexpected behaviour. + +### p2p.dial_timeout + +Timeout duration for the low-level dialer that connects to the remote address on the TCP network. + +```toml +dial_timeout = "3s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +This parameter is the timeout value for dialing on TCP networks. If a hostname is used instead of an IP address and the +hostname resolves to multiple IP addresses, the timeout is spread over each consecutive dial, such that each is given an +appropriate fraction of the time to connect. + +Setting the value to `"0s"` disables the timeout. + +## Mempool +Mempool allows gathering and broadcasting uncommitted transactions among nodes. + +The **mempool** is storage for uncommitted transactions; the **mempool cache** is internal storage within the +mempool for seen transactions. The mempool cache provides a list of transactions already received to filter out +incoming duplicate transactions and prevent duplicate full transaction validations. + +### mempool.type +The type of mempool this node will use. +```toml +type = "flood" +``` + +| Value type | string | +|:--------------------|:----------| +| **Possible values** | `"flood"` | +| | `"nop"` | + +`"flood"` is the original mempool implemented for CometBFT. It is a concurrent linked list with flooding gossip +protocol. + +`"nop"` is a "no operation" or disabled mempool, where the ABCI application is responsible for storing, disseminating and +proposing transactions. Note, that it requires empty blocks to be created: +[`consensus.create_empty_blocks = true`](#consensuscreate_empty_blocks) has to be set. + +### mempool.recheck +Validity check of transactions already in the mempool when a block is finalized. +```toml +recheck = true +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `true` | +| | `false` | + +Committing a block affects the application state, hence the remaining transactions in the mempool after a block commit +might become invalid. Setting `recheck = true` will go through the remaining transactions and remove invalid ones. + +If your application may remove transactions passed by CometBFT to your `PrepareProposal` handler, +you probably want to set this configuration to `true` to avoid possible leaks in your mempool +(transactions staying in the mempool until the node is next restarted). +### mempool.broadcast +Broadcast the mempool content (uncommitted transactions) to other nodes. +```toml +broadcast = true +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `true` | +| | `false` | + +This ensures that uncommitted transactions have a chance to reach multiple validators and get committed by one of them. + +Setting this to `false` will stop the mempool from relaying transactions to other peers. +Validators behind sentry nodes typically set this to `false`, +as their sentry nodes take care of disseminating transactions to the rest of the network. + +### mempool.wal_dir +Mempool write-ahead log folder path. +```toml +wal_dir = "" +``` + +| Value type | string | +|:--------------------|:------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME` | +| | absolute directory path | +| | `""` | + +In case `$CMTHOME` is unset, it defaults to `$HOME/.cometbft`. + +This value is unused by CometBFT. It was not hooked up to the mempool reactor. + +The mempool implementation does not persist any transaction data to disk (unlike evidence). + +### mempool.size +Maximum number of transactions in the mempool. +```toml +size = 5000 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +If the mempool is full, incoming transactions are dropped. + +The value `0` is undefined. + +### mempool.max_tx_bytes +Maximum size in bytes of a single transaction accepted into the mempool. +```toml +max_tx_bytes = 1048576 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +Transactions bigger than the maximum configured size are rejected by mempool, +this applies to both transactions submitted by clients via RPC endpoints, and +transactions receveing from peers on the mempool protocol. + +### mempool.max_txs_bytes +The maximum size in bytes of all transactions stored in the mempool. +```toml +max_txs_bytes = 67108864 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +This is the raw, total size in bytes of all transactions in the mempool. For example, given 1MB +transactions and a 5MB maximum mempool byte size, the mempool will +only accept five transactions. + +The maximum mempool byte size should be a factor of the network's maximum block size +(which is a [consensus parameter](https://docs.cometbft.com/v1.0/spec/abci/abci++_app_requirements#blockparamsmaxbytes)). +The rationale is to consider how many blocks have to be produced in order to +drain all transactions stored in a full mempool. + +When the mempool is full, incoming transactions are dropped. + +The default value is 64 Mibibyte (2^26 bytes). +This is roughly equivalent to 16 blocks of 4 MiB. + +### mempool.cache_size +Mempool internal cache size for already seen transactions. +```toml +cache_size = 10000 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +The mempool cache is an internal store for transactions that the local node has already seen. Storing these transactions help in filtering incoming duplicate +transactions: we can compare incoming transactions to already seen transactions and filter them out without going +through the process of validating the incoming transaction. + +### mempool.keep-invalid-txs-in-cache +Invalid transactions might become valid in the future, hence they are not added to the mempool cache by default. +Turning this setting on will add an incoming transaction to the cache even if it is deemed invalid by the application (via `CheckTx`). +```toml +keep-invalid-txs-in-cache = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +If this setting is set to `true`, the mempool cache will add incoming transactions even if they are invalid. It is useful in cases when +invalid transactions can never become valid again. + +This setting can be used by operators to lower the impact of some spam transactions: when a large number of duplicate +spam transactions are noted on the network, temporarily turning this setting to `true` will filter out the duplicates +quicker than validating each transaction one-by-one. It will also filter out transactions that are supposed to become +valid at a later date. + +### mempool.experimental_max_gossip_connections_to_persistent_peers +> EXPERIMENTAL parameter! + +Limit the number of persistent peer nodes that get mempool transaction broadcasts. +```toml +experimental_max_gossip_connections_to_persistent_peers = 0 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +When set to `0`, the mempool is broadcasting to all the nodes listed in the +[`p2p.persistent_peers`](#p2ppersistent_peers) list. If the number is above `0`, the number of nodes that get broadcasts +will be limited to this setting. + +Unconditional peers and peers not listed in the [`p2p.persistent_peers`](#p2ppersistent_peers) list are not affected by +this parameter. + +See +[`mempool.experimental_max_gossip_connections_to_non_persistent_peers`](#mempoolexperimental_max_gossip_connections_to_persistent_peers) +to limit mempool broadcasts that are not in the list of [`p2p.persistent_peers`](#p2ppersistent_peers). + +### mempool.experimental_max_gossip_connections_to_non_persistent_peers +> EXPERIMENTAL parameter! + +Limit the number of peer nodes that get mempool transaction broadcasts. This parameter does not limit nodes that are +in the [`p2p.persistent_peers`](#p2ppersistent_peers) list. +```toml +experimental_max_gossip_connections_to_non_persistent_peers = 0 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +When set to `0`, the mempool is broadcasting to all the nodes. If the number is above `0`, the number of nodes that get +broadcasts will be limited to this setting. + +Unconditional peers and peers listed in the [`p2p.persistent_peers`](#p2ppersistent_peers) list are not affected by +this parameter. + +See +[`mempool.experimental_max_gossip_connections_to_persistent_peers`](#mempoolexperimental_max_gossip_connections_to_persistent_peers) +to limit broadcasts to persistent peer nodes. + +For non-persistent peers, if enabled, a value of 10 is recommended based on experimental performance results using the +default P2P configuration. + +## State synchronization +State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine snapshot from peers +instead of fetching and replaying historical blocks. It requires some peers in the network to take and serve state +machine snapshots. State sync is not attempted if the starting node has any local state (i.e., it is recovering). + +The node will have a truncated block history, starting from the height of the snapshot. + +### statesync.enable +Enable state synchronization. +```toml +enable = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +Enable state synchronization on first start. + +### statesync.rpc_servers +Comma-separated list of RPC servers for light client verification of the synced state machine, +and retrieval of state data for node bootstrapping. +```toml +rpc_servers = "" +``` + +| Value type | string (comma-separated list) | +|:----------------------------------|:-----------------------------------| +| **Possible values within commas** | nodeID@IP:port (`"1.2.3.4:26657"`) | +| | `""` | + +At least two RPC servers have to be defined for state synchronization to work. + +### statesync.trust_height +The height of the trusted header hash. +```toml +trust_height = 0 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +`0` is only allowed when state synchronization is disabled. + +### statesync.trust_hash +Header hash obtained from a trusted source. +```toml +trust_hash = "" +``` + +| Value type | string | +|:--------------------|:-------------------| +| **Possible values** | hex-encoded number | +| | "" | + +`""` is only allowed when state synchronization is disabled. + +This is the header hash value obtained from the trusted source at height +[statesync.trust_height](#statesynctrust_height). + +### statesync.trust_period +The period during which validators can be trusted. +```toml +trust_period = "168h0m0s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +For Cosmos SDK-based chains, `statesync.trust_period` should usually be about 2/3rd of the unbonding period +(about 2 weeks) during which they can be financially punished (slashed) for misbehavior. + +### statesync.discovery_time +Time to spend discovering snapshots before initiating a restore. +```toml +discovery_time = "15s" +``` + +If `discovery_time` is > 0 and < 5 seconds, its value will be overridden to 5 seconds. + +If `discovery_time` is zero, the node will not wait for replies once it has broadcast the "snapshot request" message to its peers. If no snapshot data is received, state sync will fail without retrying. + +If `discovery_time` is >= 5 seconds, the node will broadcast the "snapshot request" message to its peers and then wait for `discovery_time`. If no snapshot data has been received after that period, the node will retry: it will broadcast the "snapshot request" message again and wait for `discovery_time`, and so on. + +### statesync.temp_dir +Temporary directory for state sync snapshot chunks. +```toml +temp_dir = "" +``` + +| Value type | string | +|:--------------------|:------------------------| +| **Possible values** | undefined | + +This value is unused by CometBFT. It was not hooked up to the state sync reactor. + +The codebase will always revert to `/tmp/` for state snapshot chunks. Make sure you have enough space on +your drive that holds `/tmp`. + +### statesync.chunk_request_timeout +The timeout duration before re-requesting a chunk, possibly from a different peer. +```toml +chunk_request_timeout = "10s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"5s"` | + +If a smaller duration is set when state syncing is enabled, an error message is raised. + +### statesync.chunk_fetchers +The number of concurrent chunk fetchers to run. + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +`0` is only allowed when state synchronization is disabled. + +## Block synchronization +Block synchronization configuration is limited to defining a version of block synchronization to use. + +### blocksync.version +Block Sync version to use. +```toml +version = "v0" +``` + +| Value type | string | +|:--------------------|:--------| +| **Possible values** | `"v0"` | + +All other versions are deprecated. Further versions may be added in future releases. + +## Consensus + +Consensus parameters define how the consensus protocol should behave. + +### consensus.wal_file + +Location of the consensus Write-Ahead Log (WAL) file. + +```toml +wal_file = "data/cs.wal/wal" +``` + +| Value type | string | +|:--------------------|:------------------------------------------------| +| **Possible values** | relative directory path, appended to `$CMTHOME` | +| | absolute directory path | + +The default relative path translates to `$CMTHOME/data/cs.wal/wal`. In case `$CMTHOME` is unset, it defaults to +`$HOME/.cometbft/data/cs.wal/wal`. + +The consensus WAL stores all consensus messages received and broadcast by a +node, as well as some important consensus events (e.g., new height and new round step). +The goal of this log is to enable a node that crashes and later recovers +to re-join consensus with the same state it has before crashing. +Recovering nodes that "forget" the actions taken before crashing are faulty +nodes that are likely to present Byzantine behavior (e.g., double signing). + +### consensus.timeout_propose + +How long a node waits for the proposal block before prevoting nil. + +```toml +timeout_propose = "3s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +The proposal block of a round of consensus is broadcast by the proposer of that round. +The `timeout_propose` should be large enough to encompass the common-case +propagation delay of a `Proposal` and one or more `BlockPart` (depending on the +proposed block size) messages from any validator to the node. + +If the proposed block is not received within `timeout_propose`, validators +issue a prevote for nil, indicating that they have not received, and +therefore are unable to vote for, the block proposed in that round. + +Setting `timeout_propose` to `0s` means that the validator does not wait at all +for the proposal block and always prevotes nil. +This has obvious liveness implications since this validator will never prevote +for proposed blocks. + +### consensus.timeout_propose_delta + +How much `timeout_propose` increases with each round. + +```toml +timeout_propose_delta = "500ms" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0ms"` | + +Consensus timeouts are adaptive. +This means that when a round of consensus fails to commit a block, the next +round of consensus will adopt increased timeout durations. +Timeouts increase linearly over rounds, so that the `timeout_propose` adopted +in round `r` is `timeout_propose + r * timeout_propose_delta`. + +### consensus.timeout_prevote + +How long a node waits, after receiving +2/3 conflicting prevotes, before pre-committing nil. + +```toml +timeout_prevote = "1s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +A validator that receives +2/3 prevotes for a block, precommits that block. +If it receives +2/3 prevotes for nil, it precommits nil. +But if prevotes are received from +2/3 validators, but the prevotes do not +match (e.g., they are for different blocks or for blocks and nil), the +validator waits for `timeout_prevote` time before precommiting nil. +This gives the validator a chance to wait for additional prevotes and to +possibly observe +2/3 prevotes for a block. + +Setting `timeout_prevote` to `0s` means that the validator will not wait +for additional prevotes (other than the mandatory +2/3) before precommitting nil. +This has important liveness implications and should be avoided. + +### consensus.timeout_prevote_delta + +How much the `timeout_prevote` increases with each round. + +```toml +timeout_prevote_delta = "500ms" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0ms"` | + +Consensus timeouts are adaptive. +This means that when a round of consensus fails to commit a block, the next +round of consensus will adopt increased timeout durations. +Timeouts increase linearly over rounds, so that the `timeout_prevote` adopted +in round `r` is `timeout_prevote + r * timeout_prevote_delta`. + +### consensus.timeout_precommit + +How long a node waits, after receiving +2/3 conflicting precommits, before moving to the next round. + +```toml +timeout_precommit = "1s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +A node that receives +2/3 precommits for a block commits that block. +This is a successful consensus round. +If no block gathers +2/3 precommits, the node cannot commit. +This is an unsuccessful consensus round and the node will start an additional +round of consensus. +Before starting the next round, the node waits for `timeout_precommit` time. +This gives the node a chance to wait for additional precommits and to possibly +observe +2/3 precommits for a block, which would allow the node to commit that +block in the current round. + +Setting `timeout_precommit` to `0s` means that the validator will not wait +for additional precommits (other than the mandatory +2/3) before moving to the +next round. +This has important liveness implications and should be avoided. + +### consensus.timeout_precommit_delta +How much the timeout_precommit increases with each round. +```toml +timeout_precommit_delta = "500ms" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0ms"` | + +Consensus timeouts are adaptive. +This means that when a round of consensus fails to commit a block, the next +round of consensus will adopt increased timeout durations. +Timeouts increase linearly over rounds, so that the `timeout_precommit` adopted +in round `r` is `timeout_precommit + r * timeout_precommit_delta`. + +### consensus.timeout_commit + +How long a node waits after committing a block, before starting on the next height. + +```toml +timeout_commit = "1s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +The `timeout_commit` represents the minimum interval between the commit of a +block until the start of the next height of consensus. +It gives the node a chance to gather additional precommits for the committed +block, more than the mandatory +2/3 precommits required to commit a block. +The more precommits are gathered for a block, the greater are the safety +guarantees and the easier is to detect misbehaving validators. + +The `timeout_commit` is not a required component of the consensus algorithm, +meaning that there are no liveness implications if it is set to `0s`. +But it may have implications in the way the application rewards validators. + +### consensus.double_sign_check_height + +How many blocks to look back to check the existence of the node's consensus votes before joining consensus. + +```toml +double_sign_check_height = 0 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +When non-zero, the validator will panic upon restart if the validator's current +consensus key was used to sign any precommit message for the last +`double_sign_check_height` blocks. +If this happens, the validators should stop the state machine, wait for some +blocks, and then restart the state machine again. + +### consensus.skip_timeout_commit + +Start the next height as soon as the node gathers all the mandatory +2/3 precommits for a block. + +```toml +skip_timeout_commit = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +Setting `skip_timeout_commit` to `true` has the similar effect as setting [`timeout_commit`](#consensustimeout_commit) to `"0s"`. + +### consensus.create_empty_blocks + +Propose empty blocks if the validator's mempool does not have any transaction. + +```toml +create_empty_blocks = true +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `true` | +| | `false` | + +When set to `true`, empty blocks are produced and proposed to indicate that the +chain is still operative. +When set to `false`, blocks are not produced or proposed while there are no +transactions in the validator's mempool. + +Notice that empty blocks are still proposed whenever the application hash +(`app_hash`) has been updated. + +This is more relevant for networks with a low volume number of transactions. + +### consensus.create_empty_blocks_interval + +How long a validator should wait before proposing an empty block. + +```toml +create_empty_blocks_interval = "0s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +If there are no transactions in the validator's mempool, the validator +waits for `create_empty_blocks_interval` before producing and proposing an +empty block (with no transactions). + +If [`create_empty_blocks`](#createemptyblocks) is set to `false` and +`create_empty_blocks_interval` is set to `0s`, the validator will wait +indefinitely until a transaction is available in its mempool, +to then produce and propose a block. + +Notice that empty blocks are still proposed without waiting for `create_empty_blocks_interval` +whenever the application hash +(`app_hash`) has been updated. + +### consensus.peer_gossip_sleep_duration + +Consensus reactor internal sleep duration when there is no message to send to a peer. + +```toml +peer_gossip_sleep_duration = "100ms" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0ms"` | + +The consensus reactor gossips consensus messages, by sending or forwarding them +to peers. +When there are no messages to be sent to a peer, each reactor routine waits for +`peer_gossip_sleep_duration` time before checking if there are new messages to +be sent to that peer, or if the peer state has been meanwhile updated. + +This generic sleep duration allows other reactor routines to run when a reactor +routine has no work to do. + +### consensus.peer_gossip_intraloop_sleep_duration + +Consensus reactor upper bound for a random sleep duration. + +```toml +peer_gossip_intraloop_sleep_duration = "0s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +The consensus reactor gossips consensus messages, by sending or forwarding them +to peers. + +If `peer_gossip_intraloop_sleep_duration` is set to a non-zero value, random +sleeps are inserted in the reactor routines when the node is waiting +for `HasProposalBlockPart` messages or `HasVote` messages. +The goal is to reduce the amount of `BlockPart` and `Vote` messages sent. +The value of this parameter is the upper bound for the random duration that is +used by the sleep commands inserted in each loop of the reactor routines. + +### consensus.peer_query_maj23_sleep_duration + +Consensus reactor interval between querying peers for +2/3 vote majorities. + +```toml +peer_query_maj23_sleep_duration = "2s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +The consensus reactor gossips consensus messages, by sending or forwarding them +to peers. + +The `VoteSetMaj23` message is used by the consensus reactor to query peers +regarding vote messages (prevotes or precommits) they have for a specific +block. +These queries are only triggered when +2/3 votes are observed. + +The value of `peer_query_maj23_sleep_duration` is the interval between sending +those queries to a peer. + +## Storage +In production environments, configuring storage parameters accurately is essential as it can greatly impact the amount +of disk space utilized. + +CometBFT supports storage pruning to delete data indicated as not needed by the application or the data companion. +Other than the pruning interval and compaction options, the configuration parameters in this section refer to the data +companion. The applications pruning configuration is communicated to CometBFT via ABCI. + +Note that for some databases (GolevelDB), the data often does not get physically removed from storage due to the DB backend +not triggering compaction. In these cases it is necessary to enable forced compaction and set the compaction interval accordingly. + +### storage.discard_abci_responses +Discard ABCI responses from the state store, which can save a considerable amount of disk space. +```toml +discard_abci_responses = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +If set to `false` ABCI responses are maintained, if set to `true` ABCI responses will be pruned. + +ABCI responses are required for the `/block_results` RPC queries. + +### storage.experimental_db_key_layout + +The representation of keys in the database. The current representation of keys in Comet's stores is considered to be `v1`. + +Users can experiment with a different layout by setting this field to `v2`. Note that this is an experimental feature +and switching back from `v2` to `v1` is not supported by CometBFT. + +If the database was initially created with `v1`, it is necessary to migrate the DB before switching to `v2`. The migration +is not done automatically. + +```toml +experimental_db_key_layout = 'v1' +``` + +| Value type | string | +|:--------------------|:-------| +| **Possible values** | `v1` | +| | `v2` | + +- `v1` - The legacy layout existing in Comet prior to v1. +- `v2` - Order preserving representation ordering entries by height. + +If not specified, the default value `v1` will be used. + +### storage.compact + +If set to true, CometBFT will force compaction to happen for databases that support this feature and save on storage space. + +Setting this to true is most beneficial when used in combination with pruning as it will physically delete the entries marked for deletion. + +```toml +compact = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +`false` is the default value (forcing compaction is disabled). + +### storage.compaction_interval + +To avoid forcing compaction every time, this parameter instructs CometBFT to wait the given amount of blocks to be +pruned before triggering compaction. + +It should be tuned depending on the number of items. If your retain height is 1 block, it is too much of an overhead +to try compaction every block. But it should also not be a very large multiple of your retain height as it might incur +bigger overheads. + +| Value type | string (# blocks) | +|:--------------------|:------------------| +| **Possible values** | >= `"0"` | + +```toml +compaction_interval = '1000' +``` + +### storage.pruning.interval +The time period between automated background pruning operations. +```toml +interval = "10s" +``` + +| Value type | string (duration) | +|:--------------------|:------------------| +| **Possible values** | >= `"0s"` | + +### storage.pruning.data_companion.enabled +Tell the automatic pruning function to respect values set by the data companion. + +```toml +enabled = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +If disabled, only the application retain height will influence block pruning (but not block results pruning). + +Only enabling this at a later stage will potentially mean that blocks below the application-set retain height at the +time will not be available to the data companion. + +### storage.pruning.data_companion.initial_block_retain_height +The initial value for the data companion block retain height if the data companion has not yet explicitly set one. +If the data companion has already set a block retain height, this is ignored. +```toml +double_sign_check_height = 0 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +### storage.pruning.data_companion.initial_block_results_retain_height +The initial value for the data companion block results retain height if the data companion has not yet explicitly set +one. If the data companion has already set a block results retain height, this is ignored. +```toml +initial_block_results_retain_height = 0 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +### storage.pruning.data_companion.genesis_hash +Hash of the Genesis file, passed to CometBFT via the command line. +```toml +genesis_hash = "" +``` + +| Value type | string | +|:--------------------|:-------------------| +| **Possible values** | hex-encoded number | +| | `""` | + +If this hash mismatches the hash that CometBFT computes on the genesis file, the node is not able to boot. + +## Transaction indexer +Transaction indexer settings. + +The application will set which txs to index. +In some cases, a node operator will be able to decide which txs to index based on the configuration set in the application. + +### tx_index.indexer +What indexer to use for transactions. +```toml +indexer = "kv" +``` + +| Value type | string | +|:--------------------|:---------| +| **Possible values** | `"kv"` | +| | `"null"` | +| | `"psql"` | + +`"null"` indexer disables indexing. + +`"kv"` is the simplest possible indexer, backed by a key-value storage. +The key-value storage database backend is defined in [`db_backend`](#db_backend). + +`"psql"` indexer is backed by an external PostgreSQL server. +The server connection string is defined in [`tx_index.psql-conn`](#tx_indexpsql-conn). + +The transaction height and transaction hash is always indexed, except with the `"null"` indexer. + +### tx_index.psql-conn +The PostgreSQL connection configuration. +```toml +psql-conn = "" +``` + +| Value type | string | +|:--------------------|:-------------------------------------------------------------| +| **Possible values** | `"postgresql://:@:/?"` | +| | `""` | + +## Prometheus Instrumentation +An extensive amount of Prometheus metrics are built into CometBFT. + +### instrumentation.prometheus +Enable or disable presenting the Prometheus metrics at an endpoint. +```toml +prometheus = false +``` + +| Value type | boolean | +|:--------------------|:--------| +| **Possible values** | `false` | +| | `true` | + +When enabled, metrics are served under the `/metrics` endpoint on the +[instrumentation.prometheus_listen_addr](#instrumentationprometheus_listen_addr) address. + +### instrumentation.prometheus_listen_addr +Address to listen for Prometheus collector(s) connections. +```toml +prometheus_listen_addr = ":26660" +``` + +| Value type | string | +|:--------------------|:--------------------------------------| +| **Possible values** | Network address (`"127.0.0.1:26657"`) | + +If the IP address is omitted (see e.g. the default value) then the listening socket is bound to INADDR_ANY (`0.0.0.0`). + +The metrics endpoint only supports HTTP. + +### instrumentation.max_open_connections +Maximum number of simultaneous connections. +```toml +max_open_connections = 3 +``` + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +`0` allows unlimited connections. + +### instrumentation.namespace +Instrumentation namespace +```toml +namespace = "cometbft" +``` + +| Value type | string | +|:--------------------|:--------------------------| +| **Possible values** | Prometheus namespace name | diff --git a/docs/references/config/genesis.json.md b/docs/references/config/genesis.json.md new file mode 100644 index 00000000000..7a64495db73 --- /dev/null +++ b/docs/references/config/genesis.json.md @@ -0,0 +1,135 @@ +--- +order: 1 +parent: + title: genesis.json + description: The network genesis file + order: 1 +--- +# genesis.json +It is **crucial** that all nodes in a network must have _exactly_ the same contents in their `genesis.json` file. + +On first start, the network parameters are read from the `genesis.json` file. +On subsequent starts (node recovery), the `genesis.json` file is ignored. + +### Example +```json +{ + "genesis_time": "2024-03-01T20:22:57.532998Z", + "chain_id": "test-chain-HfdKnD", + "initial_height": "0", + "consensus_params": { + "block": { + "max_bytes": "4194304", + "max_gas": "10000000" + }, + "evidence": { + "max_age_num_blocks": "100000", + "max_age_duration": "172800000000000", + "max_bytes": "1048576" + }, + "validator": { + "pub_key_types": [ + "ed25519" + ] + }, + "version": { + "app": "0" + }, + "feature": { + "vote_extensions_enable_height": "1" + "pbts_enable_height": "1" + } + }, + "validators": [ + { + "address": "E74FBE24164CFC4F88E311C3AC92E63D0DC310D8", + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "UjxDQgVTlHJOZ7axpMl/iczMIJXiQpFxCFjwKGvzYqE=" + }, + "power": "10", + "name": "" + } + ], + "app_hash": "" +} +``` + +For a production example, you can see [here](https://github.com/cosmos/mainnet/tree/master/genesis) +the history of genesis files for the Cosmos Hub network. + +## genesis_time +Timestamp of the genesis file creation. + +| Value type | string | +|:--------------------|:---------------------------| +| **Possible values** | RFC3339-formatted datetime | + +RFC3339 has multiple representation. The one we use here has 6 digits for sub-second representation. + +## chain_id +The chain ID of the blockchain network. + +| Value type | string | +|:--------------------|:----------------------------------| +| **Possible values** | usually in `"name-number"` format | + +Cannot be empty. + +Can be maximum 50 UTF-8-encoded character. + +The `number` part is typically a revision number of the blockchain, starting at `1` and incrementing each time the network +undergoes a hard fork. + +## initial_height +Initial height at genesis. + +| Value type | string | +|:--------------------|:------------| +| **Possible values** | >= `"0"` | + +When a hard fork happens, a new chain can start from a higher initial height by setting this parameter. + +> Notes: + +>> If a Height `"0"` is specified in `initial_heigth`, then CometBFT during the genesis file validation, will change the +> initial height parameter to `"1"`. + +>> Note: A height in CometBFT is an `int64` integer therefore its maximum value is `9223372036854775807` + +## consensus_params + +The initial values for the consensus parameters. +Consensus Parameters are global parameters that apply to all nodes in the network. + +Please refer to the +[specification](https://docs.cometbft.com/v1.0/spec/abci/abci++_app_requirements#consensus-parameters) +for details on the existing consensus parameters, their default and valid values. + + +## validators +List of initial validators for consensus. + +| Value type | array of objects | | +|:----------------------------------------|:-----------------|-----------------------------------------------------------------------------------------| +| **Mandatory keys of each array object** | address | See [address](priv_validator_key.json.md#address) in priv_validator_key.json | +| | pub_key | See [pub_key.type](priv_validator_key.json.md#pub_keytype) | +| | | and [pub_key.value](priv_validator_key.json.md#pub_keyvalue) in priv_validator_key.json | +| | power | > `"0"` | +| | name | string or `""` | + +## app_hash +The initial AppHash, represented by the state embedded in the genesis file. + +| Value type | string | +|:--------------------|:-------------------| +| **Possible values** | hex-encoded number | +| | "" | + +## app_state +A raw encoded JSON value that has the application state encoded in it. + +| Value type | string | +|:--------------------|:-----------------------| +| **Possible values** | raw bytes JSON-encoded | +| | "" | diff --git a/docs/references/config/node_key.json.md b/docs/references/config/node_key.json.md new file mode 100644 index 00000000000..558a3076156 --- /dev/null +++ b/docs/references/config/node_key.json.md @@ -0,0 +1,104 @@ +--- +order: 1 +parent: + title: node_key.json + description: Description and usage of the node ID + order: 2 +--- + +## The `node_key.json` file +The node ID, the host address and the P2P port together identify a node in a CometBFT network: `nodeID@host:port`. + +The easiest way to get the `nodeID` is running the `cometbft show-node-id` command. + +The `node_key.json` file resides at `$CMTHOME/config/node_key.json`. This can be overridden at the +[node_key_file](config.toml.md#node_key_file) parameter in the [`config.toml`](config.toml.md) file. + +The file contains a private key (in [priv_key.value](#priv_keyvalue)) to an asymmetric algorithm +(in [priv_key.type](#priv_keytype)). + +The node ID is calculated by hashing the public key with the SHA256 algorithm and taking the first 20 bytes of the +result. + +### priv_key.type +The type of the key defined under [`priv_key.value`](#priv_keyvalue). + +Default example in context: +```json +{ + "priv_key": { + "type": "tendermint/PrivKeyEd25519", + "value": "jxG2ywUkVPiF4XDW1Dwa5ZfcrC0rEa4iM1y4O5qCMpYxdiypykyf9yp7C81cJTZHKMOvrnGcZiqxlMfyQsaUUA==" + } +} +``` + +| Value type | string (crypto package asymmetric encryption algorithms) | +|:--------------------|:---------------------------------------------------------| +| **Possible values** | `"tendermint/PrivKeyEd25519"` | +| | `"tendermint/PrivKeySecp256k1"` | +| | `"tendermint/PrivKeySr25519"` | + +The string values are derived from the asymmetric cryptographic implementations defined in the `crypto` package. + +CometBFT will always generate an Ed25519 key-pair for node ID using the `cometbft init` or the `cometbft gen-node-key` +commands. Other types of encryption keys have to be created manually. (See examples under +[priv_key.value](#priv_keyvalue).) + +### priv_key.value +Base64-encoded bytes, the private key of an asymmetric encryption algorithm. +The type of encryption is defined in [priv_key.type](#priv_keytype). + +Default example in context: +```json +{ + "priv_key": { + "type": "tendermint/PrivKeyEd25519", + "value": "jxG2ywUkVPiF4XDW1Dwa5ZfcrC0rEa4iM1y4O5qCMpYxdiypykyf9yp7C81cJTZHKMOvrnGcZiqxlMfyQsaUUA==" + } +} +``` + +| Value type | string (base64-encoded bytes) | +|:--------------------|:----------------------------------------------------| +| **Possible values** | base64-encoded Ed25519 private key **+ public key** | +| | base64-encoded Secp256k1 private key | +| | base64-encoded sr25519 private key | + +CometBFT will always generate an Ed25519 key-pair for node ID using the `cometbft init` or the `cometbft gen-node-key` +command. Other types of encryption keys have to be created manually. (See examples below.) + +The Ed25519 encryption implementation requires the public key concatenated in the value. The implementation ignores the +private key and uses the stored public key to generate the node ID. In the below example, we zeroed out the private key, +but the resultant concatenated bytes still produce a valid node ID. Other algorithms generate the public key from the +private key. + +Examples: + +Ed25519: +```json +{ + "priv_key": { + "type": "tendermint/PrivKeyEd25519", + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxdiypykyf9yp7C81cJTZHKMOvrnGcZiqxlMfyQsaUUA==" + } +} +``` +Secp256k1: +```json +{ + "priv_key": { + "type": "tendermint/PrivKeySecp256k1", + "value": "2swJ5TwUhhqjJW+CvVbbSnTGxqpYmb2yvib+MHyDJIU=" + } +} +``` +sr25519: +```json +{ + "priv_key": { + "type": "tendermint/PrivKeySr25519", + "value": "wf5qqY9xwJ3LlHIksw38RuAe9L533/8L3gnOUuN4w48=" + } +} +``` diff --git a/docs/references/config/priv_validator_key.json.md b/docs/references/config/priv_validator_key.json.md new file mode 100644 index 00000000000..56c05e92ff0 --- /dev/null +++ b/docs/references/config/priv_validator_key.json.md @@ -0,0 +1,110 @@ +--- +order: 1 +parent: + title: priv_validator_key.json + description: Private/public key-pair for signing consensus + order: 4 +--- +# priv_validator_key.json +CometBFT supports different key signing methods. The default method is storing the consensus (or signing) key +unencrypted on the file system in the `priv_validator_key.json` file. + +The file is located at `$CMTHOME/config/priv_validator_key.json`. If `$CMTHOME` is unset, it defaults to +`$HOME/.cometbft`. + +The file contains a [private key](#priv_keyvalue) and its corresponding [public key](#pub_keyvalue). + +A [wallet address](#address) is derived from the public key. + +### Examples +Ed25519: +```json +{ + "address": "E74FBE24164CFC4F88E311C3AC92E63D0DC310D8", + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "UjxDQgVTlHJOZ7axpMl/iczMIJXiQpFxCFjwKGvzYqE=" + }, + "priv_key": { + "type": "tendermint/PrivKeyEd25519", + "value": "9giFjwnmAKCAI95l4Q32kXsau+itGrbsvz84CTLxGnJSPENCBVOUck5ntrGkyX+JzMwgleJCkXEIWPAoa/NioQ==" + } +} +``` + +Secp256k1: +```json +{ + "address": "E5B4F106D46A46820308C49B5F92DC22D9F9ACFA", + "pub_key": { + "type": "tendermint/PubKeySecp256k1", + "value": "AhRzbjoZaiyrbCE/yJ6gwIBXjwzl8+H7W8KMAphJVUzt" + }, + "priv_key": { + "type": "tendermint/PrivKeySecp256k1", + "value": "Lfa2uW//4KGvzLXhtoHGfI5Yd2DA2gC7pOfHSkFheGg=" + } +} +``` + +Do NOT use these examples in production systems unless you are planning to give away your tokens. + +You can generate random Ed25519 keys with the `cometbft gen-validator` command. + +## address +The wallet address generated from the consensus public key. + +The wallet address is calculated by hashing the public key with the SHA256 algorithm and taking the first 20 bytes of +the result. + +## pub_key.type +The type of the key defined under [`pub_key.value`](#pub_keyvalue). + +| Value type | string (crypto package asymmetric encryption algorithms) | +|:--------------------|:---------------------------------------------------------| +| **Possible values** | `"tendermint/PubKeyEd25519"` | +| | `"tendermint/PubKeySecp256k1"` | + +The string values are derived from the asymmetric cryptographic implementations defined in the `crypto` package. + +CometBFT will always generate an Ed25519 key-pair for consensus key using the `cometbft init` or the +`cometbft gen-validator` commands. Other types of encryption keys have to be created manually. + +## pub_key.value +Base64-encoded bytes, the public key of an asymmetric encryption algorithm. +The type of encryption is defined in [pub_key.type](#pub_keytype). + +| Value type | string (base64-encoded bytes) | +|:--------------------|:------------------------------------| +| **Possible values** | base64-encoded Ed25519 public key | +| | base64-encoded Secp256k1 public key | + +CometBFT will always generate an Ed25519 key-pair for consensus key using the `cometbft init` or the +`cometbft gen-validator` commands. Other types of encryption keys have to be created manually. + +## priv_key.type +The type of the key defined under [`priv_key.value`](#priv_keyvalue). + +| Value type | string (crypto package asymmetric encryption algorithms) | +|:--------------------|:---------------------------------------------------------| +| **Possible values** | `"tendermint/PrivKeyEd25519"` | +| | `"tendermint/PrivKeySecp256k1"` | + +The string values are derived from the asymmetric cryptographic implementations defined in the `crypto` package. + +CometBFT will always generate an Ed25519 key-pair for consensus key using the `cometbft init` or the +`cometbft gen-validator` commands. Other types of encryption keys have to be created manually. + +## priv_key.value +Base64-encoded bytes, the private key of an asymmetric encryption algorithm. +The type of encryption is defined in [priv_key.type](#priv_keytype). + +| Value type | string (base64-encoded bytes) | +|:--------------------|:----------------------------------------------------| +| **Possible values** | base64-encoded Ed25519 private key **+ public key** | +| | base64-encoded Secp256k1 private key | + +CometBFT will always generate an Ed25519 key-pair for consensus key using the `cometbft init` or the +`cometbft gen-validator` commands. Other types of encryption keys have to be created manually. + +The Ed25519 encryption implementation requires the public key concatenated in the value. diff --git a/docs/references/config/priv_validator_state.json.md b/docs/references/config/priv_validator_state.json.md new file mode 100644 index 00000000000..12c991c33b2 --- /dev/null +++ b/docs/references/config/priv_validator_state.json.md @@ -0,0 +1,72 @@ +--- +order: 1 +parent: + title: priv_validator_state.json + description: Details of last signed block + order: 5 +--- +# priv_validator_state.json +When CometBFT is run as a validator and a local private validator (`PrivVal`) is adopted, it uses this file to keep data about the last signed consensus messages. + +This file is only updated if a local private validator is adopted. +(When [priv_validator_laddr](config.toml.md#priv_validator_laddr) is not set.) + +### Examples +```json +{ + "height": "0", + "round": 0, + "step": 0 +} +``` + +```json +{ + "height": "36", + "round": 0, + "step": 3, + "signature": "N813twXq5yC84wKGrD85X79iXPwtVytGdD3j8btwZ5ZyAAHSkNt6NBWvrTJUcMLqefPfG3SBdPHdfOedieeYCg==", + "signbytes": "76080211240000000000000022480A20D1823B950D1A0FD7335B4E63D2B65CF9D0CEAC13DF4E9E2DFB4765D2C69C74D0122408011220DB69B3B750BBCEAB4BC86BB1847D3E0DDB342EFAFE5731605C61A828265E09802A0C08CDF288AF0610A88CA8FE023211746573742D636861696E2D4866644B6E44" +} +``` +## height +Set to the last height that was signed. + +| Value type | string | +|:--------------------|:------------| +| **Possible values** | >= `"0"` | + +Height, a number, is presented as a string so arbitrary high numbers can be used without the limitation of the integer +maximum. + +## round +Set to the last round that was signed. + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +## step +Set to the last round step that was signed. + +| Value type | integer | +|:--------------------|:--------| +| **Possible values** | >= 0 | + +## signature +The last signature produced. This was provided at the above [height/round/step](#height). + +| Value type | string | +|:--------------------|:---------------------| +| **Possible values** | base64-encoded bytes | +| | `""` | + +## signbytes +Proto-encoding of the latest consensus message signed. Used to compare incoming requests and if possible reuse the +previous signature provided in [signature](#signature). + +| Value type | string | +|:--------------------|:------------------| +| **Possible values** | hex-encoded bytes | +| | `""` | + diff --git a/docs/qa/CometBFT-QA-34.md b/docs/references/qa/CometBFT-QA-34.md similarity index 78% rename from docs/qa/CometBFT-QA-34.md rename to docs/references/qa/CometBFT-QA-34.md index d633426407e..be462165aa8 100644 --- a/docs/qa/CometBFT-QA-34.md +++ b/docs/references/qa/CometBFT-QA-34.md @@ -8,6 +8,55 @@ parent: # CometBFT QA Results v0.34.x +## Table of Contents +- [v0.34.x - From Tendermint Core to CometBFT](#v034x---from-tendermint-core-to-cometbft) +- [Configuration and Results](#configuration-and-results) + - [Saturation Point](#saturation-point) + - [Experiments](#experiments) +- [Examining latencies](#examining-latencies) + - [CometBFT Homogeneous network](#cometbft-homogeneous-network) + - [1/2 Tendermint Core - 1/2 CometBFT](#12-tendermint-core---12-cometbft) + - [1/3 Tendermint Core - 2/3 CometBFT](#13-tendermint-core---23-cometbft) + - [2/3 Tendermint Core - 1/3 CometBFT](#23-tendermint-core---13-cometbft) +- [Prometheus Metrics](#prometheus-metrics) + - [Mempool Size](#mempool-size) + - [Baseline](#baseline) + - [CometBFT Homogeneous network](#cometbft-homogeneous-network-1) + - [1/2 Tendermint Core - 1/2 CometBFT](#12-tendermint-core---12-cometbft-1) + - [1/3 Tendermint Core - 2/3 CometBFT](#13-tendermint-core---23-cometbft-1) + - [2/3 Tendermint Core - 1/3 CometBFT](#23-tendermint-core---13-cometbft-1) + - [Consensus Rounds per Height](#consensus-rounds-per-height) + - [Baseline](#baseline-1) + - [CometBFT Homogeneous network](#cometbft-homogeneous-network-2) + - [1/2 Tendermint Core - 1/2 CometBFT](#12-tendermint-core---12-cometbft-2) + - [1/3 Tendermint Core - 2/3 CometBFT](#13-tendermint-core---23-cometbft-2) + - [2/3 Tendermint Core - 1/3 CometBFT](#23-tendermint-core---13-cometbft-2) + - [Peers](#peers) + - [Baseline](#baseline-2) + - [CometBFT Homogeneous network](#cometbft-homogeneous-network-3) + - [1/2 Tendermint Core - 1/2 CometBFT](#12-tendermint-core---12-cometbft-3) + - [1/3 Tendermint Core - 2/3 CometBFT](#13-tendermint-core---23-cometbft-3) + - [2/3 Tendermint Core - 1/3 CometBFT](#23-tendermint-core---13-cometbft-3) + - [Blocks Produced per Minute, Transactions Processed per Minute](#blocks-produced-per-minute-transactions-processed-per-minute) + - [Baseline](#baseline-3) + - [CometBFT Homogeneous network](#cometbft-homogeneous-network-4) + - [1/2 Tendermint Core - 1/2 CometBFT](#12-tendermint-core---12-cometbft-4) + - [1/3 Tendermint Core - 2/3 CometBFT](#13-tendermint-core---23-cometbft-4) + - [2/3 Tendermint Core - 1/3 CometBFT](#23-tendermint-core---13-cometbft-4) + - [Memory Resident Set Size](#memory-resident-set-size) + - [Baseline](#baseline-4) + - [CometBFT Homogeneous network](#cometbft-homogeneous-network-5) + - [1/2 Tendermint Core - 1/2 CometBFT](#12-tendermint-core---12-cometbft-5) + - [1/3 Tendermint Core - 2/3 CometBFT](#13-tendermint-core---23-cometbft-5) + - [2/3 Tendermint Core - 1/3 CometBFT](#23-tendermint-core---13-cometbft-5) + - [CPU utilization](#cpu-utilization) + - [Baseline](#baseline-5) + - [CometBFT Homogeneous network](#cometbft-homogeneous-network-6) + - [1/2 Tendermint Core - 1/2 CometBFT](#12-tendermint-core---12-cometbft-6) + - [1/3 Tendermint Core - 2/3 CometBFT](#13-tendermint-core---23-cometbft-6) + - [2/3 Tendermint Core - 1/3 CometBFT](#23-tendermint-core---13-cometbft-6) +- [Test Results](#test-results) + ## 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 @@ -114,7 +163,7 @@ This section reports on the key Prometheus metrics extracted from the following * Mixed network, 1/3 Tendermint Core `v0.34.26` and 2/3 running CometBFT: experiment with UUID starting with `fc5e`. * Mixed network, 2/3 Tendermint Core `v0.34.26` and 1/3 running CometBFT: experiment with UUID starting with `4759`. -We make explicit comparisons between the baseline and the homogenous setups, but refrain from +We make explicit comparisons between the baseline and the homogeneous setups, but refrain from commenting on the mixed network experiment unless they show some exceptional results. ### Mempool Size @@ -191,13 +240,13 @@ on the corresponding plot, shown above. ### Peers -The following plots show how many peers a node had throughtout the experiment. +The following plots show how many peers a node had throughout the experiment. The thick red dashed line represents the moving average over a sliding window of 20 seconds. #### Baseline -The following graph shows the that the number of peers was stable throughout the experiment. +The following graph shows that the number of peers was stable throughout the experiment. 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). @@ -236,7 +285,7 @@ The thick red dashed line show the rates' moving averages. #### Baseline -The average number of blocks/minute oscilate between 10 and 40. +The average number of blocks/minute oscillate between 10 and 40. ![heights](img34/baseline/block_rate_regular.png) @@ -327,7 +376,7 @@ command, and their average value. #### CometBFT Homogeneous network -The load in the homogenous network is, similarly to the baseline case, below 5 and, therefore, normal. +The load in the homogeneous network is, similarly to the baseline case, below 5 and, therefore, normal. ![load1-homogeneous](img34/homogeneous/cpu.png) @@ -358,7 +407,7 @@ As expected, the average plot also looks similar. 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. -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. +Although not the main goal, a comparison of metric numbers with the homogeneous case and the baseline scenarios show similar results and therefore we can conclude that mixing compatible Tendermint Core and CometBFT introduces no 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/CometBFT-QA-37.md b/docs/references/qa/CometBFT-QA-37.md similarity index 91% rename from docs/qa/CometBFT-QA-37.md rename to docs/references/qa/CometBFT-QA-37.md index 1717ecf3ecd..4235b370b5c 100644 --- a/docs/qa/CometBFT-QA-37.md +++ b/docs/references/qa/CometBFT-QA-37.md @@ -12,6 +12,19 @@ This iteration of the QA was run on CometBFT `v0.37.0-alpha3`, the first `v0.37. 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). +## Table of Contents +- [Testbed](#testbed) + - [Saturation point](#saturation-point) +- [Examining latencies](#examining-latencies) +- [Prometheus Metrics on the Chosen Experiment](#prometheus-metrics-on-the-chosen-experiment) + - [Mempool Size](#mempool-size) + - [Peers](#peers) + - [Consensus Rounds per Height](#consensus-rounds-per-height) + - [Blocks Produced per Minute, Transactions Processed per Minute](#blocks-produced-per-minute-transactions-processed-per-minute) + - [Memory Resident Set Size](#memory-resident-set-size) + - [CPU utilization](#cpu-utilization) +- [Test Results](#test-results) + ## Testbed As in other iterations of our QA process, we have used a 200-node network as testbed, plus nodes to introduce load and collect metrics. diff --git a/docs/references/qa/CometBFT-QA-38.md b/docs/references/qa/CometBFT-QA-38.md new file mode 100644 index 00000000000..17c6f78416f --- /dev/null +++ b/docs/references/qa/CometBFT-QA-38.md @@ -0,0 +1,592 @@ +--- +order: 1 +parent: + title: CometBFT QA Results v0.38.x + description: This is a report on the results obtained when running CometBFT v0.38.x on testnets + order: 5 +--- + +# CometBFT QA Results v0.38.x + +This iteration of the QA was run on CometBFT `v0.38.0-alpha.2`, the second +`v0.38.x` version from the CometBFT repository. + +The changes with respect to the baseline, `v0.37.0-alpha.3` from Feb 21, 2023, +include the introduction of the `FinalizeBlock` method to complete the full +range of ABCI++ functionality (ABCI 2.0), and other several improvements +described in the +[CHANGELOG](https://github.com/cometbft/cometbft/blob/v0.38.0-alpha.2/CHANGELOG.md). + +## Table of Contents +- [CometBFT QA Results v0.38.x](#cometbft-qa-results-v038x) + - [Table of Contents](#table-of-contents) + - [Issues discovered](#issues-discovered) + - [200 Node Testnet](#200-node-testnet) + - [Saturation point](#saturation-point) + - [Latencies](#latencies) + - [Prometheus Metrics on the Chosen Experiment](#prometheus-metrics-on-the-chosen-experiment) + - [Mempool Size](#mempool-size) + - [Peers](#peers) + - [Consensus Rounds per Height](#consensus-rounds-per-height) + - [Blocks Produced per Minute, Transactions Processed per Minute](#blocks-produced-per-minute-transactions-processed-per-minute) + - [Memory Resident Set Size](#memory-resident-set-size) + - [CPU utilization](#cpu-utilization) + - [Comparison to baseline](#comparison-to-baseline) + - [Impact of vote extension signature verification](#impact-of-vote-extension-signature-verification) + - [Test Results](#test-results) + - [Rotating Node Testnet](#rotating-node-testnet) + - [Latencies](#latencies-1) + - [Prometheus Metrics](#prometheus-metrics) + - [Blocks and Transactions per minute](#blocks-and-transactions-per-minute) + - [Peers](#peers-1) + - [Memory Resident Set Size](#memory-resident-set-size-1) + - [CPU utilization](#cpu-utilization-1) + - [Test Result](#test-result) + - [Vote Extensions Testbed](#vote-extensions-testbed) + - [Latency](#latency) + - [Blocks and Transactions per minute](#blocks-and-transactions-per-minute-1) + - [Overview](#overview) + - [First run](#first-run) + - [Number of rounds](#number-of-rounds) + - [CPU](#cpu) + - [Resident Memory](#resident-memory) + - [Mempool size](#mempool-size-1) + - [Results](#results) + +## Issues discovered + +* (critical, fixed) [\#539] and [\#546] - This bug causes the proposer to crash in + `PrepareProposal` because it does not have extensions while it should. + This happens mainly when the proposer was catching up. +* (critical, fixed) [\#562] - There were several bugs in the metrics-related + logic that were causing panics when the testnets were started. + +## 200 Node Testnet + +As in other iterations of our QA process, we have used a 200-node network as +testbed, plus nodes to introduce load and collect metrics. + +### Saturation point + +As in previous iterations of our QA experiments, we first find the transaction +load on which the system begins to show a degraded performance. Then we run the +experiments with the system subjected to a load slightly under the saturation +point. The method to identify the saturation point is explained +[here](CometBFT-QA-34.md#saturation-point) and its application to the baseline +is described [here](TMCore-QA-37.md#finding-the-saturation-point). + +The following table summarizes the results for the different experiments +(extracted from +[`v038_report_tabbed.txt`](img38/200nodes/v038_report_tabbed.txt)). The X axis +(`c`) is the number of connections created by the load runner process to the +target node. The Y axis (`r`) is the rate or number of transactions issued per +second. + +| | c=1 | c=2 | c=4 | +| ------ | --------: | --------: | ----: | +| r=200 | 17800 | **33259** | 33259 | +| r=400 | **35600** | 41565 | 41384 | +| r=800 | 36831 | 38686 | 40816 | +| r=1600 | 40600 | 45034 | 39830 | + +We can observe in the table that the system is saturated beyond the diagonal +defined by the entries `c=1,r=400` and `c=2,r=200`. Entries in the diagonal have +the same amount of transaction load, so we can consider them equivalent. For the +chosen diagonal, the expected number of processed transactions is `1 * 400 tx/s * 89 s = 35600`. +(Note that we use 89 out of 90 seconds of the experiment because the last transaction batch +coincides with the end of the experiment and is thus not sent.) The experiments in the diagonal +below expect double that number, that is, `1 * 800 tx/s * 89 s = 71200`, but the +system is not able to process such load, thus it is saturated. + +Therefore, for the rest of these experiments, we chose `c=1,r=400` as the +configuration. We could have chosen the equivalent `c=2,r=200`, which is the same +used in our baseline version, but for simplicity we decided to use the one with +only one connection. + +Also note that, compared to the previous QA tests, we have tried to find the +saturation point within a higher range of load values for the rate `r`. In +particular we run tests with `r` equal to or above `200`, while in the previous +tests `r` was `200` or lower. In particular, for our baseline version we didn't +run the experiment on the configuration `c=1,r=400`. + +For comparison, this is the table with the baseline version, where the +saturation point is beyond the diagonal defined by `r=200,c=2` and `r=100,c=4`. + +| | c=1 | c=2 | c=4 | +| ----- | ----: | --------: | --------: | +| r=25 | 2225 | 4450 | 8900 | +| r=50 | 4450 | 8900 | 17800 | +| r=100 | 8900 | 17800 | **35600** | +| r=200 | 17800 | **35600** | 38660 | + +### Latencies + +The following figure plots the latencies of the experiment carried out with the +configuration `c=1,r=400`. + +![latency-1-400](img38/200nodes/e_de676ecf-038e-443f-a26a-27915f29e312.png). + +For reference, the following figure shows the latencies of one of the +experiments for `c=2,r=200` in the baseline. + +![latency-2-200-37](img37/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png) + +As can be seen, in most cases the latencies are very similar, and in some cases, +the baseline has slightly higher latencies than the version under test. Thus, +from this small experiment, we can say that the latencies measured on the two +versions are equivalent, or at least that the version under test is not worse +than the baseline. + +### Prometheus Metrics on the Chosen Experiment + +This section further examines key metrics for this experiment extracted from +Prometheus data regarding the chosen experiment with configuration `c=1,r=400`. + +#### 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. 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](img38/200nodes/mempool_size.png) + +The following picture shows the evolution of the average mempool size over all +full nodes, which mostly oscilates between 1000 and 2500 outstanding +transactions. + +![mempool-avg](img38/200nodes/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](img37/200nodes_cmt037/mempool_size.png) + +![mempool-avg-baseline](img37/200nodes_cmt037/avg_mempool_size.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 20 and 70 for most nodes). The red +dashed line denotes the average value. + +![peers](img38/200nodes/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](img37/200nodes_cmt037/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. + +![rounds](img38/200nodes/rounds.png) + +The following specific run of the baseline required some nodes to reach round 1. + +![rounds](img37/200nodes_cmt037/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. That is, it shows when each node learned that a new block +had been agreed upon. + +![heights](img38/200nodes/block_rate.png) + +For most of the time when load was being applied to the system, most of the +nodes stayed around 20 blocks/minute. + +The spike to more than 100 blocks/minute is due to a slow node catching up. + +The baseline experienced a similar behavior. + +![heights-baseline](img37/200nodes_cmt037/block_rate.png) + +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](img38/200nodes/total_txs_rate.png) + +The following is the transaction processing rate of the baseline, which is +similar to above. + +![total-txs-baseline](img37/200nodes_cmt037/total_txs_rate.png) + + +#### Memory Resident Set Size + +The following graph shows the Resident Set Size of all monitored processes, with +maximum memory usage of 1.6GB, slightly lower than the baseline shown after. + +![rss](img38/200nodes/memory.png) + +A similar behavior was shown in the baseline, with even a slightly higher memory +usage. + +![rss](img37/200nodes_cmt037/memory.png) + +The memory of all processes went down as the load is removed, showing no signs +of unconstrained growth. + + +#### CPU utilization + +##### Comparison to baseline + +The best metric from Prometheus to gauge CPU utilization in a Unix machine is +`load1`, as it usually appears in the [output of +`top`](https://www.digitalocean.com/community/tutorials/load-average-in-linux). + +The load is contained below 5 on most nodes, as seen in the following graph. + +![load1](img38/200nodes/cpu.png) + +The baseline had a similar behavior. + +![load1-baseline](img37/200nodes_cmt037/cpu.png) + +##### Impact of vote extension signature verification + +It is important to notice that the baseline (`v0.37.x`) does not implement vote extensions, +whereas the version under test (`v0.38.0-alpha.2`) _does_ implement them, and they are +configured to be activated since height 1. +The e2e application used in these tests verifies all received vote extension signatures (up to 175) +twice per height: upon `PrepareProposal` (for sanity) and upon `ProcessProposal` (to demonstrate how +real applications can do it). + +The fact that there is no noticeable difference in the CPU utilization plots of +the baseline and `v0.38.0-alpha.2` means that re-verifying up 175 vote extension signatures twice +(besides the initial verification done by CometBFT when receiving them from the network) +has no performance impact in the current version of the system: the bottlenecks are elsewhere. +Thus, we should focus on optimizing other parts of the system: the ones that cause the current +bottlenecks (mempool gossip duplication, leaner proposal structure, optimized consensus gossip). + +### Test Results + +The comparison against the baseline results show that both scenarios had similar +numbers and are therefore equivalent. + +A conclusion of these tests is shown in the following table, along with the +commit versions used in the experiments. + +| Scenario | Date | Version | Result | +| -------- | ---------- | ---------------------------------------------------------- | ------ | +| 200-node | 2023-05-21 | v0.38.0-alpha.2 (1f524d12996204f8fd9d41aa5aca215f80f06f5e) | Pass | + + +## Rotating Node Testnet + +We use `c=1,r=400` as load, which can be considered a safe workload, as it was close to (but below) +the saturation point in the 200 node testnet. This testnet has less nodes (10 validators and 25 full nodes). + +Importantly, the baseline considered in this section is `v0.37.0-alpha.2` (Tendermint Core), +which is **different** from the one used in the [previous section](#200-node-testbed). +The reason is that this testnet was not re-tested for `v0.37.0-alpha.3` (CometBFT), +since it was not deemed necessary. + +Unlike in the baseline tests, the version of CometBFT used for these tests is _not_ affected by [\#9539], +which was fixed right after having run rotating testnet for `v0.37`. +As a result, the load introduced in this iteration of the test is higher as transactions do not get rejected. + +### Latencies + +The plot of all latencies can be seen here. + +![rotating-all-latencies](img38/rotating/rotating_latencies.png) + +Which is similar to the baseline. + +![rotating-all-latencies-bl](img37/200nodes_tm037/v037_rotating_latencies.png) + +The average increase of about 1 second with respect to the baseline is due to the higher +transaction load produced (remember the baseline was affected by [\#9539], whereby most transactions +produced were rejected by `CheckTx`). + +### Prometheus Metrics + +The set of metrics shown here roughly match those shown on the baseline (`v0.37`) for the same experiment. +We also show the baseline results for comparison. + +#### Blocks and Transactions per minute + +This following plot shows the blocks produced per minute. + +![rotating-heights](img38/rotating/rotating_block_rate.png) + +This is similar to the baseline, shown below. + +![rotating-heights-bl](img37/rotating/rotating_block_rate.png) + +The following plot shows only the heights reported by ephemeral nodes, both when they were blocksyncing +and when they were running consensus. +The second plot is the baseline plot for comparison. The baseline lacks the heights when the nodes were +blocksyncing as that metric was implemented afterwards. + +![rotating-heights-ephe](img38/rotating/rotating_eph_heights.png) + +![rotating-heights-ephe-bl](img37/rotating/rotating_eph_heights.png) + +We see that heights follow a similar pattern in both plots: they grow in length as the experiment advances. + +The following plot shows the transactions processed per minute. + +![rotating-total-txs](img38/rotating/rotating_txs_rate.png) + +For comparison, this is the baseline plot. + +![rotating-total-txs-bl](img37/rotating/rotating_txs_rate.png) + +We can see the rate is much lower in the baseline plot. +The reason is that the baseline was affected by [\#9539], whereby `CheckTx` rejected most transactions +produced by the load runner. + +#### Peers + +The plot below shows the evolution of the number of peers throughout the experiment. + +![rotating-peers](img38/rotating/rotating_peers.png) + +This is the baseline plot, for comparison. + +![rotating-peers-bl](img37/rotating/rotating_peers.png) + +The plotted values and their evolution are comparable in both plots. + +For further details on these plots, see the [this section](TMCore-QA-34.md#peers-1). + +#### Memory Resident Set Size + +The average Resident Set Size (RSS) over all processes is notably bigger on `v0.38.0-alpha.2` than on the baseline. +The reason for this is, again, the fact that `CheckTx` was rejecting most transactions submitted on the baseline +and therefore the overall transaction load was lower on the baseline. +This is consistent with the difference seen in the transaction rate plots +in the [previous section](#blocks-and-transactions-per-minute). + +![rotating-rss-avg](img38/rotating/rotating_avg_memory.png) + +![rotating-rss-avg-bl](img37/rotating/rotating_avg_memory.png) + +#### CPU utilization + +The plots show metric `load1` for all nodes for `v0.38.0-alpha.2` and for the baseline. + +![rotating-load1](img38/rotating/rotating_cpu.png) + +![rotating-load1-bl](img37/rotating/rotating_cpu.png) + +In both cases, it is contained under 5 most of the time, which is considered normal load. +The load seems to be more important on `v0.38.0-alpha.2` on average because of the bigger +number of transactions processed per minute as compared to the baseline. + +### Test Result + +| Scenario | Date | Version | Result | +| -------- | ---------- | ---------------------------------------------------------- | ------ | +| Rotating | 2023-05-23 | v0.38.0-alpha.2 (e9abb116e29beb830cf111b824c8e2174d538838) | Pass | + + + +## Vote Extensions Testbed + +In this testnet we evaluate the effect of varying the sizes of vote extensions added to pre-commit votes on the performance of CometBFT. +The test uses the Key/Value store in our [[end-to-end]] test framework, which has the following simplified flow: + +1. When validators send their pre-commit votes to a block of height $i$, they first extend the vote as they see fit in `ExtendVote`. +2. When a proposer for height $i+1$ creates a block to propose, in `PrepareProposal`, it prepends the transactions with a special transaction, which modifies a reserved key. The transaction value is derived from the extensions from height $i$; in this example, the value is derived from the vote extensions and includes the set itself, hexa encoded as string. +3. When a validator sends their pre-vote for the block proposed in $i+1$, they first double check in `ProcessProposal` that the special transaction in the block was properly built by the proposer. +4. When validators send their pre-commit for the block proposed in $i+1$, they first extend the vote, and the steps repeat for heights $i+2$ and so on. + +For this test, extensions are random sequences of bytes with a predefined `vote_extension_size`. +Hence, two effects are seen on the network. +First, pre-commit vote message sizes will increase by the specified `vote_extension_size` and, second, block messages will increase by twice `vote_extension_size`, given then hexa encoding of extensions, times the number of extensions received, i.e. at least 2/3 of 175. + +All tests were performed on commit d5baba237ab3a04c1fd4a7b10927ba2e6a2aab27, which corresponds to v0.38.0-alpha.2 plus commits to add the ability to vary the vote extension sizes to the test application. +Although the same commit is used for the baseline, in this configuration the behavior observed is the same as in the "vanilla" v0.38.0-alpha.2 test application, that is, vote extensions are 8-byte integers, compressed as variable size integers instead of a random sequence of size `vote_extension_size`. + +The following table summarizes the test cases. + +| Name | Extension Size (bytes) | Date | +| -------- | ---------------------- | ---------- | +| baseline | 8 (varint) | 2023-05-26 | +| 2k | 2048 | 2023-05-29 | +| 4k | 4094 | 2023-05-29 | +| 8k | 8192 | 2023-05-26 | +| 16k | 16384 | 2023-05-26 | +| 32k | 32768 | 2023-05-26 | + + +### Latency + +The following figures show the latencies observed on each of the 5 runs of each experiment; +the redline shows the average of each run. +It can be easily seen from these graphs that the larger the vote extension size, the more latency varies and the more common higher latencies become. +Even in the case of extensions of size 2k, the mean latency goes from below 5s to nearly 10s. + +**Baseline** + +![](img38/voteExtensions/all_experiments_baseline.png) + +**2k** + +![](img38/voteExtensions/all_experiments_2k.png) + +**4k** + +![](img38/voteExtensions/all_experiments_4k.png) + +**8k** + +![](img38/voteExtensions/all_experiments_8k.png) + +**16k** + +![](img38/voteExtensions/all_experiments_16k.png) + +**32k** + +![](img38/voteExtensions/all_experiments_32k.png) + +The following graphs combine all the runs of the same experiment. +They show that latency variation greatly increases with the increase of vote extensions. +In particular, for the 16k and 32k cases, the system goes through large gaps without transaction delivery. +As discussed later, this is the result of heights taking multiple rounds to finish and new transactions being held until the next block is agreed upon. + +| | | +| ---------------------------------------------------------- | ------------------------------------------------ | +| baseline ![](img38/voteExtensions/all_c1r400_baseline.png) | 2k ![](img38/voteExtensions/all_c1r400_2k.png) | +| 4k ![](img38/voteExtensions/all_c1r400_4k.png) | 8k ![](img38/voteExtensions/all_c1r400_8k.png) | +| 16k ![](img38/voteExtensions/all_c1r400_16k.png) | 32k ![](img38/voteExtensions/all_c1r400_32k.png) | + + +### Blocks and Transactions per minute + +The following plots show the blocks produced per minute and transactions processed per minute. +We have divided the presentation in an overview section, which shows the metrics for the whole experiment (five runs) and a detailed sample, which shows the metrics for the first of the five runs. +We repeat the approach for the other metrics as well. +The dashed red line shows the moving average over a 20s window. + +#### Overview + +It is clear from the overview plots that as the vote extension sizes increase, the rate of block creation decreases. +Although the rate of transaction processing also decreases, it does not seem to decrease as fast. + +| Experiment | Block creation rate | Transaction rate | +| ------------ | ----------------------------------------------------------- | ------------------------------------------------------------- | +| **baseline** | ![block rate](img38/voteExtensions/baseline_block_rate.png) | ![txs rate](img38/voteExtensions/baseline_total_txs_rate.png) | +| **2k** | ![block rate](img38/voteExtensions/02k_block_rate.png) | ![txs rate](img38/voteExtensions/02k_total_txs_rate.png) | +| **4k** | ![block rate](img38/voteExtensions/04k_block_rate.png) | ![txs rate](img38/voteExtensions/04k_total_txs_rate.png) | +| **8k** | ![block rate](img38/voteExtensions/8k_block_rate.png) | ![txs rate](img38/voteExtensions/08k_total_txs_rate.png) | +| **16k** | ![block rate](img38/voteExtensions/16k_block_rate.png) | ![txs rate](img38/voteExtensions/16k_total_txs_rate.png) | +| **32k** | ![block rate](img38/voteExtensions/32k_block_rate.png) | ![txs rate](img38/voteExtensions/32k_total_txs_rate.png) | + +#### First run + +| Experiment | Block creation rate | Transaction rate | +| ------------ | ------------------------------------------------------------- | --------------------------------------------------------------- | +| **baseline** | ![block rate](img38/voteExtensions/baseline_1_block_rate.png) | ![txs rate](img38/voteExtensions/baseline_1_total_txs_rate.png) | +| **2k** | ![block rate](img38/voteExtensions/02k_1_block_rate.png) | ![txs rate](img38/voteExtensions/02k_1_total_txs_rate.png) | +| **4k** | ![block rate](img38/voteExtensions/04k_1_block_rate.png) | ![txs rate](img38/voteExtensions/04k_1_total_txs_rate.png) | +| **8k** | ![block rate](img38/voteExtensions/08k_1_block_rate.png) | ![txs rate](img38/voteExtensions/08k_1_total_txs_rate.png) | +| **16k** | ![block rate](img38/voteExtensions/16k_1_block_rate.png) | ![txs rate](img38/voteExtensions/16k_1_total_txs_rate.png) | +| **32k** | ![block rate](img38/voteExtensions/32k_1_block_rate.png) | ![txs rate](img38/voteExtensions/32k_1_total_txs_rate.png) | + + +### Number of rounds + +The effect of vote extensions are also felt on the number of rounds needed to reach consensus. +The following graphs show the number of the highest round required to reach consensus during the whole experiment. + +In the baseline and low vote extension lengths, most blocks were agreed upon during round 0. +As the load increases, more and more rounds were required. +In the 32k case se see round 5 being reached frequently. + +| Experiment | Number of Rounds per block | +| ------------ | ------------------------------------------------------------- | +| **baseline** | ![number of rounds](img38/voteExtensions/baseline_rounds.png) | +| **2k** | ![number of rounds](img38/voteExtensions/02k_rounds.png) | +| **4k** | ![number of rounds](img38/voteExtensions/04k_rounds.png) | +| **8k** | ![number of rounds](img38/voteExtensions/08k_rounds.png) | +| **16k** | ![number of rounds](img38/voteExtensions/16k_rounds.png) | +| **32k** | ![number of rounds](img38/voteExtensions/32k_rounds.png) | + + +We conjecture that the reason is that the timeouts used are inadequate for the extra traffic in the network. + +### CPU + +The CPU usage reached the same peaks on all tests, but the following graphs show that with larger Vote Extensions, nodes take longer to reduce the CPU usage. +This could mean that a backlog of processing is forming during the execution of the tests with larger extensions. + + +| Experiment | CPU | +| ------------ | ----------------------------------------------------- | +| **baseline** | ![cpu-avg](img38/voteExtensions/baseline_avg_cpu.png) | +| **2k** | ![cpu-avg](img38/voteExtensions/02k_avg_cpu.png) | +| **4k** | ![cpu-avg](img38/voteExtensions/04k_avg_cpu.png) | +| **8k** | ![cpu-avg](img38/voteExtensions/08k_avg_cpu.png) | +| **16k** | ![cpu-avg](img38/voteExtensions/16k_avg_cpu.png) | +| **32k** | ![cpu-avg](img38/voteExtensions/32k_avg_cpu.png) | + +### Resident Memory + +The same conclusion reached for CPU usage may be drawn for the memory. +That is, that a backlog of work is formed during the tests and catching up (freeing of memory) happens after the test is done. + +A more worrying trend is that the bottom of the memory usage seems to increase in between runs. +We have investigated this in longer runs and confirmed that there is no such a trend. + + + +| Experiment | Resident Set Size | +| ------------ | -------------------------------------------------------- | +| **baseline** | ![rss-avg](img38/voteExtensions/baseline_avg_memory.png) | +| **2k** | ![rss-avg](img38/voteExtensions/02k_avg_memory.png) | +| **4k** | ![rss-avg](img38/voteExtensions/04k_avg_memory.png) | +| **8k** | ![rss-avg](img38/voteExtensions/08k_avg_memory.png) | +| **16k** | ![rss-avg](img38/voteExtensions/16k_avg_memory.png) | +| **32k** | ![rss-avg](img38/voteExtensions/32k_avg_memory.png) | + +### Mempool size + +This metric shows how many transactions are outstanding in the nodes' mempools. +Observe that in all runs, the average number of transactions in the mempool quickly drops to near zero between runs. + + +| Experiment | Resident Set Size | +| ------------ | ------------------------------------------------------------------ | +| **baseline** | ![mempool-avg](img38/voteExtensions/baseline_avg_mempool_size.png) | +| **2k** | ![mempool-avg](img38/voteExtensions/02k_avg_mempool_size.png) | +| **4k** | ![mempool-avg](img38/voteExtensions/04k_avg_mempool_size.png) | +| **8k** | ![mempool-avg](img38/voteExtensions/08k_avg_mempool_size.png) | +| **16k** | ![mempool-avg](img38/voteExtensions/16k_avg_mempool_size.png) | +| **32k** | ![mempool-avg](img38/voteExtensions/32k_avg_mempool_size.png) | + + + + + +### Results + +| Scenario | Date | Version | Result | +| -------- | ---------- | ------------------------------------------------------------------------------------- | ------ | +| VESize | 2023-05-23 | v0.38.0-alpha.2 + varying vote extensions (9fc711b6514f99b2dc0864fc703cb81214f01783) | N/A | + + + +[\#9539]: https://github.com/tendermint/tendermint/issues/9539 +[\#9548]: https://github.com/tendermint/tendermint/issues/9548 +[\#539]: https://github.com/cometbft/cometbft/issues/539 +[\#546]: https://github.com/cometbft/cometbft/issues/546 +[\#562]: https://github.com/cometbft/cometbft/issues/562 +[end-to-end]: https://github.com/cometbft/cometbft/tree/main/test/e2e diff --git a/docs/references/qa/CometBFT-QA-v1.md b/docs/references/qa/CometBFT-QA-v1.md new file mode 100644 index 00000000000..9284c31dc92 --- /dev/null +++ b/docs/references/qa/CometBFT-QA-v1.md @@ -0,0 +1,477 @@ +--- +order: 1 +parent: + title: QA results for CometBFT v1.x + description: This is a report on the results obtained when running CometBFT v1.x on testnets + order: 5 +--- + +## Table of Contents +- [QA results for CometBFT v1.x](#qa-results-for-cometbft-v1x) + - [Latency emulation (LE)](#latency-emulation-le) + - [Storage optimizations](#storage-optimizations) + - [Saturation point](#saturation-point) + - [With latency emulation](#with-latency-emulation) + - [200-nodes test](#200-nodes-test) + - [Latencies](#latencies) + - [Metrics](#metrics) + - [Mempool size](#mempool-size) + - [Peers](#peers) + - [Consensus rounds](#consensus-rounds) + - [Blocks produced per minute and transactions processed per minute](#blocks-produced-per-minute-and-transactions-processed-per-minute) + - [Memory resident set size](#memory-resident-set-size) + - [CPU utilization](#cpu-utilization) + - [Test Results](#test-results) + - [Test results with latency emulation](#test-results-with-latency-emulation) + - [Rotating Nodes Testnet](#rotating-nodes-testnet) + - [Latencies](#latencies-1) + - [Prometheus Metrics](#prometheus-metrics) + - [Blocks and Transactions per minute](#blocks-and-transactions-per-minute) + - [Peers](#peers-1) + - [Memory Resident Set Size](#memory-resident-set-size-1) + - [CPU utilization](#cpu-utilization-1) + - [Test Result](#test-result) + +# QA results for CometBFT v1.x + +We run this iteration of the [Quality Assurance (QA)][qa] process on CometBFT `v1.0.0-alpha.2`, the +second tag of the backport branch `v1.x` from the CometBFT repository. The previous QA tests were +performed on `v0.38.0-alpha.2` from May 21, 2023, which we use here as a baseline for comparison. +There are many changes with respect to the baseline. In particular, new features that can affect +performance are some improvements to bandwidth consumption and proposer-based timestamps (PBTS). For +the full list of changes, check out the +[CHANGELOG](https://github.com/cometbft/cometbft/blob/v1.0.0-alpha.2/CHANGELOG.md). + +The primary objective of the QA process is to ensure that no significant regressions have occurred +compared to the previous version. We consider that a regression is present if there is a variance +greater than 10% in the results. After having performed the experiments, we have determined that no +notable differences exist when compared to the baseline. Consequently, version `v1.0.0-alpha.2` has +successfully passed the QA tests. + +In the remainder of this document we present and analyse the results obtained. The main steps of the +QA process are the following: +- [Saturation point](#saturation-point): On a network with 200 nodes, identify its saturation point, + that is, the transaction load where system performance begins to degrade. Subsequent QA + experiments will subject the system to a load slightly below this saturation point. +- [200-nodes test](#200-nodes-test): Apply a consistent transaction load to the 200-nodes network + for a fixed duration. Then, gather metrics and block data to calculate latencies and compare them + with the baseline results. +- Rotating-nodes test: Initially, deploy 10 validators and 3 seed nodes. Start the same load + (saturation point) used for the previous tests. Then, launch 25 full nodes, wait until they are + caught up to the latest height (minus 100) using Block Sync, and then stop them and wipe out their + data on disk. Repeat this process until the chain reaches height 3000. Then, stop the load and + wait for the full nodes to catch up one more time. + +## Latency emulation (LE) + +For the first time in the QA process we are introducing latency emulation (LE) into our experiments. +We typically deploy all the testnet nodes within the same region of a DigitalOcean data center to +keep the costs low. However, this setup creates unrealistic communication between nodes due to +minimal latency. To address this, while still deploying the testnet in a single region, we can now +emulate latency by adding random delays into outgoing messages. + +Here's how we emulate latency: +- Reference real latency data: We utilize [a table][aws-latencies] containing real data collected + from AWS, which includes average latencies between different AWS data centers worldwide. +- Assign zones: When defining the testnet, each node is randomly assigned a "zone", corresponding + to one of the regions listed in the latency table. +- Set delays: Prior to launching CometBFT on each node, we execute a script to configure added + delays between the current node and every other zone, as specified in the latency table. This + script utilizes the `tc` utility to control network traffic at the kernel level. + +Up until now, all QA results were obtained without latency emulation. To ensure fair comparisons, we +will conduct a two-step analysis. First, we will compare the QA results of `v0.38` (the baseline) +with those of `v1` without latency emulation. Secondly, we will compare the results of `v1` with and +without latency emulation. + +It's important to note that the results with latency emulation in this report are not used to assess +whether `v1.0.0-alpha.2` passes the QA tests. Instead, they serve as a baseline for future QA tests to +be conducted for upcoming releases. + +## Storage optimizations + +We have conducted several experiments aimed to address concerns regarding storage efficiency and +performance of CometBFT. These experiments focused on various aspects, including the effectiveness +of the pruning mechanism, the impact of different database key layouts, and the performance of +alternative database engines like PebbleDB. For a comprehensive overview, you can access the full +report [here](../storage/README.md). + +The experiments were performed on different versions of CometBFT. Of particular relevance for this +report are those where we targeted a version based on `v1.0.0-alpha.1`. The main difference with +`v1.0.0-alpha.2` is PBTS, which does not impact storage performance. Hence, we consider the results +obtained equally applicable to `v1.0.0-alpha.2`. In particular, both versions include the data +companion API, background pruning, compaction, and support for different key layouts. + +To summarize the findings relevant to `v1`: +- Pruning does not negatively affect the node performance, though it showed to be ineffective at + controlling storage growth. However, combining pruning with forced compaction and the new key + layout proved to be an effective strategy, which we recommend adopting. +- Experiments reveal mixed results regarding the impact of different database key layouts on + performance. While some scenarios exhibit improvements in block processing times and storage + efficiency, particularly with the new key layout, further analysis suggests that the benefits of + the new layout were not consistently realized across different environments. Consequently, we've + released the new key layout as purely experimental. +- Tests with PebbleDB showed promising performance improvements, especially when paired with the new + key layout. PebbleDB exhibits superior handling of compaction without the need of manual + intervention. + +## Saturation point + +The initial phase of our QA process involves identifying the saturation point within the testnet. As +in previous iterations, our testbed comprises 200 nodes (175 validator nodes, 20 full nodes, and 5 +seed nodes), along with one node dedicated to sending transaction load, and another for metric +collection. All nodes use the same, default configuration. The experiment entails multiple +iterations, each lasting 90 seconds, with varied load configurations. A configuration is +characterized by: +- `c`, denoting the number of connections from the load runner process to the target node, and +- `r`, indicating the rate or frequency of transactions submitted per second. Each connection + dispatches `r` transactions per second. + +All transactions are 1024 bytes long. +For more details on the methodology to identify the saturation point, see +[here](method.md#running-the-test). + +The figure below shows the values obtained for v1 and v0.38 (the baseline). It's important to note +that configurations that have the same amount of total transaction load are regarded as equivalent. +For example, `c=1,r=400` and `c=2,r=200` are plotted on the same x-axis value corresponding to their +total rate of 400 tx/s, which corresponds to configuration with `c=1`. + +![saturation-plot](imgs/v1/saturation/saturation_v1_v038.png) + +In the figure, we observe that up to a rate of 400 tx/s, the obtained values closely match or are +equal to the expected number of processed transactions, which is 35600 txs. However, beyond this +point, the system becomes overloaded and cannot process all incoming transactions, resulting in +dropped transactions. This state indicates that the system is saturated. The expected number of +processed transactions is calculated as `c * r * 89 s = 35600 txs`. It's worth noting that we +utilize 89 out of 90 seconds of the experiment duration, as the final transaction batch coincides +with the end of the experiment and is thus not sent. + +The complete results from which the figure was generated can be found in the file +[`v1_report_tabbed.txt`](imgs/v1/200nodes/v1_report_tabbed.txt). The following table summarizes the +values plotted in the figure, that is, the number of transaction processed. We can see the +saturation point in the diagonal defined by `c=1,r=400` and `c=2,r=200`: + +| r | c=1 | c=2 | c=4 | +| ---: | --------: | --------: | ----: | +| 200 | 17800 | **34600** | 50464 | +| 400 | **31200** | 54706 | 49463 | +| 800 | 51146 | 51917 | 41376 | +| 1600 | 50889 | 47732 | 45530 | + +For comparison, this is the table obtained on the baseline version, with the same saturation point: + +| r | c=1 | c=2 | c=4 | +| ---: | --------: | --------: | ----: | +| 200 | 17800 | **33259** | 33259 | +| 400 | **35600** | 41565 | 41384 | +| 800 | 36831 | 38686 | 40816 | +| 1600 | 40600 | 45034 | 39830 | + +In conclusion, we chose `c=1,r=400` as the transaction load that we will use in the rest of QA +process. This is the same value used in the previous QA tests. + +### With latency emulation + +For comparing where the network starts to saturate in `v1` with and without latency emulation, we +run a new set of experiments with different configurations of transaction loads: we use only one +connection and a transaction rate ranging from 100 to 1000 tx/s, in intervals of 100. The figure +depicts in total six instances of these experiments, three with latency emulation and three without. + +![v1_saturation](imgs/v1/saturation/saturation_v1_LE.png) + +Up to 300 tx/s, the throughput is optimal for both configurations. However, when the load increases +beyond this threshold, not all transactions are processed. Given the limited number of experiments +conducted, it's challenging to conclusively determine which configuration offers better throughput. +Nevertheless, we can still say that there are no big discrepancies in the obtained values on both +scenarios. + +## 200-nodes test + +This experiment consists in running the 200-nodes network, injecting a load of 400 tx/s (`c=1,r=400`) +during 90 seconds, and collecting the metrics. The network composition is the same as used for +finding the saturation point. + +For the experiments with latency emulation we have set a duration of 180 seconds instead of 90. + +### Latencies + +The following figures show the latencies of the experiment. Each dot represents a block: at which +time it was created (x axis) and the average latency of its transactions (y axis). + +| v0.38 | v1 (without LE / with LE) +|:--------------:|:--------------:| +| ![latency-1-400-v38](img38/200nodes/e_de676ecf-038e-443f-a26a-27915f29e312.png) | ![latency-1-400-v1](imgs/v1/200nodes/latencies/e_8e4e1e81-c171-4879-b86f-bce96ee2e861.png) +| | ![latency-1-400-v1-le](imgs/v1/200nodes_with_latency_emulation/latencies/e_8190e83a-9135-444b-92fb-4efaeaaf2b52.png) + +In both cases, most latencies are around or below 4 seconds. On `v0.38` there are peaks reaching 10 +seconds, while on `v1` (without LE) the only peak reaches 8 seconds. Even if both images are +similar, it's crucial to note that `v0.38` implements [BFT time][bft-time], while the experiments on +`v1` were performed with [PBTS][pbts]. The implication is that PBTS tends to produce slightly +smaller latencies. The reason is that, in PBTS, the block's timestamp is the proposer's wallclock +value at the moment the block was created. For reference, with BFT time, the block's timestamp is +the median of the timestamp of all precommits in the previous height. Each of these timestamps +reflects the validator's wallclock time when the precommit is sent. Consequently, latencies +calculated when BFT time is active tend to contain one extra network propagation delay--the one +whereby precommits are disseminated. + +With these considerations in mind, and taking into account that this is a small experiment, we infer +that the latencies measured on `v1` are not worse than those of the baseline. With latency +emulation, the latencies are considerably higher, as expected. + +### Metrics + +In this section we analyse key metrics extracted from Prometheus data on the 200-nodes experiment +with configuration `c=1,r=400`. + +#### Mempool size + +The following figures show the evolution of the average and maximum mempool size over all full +nodes. + +**Average size** On `v1`, the average mempool size mostly stays below 1000 outstanding transactions +except for a peak above 2000, coinciding with the moment the system reached round number 1 (see +below). For these particular runs, this result is better than the baseline, which oscilates between +1000 and 2500. + +With latency emulation, the average mempool size stays mostly above 2000 outstanding transactions +with peaks almost reaching the maximum mempool size of 5000 transactions. + +| v0.38 | v1 (without LE / with LE) +| :--------------:|:--------------:| +| ![mempool-avg-baseline](img38/200nodes/avg_mempool_size_ylim.png) | ![mempool-avg](imgs/v1/200nodes/metrics/avg_mempool_size.png) +| | ![mempool-avg-le](imgs/v1/200nodes_with_latency_emulation/metrics/avg_mempool_size.png) + +**Maximum size** The maximum mempool size indicates when one or more nodes have reached their +maximum capacity in terms of the number of transactions they can hold. In version `v0.38`, it's +apparent that most of the time, at least one node is dropping incoming transactions. +Conversely, in `v1`, this happens less often, especially after reaching round 1 (as detailed below). + +However, when we introduce latency emulation into `v1`, there is consistently at least one node with +a saturated mempool. + +| v0.38 | v1 (without LE / with LE) +| :--------------:|:--------------:| +| ![mempool-cumulative-baseline](img38/200nodes/mempool_size_max.png) | ![mempoool-cumulative](imgs/v1/200nodes/metrics/mempool_size_max.png) +| | ![mempoool-cumulative-le](imgs/v1/200nodes_with_latency_emulation/metrics/mempool_size_max.png) + +#### Peers + +On all experiments, the number of peers was stable on all nodes. As expected, the seed nodes have +more peers (around 125) than the rest (between 20 and 70 for most nodes). The red dashed line +denotes the average value. Just as in the baseline, the fact that non-seed nodes reach more than 50 +peers is due to [\#486]. + +| v0.38 | v1 (without LE / with LE) +|:--------------:|:--------------:| +| ![peers](img38/200nodes/peers.png) | ![peers](imgs/v1/200nodes/metrics/peers.png) +| | ![peers](imgs/v1/200nodes_with_latency_emulation/metrics/peers.png) + +#### Consensus rounds + +On both versions, most blocks took just one round to reach consensus, except for a few cases when +a second round was needed. On these two particular runs, we observe that `v0.38` required an extra +round on more occasions than `v1`. + +With latency emulation, the performance is notably worse: the consensus module requires an extra +round more often, even needing four rounds to finalise a block. This indicates that the values of +consensus timeouts should be increased, so that to represent the actual delays in the network. + +| v0.38 | v1 (without LE / with LE) +|:--------------:|:--------------:| +| ![rounds](img38/200nodes/rounds_ylim.png) | ![rounds](imgs/v1/200nodes/metrics/rounds.png) +| | ![rounds](imgs/v1/200nodes_with_latency_emulation/metrics/rounds.png) + +#### Blocks produced per minute and transactions processed per minute + +These figures show the rate in which blocks were created from the point of view of each node, +indicating when each node learned that a new block had been agreed upon. Throughout much of the load +application period, the majority of nodes maintained a rate of between 20 and 40 blocks per minute. +A spike to more than 100 blocks per minute occurred due to a slower node catching up. In the +baseline scenario, most blocks had a somewhat slower rate of approximately between 10 and 30 blocks +per minute. + +| v0.38 | v1 (without LE / with LE) +|:--------------:|:--------------:| +| ![heights-baseline](img38/200nodes/block_rate.png) | ![heights](imgs/v1/200nodes/metrics/block_rate.png) +| | ![heights](imgs/v1/200nodes_with_latency_emulation/metrics/block_rate.png) + +| v0.38 | v1 (without LE / with LE) +|:--------------:|:--------------:| +| ![total-txs-baseline](img38/200nodes/total_txs_rate_ylim.png) | ![total-txs](imgs/v1/200nodes/metrics/total_txs_rate.png) +| | ![total-txs](imgs/v1/200nodes_with_latency_emulation/metrics/total_txs_rate.png) + +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. + +With latency emulation (LE), there is a noticeable degradation in throughput. The block generation +rate drops from approximately 30 blocks per minute (without LE) to around 10 blocks per minute. +Since the rates of transaction processing are similar, this means that more transactions are +included in the blocks, as shown in the following images. The most probable reason is that, once block latency is higher with latency emulation, more transactions are available at the proposer when it is ready to propose a new block. Note that the maximum block size is 4 Mb. + +| v0.38 | v1 (without LE / with LE) +|:--------------:|:--------------:| +| ![block-size-v038](img38/200nodes/block_size_bytes.png) | ![block-size-v1](imgs/v1/200nodes/metrics/block_size_bytes.png) +| | ![block-size-v1-le](imgs/v1/200nodes_with_latency_emulation/metrics/block_size_bytes.png) + +#### Memory resident set size + +The following graphs show the Resident Set Size of all monitored processes. Most nodes use less than +0.9 GB of memory, and a maximum of 1.3GB. In all cases, the memory usage in `v1` is less than in the +baseline. On all processes, the memory usage went down as the load was being removed, showing no +signs of unconstrained growth. With latency emulation, the results are comparable. + +| v0.38 | v1 (without LE / with LE) +|:--------------:|:--------------:| +|![rss](img38/200nodes/memory_ylim.png) | ![rss](imgs/v1/200nodes/metrics/memory.png) +| | ![rss](imgs/v1/200nodes_with_latency_emulation/metrics/memory.png) + +#### CPU utilization + +The most reliable metric from Prometheus for assessing CPU utilization in a Unix machine is `load1`, +commonly found in the [output of +`top`](https://www.digitalocean.com/community/tutorials/load-average-in-linux). In these scenarios, +the load remains consistently below 4 on the majority of nodes, with the baseline exhibiting a +similar pattern. With latency emulation, the CPU load reaches 5 on some nodes, probably due to +having a busier mempool and processing more rounds. + +| v0.38 | v1 (without LE / with LE) +|:--------------:|:--------------:| +| ![load1-baseline](img38/200nodes/cpu.png) | ![load1](imgs/v1/200nodes/metrics/cpu.png) +| | ![load1](imgs/v1/200nodes_with_latency_emulation/metrics/cpu.png) + +### Test Results + +We have demonstrated that there are no regressions when comparing CometBFT `v1.0.0-alpha.2` against +the results obtained for `v0.38`. In fact, the observed results are identical to, or occasionally even +slightly better than those of the baseline. We therefore conclude that this version of CometBFT has +passed the test. + +| Scenario | Date | Version | Result | +| --------- | ---------- | --------------------------------------------------------- | ------ | +| 200-nodes | 2024-03-21 | v1.0.0-alpha.2 (4ced46d3d742bdc6093050bd67d9bbde830b6df2) | Pass | + +#### Test results with latency emulation + +As expected, the introduction of emulated latencies to the network results in a degradation of +performance for `v1` compared to `v1` without latency emulation, although not by an order of +magnitude. Moving forward with the next QA tests, it may be prudent to consider adjusting the +saturation point to a slightly lower value. Determining this adjustment will require conducting new +experiments on the network with latency emulation. + +## Rotating Nodes Testnet + +As done in past releases, we use `c=1,r=400` as load, as the saturation point in the 200-node test +has not changed from `v0.38.x` (see the corresponding [section](#saturation-point) above). +Further, although latency emulation is now available, we decided to run this test case +without latency emulation (LE); this choice may change in future releases. + +The baseline considered in this test case is `v0.38.0-alpha.2`, as described +in the [introduction](#qa-results-for-cometbft-v1x) above. + +### Latencies + +The following two plots show latencies for the whole experiment. +We see the baseline (`v0.38.0-alpha.2`) on the left, and the current version +on the right. + +We can appreciate that most latencies are under 4 seconds in both cases, +and both graphs have a comparable amount of outliers between 4 seconds and 11 seconds. + +| v0.38.0 | v1.0.0 (without LE) | +| :-----------------------------------------------------------------: | :-------------------------------------------------------: | +| ![rotating-all-latencies-bl](img38/rotating/rotating_latencies.png) | ![rotating-all-latencies](imgs/v1/rotating/latencies.png) | + + +### Prometheus Metrics + +This section shows relevant metrics both on `v1.0.0` and the baseline (`v0.38.0`). +In general, all metrics roughly match those seen on the baseline +for the rotating node experiment. + +#### Blocks and Transactions per minute + +The following two plots show the blocks produced per minute. In both graphs, most nodes stabilize around 40 blocks per minute. + +| v0.38.0 | v1.0.0 (without LE) | +| :------------------------------------------------------------: | :-------------------------------------------------------------------: | +| ![rotating-heights-bl](img38/rotating/rotating_block_rate.png) | ![rotating-heights](imgs/v1/rotating/metrics/rotating_block_rate.png) | + +The following plots show only the heights reported by ephemeral nodes, both when they were blocksyncing +and when they were running consensus. + +| v0.38.0 | v1.0.0 (without LE) | +| :------------------------------------------------------------------: | :----------------------------------------------------------------: | +| ![rotating-heights-ephe-bl](img38/rotating/rotating_eph_heights.png) | ![rotating-heights-ephe](imgs/v1/rotating/metrics/rotating_eph_heights.png) | + +In both cases, we see the main loop of the `rotating` test case repeat itself a number of times. +Ephemeral nodes are stopped, their persisted state is wiped out, their config is transferred over +from the orchestrating node, they are started, we wait for all of them to catch up via blocksync, +and the whole cycle starts over. All these steps are carried out via `ansible` playbooks. + +We see that there are less cycles in `v1.0.0`. The reason is the following. +All `ansible` steps are currently run from the orchestrating node (i.e., the engineer's laptop). +The orchestrating node when running the rotating nodes test case for `v1.0.0` +was connected to a network connection that was slower than when the equivalent test was run for `v0.38.x`. +This caused the steps reconfiguring ephemeral nodes at the end of each cycle to be somewhat slower. +This can be noticed in the graphs when comparing the width (in x-axis terms) of the gaps without metric +from the end of a cycle to the beginning of the next one. + +If we focus on the _width_ of periods when ephemeral nodes are blocksynching, we see that they are slightly narrower +in `v1.0.0`. This is likely due to the improvements introduced as part of the issues +[#1283](https://github.com/cometbft/cometbft/issues/1283), +[#2379](https://github.com/cometbft/cometbft/issues/2379), and +[#2465](https://github.com/cometbft/cometbft/issues/2465). + +The following plots show the transactions processed per minute. + +| v0.38.0 | v1.0.0 (without LE) | +| :------------------------------------------------------------: | :-------------------------------------------------------------------: | +| ![rotating-total-txs-bl](img38/rotating/rotating_txs_rate.png) | ![rotating-total-txs](imgs/v1/rotating/metrics/rotating_txs_rate.png) | + +They seem similar, except for an outlier in the `v1.0.0` plot. + +#### Peers + +The plots below show the evolution of the number of peers throughout the experiment. + +| v0.38.0 | v1.0.0 (without LE) | +| :-----------------------------------------------------: | :------------------------------------------------------------: | +| ![rotating-peers-bl](img38/rotating/rotating_peers.png) | ![rotating-peers](imgs/v1/rotating/metrics/rotating_peers.png) | + +The plotted values and their evolution show the same dynamics in both plots. +Nevertheless, all nodes seem to acquire more peers when ephemeral node are catching up in the `v1.0.0` experiment. + +For further explanations on these plots, see the [this section](TMCore-QA-34.md#peers-1). + +#### Memory Resident Set Size + +These plots show the average Resident Set Size (RSS) over all processes. +They are comparable in both releases. + +| v0.38.0 | v1.0.0 (without LE) | +| :------------------------------------------------------------: | :-------------------------------------------------------------------: | +| ![rotating-rss-avg-bl](img38/rotating/rotating_avg_memory.png) | ![rotating-rss-avg](imgs/v1/rotating/metrics/rotating_avg_memory.png) | + +#### CPU utilization + +The plots below show metric `load1` for all nodes for `v1.0.0-alpha.2` and for the baseline (`v0.38.0`). + +| v0.38.0 | v1.0.0 (without LE) | +| :---------------------------------------------------: | :-------------------------------------------------: | +| ![rotating-load1-bl](img38/rotating/rotating_cpu.png) | ![rotating-load1](imgs/v1/rotating/metrics/rotating_cpu.png) | + +In both cases, it is contained under 5 most of the time, which is considered normal load. + +### Test Result + +| Scenario | Date | Version | Result | +| -------- | ---------- | --------------------------------------------------------- | ------ | +| Rotating | 2024-04-03 | v1.0.0-alpha.2 (e42f62b681a2d0b05607a61d834afea90f73d366) | Pass | + +[qa]: README.md#cometbft-quality-assurance +[aws-latencies]: https://github.com/cometbft/cometbft/blob/v1.0.0-alpha.2/test/e2e/pkg/latency/aws-latencies.csv +[latency-emulator-script]: https://github.com/cometbft/cometbft/blob/v1.0.0-alpha.2/test/e2e/pkg/latency/latency-setter.py +[bft-time]: ../../../spec/consensus/bft-time.md +[pbts]: ../../../spec/consensus/proposer-based-timestamp/README.md +[\#486]: https://github.com/cometbft/cometbft/issues/486 +[end-to-end]: https://github.com/cometbft/cometbft/tree/main/test/e2e diff --git a/docs/qa/README.md b/docs/references/qa/README.md similarity index 81% rename from docs/qa/README.md rename to docs/references/qa/README.md index d59049074bc..78610688f46 100644 --- a/docs/qa/README.md +++ b/docs/references/qa/README.md @@ -3,7 +3,7 @@ order: 1 parent: title: CometBFT Quality Assurance description: This is a report on the process followed and results obtained when running v0.34.x on testnets - order: 2 + order: 7 --- # CometBFT Quality Assurance @@ -14,7 +14,7 @@ This directory is to live in multiple branches. On each release branch, the contents of this directory reflect the status of the process at the time the Quality Assurance process was applied for that release. -File [method](./method.md) keeps track of the process followed to obtain the results +File [method](method.md) keeps track of the process followed to obtain the results 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. @@ -23,3 +23,5 @@ The following releases have undergone the Quality Assurance process, and the cor * [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. +* [v0.38.x](CometBFT-QA-38.md) - Tested on v0.38.0-alpha.2, using v0.37.x results as baseline. +* [v1.x](CometBFT-QA-v1.md) - Tested on v1.0.0-alpha.2, using v0.38.x results as baseline. diff --git a/docs/qa/TMCore-QA-34.md b/docs/references/qa/TMCore-QA-34.md similarity index 91% rename from docs/qa/TMCore-QA-34.md rename to docs/references/qa/TMCore-QA-34.md index e5764611c06..fbf85401b58 100644 --- a/docs/qa/TMCore-QA-34.md +++ b/docs/references/qa/TMCore-QA-34.md @@ -8,6 +8,27 @@ parent: # Tendermint Core QA Results v0.34.x +## Table of Contents +- [200 Node Testnet](#200-node-testnet) + - [Finding the Saturation Point](#finding-the-saturation-point) + - [Examining latencies](#examining-latencies) + - [Prometheus Metrics on the Chosen Experiment](#prometheus-metrics-on-the-chosen-experiment) + - [Mempool Size](#mempool-size) + - [Peers](#peers) + - [Consensus Rounds per Height](#consensus-rounds-per-height) + - [Blocks Produced per Minute, Transactions Processed per Minute](#blocks-produced-per-minute-transactions-processed-per-minute) + - [Memory Resident Set Size](#memory-resident-set-size) + - [CPU utilization](#cpu-utilization) + - [Test Result](#test-result) +- [Rotating Node Testnet](#rotating-node-testnet) + - [Latencies](#latencies) + - [Prometheus Metrics](#prometheus-metrics) + - [Blocks and Transactions per minute](#blocks-and-transactions-per-minute) + - [Peers](#peers-1) + - [Memory Resident Set Size](#memory-resident-set-size-1) + - [CPU utilization](#cpu-utilization-1) + - [Test Result](#test-result-1) + ## 200 Node Testnet ### Finding the Saturation Point diff --git a/docs/qa/TMCore-QA-37.md b/docs/references/qa/TMCore-QA-37.md similarity index 91% rename from docs/qa/TMCore-QA-37.md rename to docs/references/qa/TMCore-QA-37.md index edff57b0276..624c6704dd9 100644 --- a/docs/qa/TMCore-QA-37.md +++ b/docs/references/qa/TMCore-QA-37.md @@ -8,6 +8,28 @@ parent: # Tendermint Core QA Results v0.37.x +## Table of Contents +- [Issues discovered](#issues-discovered) +- [200 Node Testnet](#200-node-testnet) + - [Finding the Saturation Point](#finding-the-saturation-point) + - [Examining latencies](#examining-latencies) + - [Prometheus Metrics on the Chosen Experiment](#prometheus-metrics-on-the-chosen-experiment) + - [Mempool Size](#mempool-size) + - [Peers](#peers) + - [Consensus Rounds per Height](#consensus-rounds-per-height) + - [Blocks Produced per Minute, Transactions Processed per Minute](#blocks-produced-per-minute-transactions-processed-per-minute) + - [Memory Resident Set Size](#memory-resident-set-size) + - [CPU utilization](#cpu-utilization) + - [Test Result](#test-result) +- [Rotating Node Testnet](#rotating-node-testnet) + - [Latencies](#latencies) + - [Prometheus Metrics](#prometheus-metrics) + - [Blocks and Transactions per minute](#blocks-and-transactions-per-minute) + - [Peers](#peers-1) + - [Memory Resident Set Size](#memory-resident-set-size-1) + - [CPU utilization](#cpu-utilization-1) + - [Test Result](#test-result-1) + ## Issues discovered During this iteration of the QA process, the following issues were found: diff --git a/docs/qa/img34/baseline/avg_cpu.png b/docs/references/qa/img34/baseline/avg_cpu.png similarity index 100% rename from docs/qa/img34/baseline/avg_cpu.png rename to docs/references/qa/img34/baseline/avg_cpu.png diff --git a/docs/qa/img34/baseline/avg_memory.png b/docs/references/qa/img34/baseline/avg_memory.png similarity index 100% rename from docs/qa/img34/baseline/avg_memory.png rename to docs/references/qa/img34/baseline/avg_memory.png diff --git a/docs/qa/img34/baseline/avg_mempool_size.png b/docs/references/qa/img34/baseline/avg_mempool_size.png similarity index 100% rename from docs/qa/img34/baseline/avg_mempool_size.png rename to docs/references/qa/img34/baseline/avg_mempool_size.png diff --git a/docs/qa/img34/baseline/block_rate_regular.png b/docs/references/qa/img34/baseline/block_rate_regular.png similarity index 100% rename from docs/qa/img34/baseline/block_rate_regular.png rename to docs/references/qa/img34/baseline/block_rate_regular.png diff --git a/docs/qa/img34/baseline/cpu.png b/docs/references/qa/img34/baseline/cpu.png similarity index 100% rename from docs/qa/img34/baseline/cpu.png rename to docs/references/qa/img34/baseline/cpu.png diff --git a/docs/qa/img34/baseline/memory.png b/docs/references/qa/img34/baseline/memory.png similarity index 100% rename from docs/qa/img34/baseline/memory.png rename to docs/references/qa/img34/baseline/memory.png diff --git a/docs/qa/img34/baseline/mempool_size.png b/docs/references/qa/img34/baseline/mempool_size.png similarity index 100% rename from docs/qa/img34/baseline/mempool_size.png rename to docs/references/qa/img34/baseline/mempool_size.png diff --git a/docs/qa/img34/baseline/peers.png b/docs/references/qa/img34/baseline/peers.png similarity index 100% rename from docs/qa/img34/baseline/peers.png rename to docs/references/qa/img34/baseline/peers.png diff --git a/docs/qa/img34/baseline/rounds.png b/docs/references/qa/img34/baseline/rounds.png similarity index 100% rename from docs/qa/img34/baseline/rounds.png rename to docs/references/qa/img34/baseline/rounds.png diff --git a/docs/qa/img34/baseline/total_txs_rate_regular.png b/docs/references/qa/img34/baseline/total_txs_rate_regular.png similarity index 100% rename from docs/qa/img34/baseline/total_txs_rate_regular.png rename to docs/references/qa/img34/baseline/total_txs_rate_regular.png diff --git a/docs/qa/img34/cmt1tm1/all_experiments.png b/docs/references/qa/img34/cmt1tm1/all_experiments.png similarity index 100% rename from docs/qa/img34/cmt1tm1/all_experiments.png rename to docs/references/qa/img34/cmt1tm1/all_experiments.png diff --git a/docs/qa/img34/cmt1tm1/avg_cpu.png b/docs/references/qa/img34/cmt1tm1/avg_cpu.png similarity index 100% rename from docs/qa/img34/cmt1tm1/avg_cpu.png rename to docs/references/qa/img34/cmt1tm1/avg_cpu.png diff --git a/docs/qa/img34/cmt1tm1/avg_memory.png b/docs/references/qa/img34/cmt1tm1/avg_memory.png similarity index 100% rename from docs/qa/img34/cmt1tm1/avg_memory.png rename to docs/references/qa/img34/cmt1tm1/avg_memory.png diff --git a/docs/qa/img34/cmt1tm1/avg_mempool_size.png b/docs/references/qa/img34/cmt1tm1/avg_mempool_size.png similarity index 100% rename from docs/qa/img34/cmt1tm1/avg_mempool_size.png rename to docs/references/qa/img34/cmt1tm1/avg_mempool_size.png diff --git a/docs/qa/img34/cmt1tm1/block_rate_regular.png b/docs/references/qa/img34/cmt1tm1/block_rate_regular.png similarity index 100% rename from docs/qa/img34/cmt1tm1/block_rate_regular.png rename to docs/references/qa/img34/cmt1tm1/block_rate_regular.png diff --git a/docs/qa/img34/cmt1tm1/cpu.png b/docs/references/qa/img34/cmt1tm1/cpu.png similarity index 100% rename from docs/qa/img34/cmt1tm1/cpu.png rename to docs/references/qa/img34/cmt1tm1/cpu.png diff --git a/docs/qa/img34/cmt1tm1/memory.png b/docs/references/qa/img34/cmt1tm1/memory.png similarity index 100% rename from docs/qa/img34/cmt1tm1/memory.png rename to docs/references/qa/img34/cmt1tm1/memory.png diff --git a/docs/qa/img34/cmt1tm1/mempool_size.png b/docs/references/qa/img34/cmt1tm1/mempool_size.png similarity index 100% rename from docs/qa/img34/cmt1tm1/mempool_size.png rename to docs/references/qa/img34/cmt1tm1/mempool_size.png diff --git a/docs/qa/img34/cmt1tm1/peers.png b/docs/references/qa/img34/cmt1tm1/peers.png similarity index 100% rename from docs/qa/img34/cmt1tm1/peers.png rename to docs/references/qa/img34/cmt1tm1/peers.png diff --git a/docs/qa/img34/cmt1tm1/rounds.png b/docs/references/qa/img34/cmt1tm1/rounds.png similarity index 100% rename from docs/qa/img34/cmt1tm1/rounds.png rename to docs/references/qa/img34/cmt1tm1/rounds.png diff --git a/docs/qa/img34/cmt1tm1/total_txs_rate_regular.png b/docs/references/qa/img34/cmt1tm1/total_txs_rate_regular.png similarity index 100% rename from docs/qa/img34/cmt1tm1/total_txs_rate_regular.png rename to docs/references/qa/img34/cmt1tm1/total_txs_rate_regular.png diff --git a/docs/qa/img34/cmt2tm1/all_experiments.png b/docs/references/qa/img34/cmt2tm1/all_experiments.png similarity index 100% rename from docs/qa/img34/cmt2tm1/all_experiments.png rename to docs/references/qa/img34/cmt2tm1/all_experiments.png diff --git a/docs/qa/img34/cmt2tm1/avg_cpu.png b/docs/references/qa/img34/cmt2tm1/avg_cpu.png similarity index 100% rename from docs/qa/img34/cmt2tm1/avg_cpu.png rename to docs/references/qa/img34/cmt2tm1/avg_cpu.png diff --git a/docs/qa/img34/cmt2tm1/avg_memory.png b/docs/references/qa/img34/cmt2tm1/avg_memory.png similarity index 100% rename from docs/qa/img34/cmt2tm1/avg_memory.png rename to docs/references/qa/img34/cmt2tm1/avg_memory.png diff --git a/docs/qa/img34/cmt2tm1/avg_mempool_size.png b/docs/references/qa/img34/cmt2tm1/avg_mempool_size.png similarity index 100% rename from docs/qa/img34/cmt2tm1/avg_mempool_size.png rename to docs/references/qa/img34/cmt2tm1/avg_mempool_size.png diff --git a/docs/qa/img34/cmt2tm1/block_rate_regular.png b/docs/references/qa/img34/cmt2tm1/block_rate_regular.png similarity index 100% rename from docs/qa/img34/cmt2tm1/block_rate_regular.png rename to docs/references/qa/img34/cmt2tm1/block_rate_regular.png diff --git a/docs/qa/img34/cmt2tm1/cpu.png b/docs/references/qa/img34/cmt2tm1/cpu.png similarity index 100% rename from docs/qa/img34/cmt2tm1/cpu.png rename to docs/references/qa/img34/cmt2tm1/cpu.png diff --git a/docs/qa/img34/cmt2tm1/memory.png b/docs/references/qa/img34/cmt2tm1/memory.png similarity index 100% rename from docs/qa/img34/cmt2tm1/memory.png rename to docs/references/qa/img34/cmt2tm1/memory.png diff --git a/docs/qa/img34/cmt2tm1/mempool_size.png b/docs/references/qa/img34/cmt2tm1/mempool_size.png similarity index 100% rename from docs/qa/img34/cmt2tm1/mempool_size.png rename to docs/references/qa/img34/cmt2tm1/mempool_size.png diff --git a/docs/qa/img34/cmt2tm1/peers.png b/docs/references/qa/img34/cmt2tm1/peers.png similarity index 100% rename from docs/qa/img34/cmt2tm1/peers.png rename to docs/references/qa/img34/cmt2tm1/peers.png diff --git a/docs/qa/img34/cmt2tm1/rounds.png b/docs/references/qa/img34/cmt2tm1/rounds.png similarity index 100% rename from docs/qa/img34/cmt2tm1/rounds.png rename to docs/references/qa/img34/cmt2tm1/rounds.png diff --git a/docs/qa/img34/cmt2tm1/total_txs_rate_regular.png b/docs/references/qa/img34/cmt2tm1/total_txs_rate_regular.png similarity index 100% rename from docs/qa/img34/cmt2tm1/total_txs_rate_regular.png rename to docs/references/qa/img34/cmt2tm1/total_txs_rate_regular.png diff --git a/docs/qa/img34/homogeneous/all_experiments.png b/docs/references/qa/img34/homogeneous/all_experiments.png similarity index 100% rename from docs/qa/img34/homogeneous/all_experiments.png rename to docs/references/qa/img34/homogeneous/all_experiments.png diff --git a/docs/qa/img34/homogeneous/avg_cpu.png b/docs/references/qa/img34/homogeneous/avg_cpu.png similarity index 100% rename from docs/qa/img34/homogeneous/avg_cpu.png rename to docs/references/qa/img34/homogeneous/avg_cpu.png diff --git a/docs/qa/img34/homogeneous/avg_memory.png b/docs/references/qa/img34/homogeneous/avg_memory.png similarity index 100% rename from docs/qa/img34/homogeneous/avg_memory.png rename to docs/references/qa/img34/homogeneous/avg_memory.png diff --git a/docs/qa/img34/homogeneous/avg_mempool_size.png b/docs/references/qa/img34/homogeneous/avg_mempool_size.png similarity index 100% rename from docs/qa/img34/homogeneous/avg_mempool_size.png rename to docs/references/qa/img34/homogeneous/avg_mempool_size.png diff --git a/docs/qa/img34/homogeneous/block_rate_regular.png b/docs/references/qa/img34/homogeneous/block_rate_regular.png similarity index 100% rename from docs/qa/img34/homogeneous/block_rate_regular.png rename to docs/references/qa/img34/homogeneous/block_rate_regular.png diff --git a/docs/qa/img34/homogeneous/cpu.png b/docs/references/qa/img34/homogeneous/cpu.png similarity index 100% rename from docs/qa/img34/homogeneous/cpu.png rename to docs/references/qa/img34/homogeneous/cpu.png diff --git a/docs/qa/img34/homogeneous/memory.png b/docs/references/qa/img34/homogeneous/memory.png similarity index 100% rename from docs/qa/img34/homogeneous/memory.png rename to docs/references/qa/img34/homogeneous/memory.png diff --git a/docs/qa/img34/homogeneous/mempool_size.png b/docs/references/qa/img34/homogeneous/mempool_size.png similarity index 100% rename from docs/qa/img34/homogeneous/mempool_size.png rename to docs/references/qa/img34/homogeneous/mempool_size.png diff --git a/docs/qa/img34/homogeneous/peers.png b/docs/references/qa/img34/homogeneous/peers.png similarity index 100% rename from docs/qa/img34/homogeneous/peers.png rename to docs/references/qa/img34/homogeneous/peers.png diff --git a/docs/qa/img34/homogeneous/rounds.png b/docs/references/qa/img34/homogeneous/rounds.png similarity index 100% rename from docs/qa/img34/homogeneous/rounds.png rename to docs/references/qa/img34/homogeneous/rounds.png diff --git a/docs/qa/img34/homogeneous/total_txs_rate_regular.png b/docs/references/qa/img34/homogeneous/total_txs_rate_regular.png similarity index 100% rename from docs/qa/img34/homogeneous/total_txs_rate_regular.png rename to docs/references/qa/img34/homogeneous/total_txs_rate_regular.png diff --git a/docs/qa/img34/v034_200node_latencies.png b/docs/references/qa/img34/v034_200node_latencies.png similarity index 100% rename from docs/qa/img34/v034_200node_latencies.png rename to docs/references/qa/img34/v034_200node_latencies.png diff --git a/docs/qa/img34/v034_200node_latencies_zoomed.png b/docs/references/qa/img34/v034_200node_latencies_zoomed.png similarity index 100% rename from docs/qa/img34/v034_200node_latencies_zoomed.png rename to docs/references/qa/img34/v034_200node_latencies_zoomed.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/all_experiments.png b/docs/references/qa/img34/v034_200node_tm2cmt1/all_experiments.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/all_experiments.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/all_experiments.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/avg_cpu.png b/docs/references/qa/img34/v034_200node_tm2cmt1/avg_cpu.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/avg_cpu.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/avg_cpu.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/avg_memory.png b/docs/references/qa/img34/v034_200node_tm2cmt1/avg_memory.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/avg_memory.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/avg_memory.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/avg_mempool_size.png b/docs/references/qa/img34/v034_200node_tm2cmt1/avg_mempool_size.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/avg_mempool_size.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/avg_mempool_size.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/block_rate_regular.png b/docs/references/qa/img34/v034_200node_tm2cmt1/block_rate_regular.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/block_rate_regular.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/block_rate_regular.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/c2r200_merged.png b/docs/references/qa/img34/v034_200node_tm2cmt1/c2r200_merged.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/c2r200_merged.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/c2r200_merged.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/cpu.png b/docs/references/qa/img34/v034_200node_tm2cmt1/cpu.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/cpu.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/cpu.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/memory.png b/docs/references/qa/img34/v034_200node_tm2cmt1/memory.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/memory.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/memory.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/mempool_size.png b/docs/references/qa/img34/v034_200node_tm2cmt1/mempool_size.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/mempool_size.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/mempool_size.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/peers.png b/docs/references/qa/img34/v034_200node_tm2cmt1/peers.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/peers.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/peers.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/rounds.png b/docs/references/qa/img34/v034_200node_tm2cmt1/rounds.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/rounds.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/rounds.png diff --git a/docs/qa/img34/v034_200node_tm2cmt1/total_txs_rate_regular.png b/docs/references/qa/img34/v034_200node_tm2cmt1/total_txs_rate_regular.png similarity index 100% rename from docs/qa/img34/v034_200node_tm2cmt1/total_txs_rate_regular.png rename to docs/references/qa/img34/v034_200node_tm2cmt1/total_txs_rate_regular.png diff --git a/docs/qa/img34/v034_latency_throughput.png b/docs/references/qa/img34/v034_latency_throughput.png similarity index 100% rename from docs/qa/img34/v034_latency_throughput.png rename to docs/references/qa/img34/v034_latency_throughput.png diff --git a/docs/qa/img34/v034_r200c2_heights.png b/docs/references/qa/img34/v034_r200c2_heights.png similarity index 100% rename from docs/qa/img34/v034_r200c2_heights.png rename to docs/references/qa/img34/v034_r200c2_heights.png diff --git a/docs/qa/img34/v034_r200c2_load-runner.png b/docs/references/qa/img34/v034_r200c2_load-runner.png similarity index 100% rename from docs/qa/img34/v034_r200c2_load-runner.png rename to docs/references/qa/img34/v034_r200c2_load-runner.png diff --git a/docs/qa/img34/v034_r200c2_load1.png b/docs/references/qa/img34/v034_r200c2_load1.png similarity index 100% rename from docs/qa/img34/v034_r200c2_load1.png rename to docs/references/qa/img34/v034_r200c2_load1.png diff --git a/docs/qa/img34/v034_r200c2_mempool_size.png b/docs/references/qa/img34/v034_r200c2_mempool_size.png similarity index 100% rename from docs/qa/img34/v034_r200c2_mempool_size.png rename to docs/references/qa/img34/v034_r200c2_mempool_size.png diff --git a/docs/qa/img34/v034_r200c2_mempool_size_avg.png b/docs/references/qa/img34/v034_r200c2_mempool_size_avg.png similarity index 100% rename from docs/qa/img34/v034_r200c2_mempool_size_avg.png rename to docs/references/qa/img34/v034_r200c2_mempool_size_avg.png diff --git a/docs/qa/img34/v034_r200c2_peers.png b/docs/references/qa/img34/v034_r200c2_peers.png similarity index 100% rename from docs/qa/img34/v034_r200c2_peers.png rename to docs/references/qa/img34/v034_r200c2_peers.png diff --git a/docs/qa/img34/v034_r200c2_rounds.png b/docs/references/qa/img34/v034_r200c2_rounds.png similarity index 100% rename from docs/qa/img34/v034_r200c2_rounds.png rename to docs/references/qa/img34/v034_r200c2_rounds.png diff --git a/docs/qa/img34/v034_r200c2_rss.png b/docs/references/qa/img34/v034_r200c2_rss.png similarity index 100% rename from docs/qa/img34/v034_r200c2_rss.png rename to docs/references/qa/img34/v034_r200c2_rss.png diff --git a/docs/qa/img34/v034_r200c2_rss_avg.png b/docs/references/qa/img34/v034_r200c2_rss_avg.png similarity index 100% rename from docs/qa/img34/v034_r200c2_rss_avg.png rename to docs/references/qa/img34/v034_r200c2_rss_avg.png diff --git a/docs/qa/img34/v034_r200c2_total-txs.png b/docs/references/qa/img34/v034_r200c2_total-txs.png similarity index 100% rename from docs/qa/img34/v034_r200c2_total-txs.png rename to docs/references/qa/img34/v034_r200c2_total-txs.png diff --git a/docs/qa/img34/v034_report_tabbed.txt b/docs/references/qa/img34/v034_report_tabbed.txt similarity index 100% rename from docs/qa/img34/v034_report_tabbed.txt rename to docs/references/qa/img34/v034_report_tabbed.txt diff --git a/docs/qa/img34/v034_rotating_heights.png b/docs/references/qa/img34/v034_rotating_heights.png similarity index 100% rename from docs/qa/img34/v034_rotating_heights.png rename to docs/references/qa/img34/v034_rotating_heights.png diff --git a/docs/qa/img34/v034_rotating_heights_ephe.png b/docs/references/qa/img34/v034_rotating_heights_ephe.png similarity index 100% rename from docs/qa/img34/v034_rotating_heights_ephe.png rename to docs/references/qa/img34/v034_rotating_heights_ephe.png diff --git a/docs/qa/img34/v034_rotating_latencies.png b/docs/references/qa/img34/v034_rotating_latencies.png similarity index 100% rename from docs/qa/img34/v034_rotating_latencies.png rename to docs/references/qa/img34/v034_rotating_latencies.png diff --git a/docs/qa/img34/v034_rotating_latencies_uniq.png b/docs/references/qa/img34/v034_rotating_latencies_uniq.png similarity index 100% rename from docs/qa/img34/v034_rotating_latencies_uniq.png rename to docs/references/qa/img34/v034_rotating_latencies_uniq.png diff --git a/docs/qa/img34/v034_rotating_load1.png b/docs/references/qa/img34/v034_rotating_load1.png similarity index 100% rename from docs/qa/img34/v034_rotating_load1.png rename to docs/references/qa/img34/v034_rotating_load1.png diff --git a/docs/qa/img34/v034_rotating_peers.png b/docs/references/qa/img34/v034_rotating_peers.png similarity index 100% rename from docs/qa/img34/v034_rotating_peers.png rename to docs/references/qa/img34/v034_rotating_peers.png diff --git a/docs/qa/img34/v034_rotating_rss_avg.png b/docs/references/qa/img34/v034_rotating_rss_avg.png similarity index 100% rename from docs/qa/img34/v034_rotating_rss_avg.png rename to docs/references/qa/img34/v034_rotating_rss_avg.png diff --git a/docs/qa/img34/v034_rotating_total-txs.png b/docs/references/qa/img34/v034_rotating_total-txs.png similarity index 100% rename from docs/qa/img34/v034_rotating_total-txs.png rename to docs/references/qa/img34/v034_rotating_total-txs.png diff --git a/docs/qa/img37/200nodes_cmt037/all_experiments.png b/docs/references/qa/img37/200nodes_cmt037/all_experiments.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/all_experiments.png rename to docs/references/qa/img37/200nodes_cmt037/all_experiments.png diff --git a/docs/qa/img37/200nodes_cmt037/avg_mempool_size.png b/docs/references/qa/img37/200nodes_cmt037/avg_mempool_size.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/avg_mempool_size.png rename to docs/references/qa/img37/200nodes_cmt037/avg_mempool_size.png diff --git a/docs/qa/img37/200nodes_cmt037/block_rate.png b/docs/references/qa/img37/200nodes_cmt037/block_rate.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/block_rate.png rename to docs/references/qa/img37/200nodes_cmt037/block_rate.png diff --git a/docs/qa/img37/200nodes_cmt037/cpu.png b/docs/references/qa/img37/200nodes_cmt037/cpu.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/cpu.png rename to docs/references/qa/img37/200nodes_cmt037/cpu.png diff --git a/docs/qa/img37/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png b/docs/references/qa/img37/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png rename to docs/references/qa/img37/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png diff --git a/docs/qa/img37/200nodes_cmt037/memory.png b/docs/references/qa/img37/200nodes_cmt037/memory.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/memory.png rename to docs/references/qa/img37/200nodes_cmt037/memory.png diff --git a/docs/qa/img37/200nodes_cmt037/mempool_size.png b/docs/references/qa/img37/200nodes_cmt037/mempool_size.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/mempool_size.png rename to docs/references/qa/img37/200nodes_cmt037/mempool_size.png diff --git a/docs/qa/img37/200nodes_cmt037/peers.png b/docs/references/qa/img37/200nodes_cmt037/peers.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/peers.png rename to docs/references/qa/img37/200nodes_cmt037/peers.png diff --git a/docs/qa/img37/200nodes_cmt037/rounds.png b/docs/references/qa/img37/200nodes_cmt037/rounds.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/rounds.png rename to docs/references/qa/img37/200nodes_cmt037/rounds.png diff --git a/docs/qa/img37/200nodes_cmt037/total_txs_rate.png b/docs/references/qa/img37/200nodes_cmt037/total_txs_rate.png similarity index 100% rename from docs/qa/img37/200nodes_cmt037/total_txs_rate.png rename to docs/references/qa/img37/200nodes_cmt037/total_txs_rate.png diff --git a/docs/qa/img37/200nodes_tm037/avg_mempool_size.png b/docs/references/qa/img37/200nodes_tm037/avg_mempool_size.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/avg_mempool_size.png rename to docs/references/qa/img37/200nodes_tm037/avg_mempool_size.png diff --git a/docs/qa/img37/200nodes_tm037/block_rate_regular.png b/docs/references/qa/img37/200nodes_tm037/block_rate_regular.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/block_rate_regular.png rename to docs/references/qa/img37/200nodes_tm037/block_rate_regular.png diff --git a/docs/qa/img37/200nodes_tm037/cpu.png b/docs/references/qa/img37/200nodes_tm037/cpu.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/cpu.png rename to docs/references/qa/img37/200nodes_tm037/cpu.png diff --git a/docs/qa/img37/200nodes_tm037/memory.png b/docs/references/qa/img37/200nodes_tm037/memory.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/memory.png rename to docs/references/qa/img37/200nodes_tm037/memory.png diff --git a/docs/qa/img37/200nodes_tm037/mempool_size.png b/docs/references/qa/img37/200nodes_tm037/mempool_size.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/mempool_size.png rename to docs/references/qa/img37/200nodes_tm037/mempool_size.png diff --git a/docs/qa/img37/200nodes_tm037/peers.png b/docs/references/qa/img37/200nodes_tm037/peers.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/peers.png rename to docs/references/qa/img37/200nodes_tm037/peers.png diff --git a/docs/qa/img37/200nodes_tm037/rounds.png b/docs/references/qa/img37/200nodes_tm037/rounds.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/rounds.png rename to docs/references/qa/img37/200nodes_tm037/rounds.png diff --git a/docs/qa/img37/200nodes_tm037/total_txs_rate_regular.png b/docs/references/qa/img37/200nodes_tm037/total_txs_rate_regular.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/total_txs_rate_regular.png rename to docs/references/qa/img37/200nodes_tm037/total_txs_rate_regular.png diff --git a/docs/qa/img37/200nodes_tm037/v037_200node_latencies.png b/docs/references/qa/img37/200nodes_tm037/v037_200node_latencies.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_200node_latencies.png rename to docs/references/qa/img37/200nodes_tm037/v037_200node_latencies.png diff --git a/docs/qa/img37/200nodes_tm037/v037_latency_throughput.png b/docs/references/qa/img37/200nodes_tm037/v037_latency_throughput.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_latency_throughput.png rename to docs/references/qa/img37/200nodes_tm037/v037_latency_throughput.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_heights.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_heights.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_heights.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_heights.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_load1.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_load1.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_load1.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_load1.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_mempool_size.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_mempool_size.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_mempool_size.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_mempool_size.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_mempool_size_avg.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_mempool_size_avg.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_mempool_size_avg.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_mempool_size_avg.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_peers.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_peers.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_peers.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_peers.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_rounds.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_rounds.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_rounds.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_rounds.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_rss.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_rss.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_rss.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_rss.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_rss_avg.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_rss_avg.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_rss_avg.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_rss_avg.png diff --git a/docs/qa/img37/200nodes_tm037/v037_r200c2_total-txs.png b/docs/references/qa/img37/200nodes_tm037/v037_r200c2_total-txs.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_r200c2_total-txs.png rename to docs/references/qa/img37/200nodes_tm037/v037_r200c2_total-txs.png diff --git a/docs/qa/img37/200nodes_tm037/v037_report_tabbed.txt b/docs/references/qa/img37/200nodes_tm037/v037_report_tabbed.txt similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_report_tabbed.txt rename to docs/references/qa/img37/200nodes_tm037/v037_report_tabbed.txt diff --git a/docs/qa/img37/200nodes_tm037/v037_rotating_heights.png b/docs/references/qa/img37/200nodes_tm037/v037_rotating_heights.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_rotating_heights.png rename to docs/references/qa/img37/200nodes_tm037/v037_rotating_heights.png diff --git a/docs/qa/img37/200nodes_tm037/v037_rotating_heights_ephe.png b/docs/references/qa/img37/200nodes_tm037/v037_rotating_heights_ephe.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_rotating_heights_ephe.png rename to docs/references/qa/img37/200nodes_tm037/v037_rotating_heights_ephe.png diff --git a/docs/qa/img37/200nodes_tm037/v037_rotating_latencies.png b/docs/references/qa/img37/200nodes_tm037/v037_rotating_latencies.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_rotating_latencies.png rename to docs/references/qa/img37/200nodes_tm037/v037_rotating_latencies.png diff --git a/docs/qa/img37/200nodes_tm037/v037_rotating_load1.png b/docs/references/qa/img37/200nodes_tm037/v037_rotating_load1.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_rotating_load1.png rename to docs/references/qa/img37/200nodes_tm037/v037_rotating_load1.png diff --git a/docs/qa/img37/200nodes_tm037/v037_rotating_peers.png b/docs/references/qa/img37/200nodes_tm037/v037_rotating_peers.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_rotating_peers.png rename to docs/references/qa/img37/200nodes_tm037/v037_rotating_peers.png diff --git a/docs/qa/img37/200nodes_tm037/v037_rotating_rss_avg.png b/docs/references/qa/img37/200nodes_tm037/v037_rotating_rss_avg.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_rotating_rss_avg.png rename to docs/references/qa/img37/200nodes_tm037/v037_rotating_rss_avg.png diff --git a/docs/qa/img37/200nodes_tm037/v037_rotating_total-txs.png b/docs/references/qa/img37/200nodes_tm037/v037_rotating_total-txs.png similarity index 100% rename from docs/qa/img37/200nodes_tm037/v037_rotating_total-txs.png rename to docs/references/qa/img37/200nodes_tm037/v037_rotating_total-txs.png diff --git a/docs/references/qa/img37/rotating/rotating_avg_memory.png b/docs/references/qa/img37/rotating/rotating_avg_memory.png new file mode 100644 index 00000000000..7feb2e81261 Binary files /dev/null and b/docs/references/qa/img37/rotating/rotating_avg_memory.png differ diff --git a/docs/references/qa/img37/rotating/rotating_block_rate.png b/docs/references/qa/img37/rotating/rotating_block_rate.png new file mode 100644 index 00000000000..4bbc3c99941 Binary files /dev/null and b/docs/references/qa/img37/rotating/rotating_block_rate.png differ diff --git a/docs/references/qa/img37/rotating/rotating_cpu.png b/docs/references/qa/img37/rotating/rotating_cpu.png new file mode 100644 index 00000000000..ef4c7d30df2 Binary files /dev/null and b/docs/references/qa/img37/rotating/rotating_cpu.png differ diff --git a/docs/references/qa/img37/rotating/rotating_eph_heights.png b/docs/references/qa/img37/rotating/rotating_eph_heights.png new file mode 100644 index 00000000000..36850fb526c Binary files /dev/null and b/docs/references/qa/img37/rotating/rotating_eph_heights.png differ diff --git a/docs/references/qa/img37/rotating/rotating_peers.png b/docs/references/qa/img37/rotating/rotating_peers.png new file mode 100644 index 00000000000..c45a4d4d73b Binary files /dev/null and b/docs/references/qa/img37/rotating/rotating_peers.png differ diff --git a/docs/references/qa/img37/rotating/rotating_txs_rate.png b/docs/references/qa/img37/rotating/rotating_txs_rate.png new file mode 100644 index 00000000000..5462738e5b9 Binary files /dev/null and b/docs/references/qa/img37/rotating/rotating_txs_rate.png differ diff --git a/docs/references/qa/img38/200nodes/avg_mempool_size.png b/docs/references/qa/img38/200nodes/avg_mempool_size.png new file mode 100644 index 00000000000..36cd5f6c705 Binary files /dev/null and b/docs/references/qa/img38/200nodes/avg_mempool_size.png differ diff --git a/docs/references/qa/img38/200nodes/avg_mempool_size_ylim.png b/docs/references/qa/img38/200nodes/avg_mempool_size_ylim.png new file mode 100644 index 00000000000..e1c3108b72e Binary files /dev/null and b/docs/references/qa/img38/200nodes/avg_mempool_size_ylim.png differ diff --git a/docs/references/qa/img38/200nodes/block_rate.png b/docs/references/qa/img38/200nodes/block_rate.png new file mode 100644 index 00000000000..b2042865d5e Binary files /dev/null and b/docs/references/qa/img38/200nodes/block_rate.png differ diff --git a/docs/references/qa/img38/200nodes/block_size_bytes.png b/docs/references/qa/img38/200nodes/block_size_bytes.png new file mode 100644 index 00000000000..32bb4bffdd7 Binary files /dev/null and b/docs/references/qa/img38/200nodes/block_size_bytes.png differ diff --git a/docs/references/qa/img38/200nodes/c1r400.png b/docs/references/qa/img38/200nodes/c1r400.png new file mode 100644 index 00000000000..0c27c144f84 Binary files /dev/null and b/docs/references/qa/img38/200nodes/c1r400.png differ diff --git a/docs/references/qa/img38/200nodes/cpu.png b/docs/references/qa/img38/200nodes/cpu.png new file mode 100644 index 00000000000..15f74aeb041 Binary files /dev/null and b/docs/references/qa/img38/200nodes/cpu.png differ diff --git a/docs/references/qa/img38/200nodes/e_de676ecf-038e-443f-a26a-27915f29e312.png b/docs/references/qa/img38/200nodes/e_de676ecf-038e-443f-a26a-27915f29e312.png new file mode 100644 index 00000000000..21f5cab6ea1 Binary files /dev/null and b/docs/references/qa/img38/200nodes/e_de676ecf-038e-443f-a26a-27915f29e312.png differ diff --git a/docs/references/qa/img38/200nodes/memory.png b/docs/references/qa/img38/200nodes/memory.png new file mode 100644 index 00000000000..3e01c4ccd0b Binary files /dev/null and b/docs/references/qa/img38/200nodes/memory.png differ diff --git a/docs/references/qa/img38/200nodes/memory_ylim.png b/docs/references/qa/img38/200nodes/memory_ylim.png new file mode 100644 index 00000000000..a9e25eb2007 Binary files /dev/null and b/docs/references/qa/img38/200nodes/memory_ylim.png differ diff --git a/docs/references/qa/img38/200nodes/mempool_size.png b/docs/references/qa/img38/200nodes/mempool_size.png new file mode 100644 index 00000000000..6a897a84a15 Binary files /dev/null and b/docs/references/qa/img38/200nodes/mempool_size.png differ diff --git a/docs/references/qa/img38/200nodes/mempool_size_max.png b/docs/references/qa/img38/200nodes/mempool_size_max.png new file mode 100644 index 00000000000..e28d6724979 Binary files /dev/null and b/docs/references/qa/img38/200nodes/mempool_size_max.png differ diff --git a/docs/references/qa/img38/200nodes/peers.png b/docs/references/qa/img38/200nodes/peers.png new file mode 100644 index 00000000000..87470051950 Binary files /dev/null and b/docs/references/qa/img38/200nodes/peers.png differ diff --git a/docs/references/qa/img38/200nodes/rounds.png b/docs/references/qa/img38/200nodes/rounds.png new file mode 100644 index 00000000000..5ac53cad869 Binary files /dev/null and b/docs/references/qa/img38/200nodes/rounds.png differ diff --git a/docs/references/qa/img38/200nodes/rounds_ylim.png b/docs/references/qa/img38/200nodes/rounds_ylim.png new file mode 100644 index 00000000000..1c769d9c7a0 Binary files /dev/null and b/docs/references/qa/img38/200nodes/rounds_ylim.png differ diff --git a/docs/references/qa/img38/200nodes/total_txs_rate.png b/docs/references/qa/img38/200nodes/total_txs_rate.png new file mode 100644 index 00000000000..ac7f5e686b9 Binary files /dev/null and b/docs/references/qa/img38/200nodes/total_txs_rate.png differ diff --git a/docs/references/qa/img38/200nodes/total_txs_rate_ylim.png b/docs/references/qa/img38/200nodes/total_txs_rate_ylim.png new file mode 100644 index 00000000000..83900aef29f Binary files /dev/null and b/docs/references/qa/img38/200nodes/total_txs_rate_ylim.png differ diff --git a/docs/references/qa/img38/200nodes/v038_report_tabbed.txt b/docs/references/qa/img38/200nodes/v038_report_tabbed.txt new file mode 100644 index 00000000000..c482aeac84c --- /dev/null +++ b/docs/references/qa/img38/200nodes/v038_report_tabbed.txt @@ -0,0 +1,40 @@ +Experiment ID: 93024f38-a008-443d-9aa7-9ac44c9fe15b Experiment ID: d65a486e-4712-41b5-9f41-97e491895d2e Experiment ID: 9c39184b-b8c7-46a2-bacb-40f9961fb7a1 + Connections: 1 Connections: 2 Connections: 4 + Rate: 200 Rate: 200 Rate: 200 + Size: 1024 Size: 1024 Size: 1024 + Total Valid Tx: 17800 Total Valid Tx: 33259 Total Valid Tx: 33259 + Total Negative Latencies: 0 Total Negative Latencies: 0 Total Negative Latencies: 0 + Minimum Latency: 562.805076ms Minimum Latency: 894.026089ms Minimum Latency: 2.166875257s + Maximum Latency: 7.623963559s Maximum Latency: 16.941216187s Maximum Latency: 15.701598288s + Average Latency: 1.860012628s Average Latency: 4.033134276s Average Latency: 7.592412668s + Standard Deviation: 1.169158915s Standard Deviation: 3.427243686s Standard Deviation: 2.951797195s +Experiment ID: de676ecf-038e-443f-a26a-27915f29e312 Experiment ID: 39d571b8-f39b-4aec-bd6a-e94f28a42a63 Experiment ID: 5b855105-60b5-4c2d-ba5c-fdad0213765c + Connections: 1 Connections: 2 Connections: 4 + Rate: 400 Rate: 400 Rate: 400 + Size: 1024 Size: 1024 Size: 1024 + Total Valid Tx: 35600 Total Valid Tx: 41565 Total Valid Tx: 41384 + Total Negative Latencies: 0 Total Negative Latencies: 0 Total Negative Latencies: 0 + Minimum Latency: 565.640641ms Minimum Latency: 1.650712046s Minimum Latency: 2.796290248s + Maximum Latency: 10.051316705s Maximum Latency: 15.897581951s Maximum Latency: 20.124431723s + Average Latency: 3.499369173s Average Latency: 8.635543807s Average Latency: 10.596146863s + Standard Deviation: 1.926805844s Standard Deviation: 2.535678364s Standard Deviation: 3.193742233s +Experiment ID: db10ca9e-6cf8-4dc9-9284-6e767e4b4346 Experiment ID: f57af87d-d342-41f7-a0eb-baa87a4b2257 Experiment ID: 32819ea0-1a59-41de-8aa6-b70f68697520 + Connections: 1 Connections: 2 Connections: 4 + Rate: 800 Rate: 800 Rate: 800 + Size: 1024 Size: 1024 Size: 1024 + Total Valid Tx: 36831 Total Valid Tx: 38686 Total Valid Tx: 40816 + Total Negative Latencies: 0 Total Negative Latencies: 0 Total Negative Latencies: 0 + Minimum Latency: 1.203966853s Minimum Latency: 728.863446ms Minimum Latency: 1.559342549s + Maximum Latency: 21.411365818s Maximum Latency: 24.349050642s Maximum Latency: 25.791215028s + Average Latency: 9.213156739s Average Latency: 11.194994374s Average Latency: 11.950851892s + Standard Deviation: 4.909584729s Standard Deviation: 5.199186587s Standard Deviation: 4.315394253s +Experiment ID: 587762c4-3fd4-4799-9f3b-9e6971b353ba Experiment ID: 489b2623-a3e4-453f-a771-5d05e7de4a1f Experiment ID: 98605df2-3b16-46db-8675-2980bc84ea2b + Connections: 1 Connections: 2 Connections: 4 + Rate: 1600 Rate: 1600 Rate: 1600 + Size: 1024 Size: 1024 Size: 1024 + Total Valid Tx: 40600 Total Valid Tx: 45034 Total Valid Tx: 39830 + Total Negative Latencies: 0 Total Negative Latencies: 0 Total Negative Latencies: 0 + Minimum Latency: 998.07523ms Minimum Latency: 1.43819209s Minimum Latency: 1.50664776s + Maximum Latency: 18.565312759s Maximum Latency: 17.098811297s Maximum Latency: 20.346885373s + Average Latency: 8.78128586s Average Latency: 8.957419021s Average Latency: 12.113245591s + Standard Deviation: 3.305897473s Standard Deviation: 2.734640455s Standard Deviation: 4.029854219s diff --git a/docs/references/qa/img38/rotating/rotating_avg_memory.png b/docs/references/qa/img38/rotating/rotating_avg_memory.png new file mode 100644 index 00000000000..43dadcabea0 Binary files /dev/null and b/docs/references/qa/img38/rotating/rotating_avg_memory.png differ diff --git a/docs/references/qa/img38/rotating/rotating_block_rate.png b/docs/references/qa/img38/rotating/rotating_block_rate.png new file mode 100644 index 00000000000..e627064a345 Binary files /dev/null and b/docs/references/qa/img38/rotating/rotating_block_rate.png differ diff --git a/docs/references/qa/img38/rotating/rotating_cpu.png b/docs/references/qa/img38/rotating/rotating_cpu.png new file mode 100644 index 00000000000..f51403d409b Binary files /dev/null and b/docs/references/qa/img38/rotating/rotating_cpu.png differ diff --git a/docs/references/qa/img38/rotating/rotating_eph_heights.png b/docs/references/qa/img38/rotating/rotating_eph_heights.png new file mode 100644 index 00000000000..6c8e08eeee8 Binary files /dev/null and b/docs/references/qa/img38/rotating/rotating_eph_heights.png differ diff --git a/docs/references/qa/img38/rotating/rotating_latencies.png b/docs/references/qa/img38/rotating/rotating_latencies.png new file mode 100644 index 00000000000..8031d7cda80 Binary files /dev/null and b/docs/references/qa/img38/rotating/rotating_latencies.png differ diff --git a/docs/references/qa/img38/rotating/rotating_peers.png b/docs/references/qa/img38/rotating/rotating_peers.png new file mode 100644 index 00000000000..b0ac6a2b08d Binary files /dev/null and b/docs/references/qa/img38/rotating/rotating_peers.png differ diff --git a/docs/references/qa/img38/rotating/rotating_txs_rate.png b/docs/references/qa/img38/rotating/rotating_txs_rate.png new file mode 100644 index 00000000000..d3ae71413ac Binary files /dev/null and b/docs/references/qa/img38/rotating/rotating_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/02k_1_block_rate.png b/docs/references/qa/img38/voteExtensions/02k_1_block_rate.png new file mode 100644 index 00000000000..ff314bd7ba5 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/02k_1_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/02k_1_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/02k_1_total_txs_rate.png new file mode 100644 index 00000000000..67a0cbb582b Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/02k_1_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/02k_avg_cpu.png b/docs/references/qa/img38/voteExtensions/02k_avg_cpu.png new file mode 100644 index 00000000000..2eb9683ec4c Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/02k_avg_cpu.png differ diff --git a/docs/references/qa/img38/voteExtensions/02k_avg_memory.png b/docs/references/qa/img38/voteExtensions/02k_avg_memory.png new file mode 100644 index 00000000000..955d1136294 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/02k_avg_memory.png differ diff --git a/docs/references/qa/img38/voteExtensions/02k_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/02k_avg_mempool_size.png new file mode 100644 index 00000000000..426867db67b Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/02k_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/02k_block_rate.png b/docs/references/qa/img38/voteExtensions/02k_block_rate.png new file mode 100644 index 00000000000..0a53ccf7886 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/02k_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/02k_rounds.png b/docs/references/qa/img38/voteExtensions/02k_rounds.png new file mode 100644 index 00000000000..b932e80d423 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/02k_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/02k_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/02k_total_txs_rate.png new file mode 100644 index 00000000000..c7040fb86b8 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/02k_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/04k_1_block_rate.png b/docs/references/qa/img38/voteExtensions/04k_1_block_rate.png new file mode 100644 index 00000000000..9f9564a6fd9 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/04k_1_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/04k_1_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/04k_1_total_txs_rate.png new file mode 100644 index 00000000000..e69096d7e47 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/04k_1_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/04k_avg_cpu.png b/docs/references/qa/img38/voteExtensions/04k_avg_cpu.png new file mode 100644 index 00000000000..be251929236 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/04k_avg_cpu.png differ diff --git a/docs/references/qa/img38/voteExtensions/04k_avg_memory.png b/docs/references/qa/img38/voteExtensions/04k_avg_memory.png new file mode 100644 index 00000000000..50503a3abc0 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/04k_avg_memory.png differ diff --git a/docs/references/qa/img38/voteExtensions/04k_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/04k_avg_mempool_size.png new file mode 100644 index 00000000000..3e3eea8ed55 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/04k_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/04k_block_rate.png b/docs/references/qa/img38/voteExtensions/04k_block_rate.png new file mode 100644 index 00000000000..f0bd5c2a1ba Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/04k_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/04k_rounds.png b/docs/references/qa/img38/voteExtensions/04k_rounds.png new file mode 100644 index 00000000000..64bb878f767 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/04k_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/04k_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/04k_total_txs_rate.png new file mode 100644 index 00000000000..be5ab70aefe Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/04k_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_1_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/08k_1_avg_mempool_size.png new file mode 100644 index 00000000000..00cc236c365 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_1_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_1_block_rate.png b/docs/references/qa/img38/voteExtensions/08k_1_block_rate.png new file mode 100644 index 00000000000..9caa120f734 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_1_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_1_rounds.png b/docs/references/qa/img38/voteExtensions/08k_1_rounds.png new file mode 100644 index 00000000000..809a97eed94 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_1_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_1_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/08k_1_total_txs_rate.png new file mode 100644 index 00000000000..ce1c5c7d8cb Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_1_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_avg_cpu.png b/docs/references/qa/img38/voteExtensions/08k_avg_cpu.png new file mode 100644 index 00000000000..c78af4f2960 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_avg_cpu.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_avg_memory.png b/docs/references/qa/img38/voteExtensions/08k_avg_memory.png new file mode 100644 index 00000000000..cd36d056262 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_avg_memory.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/08k_avg_mempool_size.png new file mode 100644 index 00000000000..dd852e9bb8f Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_rounds.png b/docs/references/qa/img38/voteExtensions/08k_rounds.png new file mode 100644 index 00000000000..0bd983039d6 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/08k_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/08k_total_txs_rate.png new file mode 100644 index 00000000000..87cb6e4bad9 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/08k_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_1_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/16k_1_avg_mempool_size.png new file mode 100644 index 00000000000..3eb5b73d3f1 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_1_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_1_block_rate.png b/docs/references/qa/img38/voteExtensions/16k_1_block_rate.png new file mode 100644 index 00000000000..12025af8c8f Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_1_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_1_rounds.png b/docs/references/qa/img38/voteExtensions/16k_1_rounds.png new file mode 100644 index 00000000000..15d6feb220d Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_1_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_1_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/16k_1_total_txs_rate.png new file mode 100644 index 00000000000..65cb0c11554 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_1_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_avg_cpu.png b/docs/references/qa/img38/voteExtensions/16k_avg_cpu.png new file mode 100644 index 00000000000..6fff44dab93 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_avg_cpu.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_avg_memory.png b/docs/references/qa/img38/voteExtensions/16k_avg_memory.png new file mode 100644 index 00000000000..218ef0bd6d1 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_avg_memory.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/16k_avg_mempool_size.png new file mode 100644 index 00000000000..73881a1533a Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_block_rate.png b/docs/references/qa/img38/voteExtensions/16k_block_rate.png new file mode 100644 index 00000000000..73cbba282d3 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_rounds.png b/docs/references/qa/img38/voteExtensions/16k_rounds.png new file mode 100644 index 00000000000..7458188b7a1 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/16k_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/16k_total_txs_rate.png new file mode 100644 index 00000000000..5d44a422dc4 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/16k_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_1_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/32k_1_avg_mempool_size.png new file mode 100644 index 00000000000..273f1b8b818 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_1_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_1_block_rate.png b/docs/references/qa/img38/voteExtensions/32k_1_block_rate.png new file mode 100644 index 00000000000..d469e947555 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_1_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_1_rounds.png b/docs/references/qa/img38/voteExtensions/32k_1_rounds.png new file mode 100644 index 00000000000..347263dd89a Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_1_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_1_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/32k_1_total_txs_rate.png new file mode 100644 index 00000000000..0d0451acdec Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_1_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_avg_cpu.png b/docs/references/qa/img38/voteExtensions/32k_avg_cpu.png new file mode 100644 index 00000000000..5464681c2fc Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_avg_cpu.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_avg_memory.png b/docs/references/qa/img38/voteExtensions/32k_avg_memory.png new file mode 100644 index 00000000000..4cea5df70f0 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_avg_memory.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/32k_avg_mempool_size.png new file mode 100644 index 00000000000..e573eca2ae4 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_block_rate.png b/docs/references/qa/img38/voteExtensions/32k_block_rate.png new file mode 100644 index 00000000000..f3ebf625537 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_rounds.png b/docs/references/qa/img38/voteExtensions/32k_rounds.png new file mode 100644 index 00000000000..a7a0597c24e Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/32k_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/32k_total_txs_rate.png new file mode 100644 index 00000000000..fdd93e25277 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/32k_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/8k_block_rate.png b/docs/references/qa/img38/voteExtensions/8k_block_rate.png new file mode 100644 index 00000000000..da0a378adaf Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/8k_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_c1r400_16k.png b/docs/references/qa/img38/voteExtensions/all_c1r400_16k.png new file mode 100644 index 00000000000..d7e18134faf Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_c1r400_16k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_c1r400_2k.png b/docs/references/qa/img38/voteExtensions/all_c1r400_2k.png new file mode 100644 index 00000000000..9682d84a23f Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_c1r400_2k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_c1r400_32k.png b/docs/references/qa/img38/voteExtensions/all_c1r400_32k.png new file mode 100644 index 00000000000..5179fd21218 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_c1r400_32k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_c1r400_4k.png b/docs/references/qa/img38/voteExtensions/all_c1r400_4k.png new file mode 100644 index 00000000000..46d67719cb0 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_c1r400_4k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_c1r400_64k.png b/docs/references/qa/img38/voteExtensions/all_c1r400_64k.png new file mode 100644 index 00000000000..04ff7e76096 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_c1r400_64k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_c1r400_8k.png b/docs/references/qa/img38/voteExtensions/all_c1r400_8k.png new file mode 100644 index 00000000000..b54ed7d892a Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_c1r400_8k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_c1r400_baseline.png b/docs/references/qa/img38/voteExtensions/all_c1r400_baseline.png new file mode 100644 index 00000000000..2c094f58fd7 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_c1r400_baseline.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_experiments_16k.png b/docs/references/qa/img38/voteExtensions/all_experiments_16k.png new file mode 100644 index 00000000000..c7a1f6da203 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_experiments_16k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_experiments_2k.png b/docs/references/qa/img38/voteExtensions/all_experiments_2k.png new file mode 100644 index 00000000000..ea717d55962 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_experiments_2k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_experiments_32k.png b/docs/references/qa/img38/voteExtensions/all_experiments_32k.png new file mode 100644 index 00000000000..ee4cf339d23 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_experiments_32k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_experiments_4k.png b/docs/references/qa/img38/voteExtensions/all_experiments_4k.png new file mode 100644 index 00000000000..eb4c569cba7 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_experiments_4k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_experiments_64k.png b/docs/references/qa/img38/voteExtensions/all_experiments_64k.png new file mode 100644 index 00000000000..f7abbae58e0 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_experiments_64k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_experiments_8k.png b/docs/references/qa/img38/voteExtensions/all_experiments_8k.png new file mode 100644 index 00000000000..cbaaf5c9eb2 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_experiments_8k.png differ diff --git a/docs/references/qa/img38/voteExtensions/all_experiments_baseline.png b/docs/references/qa/img38/voteExtensions/all_experiments_baseline.png new file mode 100644 index 00000000000..b27ec5d625c Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/all_experiments_baseline.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_1_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/baseline_1_avg_mempool_size.png new file mode 100644 index 00000000000..63c86687b13 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_1_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_1_block_rate.png b/docs/references/qa/img38/voteExtensions/baseline_1_block_rate.png new file mode 100644 index 00000000000..46f0a4ee8ac Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_1_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_1_rounds.png b/docs/references/qa/img38/voteExtensions/baseline_1_rounds.png new file mode 100644 index 00000000000..1e6db5e3838 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_1_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_1_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/baseline_1_total_txs_rate.png new file mode 100644 index 00000000000..75f9ab435ce Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_1_total_txs_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_avg_cpu.png b/docs/references/qa/img38/voteExtensions/baseline_avg_cpu.png new file mode 100644 index 00000000000..2c1bca8bf06 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_avg_cpu.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_avg_memory.png b/docs/references/qa/img38/voteExtensions/baseline_avg_memory.png new file mode 100644 index 00000000000..f0529880b4c Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_avg_memory.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_avg_mempool_size.png b/docs/references/qa/img38/voteExtensions/baseline_avg_mempool_size.png new file mode 100644 index 00000000000..179693cc610 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_avg_mempool_size.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_block_rate.png b/docs/references/qa/img38/voteExtensions/baseline_block_rate.png new file mode 100644 index 00000000000..20073522c84 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_block_rate.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_rounds.png b/docs/references/qa/img38/voteExtensions/baseline_rounds.png new file mode 100644 index 00000000000..468d4e2ff8e Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_rounds.png differ diff --git a/docs/references/qa/img38/voteExtensions/baseline_total_txs_rate.png b/docs/references/qa/img38/voteExtensions/baseline_total_txs_rate.png new file mode 100644 index 00000000000..306793d5d21 Binary files /dev/null and b/docs/references/qa/img38/voteExtensions/baseline_total_txs_rate.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/latencies/e_8e4e1e81-c171-4879-b86f-bce96ee2e861.png b/docs/references/qa/imgs/v1/200nodes/latencies/e_8e4e1e81-c171-4879-b86f-bce96ee2e861.png new file mode 100644 index 00000000000..8b636364df3 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/latencies/e_8e4e1e81-c171-4879-b86f-bce96ee2e861.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/avg_cpu.png b/docs/references/qa/imgs/v1/200nodes/metrics/avg_cpu.png new file mode 100644 index 00000000000..9606bfecdd1 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/avg_cpu.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/avg_memory.png b/docs/references/qa/imgs/v1/200nodes/metrics/avg_memory.png new file mode 100644 index 00000000000..ac50a161519 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/avg_memory.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/avg_mempool_size.png b/docs/references/qa/imgs/v1/200nodes/metrics/avg_mempool_size.png new file mode 100644 index 00000000000..ab22f0c8ded Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/avg_mempool_size.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/block_rate.png b/docs/references/qa/imgs/v1/200nodes/metrics/block_rate.png new file mode 100644 index 00000000000..ab8d4226604 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/block_rate.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/block_rate_regular.png b/docs/references/qa/imgs/v1/200nodes/metrics/block_rate_regular.png new file mode 100644 index 00000000000..34298d9c4f0 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/block_rate_regular.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/block_size_bytes.png b/docs/references/qa/imgs/v1/200nodes/metrics/block_size_bytes.png new file mode 100644 index 00000000000..64ca4cd06f1 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/block_size_bytes.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/blocks.png b/docs/references/qa/imgs/v1/200nodes/metrics/blocks.png new file mode 100644 index 00000000000..b57e006b3f6 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/blocks.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/cpu.png b/docs/references/qa/imgs/v1/200nodes/metrics/cpu.png new file mode 100644 index 00000000000..4dff228ade7 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/cpu.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/memory.png b/docs/references/qa/imgs/v1/200nodes/metrics/memory.png new file mode 100644 index 00000000000..c1598ed1e75 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/memory.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/mempool_size.png b/docs/references/qa/imgs/v1/200nodes/metrics/mempool_size.png new file mode 100644 index 00000000000..4f1fd20dbaf Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/mempool_size.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/mempool_size_max.png b/docs/references/qa/imgs/v1/200nodes/metrics/mempool_size_max.png new file mode 100644 index 00000000000..5f81a480f70 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/mempool_size_max.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/peers.png b/docs/references/qa/imgs/v1/200nodes/metrics/peers.png new file mode 100644 index 00000000000..d83174e2b34 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/peers.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/rounds.png b/docs/references/qa/imgs/v1/200nodes/metrics/rounds.png new file mode 100644 index 00000000000..eef946e4545 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/rounds.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/total_txs.png b/docs/references/qa/imgs/v1/200nodes/metrics/total_txs.png new file mode 100644 index 00000000000..7996975997d Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/total_txs.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/total_txs_rate.png b/docs/references/qa/imgs/v1/200nodes/metrics/total_txs_rate.png new file mode 100644 index 00000000000..a1efeea2b85 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/total_txs_rate.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/metrics/total_txs_rate_regular.png b/docs/references/qa/imgs/v1/200nodes/metrics/total_txs_rate_regular.png new file mode 100644 index 00000000000..3890ebf3ab7 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes/metrics/total_txs_rate_regular.png differ diff --git a/docs/references/qa/imgs/v1/200nodes/v1_report_tabbed.txt b/docs/references/qa/imgs/v1/200nodes/v1_report_tabbed.txt new file mode 100644 index 00000000000..be4b2ee85d3 --- /dev/null +++ b/docs/references/qa/imgs/v1/200nodes/v1_report_tabbed.txt @@ -0,0 +1,40 @@ +Experiment ID: 73d1ecf6-2dbe-4288-bd84-72e286d939be Experiment ID: b3447e8e-f85e-48be-bb05-bf1b35b9e8b6 Experiment ID: 7b76c980-4882-4be7-898f-7ba7c4c950a2 + Connections: 1 Connections: 2 Connections: 4 + Rate: 200 Rate: 200 Rate: 200 + Size: 1024 Size: 1024 Size: 1024 + Total Valid Tx: 17800 Total Valid Tx: 34600 Total Valid Tx: 50464 + Total Negative Latencies: 0 Total Negative Latencies: 0 Total Negative Latencies: 0 + Minimum Latency: 1.710409731s Minimum Latency: 1.934148332s Minimum Latency: 3.207030208s + Maximum Latency: 8.977271598s Maximum Latency: 19.921012538s Maximum Latency: 22.695517951s + Average Latency: 3.873914787s Average Latency: 6.759146915s Average Latency: 9.394390517s + Standard Deviation: 1.80382447s Standard Deviation: 4.158131769s Standard Deviation: 4.907778924s +Experiment ID: 240abfc5-2e9f-4096-8d25-87b8890b419f Experiment ID: 99e88ddf-f0bd-4d44-98ac-cee52e2a74a6 Experiment ID: 88664d81-9d37-4820-a60e-8c0d2a9b2d63 + Connections: 1 Connections: 2 Connections: 4 + Rate: 400 Rate: 400 Rate: 400 + Size: 1024 Size: 1024 Size: 1024 + Total Valid Tx: 31200 Total Valid Tx: 54706 Total Valid Tx: 49463 + Total Negative Latencies: 0 Total Negative Latencies: 0 Total Negative Latencies: 0 + Minimum Latency: 2.050980308s Minimum Latency: 2.74995384s Minimum Latency: 4.469911766s + Maximum Latency: 26.195522089s Maximum Latency: 23.182542187s Maximum Latency: 16.480603178s + Average Latency: 9.280762294s Average Latency: 9.360818846s Average Latency: 9.976733037s + Standard Deviation: 7.166791513s Standard Deviation: 4.378492426s Standard Deviation: 3.223167612s +Experiment ID: 3efdd2a0-8bef-43d0-a0f0-6dce2b63825f Experiment ID: 3a49bc80-f63f-4d97-9663-3a02838fe1e8 Experiment ID: 1c2492ff-b82b-48a2-a975-bb252365521a + Connections: 1 Connections: 2 Connections: 4 + Rate: 800 Rate: 800 Rate: 800 + Size: 1024 Size: 1024 Size: 1024 + Total Valid Tx: 51146 Total Valid Tx: 51917 Total Valid Tx: 41376 + Total Negative Latencies: 0 Total Negative Latencies: 0 Total Negative Latencies: 0 + Minimum Latency: 3.026020902s Minimum Latency: 4.617306731s Minimum Latency: 4.400844549s + Maximum Latency: 21.969169815s Maximum Latency: 29.138788503s Maximum Latency: 39.972301945s + Average Latency: 9.039266773s Average Latency: 11.676386139s Average Latency: 16.583749953s + Standard Deviation: 4.734959842s Standard Deviation: 6.190789791s Standard Deviation: 8.729665317s +Experiment ID: 685cca77-ce3b-483f-9af8-6eafbdb03f7f Experiment ID: ba5cd52a-e3e6-4e35-86e3-5b391395650b Experiment ID: d27c4154-7c64-4379-91f9-0dc9b5f4c1d0 + Connections: 1 Connections: 2 Connections: 4 + Rate: 1600 Rate: 1600 Rate: 1600 + Size: 1024 Size: 1024 Size: 1024 + Total Valid Tx: 50889 Total Valid Tx: 47732 Total Valid Tx: 45530 + Total Negative Latencies: 0 Total Negative Latencies: 0 Total Negative Latencies: 0 + Minimum Latency: 4.411916099s Minimum Latency: 4.734922576s Minimum Latency: 5.500813279s + Maximum Latency: 24.512517023s Maximum Latency: 21.733104885s Maximum Latency: 30.120411703s + Average Latency: 11.022462182s Average Latency: 12.420967288s Average Latency: 13.648996358s + Standard Deviation: 4.882919113s Standard Deviation: 4.803231316s Standard Deviation: 6.370448765s diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/latencies/e_8190e83a-9135-444b-92fb-4efaeaaf2b52.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/latencies/e_8190e83a-9135-444b-92fb-4efaeaaf2b52.png new file mode 100644 index 00000000000..3845545b6a6 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/latencies/e_8190e83a-9135-444b-92fb-4efaeaaf2b52.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_cpu.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_cpu.png new file mode 100644 index 00000000000..0de9421dfb0 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_cpu.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_memory.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_memory.png new file mode 100644 index 00000000000..8fba818cb0b Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_memory.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_mempool_size.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_mempool_size.png new file mode 100644 index 00000000000..ec2f37acee5 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/avg_mempool_size.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_rate.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_rate.png new file mode 100644 index 00000000000..3cad284563f Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_rate.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_rate_regular.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_rate_regular.png new file mode 100644 index 00000000000..d051e062460 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_rate_regular.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_size_bytes.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_size_bytes.png new file mode 100644 index 00000000000..14b2cb8a970 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/block_size_bytes.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/blocks.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/blocks.png new file mode 100644 index 00000000000..6fcacbb1dc0 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/blocks.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/cpu.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/cpu.png new file mode 100644 index 00000000000..abce498e933 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/cpu.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/memory.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/memory.png new file mode 100644 index 00000000000..2e7bc154f66 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/memory.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/mempool_size.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/mempool_size.png new file mode 100644 index 00000000000..f00dd24b882 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/mempool_size.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/mempool_size_max.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/mempool_size_max.png new file mode 100644 index 00000000000..fcf3526d12b Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/mempool_size_max.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/peers.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/peers.png new file mode 100644 index 00000000000..44045259063 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/peers.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/rounds.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/rounds.png new file mode 100644 index 00000000000..e80bfc91473 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/rounds.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs.png new file mode 100644 index 00000000000..03ff5a3aa1f Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs_rate.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs_rate.png new file mode 100644 index 00000000000..308fd362e9a Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs_rate.png differ diff --git a/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs_rate_regular.png b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs_rate_regular.png new file mode 100644 index 00000000000..b6a4fe443e6 Binary files /dev/null and b/docs/references/qa/imgs/v1/200nodes_with_latency_emulation/metrics/total_txs_rate_regular.png differ diff --git a/docs/references/qa/imgs/v1/rotating/latencies.png b/docs/references/qa/imgs/v1/rotating/latencies.png new file mode 100644 index 00000000000..581672f7e48 Binary files /dev/null and b/docs/references/qa/imgs/v1/rotating/latencies.png differ diff --git a/docs/references/qa/imgs/v1/rotating/metrics/rotating_avg_memory.png b/docs/references/qa/imgs/v1/rotating/metrics/rotating_avg_memory.png new file mode 100644 index 00000000000..2b2696e093d Binary files /dev/null and b/docs/references/qa/imgs/v1/rotating/metrics/rotating_avg_memory.png differ diff --git a/docs/references/qa/imgs/v1/rotating/metrics/rotating_block_rate.png b/docs/references/qa/imgs/v1/rotating/metrics/rotating_block_rate.png new file mode 100644 index 00000000000..d1a42aee7af Binary files /dev/null and b/docs/references/qa/imgs/v1/rotating/metrics/rotating_block_rate.png differ diff --git a/docs/references/qa/imgs/v1/rotating/metrics/rotating_cpu.png b/docs/references/qa/imgs/v1/rotating/metrics/rotating_cpu.png new file mode 100644 index 00000000000..35da6294486 Binary files /dev/null and b/docs/references/qa/imgs/v1/rotating/metrics/rotating_cpu.png differ diff --git a/docs/references/qa/imgs/v1/rotating/metrics/rotating_eph_heights.png b/docs/references/qa/imgs/v1/rotating/metrics/rotating_eph_heights.png new file mode 100644 index 00000000000..09a49c6616b Binary files /dev/null and b/docs/references/qa/imgs/v1/rotating/metrics/rotating_eph_heights.png differ diff --git a/docs/references/qa/imgs/v1/rotating/metrics/rotating_peers.png b/docs/references/qa/imgs/v1/rotating/metrics/rotating_peers.png new file mode 100644 index 00000000000..119f1c12947 Binary files /dev/null and b/docs/references/qa/imgs/v1/rotating/metrics/rotating_peers.png differ diff --git a/docs/references/qa/imgs/v1/rotating/metrics/rotating_txs_rate.png b/docs/references/qa/imgs/v1/rotating/metrics/rotating_txs_rate.png new file mode 100644 index 00000000000..e165d41c6dc Binary files /dev/null and b/docs/references/qa/imgs/v1/rotating/metrics/rotating_txs_rate.png differ diff --git a/docs/references/qa/imgs/v1/saturation/saturation-plotter-LE.py b/docs/references/qa/imgs/v1/saturation/saturation-plotter-LE.py new file mode 100755 index 00000000000..26f4bc50526 --- /dev/null +++ b/docs/references/qa/imgs/v1/saturation/saturation-plotter-LE.py @@ -0,0 +1,54 @@ +#/usr/bin/env python3 +"""Plotter for comparing saturation results on v1 with and without Letency Emulation. + +This script generates an image with the number of processed transactions for different load +configurations (tx rate and number of connections). The purpose is to find the saturation point of +the network and to compare the results between different CometBFT versions. + +Quick setup before running: +``` +python3 -m venv .venv && source .venv/bin/activate +pip install matplotlib +``` +""" +import matplotlib.pyplot as plt +import numpy as np + +# Transaction rate (x axis) +rates = np.arange(100, 1100, 100) +rates2 = [200, 400, 800, 1600] + +# expected values +expected = [(i+1) * 100 * 89 for i in range(10)] + +# v1 without LE +d1 = [8900,17800,26053,28800,32513,30455,33077,32191,30688,32395] # experiments/2024-03-26-13_47_51N/validator174 +d2 = [8900,17800,26300,25400,31371,31063,31603,32886,24521,25211] # experiments/2024-03-26-11_17_58N/validator174 +d3 = [8900,17800,26700,35600,38500,40502,51962,48328,50713,42361] # experiments/2024-03-26-20_20_33N/validator174 + +# v1 with LE +le1 = [8900,17800,26700,35600,34504,42169,38916,38004,34332,36948] # experiments/2024-03-25-17_41_09N/validator174 +le2 = [17800, 33800, 34644, 43464] # experiments/2024-03-25-12_17_12N/validator174 +le3 = [8900,17800,26700,33200,37665,51771,38631,49290,51526,46902] # experiments/2024-03-26-22_21_31N/validator174 + +fig, ax = plt.subplots(figsize=(10, 5)) +ax.plot(rates, expected, linestyle='dotted', marker=',', color='g', label='expected') +ax.plot(rates, d1, linestyle='solid', marker='o', color='b', label='without LE #1') +ax.plot(rates, d2, linestyle='solid', marker='o', color='violet', label='without LE #2') +ax.plot(rates, d3, linestyle='solid', marker='o', color='grey', label='without LE #3') +ax.plot(rates, le1, linestyle='dashed', marker='s', color='r', label='with LE #1') +ax.plot(rates2, le2, linestyle='dashed', marker='s', color='orange', label='with LE #2') +ax.plot(rates, le3, linestyle='dashed', marker='s', color='brown', label='with LE #3') + +plt.title('saturation point for v1.0.0-alpha.2, c=1') +plt.xlabel("rate (txs/s)") +plt.ylabel("txs processed in 90 seconds") +plt.xticks(np.arange(0, 1100, 200).tolist()) +ax.set_xlim([0, 1100]) +ax.set_ylim([0, 60000]) +ax.grid() +ax.legend() + +fig.tight_layout() +fig.savefig("saturation_v1_LE.png") +plt.show() diff --git a/docs/references/qa/imgs/v1/saturation/saturation-plotter.py b/docs/references/qa/imgs/v1/saturation/saturation-plotter.py new file mode 100755 index 00000000000..ee9dfbd0fa8 --- /dev/null +++ b/docs/references/qa/imgs/v1/saturation/saturation-plotter.py @@ -0,0 +1,56 @@ +#/usr/bin/env python3 +"""Plotter for comparing saturation results on v1 and v0.38. + +This script generates an image with the number of processed transactions for different load +configurations (tx rate and number of connections). The purpose is to find the saturation point of +the network and to compare the results between different CometBFT versions. + +Quick setup before running: +``` +python3 -m venv .venv && source .venv/bin/activate +pip install matplotlib +``` +""" +import matplotlib.pyplot as plt +import numpy as np + +# Expected values of processed transactions for a given transaction rate. +rates0 = [0, 3600] +expected = [r * 89 for r in rates0] + +# Transaction rate (x axis) +rates1 = [200, 400, 800, 1600] +rates2 = [r*2 for r in rates1] +rates4 = [r*2 for r in rates2] + +# v1 (without latency emulation), for number of connections c in [1,2,4] +c1 = [17800,31200,51146,50889] +c2 = [34600,54706,51917,47732] +c4 = [50464,49463,41376,45530] + +# v0.38, for number of connections c in [1,2,4] +d1 = [17800,35600,36831,40600] +d2 = [33259,41565,38686,45034] +d4 = [33259,41384,40816,39830] + +fig, ax = plt.subplots(figsize=(12, 5)) +ax.plot(rates0, expected, linestyle='dotted', marker=',', color='g', label='expected') +ax.plot(rates1, c1, linestyle='solid', marker='s', color='red', label='v1 c=1') +ax.plot(rates2, c2, linestyle='solid', marker='s', color='salmon', label='v1 c=2') +ax.plot(rates4, c4, linestyle='solid', marker='s', color='orange', label='v1 c=4') +ax.plot(rates1, d1, linestyle='dashed', marker='o', color='blue', label='v0.38 c=1') +ax.plot(rates2, d2, linestyle='dashed', marker='o', color='violet', label='v0.38 c=2') +ax.plot(rates4, d4, linestyle='dashed', marker='o', color='purple', label='v0.38 c=4') + +plt.title('finding the saturation point') +plt.xlabel("total rate over all connections (txs/s)") +plt.ylabel("txs processed in 90 seconds") +plt.xticks(np.arange(0, 3600, 200).tolist()) +ax.set_xlim([0, 3600]) +ax.set_ylim([0, 60000]) +ax.grid() +ax.legend() + +fig.tight_layout() +fig.savefig("saturation_v1_v038.png") +plt.show() diff --git a/docs/references/qa/imgs/v1/saturation/saturation_v1_LE.png b/docs/references/qa/imgs/v1/saturation/saturation_v1_LE.png new file mode 100644 index 00000000000..bc9aa01bc10 Binary files /dev/null and b/docs/references/qa/imgs/v1/saturation/saturation_v1_LE.png differ diff --git a/docs/references/qa/imgs/v1/saturation/saturation_v1_v038.png b/docs/references/qa/imgs/v1/saturation/saturation_v1_v038.png new file mode 100644 index 00000000000..812bf62945c Binary files /dev/null and b/docs/references/qa/imgs/v1/saturation/saturation_v1_v038.png differ diff --git a/docs/references/qa/imgs/v1/saturation/throughput_vs_latencies_v1_with_LE.png b/docs/references/qa/imgs/v1/saturation/throughput_vs_latencies_v1_with_LE.png new file mode 100644 index 00000000000..bc2f4adbae9 Binary files /dev/null and b/docs/references/qa/imgs/v1/saturation/throughput_vs_latencies_v1_with_LE.png differ diff --git a/docs/references/qa/imgs/v1/saturation/throughput_vs_latencies_v1_without_LE.png b/docs/references/qa/imgs/v1/saturation/throughput_vs_latencies_v1_without_LE.png new file mode 100644 index 00000000000..95b2faf42be Binary files /dev/null and b/docs/references/qa/imgs/v1/saturation/throughput_vs_latencies_v1_without_LE.png differ diff --git a/docs/references/qa/method.md b/docs/references/qa/method.md new file mode 100644 index 00000000000..b906e4726f5 --- /dev/null +++ b/docs/references/qa/method.md @@ -0,0 +1,319 @@ +--- +order: 1 +parent: + title: Method + order: 1 +--- + +# Method + +This document provides a detailed description of the QA process. +It is intended to be used by engineers reproducing the experimental setup for future tests of CometBFT. + +The (first iteration of the) QA process as described [in the RELEASES.md document][releases] +was applied to version v0.34.x in order to have a set of results acting as benchmarking baseline. +This baseline is then compared with results obtained in later versions. +See [RELEASES.md][releases] for a description of the tests that we run on the QA process. + +Out of the testnet-based test cases described in [the releases document][releases] we focused on two of them: +_200 Node Test_, and _Rotating Nodes Test_. + +[releases]: https://github.com/cometbft/cometbft/blob/main/RELEASES.md#large-scale-testnets + +## Table of Contents +- [Method](#method) + - [Table of Contents](#table-of-contents) + - [Software Dependencies](#software-dependencies) + - [Infrastructure Requirements to Run the Tests](#infrastructure-requirements-to-run-the-tests) + - [Requirements for Result Extraction](#requirements-for-result-extraction) + - [200 Node Testnet](#200-node-testnet) + - [Running the test](#running-the-test) + - [Result Extraction](#result-extraction) + - [Steps](#steps) + - [Extracting Prometheus Metrics](#extracting-prometheus-metrics) + - [Rotating Node Testnet](#rotating-node-testnet) + - [Running the test](#running-the-test-1) + - [Result Extraction](#result-extraction-1) + - [Vote Extensions Testnet](#vote-extensions-testnet) + - [Running the test](#running-the-test-2) + - [Result Extraction](#result-extraction-2) + +## Software Dependencies + +### Infrastructure Requirements to Run the Tests + +* An account at Digital Ocean (DO), with a high droplet limit (>202) +* The machine to orchestrate the tests should have the following installed: + * A clone of the [testnet repository][testnet-repo] + * This repository contains all the scripts mentioned in the remainder of this section + * [Digital Ocean CLI][doctl] + * [Terraform CLI][Terraform] + * [Ansible CLI][Ansible] + +[testnet-repo]: https://github.com/cometbft/qa-infra +[Ansible]: https://docs.ansible.com/ansible/latest/index.html +[Terraform]: https://www.terraform.io/docs +[doctl]: https://docs.digitalocean.com/reference/doctl/how-to/install/ + +### Requirements for Result Extraction + +* [Prometheus DB][prometheus] to collect metrics from nodes +* Prometheus DB to process queries (may be different node from the previous) +* blockstore DB of one of the full nodes in the testnet + + +[prometheus]: https://prometheus.io/ + +## 200 Node Testnet + +This test consists in spinning up 200 nodes (175 validators + 20 full nodes + 5 seed nodes) and +performing two experiments: +- First we find the [saturation point](saturation) of the network by running the script + [200-node-loadscript.sh][200-node-loadscript.sh]. +- Then we run several times the testnet using the saturation point to collect data. + +The script [200-node-loadscript.sh] runs multiple transaction load instances with all possible +combinations of the following parameters: +- number of transactions sent per second (the rate): 200, 400, 800, and 1600. +- number of connections to the target node: 1, 2, and 4. + +Additionally: +- The size of each transaction is 1024 bytes. +- The duration of each test is 90 seconds. +- There is one target node (a validator) that receives all the load. +- After each test iteration, it waits that the mempool is empty and then wait `120 + rate /60` + seconds more. + +[200-node-loadscript.sh]: https://github.com/cometbft/qa-infra/blob/main/ansible/scripts/200-node-loadscript.sh +[saturation]: CometBFT-QA-34.md#saturation-point + +### Running the test + +This section explains how the tests were carried out for reproducibility purposes. + +1. [If you haven't done it before] + Follow steps 1-5 of the `README.md` at the top of the testnet repository to configure Terraform and the DigitalOcean CLI (`doctl`). +2. In the `experiment.mk` file, set the following variables (do NOT commit these changes): + 1. Set `MANIFEST` to point to the file `testnets/200-nodes-with-zones.toml`. + 2. Set `VERSION_TAG` to the git hash that is to be tested. + * If you are running the base test, which implies an homogeneous network (all nodes are running the same version), + then make sure makefile variable `VERSION2_WEIGHT` is set to 0 + * If you are running a mixed network, set the variable `VERSION2_TAG` to the other version you want deployed + in the network. + Then adjust the weight variables `VERSION_WEIGHT` and `VERSION2_WEIGHT` to configure the + desired proportion of nodes running each of the two configured versions. +3. Follow steps 5-11 of the `README.md` to configure and start the 200 node testnet. + * WARNING: Do NOT forget to run `make terraform-destroy` as soon as you are done with the tests (see step 9) +4. As a sanity check, connect to the Prometheus node's web interface (port 9090) + and check the graph for the `cometbft_consensus_height` metric. All nodes + should be increasing their heights. + + * Run `ansible --list-hosts prometheus` to obtain the Prometheus node's IP address. + * The following URL will display the metrics `cometbft_consensus_height` and `cometbft_mempool_size`: + + ``` + http://:9090/classic/graph?g0.range_input=1h&g0.expr=cometbft_consensus_height&g0.tab=0&g1.range_input=1h&g1.expr=cometbft_mempool_size&g1.tab=0 + ``` + +5. Discover the saturation point of the network. If you already know it, skip this step. + * Run `make loadrunners-init`, in case the load runner is not yet initialised. This will copy the + loader scripts to the `testnet-load-runner` node and install the load tool. + * Run `ansible --list-hosts loadrunners` to find the IP address of the `testnet-load-runner` node. + * `ssh` into `testnet-load-runner`. + * We will run a script that takes about 40 mins to complete, so it is suggested to first run `tmux` in case the ssh session breaks. + * `tmux` quick cheat sheet: `ctrl-b a` to attach to an existing session; `ctrl-b %` to split the current pane vertically; `ctrl-b ;` to toggle to last active pane. + * Find the *internal* IP address of a full node (for example, `validator000`). This node will receive all transactions from the load runner node. + * Run `/root/200-node-loadscript.sh ` from the load runner node, where `` is the internal IP address of a full node. + * The script runs 90-seconds-long experiments in a loop with different load values. + * Follow the steps of the [Result Extraction](#result-extraction) section below to obtain the file `report_tabbed.txt`. + +6. Run several transaction load instances (typically 5), each of 90 seconds, using a load somewhat below the saturation point. + * Set the Makefile variables `LOAD_CONNECTIONS`, `LOAD_TX_RATE`, to values that will produce the desired transaction load. + * Set `LOAD_TOTAL_TIME` to 91 (seconds). The extra second is because the last transaction batch + coincides with the end of the experiment and is thus not sent. + * Run `make runload` and wait for it to complete. You may want to run this several times so the data from different runs can be compared. +7. Run `make retrieve-data` to gather all relevant data from the testnet into the orchestrating machine + * Alternatively, you may want to run `make retrieve-prometheus-data` and `make retrieve-blockstore` separately. + The end result will be the same. + * `make retrieve-blockstore` accepts the following values in makefile variable `RETRIEVE_TARGET_HOST` + * `any`: (which is the default) picks up a full node and retrieves the blockstore from that node only. + * `all`: retrieves the blockstore from all full nodes; this is extremely slow, and consumes plenty of bandwidth, + so use it with care. + * the name of a particular full node (e.g., `validator01`): retrieves the blockstore from that node only. +8. Verify that the data was collected without errors + * at least one blockstore DB for a CometBFT validator + * the Prometheus database from the Prometheus node + * for extra care, you can run `zip -T` on the `prometheus.zip` file and (one of) the `blockstore.db.zip` file(s) +9. **Run `make terraform-destroy`** + * Don't forget to type `yes`! Otherwise you're in trouble. + +### Result Extraction + +The method for extracting the results described here is highly manual (and exploratory) at this stage. +The CometBFT team should improve it at every iteration to increase the amount of automation. + +#### Saturation point + +For identifying the saturation point, run from the `qa-infra` repository: +```sh +./script/reports/saturation-gen-table.sh +``` +where `` is the directory where the results of the experiments were downloaded. +This directory should contain the file `blockstore.db.zip`. The script will automatically: +1. Unzip `blockstore.db.zip`, if not already. +2. Run the tool `test/loadtime/cmd/report` to extract data for all instances with different + transaction load. + - This will generate an intermediate file `report.txt` that contains an unordered list of + experiments results with varying concurrent connections and transaction rate. +3. Generate the files: + - `report_tabbed.txt` with results formatted as a matrix, where rows are a particular tx rate and + columns are a particular number of websocket connections. + - `saturation_table.tsv` which just contains columns with the number of processed transactions; + this is handy to create a Markdown table for the report. + +#### Latencies + +For generating images on latency, run from the `qa-infra` repository: +```sh +./script/reports/latencies-gen-images.sh +``` +As above, `` should contain the file `blockstore.db.zip`. +The script will automatically: +1. Unzip `blockstore.db.zip`, if not already. +2. Generate a file with raw results `results/raw.csv` using the tool `test/loadtime/cmd/report`. +3. Setup a Python virtual environment and install the dependencies required for running the scripts + in the steps below. +4. Generate a latency vs throughput images, using [`latency_throughput.py`]. This plot is useful to + visualize the saturation point. +5. Generate a series of images with the average latency of each block for each experiment instance + and configuration, using [`latency_plotter.py`]. This plots may help with visualizing latency vs. + throughput variation. + +[`latency_throughput.py`]: ../../../scripts/qa/reporting/README.md#Latency-vs-Throughput-Plotting +[`latency_plotter.py`]: ../../../scripts/qa/reporting/README.md#Latency-vs-Throughput-Plotting-version-2 + +#### Prometheus metrics + +1. From the `qa-infra` repository, run: + ```sh + ./script/reports/prometheus-start-local.sh + ``` + where `` is the directory where the results of the experiments were + downloaded. This directory should contain the file `blockstore.db.zip`. This script will: + - kill any running Prometheus server, + - unzip the Prometheus database retrieved from the testnet, and + - start a Prometheus server on the default `localhost:9090`, bootstrapping the downloaded data + as database. +2. Identify the time window you want to plot in your graphs. In particular, search for the start + time and duration of the window. +3. Run: + ```sh + ./script/reports/prometheus-gen-images.sh [] [] + ``` + where `` is in the format `'%Y-%m-%dT%H:%M:%SZ'` and `` is in seconds. + This will download, set up a Python virtual environment with required dependencies, and execute + the script [`prometheus_plotter.py`]. The optional parameter `` is one of `200_nodes` + (default), `rotating`, and `vote_extensions`; `` is just for putting in the title + of the plot. + +[`prometheus_plotter.py`]: ../../../scripts/qa/reporting/README.md#prometheus-metrics + +## Rotating Node Testnet + +### Running the test + +This section explains how the tests were carried out for reproducibility purposes. + +1. [If you haven't done it before] + Follow the [set up][qa-setup] steps of the `README.md` at the top of the testnet repository to + configure Terraform, and `doctl`. +2. In the `experiment.mk` file, set the following variables (do NOT commit these changes): + * Set `MANIFEST` to point to the file `testnets/rotating.toml`. + * Set `VERSION_TAG` to the git hash that is to be tested. + * Set `EPHEMERAL_SIZE` to 25. +3. Follow the [testnet starting][qa-start] steps of the `README.md` to configure and start the + the rotating node testnet. + * WARNING: Do NOT forget to run `make terraform-destroy` as soon as you are done with the tests. +4. As a sanity check, connect to the Prometheus node's web interface and check the graph for the + `cometbft_consensus_height` metric. All nodes should be increasing their heights. +5. On a different shell, + * run `make loadrunners-init` to initialize the load runner. + * run `make runload ITERATIONS=1 LOAD_CONNECTIONS=X LOAD_TX_RATE=Y LOAD_TOTAL_TIME=Z` + * `X` and `Y` should reflect a load below the saturation point (see, e.g., + [this paragraph](CometBFT-QA-38#saturation-point) for further info) + * `Z` (in seconds) should be big enough to keep running throughout the test, until we manually stop it in step 7. + In principle, a good value for `Z` is `7200` (2 hours) +6. 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 the full length + of the experiment. + * [This][rotating-prometheus] is an example Prometheus URL you can use to monitor the test case's progress. +7. When the height of the chain reaches 3000, stop the `make runload` script. +8. When the rotate script has made two iterations (i.e., all ephemeral nodes have caught up twice) + after height 3000 was reached, stop `make rotate`. +9. Run `make stop-network`. +10. Run `make retrieve-data` to gather all relevant data from the testnet into the orchestrating machine +11. Verify that the data was collected without errors + * at least one blockstore DB for a CometBFT validator + * the Prometheus database from the Prometheus node + * for extra care, you can run `zip -T` on the `prometheus.zip` file and (one of) the `blockstore.db.zip` file(s) +12. **Run `make terraform-destroy`** + +Steps 8 to 10 are highly manual at the moment and will be improved in next iterations. + +### Result Extraction + +In order to obtain a latency plot, follow the instructions above for the 200 node experiment, +but the `results.txt` file contains only one experiment. + +As for prometheus, the same method as for the 200 node experiment can be applied. + +## Vote Extensions Testnet + +### Running the test + +This section explains how the tests were carried out for reproducibility purposes. + +1. [If you haven't done it before] + Follow the [set up][qa-setup] steps of the `README.md` at the top of the testnet repository to + configure Terraform, and `doctl`. +2. In the `experiment.mk` file, set the following variables (do NOT commit these changes): + 1. Set `MANIFEST` to point to the file `testnets/varyVESize.toml`. + 2. Set `VERSION_TAG` to the git hash that is to be tested. +3. Follow the [testnet starting][qa-start] steps of the `README.md` to configure and start + the testnet. + * WARNING: Do NOT forget to run `make terraform-destroy` as soon as you are done with the tests +4. Configure the load runner to produce the desired transaction load. + * set makefile variables `ROTATE_CONNECTIONS`, `ROTATE_TX_RATE`, to values that will produce the desired transaction load. + * set `ROTATE_TOTAL_TIME` to 150 (seconds). + * set `ITERATIONS` to the number of iterations that each configuration should run for. +5. Execute the [testnet starting][qa-start] steps of the `README.md` file at the testnet repository. +6. Repeat the following steps for each desired `vote_extension_size` + 1. Update the configuration (you can skip this step if you didn't change the `vote_extension_size`) + * Update the `vote_extensions_size` in the `testnet.toml` to the desired value. + * `make configgen` + * `ANSIBLE_SSH_RETRIES=10 ansible-playbook ./ansible/re-init-testapp.yaml -u root -i ./ansible/hosts --limit=validators -e "testnet_dir=testnet" -f 20` + * `make restart` + 2. Run the test + * `make runload` + This will repeat the tests `ITERATIONS` times every time it is invoked. + 3. Collect your data + * `make retrieve-data` + Gathers all relevant data from the testnet into the orchestrating machine, inside folder `experiments`. + Two subfolders are created, one blockstore DB for a CometBFT validator and one for the Prometheus DB data. + * Verify that the data was collected without errors with `zip -T` on the `prometheus.zip` file and (one of) the `blockstore.db.zip` file(s). +7. Clean up your setup. + * `make terraform-destroy`; don't forget that you need to type **yes** for it to complete. + + +### Result Extraction + +In order to obtain a latency plot, follow the instructions above for the 200 node experiment, but: + +* The `results.txt` file contains only one experiment +* Therefore, no need for any `for` loops + +As for Prometheus, the same method as for the 200 node experiment can be applied. + +[qa-setup]: https://github.com/cometbft/qa-infra/blob/main/README.md#setup +[qa-start]: https://github.com/cometbft/qa-infra/blob/main/README.md#start-the-network +[rotating-prometheus]: http://PROMETHEUS-NODE-IP:9090/classic/graph?g0.expr=cometbft_consensus_height%7Bjob%3D~%22ephemeral.*%22%7D%3Ecometbft_blocksync_latest_block_height%7Bjob%3D~%22ephemeral.*%22%7D%20or%20cometbft_blocksync_latest_block_height%7Bjob%3D~%22ephemeral.*%22%7D&g0.tab=0&g0.display_mode=lines&g0.show_exemplars=0&g0.range_input=1h40m&g1.expr=cometbft_mempool_size%7Bjob!~%22ephemeral.*%22%7D&g1.tab=0&g1.display_mode=lines&g1.show_exemplars=0&g1.range_input=1h40m&g2.expr=cometbft_consensus_num_txs%7Bjob!~%22ephemeral.*%22%7D&g2.tab=0&g2.display_mode=lines&g2.show_exemplars=0&g2.range_input=1h40m diff --git a/docs/rfc/README.md b/docs/references/rfc/README.md similarity index 63% rename from docs/rfc/README.md rename to docs/references/rfc/README.md index 6693c1ff65b..f4bb42feabb 100644 --- a/docs/rfc/README.md +++ b/docs/references/rfc/README.md @@ -15,7 +15,7 @@ discussion that might otherwise only be recorded in an ad-hoc way (for example, via gists or Google docs) that are difficult to discover for someone after the fact. An RFC _may_ give rise to more specific architectural _decisions_ for CometBFT, but those decisions must be recorded separately in -[Architecture Decision Records (ADR)](../architecture/). +[Architecture Decision Records (ADR)](./../architecture/README.md). As a rule of thumb, if you can articulate a specific question that needs to be answered, write an ADR. If you need to explore the topic and get input from @@ -32,7 +32,7 @@ An RFC should provide: substance of the discussion (links to other documents are fine here). - The **discussion**, the primary content of the document. -The [rfc-template.md](./rfc-template.md) file includes placeholders for these +The [rfc-template.md](rfc-template.md) file includes placeholders for these sections. ## Table of Contents @@ -42,4 +42,11 @@ relating to Tendermint Core prior to forking, please see [this list](./tendermint-core/). -- [RFC-100: ABCI Vote Extension Propagation](./rfc-100-abci-vote-extension-propag.md) +- [RFC-100: ABCI Vote Extension Propagation](rfc-100-abci-vote-extension-propag.md) +- [RFC-101: Banning peers based on ResponseCheckTx](rfc-101-p2p-bad-peers-checktx.md) +- [RFC-102: Improve forward compatibility of proto-generated Rust code](rfc-102-rust-gen-builders.md) +- [RFC-103: Incoming transactions when node is catching up](rfc-103-incoming-txs-when-catching-up.md) +- [RFC-104: Internal messaging using the actor model](rfc-104-actor-model.md) +- [RFC-105: Allowing Non-Determinism in `ProcessProposal`](rfc-105-non-det-process-proposal.md) +- [RFC-106: Separation of non-idempotent methods in data companion API](rfc-106-separate-stateful-methods.md) +- [RFC-107: Internal signalling using event observers](rfc-107-event-observer.md) diff --git a/docs/references/rfc/images/rfc-103-optimization-comparison.png b/docs/references/rfc/images/rfc-103-optimization-comparison.png new file mode 100644 index 00000000000..9e71d7187ef Binary files /dev/null and b/docs/references/rfc/images/rfc-103-optimization-comparison.png differ diff --git a/docs/rfc/rfc-100-abci-vote-extension-propag.md b/docs/references/rfc/rfc-100-abci-vote-extension-propag.md similarity index 99% rename from docs/rfc/rfc-100-abci-vote-extension-propag.md rename to docs/references/rfc/rfc-100-abci-vote-extension-propag.md index de3296e5a21..f57cc250263 100644 --- a/docs/rfc/rfc-100-abci-vote-extension-propag.md +++ b/docs/references/rfc/rfc-100-abci-vote-extension-propag.md @@ -156,7 +156,7 @@ discussions and need to be addressed. They are (roughly) ordered from easiest to If sets *valseth* and *valseth+1* are disjoint, more than *2nh/3* of validators in height *h* should - have actively participated in conensus in *h*. So, as of height *h*, only a minority of validators + have actively participated in consensus in *h*. So, as of height *h*, only a minority of validators in *h* can be lagging behind, although they could all lag behind from *h+1* on, as they are no longer validators, only full nodes. This situation falls under the assumptions of case (h) below. @@ -684,7 +684,7 @@ remain valid, but we need to add a new condition. - The node is still at a height *h < he*. We have taken the changes required by the base implementation, -initially decribed in section +initially described in section [Base Implementation](#base-implementation-persist-and-propagate-extended-commit-history), and adapted them so that they support upgrading to ABCI 2.0 in the terms described earlier in this section: diff --git a/docs/references/rfc/rfc-101-p2p-bad-peers-checktx.md b/docs/references/rfc/rfc-101-p2p-bad-peers-checktx.md new file mode 100644 index 00000000000..5bd61797a31 --- /dev/null +++ b/docs/references/rfc/rfc-101-p2p-bad-peers-checktx.md @@ -0,0 +1,513 @@ +# RFC 101: Banning peers based on ResponseCheckTx + +## Changelog +- Nov 4, 2022: Initial draft (jmalicevic) +- Nov 8, 2022: Updated draft (jmalicevic) +- Nov 11, 2022: Updated based on PR comments (jmalicevic) +- Nov 14, 2022: Updated current peer banning mechanisms (jmalicevic) +- Mar 30, 2023: Final conclusions and further steps (jmalicevic) + +## Abstract + +In CometBFT, nodes receive transactions either from external clients via RPC, +or from their peers via p2p. Upon receiving a transaction, a node runs `CheckTx` on it. This is +an application specific check whose return code with a zero value indicates the transaction +has passed this check, and can be added into the mempool. Any non-zero code indicates the transaction +is not valid. Thus, the main role of `CheckTx` is to, as early as possible, prevent invalid transactions +from entering the mempool. + +`CheckTx` will never place a transaction failing the check into the mempool. But there are scenarios where a, +once valid, transaction can become invalid. And there are valid, non-malicious, scenarios in which a transaction will not +pass this check (including nodes getting different transactions at different times, meaning some +of them might be obsolete at the time of the check; state changes upon block execution etc.). +However, CometBFT users observed that +there are transactions that can never have been or will never be valid. They thus propose +to introduce a special response code for `CheckTx` to indicate this behaviour, and ban the peers +who gossip such transactions. Additionally, users expressed a need for banning peers who +repeatedly send transactions failing `CheckTx`. + +The main goal of this document is to analyse the cases where peers could be banned when they send +transactions failing `CheckTx`, and provide the exact conditions that a peer and transaction have +to satisfy in order to mark the peer as bad. + +This document will also include a proposal for implementing these changes within the mempool, including +potential changes to the existing mempool logic and implementation. + + +## Background + +This work was triggered by issue [#7918](https://github.com/tendermint/tendermint/issues/7918) and a related +discussion in [#2185](https://github.com/tendermint/tendermint/issues/2185). Additionally, +there was a [proposal](https://github.com/tendermint/tendermint/issues/6523) +to disconnect from peers after they send us transactions that constantly fail `CheckTx`. While +the actual implementation of an additional response code for `CheckTx` is straight forward there +are certain correctness aspects to consider. The questions to answer, along with identified risks will be outlined in +the discussion. + +### Existing issues and concerns + +Before diving into the details, we collected a set of issues opened by various users, arguing for +this behaviour and explaining their needs. + +- Celestia: [blacklisting peers that repeatedly send bad tx](https://github.com/celestiaorg/celestia-core/issues/867) + and investigating how [Tendermint treats large Txs](https://github.com/celestiaorg/celestia-core/issues/243) +- BigChainDb: [Handling proposers who propose bad blocks](https://github.com/bigchaindb/BEPs/issues/84) +- IBC relayers: Nodes allow transactions with a wrong `minGas` and gossip them, and other nodes keep rejecting them. Problem seen +with relayers where some nodes would have the `minGas` [parameter](https://github.com/cosmos/gaia/blob/5db8fcc9a229730f5115bed82d0f85b6db7184b4/contrib/testnets/test_platform/templates/app.toml#L8-L11) misconfigured. +- Gaia reported and [issue](https://github.com/cosmos/gaia/issues/2073) where misconfigured non-validator nodes were spamming the validatos with +transactions that were too big. The debugging was long and it was not easy to realize what was going on. + +**Acceptable duplicate transactions** + +Banning peers was also mentioned within [IBC-go](https://github.com/cosmos/ibc-go/issues/853#issuecomment-1032211020). However,the crux of the issue is preventing transactions with duplicate payload. While this is indeed undesired behaviour, this is not considered behaviour that should lead to banning a peer or even disconnecting from him. Duplicate transactions are in this case prevented using an application-specific solution. + +### Current state of mempool/p2p interaction + +Transactions received from a peer are handled within the [`Receive`](https://github.com/cometbft/cometbft/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/reactor.go#L158) routine. + +Currently, the mempool triggers a disconnect from a peer in the case of the following errors: + + - [Unknown message type](https://github.com/cometbft/cometbft/blob/main/mempool/reactor.go#L119) + +However, disconnecting from a peer is not the same as banning the peer. The p2p layer will close the connection but +the peer can reconnect without any penalty, and if the peer it is connecting to is configured to be its persistent peer, +a reconnect will be initiated +from the node. + +### Current support for peer banning + +The p2p layer implements banning peers by marking them +as bad and removing them from the list of peers to connect to for *at least* a predefined amount of time. This is done by calling the +[`MarkBad`](https://github.com/cometbft/cometbft/blob/main/spec/p2p/implementation/addressbook.md#bad-peers) routine implemented by the `Switch`. +If the node does not set the amount of time to be banned, a default value is used. +Note that the timing parameter sets the lower bound for when a peer will be unbanned. +But the p2p layer will only try to connect to banned peers if the node is not sufficiently connected. Thus the node has no +explicit control on when a reconnect attempt will be triggered. + +The application can blacklist peers via ABCI if the +[`filterPeers`](../../../spec/abci/abci++_app_requirements.md#peer-filtering) +config flag is set, by providing a set of peers to ban to CometBFT. + +If the discussion in this RFC deems a different banning mechanism is needed, +the actual implementation and design of this mechanism will be discussed in a separate RFC. +This mechanism should be generic, designed within the p2p layer and simply provide an interface +for reactors to indicate peers to ban and for how long. It should not involve any mempool +specific design considerations. + +## Discussion + +If this feature is to be implemented we need to clearly define the following: +1. What does banning a peer mean: + 1. A peer can be simply disconnected from. + 2. Peer is disconnected from and banned. + 3. Conditions for the peer to be banned. +2. If `CheckTx` signals a peer should be banned, retrieve the ID of peers to ban. +3. Are there possible attack scenarios or unexpected behaviours by allowing this. + +Any further mentions of `banning` will be agnostic to the actual way banning is implemented by the p2p layer. + + +### 1. What does banning a peer mean + +CometBFT recognizes that peers can accept transactions into their mempool as valid but then when the state changes, they can become invalid. +There are also transactions that are received that could never have been valid (for example due to misconfiguration on one node). +We thus differentiate two scenarios - a) where `CheckTx` fails due to reasons already +known and b) where `CheckTx` deems a transaction could never have been valid. + +For the sake of simplicity , in the remainder of the text we will distinguish the failures due to a) as failures +signaled with `ResponseCheckTx.code = 1` and the failures described in b), failures with `ResponseCheckTx.code > 1`, even though +the way we actually mark them in the end might differ. + +For a), a peer sends transactions that **repeatedly** fail CheckTx with `ResponseCheckTx.code = 1`, and is banned or disconnected from to avoid this. +In this case we need to define what repeatedly means. + +For b) we need to understand what is the potential reason a transaction could never have been valid on one node, but passes `CheckTx` on another node. +We need to understand all the possible scenarios in which this can happen: + +1. What happens if a node is misconfigured and allows, for example, very large transactions into the mempool. +This node would then gossip these transactions and they would always fail on other nodes. +Is this a scenario where we want nodes to disconnect from this peer and ban it but do not consider it malicious? +2. Are all other reasons for this to happen sign of malicious behaviour where a node explicitly lies? How can `CheckTx` pass on a valid node, but fail on another valid node with a `ResponseCheckTx.code > 1`? +If such behaviour is only possible when a peer is malicious, should this peer be punished or banned forever? Note that +we cannot know whether a node is a validator in order for it to be punished. Gossiping this behaviour to other peers pro-actively +also entails a different set of problems with it - how do we know we can trust peers who tell us to ban other peers. For these reasons, understanding the actual reason for these failures can be left for future work. + +For now, we will disconnect and ban the peer regardless of the exact reason a transaction +is considered to never be valid. + +#### **Banning for frequent CheckTx failures** + +If a node sends transactions that fail `CheckTx` but could be valid at some point, a peer should not be banned the first time this happens. +Only if this happens frequently enough should this be considered as spam. To define this behaviour we keep track how many times (`numFailures`) a peer +sent us invalid transactions within a time interval (`lastFailure`). This time interval should be reset every `failureResetInterval`. + +For each peer, we should have a separate `numFailures` and `lastFailure` variable. There is no need to have one per transaction. + Whenever a transaction fails, if the `now - lastFailure <= failureResetInterval`, we increment the `numFailures` for this particular peer and set the `lastFailure` to `now`. + Otherwise, we set `lastFailure` to `now` and set `numFailures` to 1. + Once the value for `numFailures` for a peer reaches `maxAllowedFailures`, the peer is disconnected from and banned. + +The reason for this logic is as follows: We deem it acceptable if every now and then a peer sends us an invalid transaction. + But if this happens very frequently, then this behaviour can be considered as spamming and we want to disconnect from the peer. + + **Discussion** + + The problem with supporting this scenario is the definition of the above mentioned parameters. It is very hard to estimate, at the CometBFT level, what these parameters should be. A possible solution is + to allow the application to set these parameters. What is unclear, how will the application know that these parameters are not well set if, due to a bug or network problems, transactions start to fail? +The network could end up with all nodes banning everyone. How would an application developer know to debug this, what to look for? + +A possible solution is to ban peers temporarily. In addition to the question on how long is temporarily, setting specific time limits for banning on a peer basis +is currently not supported by the p2p layer. + +*Banning a peer in case of duplicate transactions* + +Currently, a peer can send the same valid (or invalid) transaction [multiple times](https://github.com/cometbft/cometbft/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/clist_mempool.go#L247). Peers do not +gossip transactions to peers that have sent them that same transaction. But there is no check on whether +a node has already sent the same transaction to this peer before. There is also no check whether the transaction +that is being gossiped is currently valid or not (assuming that invalid transactions could become valid). +The transaction broadcast logic simply loops through the mempool and tries to send the transactions currently in the pool. + +If we want to ban peers based on duplicate transactions, we should either add additional checks for the cases above, or +not ban peers for this behaviour at the moment. It would be useful to gather metrics on how often a peer gossips the same +transaction and whether this is cause of significant traffic. + + +#### **Banning for sending *never-valid* transactions** + +If a transaction fails since it could never have been valid, `CheckTx` returns a `ResponseCheckTx.code` +value greater than 1. In this case, the peer should be disconnected from and banned immediately without keeping count on how often +this has happened. + +The question is whether this transaction should be kept track of in the cache? We can still store it in +the cache so that we don't run `CheckTx` on it again, but if this peer is immediately banned, maybe there is no need +to store its information. + +Now, if we want to differentiate further reasons of why this transaction is sent to a node (whether it is a sign of malice or not), +we might need more information on the actual reason for rejection. This could be done by an additional set of response codes provided by the application. + +### 2. Choosing the peer to ban + +Each transaction gossiped contains the ID of the peer that sent that transaction. Upon receiving a transaction, +a node saves the peer ID of the peer(s) that have sent it. As each peer had to have +run `CheckTx` on this transaction before adding it to its own mempool, we can assume this peer +can be held accountable for the validity of transactions it gossips. Invalid transactions are kept only in the mempool +cache and thus not gossiped. +As nodes have to complete a cryptographic handshake at the p2p layer, CometBFT guarantees that a malicious peer +cannot lie about who the sender of the transaction is. + +*Transactions received from users* + +For transactions submitted via `broadcastTxCommit`, the `SenderID` field is empty. + +**Question** Do we have mechanisms in place to handle cases when `broadcastTxCommit` submits +failing transactions (can this be a form of attack)? + +**From PR discussion** +At the moment there is no particular defense mechanism beyond rate limiting as for any RPC endpoint (which is not done internally by CometBFT). +An alternative would be to indeed internally make sure we do not get spammed with bad transaction using this endpoint. + +### 3. Attack scenarios + +While an attack by simply banning peers on failing `CheckTx` is hard to imagine, as the incentive for doing so is not clear, there are considerations with regards to the current mempool gossip implementation. + +Should we keep transactions that could never have been valid in the cache? Assuming that receiving such transactions is rare, and the peer that sent them is banned, do we need to occupy space in the mempool cache with these transactions? + +- What if nodes run different versions of CometBFT and banning is not supported in one of the versions? + +- Reserving response codes can be problematic for existing applications that may have reserved these codes for internal purposes withtou being aware that this causes a ban now. + + +## Implementation considerations + +**Indicating a new type of `CheckTx` failure** + +The initial proposal is to reserve a special response code to indicate that the transaction could never have been valid. +Due to concerns of this being a breaking change for applications that have already reserved this code for internal +purposes, there is an alternative implementation: expanding `ResponseCheckTx` with an additional field. +This field `neverValidTx` would be `false` by default. If a transaction could never have been valid, +in addition to indicating this with a non-zero response code from `CheckTx`, the application would set this field value. + +Another proposal is to expand this, by allowing the application to explicitly instruct CometBFT on whether to ban a peer or not. +This requires adding yet another field to `CheckTx`: `banPeer`. The field can have the following values: +- `0`(default): do not ban peer +- `1`: decrement peer reputation (if such a mechanism exists in the p2p layer) +- `2`: ban the peer and disconnect + +**Adding support for peer banning** + +When a transaction fails `CheckTx`, it is not stored in the mempool but **can** be stored in the cache. If it is in the cache, it cannot be resubmitted again (as it will be discovered in the cache and not checked again). These two scenarios require a different implementation of banning in case `CheckTx` failed. + +In both cases we need to keep track of the peers that sent invalid transactions. If invalid transactions are cached, +we also need to keep track of the `CheckTx` response code for each transaction. Currently the `ResponseCheckTx` code is checked in `resCbFirstTime` of the mempool. +If invalid transactions are kept in the cache, the check is ran only when a transaction is +seen for the first time. Afterwards, the transaction is cached, to avoid running `CheckTx` on transactions already checked. +Thus when a transaction is received from a peer, if it is in the cache, +`CheckTx` is not ran again, but the peers' ID is added to the list of peers who sent this particular transaction. +These transactions are rechecked once a block is committed to verify that they are still valid. + +If invalid transactions are not kept in the cache, they can be resubmitted multiple times, and `CheckTx` will be executed on them upon submission. +Therefore we do not need to remember the previous response codes for these transactions. + +In summary, if we want to support banning peers based on the frequency with which they submit invalid transactions, we need to have **additional datastructures**: +1. One to keep track of past invalid transactions +2. A datastructure to differentiate between valid and invalid *cached* transactions. If the `KeepInvalidTxsInCache` configuration parameter is not set, this datastructure + is not needed. + +We propose two ways to implement peer banning based on the result of `CheckTx`: + +1. Introduce banning when transactions are received +2. Adapt the recheck logic to support this + + + +**Peer banning when transactions are received** + +If a transaction fails `CheckTx` the +[first time it is seen](https://github.com/cometbft/cometbft/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/clist_mempool.go#L409), + the peer can be banned right there: + +>>mempool/v0/clist_mempool.go#L409 +```golang + +if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { + // Check Tx passed +} else { +// ignore bad transaction + mem.logger.Debug( + "rejected bad transaction", + "tx", types.Tx(tx).Hash(), + "peerID", peerP2PID, + "res", r, + "err", postCheckErr, + ) + mem.metrics.FailedTxs.Add(1) + + mem.banPeer(peerP2PID) + + if !mem.config.KeepInvalidTxsInCache { + // remove from cache (it might be good later) + mem.cache.Remove(tx) + } else { + // If transactins stay in the cache, remember they failed + mem.cache.invalidCachedTx.Store(tx.Key(), true) + } +} + +``` +The `KeepInvalidTxsInCache` configuration parameter defines whether an invalid transaction stays in cache. For *never-valid* +transactions, we could apply a different approach based on what we deem to be the bigger gain: +- As we do not expect to receive frequently and from many peers, and we ban the peer that sent it immediately, we do not store it in the cache to save space. This would mean +that if we did see it again, we'd ran `CheckTx` on it again. + +```golang +if !mem.config.KeepInvalidTxsInCache || r.CheckTx.Code == abci.NeverValid { + // remove from cache (it might be good later or is never valid, we'll most likely don't see it again) + mem.cache.Remove(tx) +} +``` + +- We do keep it in the cache as long as possible to avoid running `CheckTX` on it because we know, for sure, that it will never be valid. As it is rare enough, it +might not take that much space. In this case though, as we ban the sending peer immediately, we can save space by not storing peer information for this transaction. + +The question is which one is more costly, doing `CheckTx` more then once, or keeping an extra entry in the cache? + + + +As said, this code will [never be executed](https://github.com/cometbft/cometbft/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/clist_mempool.go#L239) +for transactions whose hash is found +in the cache. +Instead of remembering the cached transactions, we could have had a valid/invalid bit per transaction within the cache. As transactions themselves do not +store such information and we expect this scenario to be unlikely, instead of increasing the footprint of all transactions in the cache, +we opted to keep a map of transaction signature if the transaction is in the cache, but is invalid. Alternatively, the cache could keep two lists, one for valid, and one for invalid transactions. +This modifies the following pieces of code as follows (this is just a prototype and does not include +some obvious sanity checks): + +```golang + +// New datastructure to keep track of peer failures +type PeerFailure struct { + lastFailure time.Time + numFailures int8 +} + +type LRUTxCache struct { +// Keeping track of invalid transactions within the cache ; + invalidCachedTx map[types.TxKey]bool +} + +type CListMempool struct { + // ..existing fields + peerFailureMap map[nodeID]*PeerFailure + +} +``` + +>mempool/v0/clist_mempool.go#L239 +```golang + +if !mem.cache.Push(tx) { // if the transaction already exists in the cache + // Record a new sender for a tx we've already seen. + // Note it's possible a tx is still in the cache but no longer in the mempool + // (eg. after committing a block, txs are removed from mempool but not cache), + // so we only record the sender for txs still in the mempool. + if e, ok := mem.txsMap.Load(tx.Key()); ok { + memTx := e.(*clist.CElement).Value.(*mempoolTx) + memTx.senders.LoadOrStore(txInfo.SenderID, true) + // TODO: consider punishing peer for dups, + // its non-trivial since invalid txs can become valid, + // but they can spam the same tx with little cost to them atm. + } + + // If transaction was invalid, we need to remember the peer information + if _, ok := mem.cache.invalidCachedTx.Load(tx.Key); ok { + mem.banPeer(peerID) + } + return mempool.ErrTxInCache +} + +``` + + +```golang + +func (mem* ClistMempool) banPeer(peerID NodeID) { + numFails := 0 + // Check whether this peer has sent us transactions that fail + if val, ok := mem.peerFailureMap[peerID]; ok { + lastFailureT := val.lastFailure + numFails = val.numFails + // if the failure was recent enough, update the number of failures and + // ban peer if applicable + if time.Since(lastFailureT) <= failureResetInterval { + if numFails == maxAllowedFailures - 1 { + // Send Ban request to p2p + } + } + } + // Update the time of the last failure + mem.peerFailureMap[peerID] = { time.Now(), numFailures + 1} +} +``` +If transactions with `ResponseCheckTx.code > 1` are not deleted from the cache and we want to ban them on the first offence, +we can skip the second `if` in the code above but call `banPeer` immediately at the end of the function. The function `banPeer` should simply forward the `peerID` to the p2p layer. In fact, we do not need to store any information on this peer as the node will remove it from its peer set. + +**Signaling the ban to p2p** + +As it is the mempool **reactor** that has access to the p2p layer, not the actual mempool implementation, the peer banning function will most likely have to send the peer ID to a channel to inform the reactor of the fact that this peer should be banned. This would require adding a channel for communication into the `CListMempool` on construction, and adding a routine in the mempool reactor that waits on a response via this channel. However, the actual implementation of this is yet to be defined. + +**Implementing peer banning on recheck** + +Currently the recheck logic confirmes whether once **valid** transactions, +, where `ResponseCheckTx.code == 0`, are still valid. + +As this logic loops through the transactions in any case, we can leverage it to check whether we can ban peers. +However, this approach has several downsides: +- It is not timely enough. Recheck is executed after a block is committed, leaving room for a bad peer to send +us transactions the entire time between two blocks. +- If we want to keep track of when peers sent us a traansaction and punish them only if the misbehaviour happens +frequently enough, this approach makes it hard to keep track of when exactly was a transaction submitted. +- Rechecking if optional and node operators can disable it. +- Furthermore, rechecking is a node local configuration parameter. This means that, some nodes might be performing this check, + while others will be unaware of this. + +On the plus side this would avoid adding new logic to the mempool caching mechanism and keeping additional information about +transaction validity. But we would still have to keep the information on peers and the frequency at which they send us bad transactions. + +Transactions that became invalid on recheck should not be cause for peer banning as they have not been gossiped as invalid transactions. + +#### `PreCheck` and`PostCheck` + +The `PreCheck` and `PostCheck` functions are optional functions that can be executed before or after `CheckTx`. +Following the design outlined in this RFC, their responses are not considered for banning. + + +#### Checks outside `CheckTx` + +There are a number of checks that the mempool performs on the transaction, that are not part of `CheckTx` itself. +Those checks, have been mentioned in the user issues described at the beginning of this document: + +- Transaction size +- Proto checks +- Receiving unknown messages via the mempool channel + +The previous code snippets do not incroporate these in peer banning. If we adopt those as valid reasons for banning, we should put the corresponding logic in place. + +### Impacted mempool functionalities + +- Mempool caching: remembering failed transactions and whether they come from banned peers; Removal of transactions from + `invalidCachedTx` when a transaction is removed from cache. +- Handling of transactions failing `CheckTx`: Keeping track of how often transactions from a particular peer have failed + and banning them if the conditions for a ban are met. + +### Impact on ABCI + +- Introduction of new response codes for CheckTx. As previously noted, this might break existing applications if they reserved codes for internal purposes. +- Altering the specification to reflect this change + +### Github discussion summary + +The main concern that arose from the discussion on github is whether banning peers based on the return code of `CheckTx` +can lead to unwanted side effects, such as partitioning the network or influencing the behaviour of other nodes. + +#### *Potential failure scenarios* + +* Assume we have a network that is configured in such a way that there exists an overlay network, and a node can only influence its direct connections. +The node can force a peer to disconnect from it forever if, say, it wanted to lower the number of ways it has of getting messages to the rest of the network. +However, that could have already be done by just disconnecting or by dropping its messages. + +* A bug in `CheckTx`causes the rejection of all transactions and all nodes disconnect, how do we ensure the operator knows what has happened? + +* An attacker discovers a particular transaction that they know would be accepted, and therefore propagated, by >1/3 of the voting power on the network, + but rejected by the rest. This would result in halting the network for the period for which we blacklist "misconfigured" peers, + because >1/3 of the voting power would be blacklisted by the remaining peers. This means that if >1/3 of the voting power on a network has, + for example, a minimum transaction fee requirement much lower than the remaining nodes, and application developers return a `neverValidTx=true` + value from `CheckTx` here, they could halt their network. + + +#### *Decisions* + +The uncertainties are higher in the case of banning based on the *frequency* of the failures. This option has therefore been **dismissed**. + +As for the banning based on the return code from the application, due to the lack of strong use cases and potential unwanted side-effects, +it will not be implemented at the moment of writing the final version of this RFC (March 2023). + +An alternative is being proposed at the moment due to feedback we received when debugging the Gaia issue mentioned above. Namely, +they found that having these peers banned or even a log message about this failure would have significantly shortened the debugging +time. + +Additionally, as input from Osmosis, we got a potential security-related use case for the implementation of banning. +It was therefore proposed to first implement a log message that the transaction could never have been valid, and even send this message to the sender of the transaction, warning the node +that it sent a transaction that failed `CheckTx`. But this should not be sent on every `CheckTx` failure as it would create a lot of noise +(we mentioned the valid reasons for `CheckTx` to failures). We would indeed require adding a special code and/or the `neverValidTx` flag +to `ResponseCheckTx`, and logging this warning only if the application sets these parameters. + +This would facilitate debugging and pinpointing the problem for operators of the nodes receiving these warnings. + +Then, once we progress with the p2p specification and understand all possible implications of banning, actual peer banning can be implemented. + +#### *Discussion on minor implementation details* + +For completeness, and to make sure the information is not lost, there were a few discussions on minor implementation details. + +*Keeping transactions failing `CheckTx` with a special code in the cache* + +Without any change to the current logic, these transactions are kept in the cache, as long as they are not evicted. +Users argued for these transactions to be rare enough, that they can safely be discarded in the case a peer is actually banned after sending them. + +*Banning based on IP or nodeID* + +Banning based on IP should be sufficient as the secret connection handshake prevents spoofing. + +*Backwards compatibility* + +Other than avoiding relying solely on the response code values, there are no immediate concerns in terms of backwards compatibility. + +### References + + +- Most of the relevant links are in the [existing issues and concerns section](#existing-issues-and-concerns) + +- [`CheckTx` function description](../../../spec/abci/abci++_methods.md#checktx) + +- Github discussions on this RFC: + - [CometBFT repo - PR \#78](https://github.com/cometbft/cometbft/pull/78) + - [Tendermint repo - PR \#9675](https://github.com/tendermint/tendermint/pull/9675) diff --git a/docs/references/rfc/rfc-102-rust-gen-builders.md b/docs/references/rfc/rfc-102-rust-gen-builders.md new file mode 100644 index 00000000000..8d31b3d7881 --- /dev/null +++ b/docs/references/rfc/rfc-102-rust-gen-builders.md @@ -0,0 +1,134 @@ +# RFC 102: Improve forward compatibility of proto-generated Rust code + +## Changelog + +- 17-Apr-2023: Initial draft + +## Abstract + +In protobuf, adding a field to a message or a oneof field is considered +a backward-compatible change and language bindings should avoid +breakages on source level for such changes in the proto definitions. +This is not currently the case, in general, for Rust bindings as implemented +by [prost-build]. + +We propose to augment the prost-build code generator with an add-on providing +a forward-compatible builder API, and use the `#[non_exhaustive]` attribute on +the generated data types to forbid their use with syntax that prevents future +member additions. This will allow us to evolve CometBFT protobuf APIs without +versioning churn that's not necessary for the Go bindings. + +[prost-build]: https://crates.io/crates/prost-build + +## Background + +As we are renaming protobuf packages for CometBFT and introducing versioning +practices recommended by [buf.build][buf-versioning], it's important to lay +down the basis for future development that does not perpetuate workarounds for +limitations of a particular language binding. + +[buf-versioning]: https://buf.build/docs/best-practices/module-development/#package-versions + +### References + +* Issue [#399](https://github.com/tokio-rs/prost/issues/399) in the prost + repository captures the general problem and discussion. +* CometBFT PR [#495](https://github.com/cometbft/cometbft/pull/495) introduces + versioned protobuf definitions, currently with extra versioning applied + to accommodate API breakage caused in tendermint-rs by code generated with + prost-build. +* [Notes](https://docs.google.com/document/d/1DoxKiYtUx44xZv5my-bkfWZKY6TklvxpSUrdX9yOpNw/edit?usp=sharing) on the discussion during a 13 Apr 2023 meeting, detailing the + considerations specific to CometBFT versioning. +* [ADR 103](https://github.com/cometbft/cometbft/blob/main/docs/architecture/adr-103-proto-versioning.md) details the versioning approach as currently + accepted. + +## Discussion + +The approach taken in prost-build to represent protobuf messages is +to generate corresponding structs with all fields declared public. This is +generally preferable to a more encapsulated Rust API with member accessors, +because domain-appropriate data access and enforcement of invariants often +cannot be adequately expressed by means of protobuf and is better realized via +hand-crafted domain types. Proto3 also enforces optionality on all fields, +which (in absence of customizations) makes the generated type ugly and +sub-optimal to work with if some of the fields shall always be set to a +non-degenerate value. So use of the proto-generated types should be +dedicated to decoding and encoding protobuf, and possibly for deriving some +utility trait impls like serde that can reuse the simple structures. + +However, this allows Rust code consuming a message-derived struct type to use +struct initializer or matching syntax where all defined struct fields must be +present. If more fields are later added to the message definition without +changing its package name, and the generated struct type is updated, such +usages will fail to compile. This is not the case in Go, where field-keyed +struct initializers are allowed to omit fields, which then get initialized to +the zero value (which conveniently corresponds to the protobuf specification +for optional fields). + +To work around this, the generated struct types can be annotated with a +`#[non_exhaustive]` attribute, which forbids struct initializer syntax or +exhaustive field matching in foreign crates, making all usages of these struct +types compatible with future field additions. This alone, however, leaves only +a cludgy way to initialize messages that relies on a derived `Default` +implementation and individual field assignments. To alleviate the pain, it is +recommended to add a builder pattern API allowing ergonomic initialization +syntax. To do this manually for each generated struct, however, would be very +tedious and time-consuming. + +### Builder API generator/plugin + +To plug this gap, we propose to create a code generator in Rust to augment +the output of prost-build with a builder API for each generated struct type. +This generator can be invoked +either from `build.rs` or an in-project generator tool, or as a `buf` plugin. + +As an example, using this proto definition: + +```proto +message HelloRequest { + int version = 1; + repeated string flags = 2; +} +``` + +The generator will provide a builder API along these lines: + +```rust +impl HelloRequest { + pub fn builder() -> self::prost_builders::HelloRequestBuilder { + todo!() + } +} + +pub mod prost_builders { + pub struct HelloRequestBuilder { + inner: super::HelloRequest, + } + + impl HelloRequestBuilder { + pub fn version(mut self, version: i32) -> Self { + self.inner.version = version; + self + } + + pub fn flags(mut self, flags: impl IntoIterator) -> Self + where T: Into, + { + self.inner.flags = flags.into_iter().map(Into::into).collect(); + self + } + + pub fn build(self) -> super::HelloRequest { + self.inner + } + } +} +``` + +Note how the initializer methods of a builder can be equipped with convenient +generics, utilizing knowledge of the protobuf type system. + +### Open issues + +Do we still want to bump the version package for field additions +between major CometBFT proto releases, especially when adding important semantics? diff --git a/docs/references/rfc/rfc-103-incoming-txs-when-catching-up.md b/docs/references/rfc/rfc-103-incoming-txs-when-catching-up.md new file mode 100644 index 00000000000..161d0ff4990 --- /dev/null +++ b/docs/references/rfc/rfc-103-incoming-txs-when-catching-up.md @@ -0,0 +1,218 @@ +# RFC 103: Incoming transactions when node is catching up + +## Changelog + +- 2023-04-20: Initial version (@hvanz) +- 2023-05-02: Update following PR comments (@hvanz) +- 2023-05-04: Update following more PR comments (@hvanz) + +## Abstract + +Once a node starts running and is initialized, it can receive transactions from +clients via RPC endpoints or from other nodes via P2P channels in its mempool +reactor. The node then validates these transactions using `CheckTx` calls to the +application. This process occurs even when the node is catching up to reach the +latest block heights through state sync or block sync, and the application may +not be up to date yet with the latest height of the blockchain. If a +transaction's validity depends on the application state, it will likely be +rejected by the application when received at this stage. + +This document aims to answer the following questions: +- How should a node handle incoming transactions while catching up? Should it + reject all transactions until it switches to consensus mode, or should it call + `CheckTx` even though the application will likely deem the transaction + invalid? +- Should nodes or clients send transactions when they suspect the receiving node + is not initialized? + +## Background + +### Life cycle of a node + +A CometBFT node transitions through the following stages: set up, +initialization, catch up, and consensus. + +When a node starts executing (for instance, from the CLI with the `start` +command), it first reads its configuration files and *sets up* all its +components, including reactors, stores, P2P connections, and RPC services. Then, +the node starts running and turns on all the components. At this point we say +that the node is *initialized*. The mempool reactor is running and the [RPC +endpoints][rpc] are open, allowing the node to [receive][receive] and process +transactions from other nodes and clients. + +The node could start the consensus protocol immediately to reconstruct the block +history, but this could take a very long time. State sync and block sync are much +faster mechanisms to bootstrap the node and reach the latest heights of the +chain. While a node is performing state sync or block sync, it is in *catch up* +mode. Once synchronization finishes, the node is not necessarily at the +latest height, but it is assumed to be fairly close to it, so the node is ready +to fully participate in consensus. At this point, it switches to *consensus* +mode, which should never leave unless it is stopped or it crashes. + +### Transaction validation with CheckTx + +The `CheckTx` [method][check-tx] acts as a gatekeeper to the mempool, which +only accepts valid transactions. The validity of a transaction is defined +deterministically by the application, but it may depend on the application +state, which may change at every height. + +`CheckTx` is called: +- from the [RPC endpoints][rpc] `broadcast_tx_async`, `broadcast_tx_sync`, and + `broadcast_tx_commit`, and +- when the node [receives][receive] a `Txs` message from a peer: for each + transaction in `Txs` there will be a call to `CheckTx`. + +`CheckTx` puts the transaction in the cache, sends a `RequestCheckTx` ABCI +message to the application, and sets a callback to process a `ResponseCheckTx`. +If the application deems the transaction as valid, `CheckTx` stores the +transaction in the mempool and notifies the consensus reactor that there are +transactions available to be [put in a new block][reap]. Otherwise it does not +add the transaction to the mempool and removes it from the cache. + +### Mempool cache + +The mempool reactor implements a cache of received transactions that it uses to +discard already-seen transactions, thus avoiding processing duplicates. + +Transactions remain in the cache until the application replies that a +transaction is invalid. This can occur in three cases. +1. The first time a transaction is received and then rejected by `CheckTx`. +2. When the block executor [updates][update] the mempool, right after finalizing + and committing a block: if there was an error while executing a transaction + against the application, then it is removed from the cache. +3. When all the transactions in the mempool need to be rechecked after a new + block has been delivered to the application. Each transaction will be + validated again with `CheckTx` and removed from the cache if deemed invalid. + +In the first and third cases, the reply from the application is a +`ResponseCheckTx` message. In the second case, the reply is a +`ResponseFinalizeBlock`. + +All these cases are for removing invalid transactions, so the cache also +requires that `keep-invalid-txs-in-cache` is set to false. The configuration +`keep-invalid-txs-in-cache` is for ignoring invalid, already-seen transactions. +This is useful for applications that consider rejected transactions will never +be accepted again. + +When a transaction is received, cached, and deemed valid, but the mempool is +full, it is not kept in the cache. This is done to provide an opportunity for +the transaction to be re-validated if it is received again later, potentially +when there is sufficient free space in the mempool. + +## Discussion + +### Inbound messages + +A node that is not in consensus mode, should accept or reject incoming +transactions? The mempool reactor currently accepts and validates all incoming +transactions. It only implements the cache to discard already-seen transactions. + +There are not many reasons at this stage to have an operational mempool reactor +and the `broadcast_tx_*` [endpoints][rpc] open. One reason is to store +transactions to be able to validate them and have them ready once the node +switches to consensus mode (in particular, the node could be the next +validator). Another reason is for participating actively in the gossip protocol +for propagating transactions. In any case, the application will most probably +reject transactions if its validity depends on the application state. And the +reactor only propagates transactions that are validated and stored in the +mempool. + +__Decision__ Nodes that are catching up cannot guarantee effective handling of +incoming transactions. They are not yet prepared to participate in transaction +propagation properly. Therefore we see no strong reason at this stage for +keeping the mempool reactor operational and the `broadcast_tx_*` endpoints open. +Instead, we believe that nodes should reject incoming transactions until they +switch to consensus mode. This approach will provide clearer semantics for the +RPC endpoints, thus improving the user experience. Please refer to issue +[#785](https://github.com/cometbft/cometbft/issues/785), which will address this +decision. + +### Outbound messages + +We cannot control or predict what a client may send to the RPC endpoints, but we +can dictate what honest nodes must send to their peers. + +The gossip algorithm currently implemented is a naive *push* protocol: a node +will forward all the transactions in its mempool to all its peers, except to the +nodes from which it received the transaction. + +The protocol implements only one minor optimization. For each peer, the +`broadcastTxRoutine` [function][broadcast] in the mempool reactor iterates +through all transactions in the mempool and sends them one by one to a peer. +Just before sending a transaction, if the node suspects that the peer is lagging +behind, it waits some time before checking again if the node has caught up. This +is the [code][optimization]: +```golang +if peerState.GetHeight() < memTx.Height()-1 { + time.Sleep(PeerCatchupSleepIntervalMS * time.Millisecond) + continue +} +``` +where: +- `peerState` is the local state of the peer (updated with the information + received by the consensus reactor in `PeerState.ApplyNewRoundStepMessage` + messages), +- `memTx.Height()` is the height at which transaction `memTx.tx` was validated + (set during the handling of `CheckTx` responses), and +- `PeerCatchupSleepIntervalMS` is fixed to `100`. + +>For a historical reference, this optimization has been around since 2015. There +>is no documentation or comment on the reason it was introduced. A first version +>with only the condition to check the peer's height was introduced in a +>[commit](https://github.com/tendermint/tendermint/commit/12566f51af2bbdc73e3c79c603be0593d8cb1574) +>from September 2015. In December 2015 a huge refactoring +>[commit](https://github.com/CometBFT/cometbft/commit/ef43af19ab2af994afaf9fdb148df2918454d9c4) +>introduced the line that makes the broadcast routine sleep. + +> Note that the evidence reactor implements a similar optimization. + +Should the code for this optimization be removed from the mempool reactor to +make it consistent with how the [RPC endpoints][rpc] are implemented, that is, +without filtering any message? Experimental evidence shows that actually the +optimization works and improves the behavior of the nodes. The following picture +shows the results of an experiment with four interconnected nodes. On the left +we see the collected metrics when we run the nodes without the optimization. On +the right we see the results of running the nodes with the optimization, that +is, without modifying the code. +![rfc-103-comparison](images/rfc-103-optimization-comparison.png) The node in +orange called _validator04_ joins the network at around height 100 and starts +performing block sync. In the graph at the bottom we can see the height of all +nodes and in particular how this node starts from height 0 and catches up with +the other nodes. Also we can observe that, when the optimization is disabled +(left side), while the orange node is catching up, both its mempool size (top +graph) and the number of rejected transactions (middle graph) increases +significantly compared to the optimizated code (right side). + +__Decision__ The results presented above indicate that the optimization is +effectively improving the system's performance and should be kept for now. In +particular, the decrease in mempool size implies that the memory usage of the +catching-up node is lower compared to those with the unoptimized code. +Similarly, the decrease in the recheck rate suggests that CPU usage is also +lower. + +## References + +### Mempool Reactor + +1. [Receive][receive] +1. [broadcastTxRoutine][broadcast] +1. [Outbound optimization][optimization] + +### CListMempool + +1. [CheckTx][check-tx] +1. [Update][update] +1. [ReapMaxBytesMaxGas][reap] + +### RPC endpoints + +1. [broadcast_tx_*][rpc] + + +[receive]: https://github.com/CometBFT/cometbft/blob/23c37d65990aa8ef2cc5a442792f56eb87d4d1e9/mempool/reactor.go#L93 +[broadcast]: https://github.com/CometBFT/cometbft/blob/23c37d65990aa8ef2cc5a442792f56eb87d4d1e9/mempool/reactor.go#L132 +[optimization]: https://github.com/CometBFT/cometbft/blob/23c37d65990aa8ef2cc5a442792f56eb87d4d1e9/mempool/reactor.go#L171-L174 +[check-tx]: https://github.com/cometbft/cometbft/blob/23c37d65990aa8ef2cc5a442792f56eb87d4d1e9/mempool/clist_mempool.go#L202 +[update]: https://github.com/cometbft/cometbft/blob/23c37d65990aa8ef2cc5a442792f56eb87d4d1e9/mempool/clist_mempool.go#L577 +[reap]: https://github.com/cometbft/cometbft/blob/23c37d65990aa8ef2cc5a442792f56eb87d4d1e9/mempool/clist_mempool.go#L519 +[rpc]: https://github.com/cometbft/cometbft/blob/23c37d65990aa8ef2cc5a442792f56eb87d4d1e9/rpc/core/mempool.go#L22-L144 diff --git a/docs/references/rfc/rfc-104-actor-model.md b/docs/references/rfc/rfc-104-actor-model.md new file mode 100644 index 00000000000..f46bd732284 --- /dev/null +++ b/docs/references/rfc/rfc-104-actor-model.md @@ -0,0 +1,203 @@ +# RFC 104: Internal Messaging Using the Actor Model + +## Changelog + +- 2023-07-13: Emphasize/clarify conclusions (@thanethomson) +- 2023-06-29: First draft (@thanethomson) + +## Abstract + +At present, CometBFT is a collection of components that run concurrently within +the same process and interact with each other via several different mechanisms: + +1. The [`EventBus`][event-bus] +2. The [`Switch`][switch], where reactors can look up other reactors by name and + interact with them directly by calling their methods +3. Go channels held by reactors + +This results in a number of problems: + +- Difficulty and complexity in testing individual reactors in isolation, which + results in brittle and unnecessarily complex tests. +- Difficulty reasoning about overall system operation, which slows onboarding of + new developers and debugging. +- Non-deterministic tests which are of dubious value; these also slow down + development efforts. + +This RFC explores the possibility and potential implications of making use of +the [Actor] model internally to replace the reactor/service model, all while +coalescing the three existing concurrent communication approaches into a single +one. + +## Background + +The [Actor] model as an idea has been around since the 1970s and is most widely +known to be employed in [Erlang][erlang]. It imposes an architecture on a system +whereby all concurrent subprocesses/tasks are modelled as "actors", which are +the basic unit of concurrency in the system. Each actor is responsible for the +management of its own internal state, and the only way actor state can be +mutated is through messaging. + +### Messaging patterns + +The most trivial interface for an actor is one that has a single message +handler. + +```go +type Actor interface { + // Receive handles every incoming message sent to an actor. It is the sole + // method responsible for mutating the state of the actor. + Receive(ctx Context) +} + +type Context interface { + // System provides a reference to the primary actor system in which the + // actor is running. This allows the actor to spawn and kill other actors, + // send messages to other actors, etc. + System() ActorSystem + + // Sender provides a reference to the sender of a message, which allows the + // receiving actor to send a response if required. + Sender() ActorRef + + // Message sent by the sender. Notice the "any" type - a common pattern in + // Go-based actor frameworks, which effectively results in type erasure. + // + // It is, of course, possible to implement some degree of compile-time + // guarantees using Go generics, but this is still somewhat limited compared + // to directly calling methods on a struct. + Message() any +} +``` + +Actors can be built to facilitate different messaging patterns of varying +degrees of complexity to one or more other actors: + +- One-shot/fire-and-forget messaging +- Request/reply semantics +- Publish/subscribe mechanisms, where one actor can be created with the sole + purpose of being the pub/sub router actor, whose sole job is to manage topics, + subscribers and publishing messages on certain topics to specific subscribers + +### Existing actor frameworks + +As the actor model has grown in popularity, various actor frameworks have become +available in a variety of programming languages. Examples of frameworks in +different programming languages include: + +- [Proto Actor] (Go/C\#/Java/Kotlin) +- [Akka] (Java/Scala/C\#) +- [Quasar] (Java/Kotlin) +- [CAF] (C++) +- [ractor] (Rust) +- [Actix] (Rust) + +Most existing frameworks are incredibly complex, owing to the fact that they aim +to provide the foundation for complex, automatically scalable cloud-based +services. Issues such as distribution of actor-based computation across multiple +networked processes, as well as automatic persistence of actor state to +facilitate fault recovery, are catered for by the underlying framework. Much of +this functionality would not be useful or easily integrated into CometBFT at the +time of this writing. + +Actor frameworks normally also provide a form of supervision hierarchy that +allows for internal component failure recovery (depending on recovery policies +that can be adjusted on a per-actor basis). It also allows "supervisor" actors +greater control over the lifecycle of their "children" actors. + +## Discussion + +### Pros and cons of the actor model + +The benefits of employing the actor model in CometBFT are: + +1. Greater ease of reasoning about how different components work if they follow + well-defined patterns of interaction. +2. Simplification of tests for concurrent components, since they can be fully + exercised simply by way of messaging. This opens up the possibility of + employing model-based testing for a greater number of components. + +The drawbacks of introducing the actor model in CometBFT are: + +1. It would require refactoring the entire codebase, which would be a + non-trivial and expensive exercise. +2. When compared to calling component methods, sending messages to a component + usually results in much looser type/interface restrictions. This effectively + results in type erasure, which makes it more difficult to give compile-time + guarantees as to the correctness of the code and increases the testing burden + needed to ensure correctness. + +### Employing the actor model in CometBFT + +If CometBFT were to employ an actor model, every concurrent process would need +to be modelled as an actor. This includes every reactor/service in the system, +but also every major coroutine spawned by those reactors/services (if this is +not done, the system ends up again using a mix of concurrency approaches with +their concomitant complexity). + +### Using an existing framework + +The major benefit of using an existing framework is that one does not need to +reinvent the wheel, and reduces the quantity of code for which the CometBFT team +is responsible. + +The major drawbacks of using an existing framework are: + +1. **Additional dependency-related risk.** Using a framework introduces an + additional dependency, which could introduce new risks into the project. This + not only includes security risks, but also long-term project risk if the + dependency ends up being unmaintained. + +2. **Greater complexity.** Much of the complexity of such frameworks derives + from the idea that one may want to automatically scale an actor-based + application out horizontally and have its concurrent operations automatically + parallelized across multiple processes with all networking taken care of, as + if by "magic", by the underlying framework. + + While potentially useful in a future version of CometBFT, this particular + feature set is not considered for implementation or use in this ADR. As such, + using frameworks such as [Proto Actor] would most likely be overkill for the + needs of the CometBFT project. + +3. **Non-standard semantics/coding conventions.** Frameworks generally implement + their own semantics that diverge from standard semantics and conventions of + the programming language in which they are implemented. This is true of the + [Proto Actor] framework - one of the most popular actor frameworks written in + Go. + +4. **Loss of type information.** When interacting with actors by way of + references, one normally sends `any`-typed messages to those actors as + opposed to calling strongly typed functions. Erasing type information assists + in more loosely coupling system components, but provides poorer compile-time + correctness guarantees and increases the range of tests needed. + +### Conclusion + +It seems as though neither of adopting an actor model-based framework, nor a +strict actor model, is desirable for CometBFT due to the drawbacks covered in +this RFC. + +The primary lesson to be taken from the actor model, however, is that, if there +were a way to ensure that all reactor/service state is fully self-contained +within each reactor/service, and interacting with that reactor/service followed +a disciplined and consistent pattern, the system would be dramatically easier to +both understand and test. For instance, if all state for a particular protocol +were self-contained, single-threaded and only ever mutated directly by a single +active entity (i.e. reactor/service), the evolution of the state machine of that +protocol could be more fully exercised by testing approaches like fuzzing or +MBT. + +Implementing such changes would still involve substantial refactoring, but much +less so than introducing a full-blown actor system. It would also allow for +progressive refactoring of reactors/services over time. + +[event-bus]: https://github.com/cometbft/cometbft/blob/b23ef56f8e6d8a7015a7f816a61f2e53b0b07b0d/types/event_bus.go#L33 +[switch]: https://github.com/cometbft/cometbft/blob/b23ef56f8e6d8a7015a7f816a61f2e53b0b07b0d/p2p/switch.go#L70 +[Actor]: https://en.wikipedia.org/wiki/Actor_model +[Erlang]: https://www.erlang.org/ +[Akka]: https://akka.io/ +[Proto Actor]: https://proto.actor/ +[Quasar]: http://docs.paralleluniverse.co/quasar/ +[CAF]: https://www.actor-framework.org/ +[Actix]: https://actix.rs/docs/actix/actor +[ractor]: https://github.com/slawlor/ractor diff --git a/docs/references/rfc/rfc-105-non-det-process-proposal.md b/docs/references/rfc/rfc-105-non-det-process-proposal.md new file mode 100644 index 00000000000..51231b6f9bf --- /dev/null +++ b/docs/references/rfc/rfc-105-non-det-process-proposal.md @@ -0,0 +1,328 @@ +# RFC 105: Allowing Non-Determinism in `ProcessProposal` + +## Changelog + +- 2023-07-27: Initial proposal as a GitHub issue ([#1174][1174]) (@BrendanChou) +- 2023-09-22: First version of this text, draft coming from knowledge base (@sergio-mena) + +## Abstract + +The new methods `PrepareProposal` and `ProcessProposal` offered by ABCI 1.0 +are a powerful tool that enables new use cases for applications, +but they require application developers to use them with care. +Depending on how those methods are implemented, consensus liveness properties +might be compromised, thus risking hard-to-diagnose chain halts. + +The [ABCI 1.0 specification][abci-spec] defines a set of requirements on the application. +If application developers fulfill these requirements +in their implementation of `PrepareProposal` and `ProcessProposal`, +consensus liveness will be guaranteed. +These requirements are good enough for most applications: +they are simple to understand and relatively easy to check whether an application fulfills them. + +However, there may be applications that are unable to fulfill those requirements. +In this document we discuss such applications and propose weaker requirements that may be fulfilled instead. + +## Background + +### Consensus Properties + +Let us first refresh some theoretical concepts needed to understand the rest of this text. +We define $valid(v, s)$ a function +whose output depends exclusively on its inputs, i.e., a mathematical function. +The inputs are the value proposed $v$ (i.e., a block) +and a state $s$ of the blockchain. +Byzantine Fault Tolerant (BFT) Consensus is usually specified by the following properties. +For every height $h$ and $s_{h-1}$, where $s_{h-1}$ is the state of the blockchain +after applying the block decided in height $h-1$: + +- _agreement_: no two correct processes decide differently in $h$. +- _validity_: function $valid(v, s_{h-1})$, where $v$ is the block decided in $h$, always returns _true_. +- _termination_: all correct processes eventually decide in $h$. + +The consensus algorithm implemented in CometBFT (Tendermint) fulfills these properties. + +### ABCI Interface + +In the version of ABCI (v0.17.0) that existed before ABCI 1.0 and 2.0 (a.k.a. ABCI++), +the implementation of function $valid(v, s)$ was totally internal to CometBFT. +Technically, the application's part of the state $s$ was not considered by function $valid(v, s)$. +Thus, the application had no direct say on the validity of a block, +although it could (and still can) indirectly influence the contents of blocks via the (best-effort) ABCI method `CheckTx` +(by rejecting transactions, so that they are not included in blocks produced by correct proposers). + +With the evolution of ABCI to ABCI 1.0 and 2.0, CometBFT's implementation of +function $valid(v, s)$ has now two components: + +- the validity checks performed directly by CometBFT on blocks + (block format, hashes, etc; the same as in ABCI v0.17.0) +- the validity checks that now the application can perform as part of `ProcessProposal`; + i.e., `ProcessProposal` is now part of $valid(v, s)$ + and may use the application's part of state $s$ in validating $v$. + +With the new structure of the implementation of function $valid(v, s)$: + +- consensus _agreement_ is not affected and all processes are still required to agree on the same value +- the consensus _validity_ property is not affected since we are changing the + internals of function $valid(v, s)$; consensus _validity_ just requires this function to be true + +However, the new structure of the implementation of function $valid(v, s)$ +may affect consensus _termination_, as some implementations of `ProcessProposal` might reject values +that CometBFT's internal validity checks would otherwise accept. +In short, $valid(v, s)$ is more restrictive with ABCI++. + +This document focuses on how consensus _termination_ is affected +by the new structure of function $valid(v, s)$, +in particular, the different implementations of `ProcessProposal`. + +### ABCI 1.0 (and 2.0) Specification + +The [ABCI 1.0 specification][abci-spec] imposes a set of new requirements on the application +so that its implementation of `PrepareProposal` and `ProcessProposal` does not compromise consensus _termination_, +given the current consensus algorithm implemented in CometBFT (called Tendermint, and described in the [arXiv paper][arxiv]). +In contrast to $valid(v, s)$, which is defined as a mathematical function used for consensus's formal specification, +`PrepareProposal` and `ProcessProposal` are understood as _software functions_ (namely, Go function callbacks) in CometBFT. +We reproduce here the requirements in the ABCI 1.0 (and 2.0) specification that are relevant for this discussion. + +Let $p$ and $q$ be two correct processes. +Let $r_p$ be a round of consensus at height $h$ where $p$ is the proposer. +Let $s_{p,h-1}$ be $p$'s application's state committed for height $h-1$. +In other words, $s_{p,h-1}$ is $p$'s view of $s_{h-1}$. +Let $v_p$ be the block that $p$'s CometBFT passes +on to the application +via `RequestPrepareProposal` as proposer of round $r_p$, height $h$, +known as the _raw proposal_. +Let $u_p$ be the (possibly modified) block that $p$'s application +returns via `ResponsePrepareProposal` to CometBFT in round $r_p$, height $h$, +known as the _prepared proposal_. + +* Requirement 3 [`PrepareProposal`, `ProcessProposal`, coherence]: For any two correct processes $p$ and $q$ + if $q$'s CometBFT calls `RequestProcessProposal` on $u_p$, + $q$'s application returns _Accept_ in `ResponseProcessProposal`. + +* Requirement 4 [`ProcessProposal`, determinism-1]: + `ProcessProposal` is a (deterministic) function of the current + state and the block being processed. + In other words, for any correct process $p$, and any arbitrary block $u$, + if $p$'s CometBFT calls `RequestProcessProposal` on $u$ at height $h$, + then $p$'s application's acceptance or rejection **exclusively** depends on $u$ and $s_{p,h-1}$. + +* Requirement 5 [`ProcessProposal`, determinism-2]: + For any two correct processes *p* and *q*, and any arbitrary + block $u$, + if CometBFT instances at $p$ and $q$ call `RequestProcessProposal` on $u$ at height $h$, + then $p$'s application accepts $u$ if and only if $q$'s application accepts $u$. + Note that this requirement follows from the previous one and consensus _agreement_. + +The requirements expressed above are good enough for most applications using ABCI 1.0 or 2.0. +They are simple to understand and it is relatively easy to check whether an application's +implementation of `PrepareProposal` and `ProcessProposal` fulfills them. +All applications that are able to enforce these properties do not need to reason about +the internals of the consensus implementation: they can consider it as a black box. +This is the most desirable situation in terms of modularity between CometBFT and the application. + +The easiest (and thus canonical) way to ensure these requirements is to make sure +that `PrepareProposal` only prepares blocks $v$ that satisfy (mathematical) function $valid(v, s)$, +including the validation performed by correct processes in `ProcessProposal`. +However, `PrepareProposal` and `ProcessProposal` MAY also use other input in their +implementation and CometBFT will still guarantee consensus termination, _as long as +these implementations still ensure the requirements_. + +## Discussion + +### Breaking Determinism/Coherence Requirements + +This document is dealing with the case when an application cannot guarantee +the coherence and/or determinism requirements as stated in the ABCI 1.0 specification. + +An example of this is when `ProcessProposal` needs to take inputs from third-party entities +(e.g. price oracles) that are not guaranteed to provide exactly the same values to +different processes during the same height. +Another example is when `ProcessProposal` needs to read the system clock in order to perform its checks +(e.g. Proposer-Based Timestamp when expressed as an ABCI 1.0 application). + +### Problem Statement + +In principle, if an application's implementation of `PrepareProposal` and `ProcessProposal` +is not able to fulfill coherence and determinism requirements, +CometBFT cannot guarantee consensus _termination_ in all runs of the system. +For instance, think of an application whose implementation of `ProcessProposal` +always rejects values, which violates coherence. + +> ⚠️ Warning ⚠️ + +If application designers decide to follow this road, they must consider **both** +CometBFT and their application as one monolithic block, in order to reason about termination. +They thus lose the modularity provided when fulfilling the ABCI 1.0 requirements. +Remember that CometBFT's consensus algorithm (Tendermint) is a well-known algorithm that +has been studied, reviewed, formally analyzed, model-checked, etc. +The combination of CometBFT and an arbitrary application as one single algorithm cannot +leverage that extensive body of research applied to the Tendermint algorithm. +This situation is risky and undesirable. + +So, the questions that arise are the following. +Can we come up with a set of weaker requirements +that applications unable to fulfill the current ABCI 1.0 requirements +can still fulfill? +With this new set of requirements, can we still keep the reasoning on termination modular? +Is this set of weaker requirements still strong enough to guarantee consensus _termination_? + +### Solution Proposed + +#### Modified Consensus _validity_ + +Function $valid(v, s)$, as explained above, exclusively depends on its inputs +(a block, and the blockchain state at the previous height: $s_{h-1}$). +So it is always supposed to provide the same result when called at the same height for the same inputs, +no matter at which process. +This was the main reason for introducing the determinism requirements on `ProcessProposal` +in the ABCI 1.0 specification. + +If we are to relax the determinism requirements on the application, +we first need to modify function $valid(...)$ to be of the form $valid(v, s, x_p)$, +where $x_p$ is local to process $p$. +Parameter $x_p$, unknown to Comet, represents non-deterministic input used by the application. +As $x_p$ may be different from $x_q$ for two processes $p$ and $q$, allowing `ProcessProposal` +to use $x_p$ may break Requirements 3 to 5. + +Consensus _validity_ property is then modified as follows: + +- _weak validity_: function $valid(v, s_{h-1}, x_p)$ has returned _true_ at least once + by a correct process for the decided block $v$. + +#### Eventual Requirements + +We now relax the relevant ABCI 1.0 requirements in the following way. + +* Requirement 3b [`PrepareProposal`, `ProcessProposal`, eventual coherence]: + There exists a time $ts_{h}$ for every height $h$ such that, + for any two correct processes $p$ and $q$ and any round $r_p$ in height $h$ starting after $ts_{h}$, + if $q$'s CometBFT calls `RequestProcessProposal` on $u_p$, + $q$'s application returns _Accept_ in `ResponseProcessProposal`. + +* The determinism-related requirements, namely requirements 4 and 5, are removed. + +We call $ts_{h}$ the coherence-stabilization time for height $h$. + +If we think in terms of $valid(v, s, x_p)$, notice that it is the application's responsibility +to ensure 3b, that is, the application designers need to prove that the $x_p$ values at correct processes +are evolving in a way that eventually `ResponseProcessProposal` returns _Accept_ at all correct processes +that call `RequestProcessProposal` for height $h$ after $ts_{h}$. + +For instance, in Proposer-Based Timestamp, $x_p$ can be considered to be process $p$'s local clock, +and having clocks synchronized is the mechanism ensuring eventual acceptance of a proposal. +Finally, it is worth noting that _weak validity_ requires just one correct processes while requirement 3b +refers to all correct processes. + +#### Modifications to the Consensus Algorithm + +The Tendermint algorithm as described in the [arXiv paper][arxiv], +and as implemented in CometBFT up to version `v0.38.0`, +cannot guarantee consensus _termination_ for applications +that just fulfill requirement 3b (eventual coherence), but do not fulfill requirements 3, 4, and 5. + +For the sake of simplicity, and without loss of generality, we assume all validators have equal voting power. +We need the following modifications (in terms of the algorithm as described in page 6 of the arXiv paper): + +- remove the evaluation of `valid(v)` in lines 29, 36 and 50 (i.e. replace `valid(v)` by `true`) +- modify line 23 as follows + +> _\[Original\]_   23: **if** $valid(v) \land (lockedRound_p = −1 \lor lockedValue_p = v)$ **then** + +> _\[Modified\]_ +> +>   23a: $validValMatch := (validRound_p \neq -1 \land validValue_p = v)$ +> +>   23b: **if** $[lockedRound_p = −1 \land (validValMatch \lor valid(v))] \lor lockedValue_p=v$ **then** + +- If we consider the new _weak validity_ property, + the occurrences of `valid(v)` that we removed had become redundant, + so removing them does not affect the ability of the algorithm to fulfill consensus properties + (replacing _validity_ by _weak validity_). +- Regarding line 23, the changes have the following goals: + - If `v` matches the block we have as $validValue_p$ or $lockedValue_p$, we skip the call + to `valid(v)`. + The rationale is that, by the algorithm, if we have `v` as $validValue_p$ or $lockedValue_p$ + we have received it from at least $2f + 1$ prevotes for $v$ (line 36). + - If the previous condition is not met, then we call `valid(v)`. + - The modification to the conditions must _only_ affect the decision whether to call `valid(v)` or not. + It must not modify which part of the "if" should be taken. + +Notice we have kept the original `valid(v)` notation, but it stands for the more general $valid(v, s, x_p)$. +These algorithmic modifications have also been made to CometBFT (on branch `main`) +as part of issues [#1171][1171], and [#1230][1230]. + +#### Going further in the modifications + +The previous section describes the modifications to the algorithm we made to CometBFT. +However, we can go further in theory: these modifications are sufficient but not necessary. +The minimal necessary condition for the Tendermint algorithm to ensure consensus _weak validity_ +(as mentioned [here][valid-further1] and [here][valid-further2]) while skipping `valid(v)` +is having received valid prevote messages for the proposed block from $f + 1$ validators. +These prevotes don't even need to belong to the same round, although they need to be for the current height. +We decided not to go this far in the modifications to CometBFT for two reasons: + +* It is uncertain what practical advantages it would bring. +* It would require new custom data structures to keep track of prevotes for a block across rounds, + adding complexity to our implementation. + +### On Crash-Recovery + +Applications that opt for eventual coherence because their `ProcessProposal` implementation can be non-deterministic, +may encounter an additional problem for recovering nodes. +When replaying messages for the unfinished consensus, they may run `ProcessProposal` twice for the same height and round: +one before the crash and one after the crash. +Since `ProcessProposal` can now be non-deterministic, it is possible that both executions produce different outputs. + +This problem is analogous to the one already identified for `PrepareProposal`, which can always be non-deterministic, +and is captured in [#1035][1035]. +So, similarly to `PrepareProposal`, the current CometBFT implementation of the `PrivValidator` +includes a double-signing protection mechanism that will prevent the recovering node from sending conflicting messages +for the same height, round, and step. +This mechanism will drop any prevote message resulting from `ProcessProposal` that doesn't match a previously sent +prevote message for the same height and round. + +Until [#1035][1035] is addressed, this is considered a good enough solution in our implementation, +both for `PrepareProposal`, and for `ProcessProposal` implementations with non-determinism. + +## Conclusion + +This document has explored the possibility of relaxing the coherence and determinism properties +of the ABCI 1.0 (and 2.0) specification affecting `PrepareProposal` and `ProcessProposal` +for a class of applications that cannot guarantee them. + +We first weakened the _validity_ property of the consensus specification +in a way that keeps the overall consensus specification strong enough to be relevant. +We then proposed a weaker coherence property for ABCI 1.0 (and 2.0) that can replace the original +coherence and determinism properties related to `PrepareProposal` and `ProcessProposal`. +The new property is useful for applications that cannot fulfill the original properties +but can fulfill the new one. +Finally, we explained how to modify the Tendermint consensus algorithm, implemented in CometBFT, +to guarantee the consensus _termination_ property for applications that fulfill the new property. + +In this document, we have not formally proven that the changes we made to the algorithm, +combined with an application fulfilling weak validity, guarantee consensus properties +replacing _validity_ by _weak validity_. We plan to do this as an extension to this RFC. + +Additionally, we have not tackled the problem of applications that cannot fulfill coherence and determinism properties +that refer to vote extensions in the ABCI 2.0 specification. +We leave this as future work. + +## References + +* [ABCI 1.0 specification][abci-spec] +* [Tendermint algorithm][arxiv] +* [Issue #1171][1171] +* [Issue #1174][1174] +* [Issue #1230][1230] +* [Issue #1035][1035] +* Going further in removing `valid(v)` check: [first comment][valid-further1], [second comment][valid-further2] + +[abci-spec]: https://github.com/cometbft/cometbft/blob/main/spec/abci/abci++_app_requirements.md#formal-requirements +[arxiv]: https://arxiv.org/abs/1807.04938 +[1171]: https://github.com/cometbft/cometbft/issues/1171 +[1174]: https://github.com/cometbft/cometbft/issues/1174 +[1230]: https://github.com/cometbft/cometbft/issues/1230 +[1035]: https://github.com/cometbft/cometbft/issues/1035 +[valid-further1]: https://github.com/cometbft/cometbft/issues/1230#issuecomment-1671233308 +[valid-further2]: https://github.com/cometbft/cometbft/pull/1391#pullrequestreview-1641521760 \ No newline at end of file diff --git a/docs/references/rfc/rfc-106-separate-stateful-methods.md b/docs/references/rfc/rfc-106-separate-stateful-methods.md new file mode 100644 index 00000000000..673771e9363 --- /dev/null +++ b/docs/references/rfc/rfc-106-separate-stateful-methods.md @@ -0,0 +1,67 @@ +# RFC 106: Separation of non-idempotent methods in data companion API + +## Changelog + +- 2023-10-27: Initial revision (@mzabaluev) + +## Abstract + +[ADR 101] defined gRPC APIs to retrieve information on blocks and +block execution results for a data companion. As a special case, the caller +can specify the height parameter of 0 to retrieve data on the latest block +known to the node. In the process of implementation however, the developers +thought it necessary to also define special methods for this case. To reduce +potential for mistaken use and separate the time-dependent processing of the +"get latest" requests, we propose to eliminate the special case in the +"get by height" methods, making them idempotent. The use case for "get latest" +also needs to be scrutinized here. + +[ADR 101]: https://github.com/cometbft/cometbft/blob/main/docs/architecture/adr-101-data-companion-pull-api.md + +## Background + +In process of implementing ADR 101, convenience methods were added to retrieve +data on the latest block: +`GetLatest` to `BlockService` ([#1209]) and +`GetLatestBlockResults` to `BlockResultsService` ([#1168]) + +[#1209]: https://github.com/cometbft/cometbft/pull/1209 +[#1168]: https://github.com/cometbft/cometbft/pull/1168 + +The special treatment of the height value of 0 in `GetByHeight` and +`GetBlockResults` has been seemingly forgotten. + +### References + +* [Discussion](https://github.com/cometbft/cometbft/pull/1533#discussion_r1370861999) + on complications arising from the additional methods in + proto cleanup work for [#1530](https://github.com/cometbft/cometbft/issues/1530). + +## Discussion + +In this case, the changes driven by practicalities of implementation actually +highlight the different use cases and semantics for the respective methods. +`GetByHeight` (with a valid height) returns the same data for the same input +and so the responses can be cached at the client side, while the response +of `GetLatest` varies with time. It's also easy to erroneously use 0 as the +actual requested height in workflows using `GetByHeight` and process the result +to some ill effects down the road, rather than be stopped by a timely failure. + +For these reasons, it seems better to cleanly separate the two use cases and +remove the documentation language about the height parameter of 0 as the special +case to retrieve the latest value. Furthermore, the usefulness of the +non-idempotent "get latest block data" API for a data companion +(other than the `GetLatestHeight` stream subscription used to follow the +progress of the chain) has never been discussed or demonstrated. +If this was only a "nice to throw in" idea, perhaps it's better to remove +these methods until the need for them becomes apparent. + +## Proposed actions + +* Remove the following gRPC methods: + - `GetLatest` from `BlockService`; + - `GetLatestBlockResults` from `BlockResultsService`. +* Change the documentation for the `GetByHeight` and `GetBlockResults` methods + to not treat the height parameter of 0 as a special case. +* Revise the specifications in ADR-101 to remove the special treatment of + the height value 0. diff --git a/docs/references/rfc/rfc-107-event-observer.md b/docs/references/rfc/rfc-107-event-observer.md new file mode 100644 index 00000000000..98599d02443 --- /dev/null +++ b/docs/references/rfc/rfc-107-event-observer.md @@ -0,0 +1,240 @@ +# RFC 107: Internal Signalling Using Event Observers + +## Changelog + +- 2023-07-24: First draft (@thanethomson) + +## Abstract + +The overall problem follows from that discussed in [\#1055] and [RFC 104]: +CometBFT is difficult to reason about and change in part due to the complexity +of the internal interaction between different reactors/services. + +RFC 104 explored and ruled out the possibility of employing a loosely coupled +model like the [Actor] model. This RFC explores the possibility of a simpler, +more tightly coupled model with a range of benefits compared to the actor model +and what is currently implemented. It is possible that this would also help +simplify testing, since the tests in CometBFT are the biggest users (by volume) +of the current event bus subsystem. + +## Background + +Various design patterns are potentially useful in addressing the problem of +coupling of concurrent components in a system like CometBFT. The [Observer +Pattern], for instance, is implicitly implemented in the [`EventBus`] in +CometBFT, but in a very loosely coupled manner analogous to how it is +implemented in the Actor model. Such loosely coupled approaches are generally +better suited for cases where coupling between components needs to adapt at +runtime, but this is not the case for CometBFT - all impactful coupling happens +at compile time. This points to the possibility that this pattern is +inappropriately applied, except in the case of the WebSocket-based event +subscriptions. + +Another alternative is possible within CometBFT if one wants to access +information from other reactors/services: the [`Switch`] allows developers to +look up reactors, at runtime, and access methods directly on those reactors. +This is again an inappropriate pattern because all lookups are hard-coded, and +reactors/services are not dynamically created/destroyed at runtime. + +This suggests that a different approach is necessary for cross-component +interaction - ideally one which provides more robust compile-time guarantees +than the current ones. + +## Discussion + +A more type-safe, understandable Observer pattern is proposed here than what +currently exists in CometBFT. For example, in the consensus state there are many +places where events are published via the event bus, e.g.: + +- +- +- +- etc. + +All of these event publishing methods, not only for consensus state but for +other types of event publishers, are defined on this central `EventBus` type, +which seems to signal that its functionality should be decentralized. + +### Strongly Typed Event Observer + +A simple alternative pattern here would be to define an **event observer** +interface for every major component of the system capable of producing events. +For consensus state, this may end up looking something like: + +```golang +package consensus + +// StateObserver is specific to the consensus.State struct, and all of its +// methods are called from within consensus.State instead of using an "event +// bus". This allows for greater compile-time guarantees through doing away with +// the generic pub/sub mechanism in the event bus. +// +// Note how all methods are infallible (i.e. they do not return any errors). +// This is functionally equivalent to the fire-and-forget pattern implemented by +// the event bus. +// +// Also note how method names are prefixed by the name of the relevant producer +// of events (in this case "ConsensusState", corresponding to the +// consensus.State struct). This is intentional to allow composition of +// observers of multiple different components without function names clashing. +// +// Finally, given that this is just straightforward Go, it is up to either the +// caller or the callee to decide how to handle the concurrency of certain +// events. The event bus approach, by contrast, is always concurrent and relies +// on Go channels, which could end up filling up and causing back-pressure into +// the caller (already observed in slow WebSocket subscribers). +type StateObserver interface { + ConsensusStateNewRoundStep(ev EventDataRoundState) + ConsensusStateTimeoutPropose(ev EventDataRoundState) + ConsensusStateTimeoutWait(ev EventDataRoundState) + // ... +} +``` + +And on `consensus.State` one could easily either supply such an observer in the +constructor, or define a new method that allows one to set the observer, e.g.: + +```golang +package consensus + +func (cs *State) SetObserver(obs StateObserver) { + cs.observer = obs +} +``` + +Then, instead of publishing events via the event bus, one would simply do the +following: + +```diff +- if err := cs.eventBus.PublishEventNewRoundStep(rs); err != nil { +- cs.Logger.Error("failed publishing new round step", "err", err) +- } ++ // Notify the observer ++ cs.observer.ConsensusStateNewRoundStep(rs) +``` + +### Comparing "Subscription" Interfaces + +The `EventBus` offers two slightly different subscription mechanisms for events, +both of which rely on Go channels under the hood for their implementation. + +- [`Subscribe`] +- [`SubscribeUnbuffered`] + +The observer pattern proposed in this RFC can facilitate both patterns and more, +given that one has the option of intervening synchronously in a blocking way +when the "publisher" calls the observer event handler. Using the proposed +observer pattern, it is up to either the publisher or the observer to implement +their own concurrency. + +### Fanout Observers + +How then does one simulate the same sort of pub/sub functionality that the +`EventBus` provides using this approach? Where this sort of behaviour is +absolutely necessary, it is trivial to build a "fanout" observer that implements +this interface, e.g.: + +```golang +type StateFanoutObserver struct { + observers []StateObserver +} + +func NewStateFanoutObserver(observers ...StateObserver) *StateFanoutObserver { + return &StateFanoutObserver{ + observers: observers, + } +} + +func (o *StateFanoutObserver) ConsensusStateNewRoundStep(ev EventDataRoundStep) { + for _, obs := range o.observers { + obs.ConsensusStateNewRoundStep(ev) + } +} + +// ... +``` + +### Testing + +Many tests in the CometBFT codebase rely heavily on subscribing to specific +events directly via the event bus. This can easily be accomplished using the +approach described in the [Fanout Observers](#fanout-observers) section: + +```golang +state.SetObserver( + NewStateFanoutObserver( + // An observer specifically for use during testing. + newTestStateObserver(), + // ... other observers here that would be used in production + ), +) +``` + +One could easily also define an ergonomic observer type that would allow inline +definition and overriding of only specific event handlers: + +```golang +type testObserver struct { + newRoundStep func(EventDataRoundState) + timeoutPropose func(EventDataRoundState) + // ... +} + +func (o *testObserver) ConsensusStateNewRoundStep(ev EventDataRoundState) { + if o.newRoundStep != nil { + o.newRoundStep(ev) + } +} + +// ... + +func TestCustomObserver(t *testing.T) { + testObs := &testObserver{} + testObs.newRoundStep = func(ev EventDataRoundState) { + // Custom code here called upon new round step + } + // ... +} +``` + +### Event Subscription + +The current WebSocket-based event subscription mechanism is envisaged to go away +at some point in future, and there is no other mechanism by which external +observers can subscribe to events. + +[ADR 101], however, provides a more general alternative through which +integrators can gain access to event data from outside of the node. Once ADR 101 +has been implemented, the whole WebSocket-based interface could be removed. + +### Pros and Cons + +The benefits of the proposed approach include: + +- Greater compile-time correctness guarantees +- Code becomes easier to reason about, since one can easily follow the call + chain for certain events using one's IDE instead of needing to search the + codebase for subscriptions to certain events +- Easier to test +- Does away with needing to access internal/private `eventBus` variables within + reactors/state from tests ([example][test-eventbus-access]) +- Splits event generation and handling out into a per-package responsibility, + more cleanly separating and modularizing the codebase + +The drawbacks of the proposed approach include: + +- Potentially involves writing more code (volume-wise) than what is currently + present, although the new code would be simpler +- Concurrency concerns need to be reasoned about carefully, as back-pressure is + still possible depending on how observers are implemented + +[\#1055]: https://github.com/cometbft/cometbft/issues/1055 +[RFC 104]: rfc-104-actor-model.md +[Actor]: https://en.wikipedia.org/wiki/Actor_model +[Observer Pattern]: https://en.wikipedia.org/wiki/Observer_pattern +[`EventBus`]: https://github.com/cometbft/cometbft/blob/b23ef56f8e6d8a7015a7f816a61f2e53b0b07b0d/types/event_bus.go#L33 +[`Switch`]: https://github.com/cometbft/cometbft/blob/b23ef56f8e6d8a7015a7f816a61f2e53b0b07b0d/p2p/switch.go#L70 +[test-eventbus-access]: https://github.com/cometbft/cometbft/blob/091a1f312e5f2f4b183fab1d57d729a6c478ff1f/consensus/mempool_test.go#L40 +[ADR 101]: https://github.com/cometbft/cometbft/issues/574 +[`Subscribe`]: https://github.com/cometbft/cometbft/blob/a9deb305e51278c25ad92b249caa092d24c5fc29/types/event_bus.go#L75 +[`SubscribeUnbuffered`]: https://github.com/cometbft/cometbft/blob/a9deb305e51278c25ad92b249caa092d24c5fc29/types/event_bus.go#L86 diff --git a/docs/rfc/rfc-template.md b/docs/references/rfc/rfc-template.md similarity index 100% rename from docs/rfc/rfc-template.md rename to docs/references/rfc/rfc-template.md diff --git a/docs/references/rfc/tendermint-core/README.md b/docs/references/rfc/tendermint-core/README.md new file mode 100644 index 00000000000..014f04d9ad8 --- /dev/null +++ b/docs/references/rfc/tendermint-core/README.md @@ -0,0 +1,42 @@ +--- +order: 1 +parent: + order: false +--- + +# Tendermint Core Requests for Comments + +This document serves as a historical reference for all RFCs that were logged +during the development of Tendermint Core. + +This list is frozen as-is, and new RFCs should be added [here](../). + +## Table of Contents + +- [RFC-000: P2P Roadmap](rfc-000-p2p-roadmap.rst) +- [RFC-001: Storage Engines](rfc-001-storage-engine.rst) +- [RFC-002: Interprocess Communication](rfc-002-ipc-ecosystem.md) +- [RFC-003: Performance Taxonomy](rfc-003-performance-questions.md) +- [RFC-004: E2E Test Framework Enhancements](rfc-004-e2e-framework.rst) +- [RFC-005: Event System](rfc-005-event-system.rst) +- [RFC-006: Event Subscription](rfc-006-event-subscription.md) +- [RFC-007: Deterministic Proto Byte Serialization](rfc-007-deterministic-proto-bytes.md) +- [RFC-008: Don't Panic](rfc-008-do-not-panic.md) +- [RFC-009: Consensus Parameter Upgrades](rfc-009-consensus-parameter-upgrades.md) +- [RFC-010: P2P Light Client](rfc-010-p2p-light-client.rst) +- [RFC-011: Delete Gas](rfc-011-delete-gas.md) +- [RFC-012: Event Indexing Revisited](rfc-012-custom-indexing.md) +- [RFC-013: ABCI++](rfc-013-abci++.md) +- [RFC-014: Semantic Versioning](rfc-014-semantic-versioning.md) +- [RFC-015: ABCI++ Tx Mutation](rfc-015-abci++-tx-mutation.md) +- [RFC-016: Node Architecture](rfc-016-node-architecture.md) +- [RFC-017: ABCI++ Vote Extension Propagation](rfc-017-abci++-vote-extension-propag.md) +- [RFC-018: BLS Signature Aggregation Exploration](rfc-018-bls-agg-exploration.md) +- [RFC-019: Configuration File Versioning](rfc-019-config-version.md) +- [RFC-020: Onboarding Projects](rfc-020-onboarding-projects.rst) +- [RFC-021: The Future of the Socket Protocol](rfc-021-socket-protocol.md) +- [RFC-023: Semi-permanent Testnet](rfc-023-semi-permanent-testnet.md) +- [RFC-024: Block Structure Consolidation](rfc-024-block-structure-consolidation.md) +- [RFC-025: Application Defined Transaction Storage](rfc-025-support-app-side-mempool.md) +- [RFC-026: Banning peers based on ResponseCheckTx](rfc-026-p2p-bad-peers-checktx.md) +- [RFC-027: P2P Message Bandwidth Report](rfc-027-p2p-message-bandwidth-report.md) diff --git a/docs/rfc/tendermint-core/images/abci++.png b/docs/references/rfc/tendermint-core/images/abci++.png similarity index 100% rename from docs/rfc/tendermint-core/images/abci++.png rename to docs/references/rfc/tendermint-core/images/abci++.png diff --git a/docs/rfc/tendermint-core/images/abci.png b/docs/references/rfc/tendermint-core/images/abci.png similarity index 100% rename from docs/rfc/tendermint-core/images/abci.png rename to docs/references/rfc/tendermint-core/images/abci.png diff --git a/docs/rfc/tendermint-core/images/node-dependency-tree.svg b/docs/references/rfc/tendermint-core/images/node-dependency-tree.svg similarity index 100% rename from docs/rfc/tendermint-core/images/node-dependency-tree.svg rename to docs/references/rfc/tendermint-core/images/node-dependency-tree.svg diff --git a/docs/rfc/tendermint-core/images/receive-rate-all.png b/docs/references/rfc/tendermint-core/images/receive-rate-all.png similarity index 100% rename from docs/rfc/tendermint-core/images/receive-rate-all.png rename to docs/references/rfc/tendermint-core/images/receive-rate-all.png diff --git a/docs/rfc/tendermint-core/images/send-rate-all.png b/docs/references/rfc/tendermint-core/images/send-rate-all.png similarity index 100% rename from docs/rfc/tendermint-core/images/send-rate-all.png rename to docs/references/rfc/tendermint-core/images/send-rate-all.png diff --git a/docs/rfc/tendermint-core/images/top-3-percent-receive.png b/docs/references/rfc/tendermint-core/images/top-3-percent-receive.png similarity index 100% rename from docs/rfc/tendermint-core/images/top-3-percent-receive.png rename to docs/references/rfc/tendermint-core/images/top-3-percent-receive.png diff --git a/docs/rfc/tendermint-core/images/top-3-percent-send.png b/docs/references/rfc/tendermint-core/images/top-3-percent-send.png similarity index 100% rename from docs/rfc/tendermint-core/images/top-3-percent-send.png rename to docs/references/rfc/tendermint-core/images/top-3-percent-send.png diff --git a/docs/rfc/tendermint-core/rfc-000-p2p-roadmap.rst b/docs/references/rfc/tendermint-core/rfc-000-p2p-roadmap.rst similarity index 100% rename from docs/rfc/tendermint-core/rfc-000-p2p-roadmap.rst rename to docs/references/rfc/tendermint-core/rfc-000-p2p-roadmap.rst diff --git a/docs/rfc/tendermint-core/rfc-001-storage-engine.rst b/docs/references/rfc/tendermint-core/rfc-001-storage-engine.rst similarity index 100% rename from docs/rfc/tendermint-core/rfc-001-storage-engine.rst rename to docs/references/rfc/tendermint-core/rfc-001-storage-engine.rst diff --git a/docs/rfc/tendermint-core/rfc-002-ipc-ecosystem.md b/docs/references/rfc/tendermint-core/rfc-002-ipc-ecosystem.md similarity index 100% rename from docs/rfc/tendermint-core/rfc-002-ipc-ecosystem.md rename to docs/references/rfc/tendermint-core/rfc-002-ipc-ecosystem.md diff --git a/docs/rfc/tendermint-core/rfc-003-performance-questions.md b/docs/references/rfc/tendermint-core/rfc-003-performance-questions.md similarity index 100% rename from docs/rfc/tendermint-core/rfc-003-performance-questions.md rename to docs/references/rfc/tendermint-core/rfc-003-performance-questions.md diff --git a/docs/rfc/tendermint-core/rfc-004-e2e-framework.rst b/docs/references/rfc/tendermint-core/rfc-004-e2e-framework.rst similarity index 99% rename from docs/rfc/tendermint-core/rfc-004-e2e-framework.rst rename to docs/references/rfc/tendermint-core/rfc-004-e2e-framework.rst index 7c7b96fc8db..bd525718e9b 100644 --- a/docs/rfc/tendermint-core/rfc-004-e2e-framework.rst +++ b/docs/references/rfc/tendermint-core/rfc-004-e2e-framework.rst @@ -157,7 +157,7 @@ system outside of the process logs. When a test network stalls or fails developers should be able to quickly and easily get a sense of the state of the network and all nodes. -Improvements in persuit of this goal, include functionality that would help +Improvements in pursuit of this goal, include functionality that would help node operators in production environments by improving the quality and utility of the logging messages and other reported metrics, but also provide some tools to collect and aggregate this data for developers in the context of test @@ -199,7 +199,7 @@ interesting to engage with. These could include dimensions, such as: - As a flavor or mult-version testing, include upgrade testing, to build confidence in migration code and procedures. -- Additional test applications, particularly practical-type applciations +- Additional test applications, particularly practical-type applications including some that use gaiad and/or the cosmos-sdk. Test-only applications that simulate other kinds of applications (e.g. variable application operation latency.) diff --git a/docs/rfc/tendermint-core/rfc-005-event-system.rst b/docs/references/rfc/tendermint-core/rfc-005-event-system.rst similarity index 98% rename from docs/rfc/tendermint-core/rfc-005-event-system.rst rename to docs/references/rfc/tendermint-core/rfc-005-event-system.rst index b70ee6c05e2..2eb302dbaf3 100644 --- a/docs/rfc/tendermint-core/rfc-005-event-system.rst +++ b/docs/references/rfc/tendermint-core/rfc-005-event-system.rst @@ -71,7 +71,7 @@ Changes to Published Events As part of this process, the Tendermint team should do a study of the existing event types and ensure that there are viable production use cases for subscriptions to all event types. Instinctively it seems plausible that some -of the events may not be useable outside of tendermint, (e.g. ``TimeoutWait`` +of the events may not be usable outside of tendermint, (e.g. ``TimeoutWait`` or ``NewRoundStep``) and it might make sense to remove them. Certainly, it would be good to make sure that we don't maintain infrastructure for unused or un-useful message indefinitely. diff --git a/docs/rfc/tendermint-core/rfc-006-event-subscription.md b/docs/references/rfc/tendermint-core/rfc-006-event-subscription.md similarity index 99% rename from docs/rfc/tendermint-core/rfc-006-event-subscription.md rename to docs/references/rfc/tendermint-core/rfc-006-event-subscription.md index 0e03c119120..1da41520268 100644 --- a/docs/rfc/tendermint-core/rfc-006-event-subscription.md +++ b/docs/references/rfc/tendermint-core/rfc-006-event-subscription.md @@ -196,8 +196,8 @@ mutually exclusive. [rpc-service]: https://docs.tendermint.com/v0.34/rpc/ [rpc-methods]: https://github.com/tendermint/tendermint/blob/main/rpc/core/routes.go#L12 -[events]: ./rfc-005-event-system.rst -[rpc-transport]: ./rfc-002-ipc-ecosystem.md#rpc-transport +[events]: rfc-005-event-system.rst +[rpc-transport]: rfc-002-ipc-ecosystem.md#rpc-transport [ws]: https://datatracker.ietf.org/doc/html/rfc6455 [json-response]: https://www.jsonrpc.org/specification#response_object [json-notify]: https://www.jsonrpc.org/specification#notification diff --git a/docs/rfc/tendermint-core/rfc-007-deterministic-proto-bytes.md b/docs/references/rfc/tendermint-core/rfc-007-deterministic-proto-bytes.md similarity index 99% rename from docs/rfc/tendermint-core/rfc-007-deterministic-proto-bytes.md rename to docs/references/rfc/tendermint-core/rfc-007-deterministic-proto-bytes.md index c1521753bc1..3c7f11c2541 100644 --- a/docs/rfc/tendermint-core/rfc-007-deterministic-proto-bytes.md +++ b/docs/references/rfc/tendermint-core/rfc-007-deterministic-proto-bytes.md @@ -97,7 +97,7 @@ data structure that the digital signature signed using the process's local data. 2. Reordered all message fields to be in tag-sorted order. Tag-sorting top-level fields will place all fields of the same tag in a adjacent -to eachother within the serialized representation. +to each other within the serialized representation. 3. Reordered the contents of all `repeated` fields to be in lexicographically sorted order. diff --git a/docs/rfc/tendermint-core/rfc-008-do-not-panic.md b/docs/references/rfc/tendermint-core/rfc-008-do-not-panic.md similarity index 97% rename from docs/rfc/tendermint-core/rfc-008-do-not-panic.md rename to docs/references/rfc/tendermint-core/rfc-008-do-not-panic.md index ec8c08f5e71..1108c479866 100644 --- a/docs/rfc/tendermint-core/rfc-008-do-not-panic.md +++ b/docs/references/rfc/tendermint-core/rfc-008-do-not-panic.md @@ -26,7 +26,7 @@ reexamine our use of panics, and largely where panics happen in the code base. There are still some situations where panics are acceptable and -desireable, but it's important that Tendermint, as a project, comes to +desirable, but it's important that Tendermint, as a project, comes to consensus--perhaps in the text of this document--on the situations where it is acceptable to panic. @@ -42,7 +42,7 @@ where it is acceptable to panic. #### Initialization -It is unambiguously safe (and desireable) to panic in `init()` +It is unambiguously safe (and desirable) to panic in `init()` functions in response to any kind of error. These errors are caught by tests, and occur early enough in process initialization that they won't cause unexpected runtime crashes. diff --git a/docs/rfc/tendermint-core/rfc-009-consensus-parameter-upgrades.md b/docs/references/rfc/tendermint-core/rfc-009-consensus-parameter-upgrades.md similarity index 100% rename from docs/rfc/tendermint-core/rfc-009-consensus-parameter-upgrades.md rename to docs/references/rfc/tendermint-core/rfc-009-consensus-parameter-upgrades.md diff --git a/docs/rfc/tendermint-core/rfc-010-p2p-light-client.rst b/docs/references/rfc/tendermint-core/rfc-010-p2p-light-client.rst similarity index 100% rename from docs/rfc/tendermint-core/rfc-010-p2p-light-client.rst rename to docs/references/rfc/tendermint-core/rfc-010-p2p-light-client.rst diff --git a/docs/rfc/tendermint-core/rfc-011-delete-gas.md b/docs/references/rfc/tendermint-core/rfc-011-delete-gas.md similarity index 100% rename from docs/rfc/tendermint-core/rfc-011-delete-gas.md rename to docs/references/rfc/tendermint-core/rfc-011-delete-gas.md diff --git a/docs/rfc/tendermint-core/rfc-012-custom-indexing.md b/docs/references/rfc/tendermint-core/rfc-012-custom-indexing.md similarity index 98% rename from docs/rfc/tendermint-core/rfc-012-custom-indexing.md rename to docs/references/rfc/tendermint-core/rfc-012-custom-indexing.md index 489bcccc1d2..83d03a32207 100644 --- a/docs/rfc/tendermint-core/rfc-012-custom-indexing.md +++ b/docs/references/rfc/tendermint-core/rfc-012-custom-indexing.md @@ -56,7 +56,7 @@ a datum published to or received from the pubsub bus, and **ABCI event** or **Indexing** in this context means recording the association between certain ABCI metadata and the blocks or transactions they're attached to. The ABCI metadata typically carry application-specific details like sender and recipient -addresses, catgory tags, and so forth, that are not part of consensus but are +addresses, category tags, and so forth, that are not part of consensus but are used by UI tools to find and display transactions of interest. The consensus node records the blocks and transactions as part of its block @@ -128,7 +128,7 @@ proprietary indexer. These include: are reported to a custom indexer. - The interface requires the implementation to define methods for the legacy - search and query API. This requirement comes from the integation with the + search and query API. This requirement comes from the integration with the [event subscription RPC API][event-rpc], but actually supporting these methods is not trivial. @@ -199,7 +199,7 @@ Inevitably, a question will arise whether we could implement both strategies and toggle between them with a flag. That would be a worst-case scenario, requiring us to maintain the complexity of two very-different operational concerns. If our goal is that Tendermint should be as simple, efficient, and -trustworthy as posible, there is not a strong case for making these options +trustworthy as possible, there is not a strong case for making these options configurable: We should pick a side and commit to it. ### Design Principles diff --git a/docs/rfc/tendermint-core/rfc-013-abci++.md b/docs/references/rfc/tendermint-core/rfc-013-abci++.md similarity index 96% rename from docs/rfc/tendermint-core/rfc-013-abci++.md rename to docs/references/rfc/tendermint-core/rfc-013-abci++.md index 6e83c9aa227..cd031c2110f 100644 --- a/docs/rfc/tendermint-core/rfc-013-abci++.md +++ b/docs/references/rfc/tendermint-core/rfc-013-abci++.md @@ -155,7 +155,7 @@ There is data that the app needs the validator to sign over in their vote, and t - Unsigned app vote data: A use case of this is if you wanted validator backed oracles, where each validator independently signs some oracle data in their vote, and the median of these values is used on chain. Thus we leverage consensus' signing process for convenience, and use that same key to sign the oracle data. - Self-authenticating vote data: A use case of this is in threshold random beacons. Every validator produces a threshold beacon share. This threshold beacon share can be verified by any node in the network, given the share and the validators public key (which is not the same as its consensus public key). However, this decryption share will not make it into the subsequent block's header. They will be aggregated by the subsequent block proposer to get a single random beacon value that will appear in the subsequent block's header. Everyone can then verify that this aggregated value came from the requisite threshold of the validator set, without increasing the bandwidth for full nodes or light clients. To achieve this goal, the self-authenticating vote data cannot be signed over by the consensus key along with the rest of the vote, as that would require all full nodes & light clients to know this data in order to verify the vote. -The `CanonicalVote` struct will acommodate the `UnsignedAppVoteData` field by adding another string to its encoding, after the `chain-id`. This should not interfere with existing hardware signing integrations, as it does not affect the constant offset for the `height` and `round`, and the vote size does not have an explicit upper bound. (So adding this unsigned app vote data field is equivalent from the HSM's perspective as having a superlong chain-ID) +The `CanonicalVote` struct will accommodate the `UnsignedAppVoteData` field by adding another string to its encoding, after the `chain-id`. This should not interfere with existing hardware signing integrations, as it does not affect the constant offset for the `height` and `round`, and the vote size does not have an explicit upper bound. (So adding this unsigned app vote data field is equivalent from the HSM's perspective as having a superlong chain-ID) **RFC**: Please comment if you think it will be fine to have elongate the message the HSM signs, or if we need to explore pre-hashing the app vote data. @@ -178,11 +178,11 @@ The `Unbatched` header and `rawcommit` will never be broadcasted, they will be c For brevity in exposition above, we did not discuss the trade-offs that may occur in interprocess communication delays that these changs will introduce. These new ABCI methods add more locations where the application must communicate with the consensus engine. -In most configurations, we expect that the consensus engine and the application will be either statically or dynamically linked, so all communication is a matter of at most adjusting the memory model the data is layed out within. -This memory model conversion is typically considered negligible, as delay here is measured on the order of microseconds at most, whereas we face milisecond delays due to cryptography and network overheads. +In most configurations, we expect that the consensus engine and the application will be either statically or dynamically linked, so all communication is a matter of at most adjusting the memory model the data is laid out within. +This memory model conversion is typically considered negligible, as delay here is measured on the order of microseconds at most, whereas we face millisecond delays due to cryptography and network overheads. Thus we ignore the overhead in the case of linked libraries. -In the case where the consensus engine and the application are ran in separate processes, and thus communicate with a form of Inter-process communication (IPC), the delays can easily become on the order of miliseconds based upon the data sent. Thus its important to consider whats happening here. +In the case where the consensus engine and the application are ran in separate processes, and thus communicate with a form of Inter-process communication (IPC), the delays can easily become on the order of milliseconds based upon the data sent. Thus its important to consider what's happening here. We go through this phase by phase. ##### Prepare proposal IPC overhead diff --git a/docs/rfc/tendermint-core/rfc-014-semantic-versioning.md b/docs/references/rfc/tendermint-core/rfc-014-semantic-versioning.md similarity index 100% rename from docs/rfc/tendermint-core/rfc-014-semantic-versioning.md rename to docs/references/rfc/tendermint-core/rfc-014-semantic-versioning.md diff --git a/docs/rfc/tendermint-core/rfc-015-abci++-tx-mutation.md b/docs/references/rfc/tendermint-core/rfc-015-abci++-tx-mutation.md similarity index 99% rename from docs/rfc/tendermint-core/rfc-015-abci++-tx-mutation.md rename to docs/references/rfc/tendermint-core/rfc-015-abci++-tx-mutation.md index 92d9ed66877..f3bcca0212e 100644 --- a/docs/rfc/tendermint-core/rfc-015-abci++-tx-mutation.md +++ b/docs/references/rfc/tendermint-core/rfc-015-abci++-tx-mutation.md @@ -132,7 +132,7 @@ Malicious nodes will be granted a new vector for censoring transactions. There is no guarantee that a replaced transactions is actually executed at all. A malicious node could censor a transaction by simply listing it as replaced. Honest nodes seeing the replacement would flush the transaction from their mempool -and not execute or propose it it in later blocks. +and not execute or propose it in later blocks. ### Transaction tracking implementations diff --git a/docs/rfc/tendermint-core/rfc-016-node-architecture.md b/docs/references/rfc/tendermint-core/rfc-016-node-architecture.md similarity index 88% rename from docs/rfc/tendermint-core/rfc-016-node-architecture.md rename to docs/references/rfc/tendermint-core/rfc-016-node-architecture.md index 29098d29730..b43e16237f2 100644 --- a/docs/rfc/tendermint-core/rfc-016-node-architecture.md +++ b/docs/references/rfc/tendermint-core/rfc-016-node-architecture.md @@ -7,7 +7,7 @@ ## Abstract -The `node` package is the entry point into the Tendermint codebase, used both by the command line and programatically to create the nodes that make up a network. The package has suffered the most from the evolution of the codebase, becoming bloated as developers clipped on their bits of code here and there to get whatever feature they wanted working. +The `node` package is the entry point into the Tendermint codebase, used both by the command line and programmatically to create the nodes that make up a network. The package has suffered the most from the evolution of the codebase, becoming bloated as developers clipped on their bits of code here and there to get whatever feature they wanted working. The decisions made at the node level have the biggest impact to simplifying the protocols within them, unlocking better internal designs and making Tendermint more intuitive to use and easier to understand from the outside. Work, in minor increments, has already begun on this section of the codebase. This document exists to spark forth the necessary discourse in a few related areas that will help the team to converge on the long term makeup of the node. @@ -19,7 +19,7 @@ The following is a list of points of discussion around the architecture of the n The node object is currently stuffed with every component that possibly exists within Tendermint. In the constructor, all objects are built and interlaid with one another in some awkward dance. My guiding principle is that the node should only be made up of the components that it wants to have direct control of throughout its life. The node is a service which currently has the purpose of starting other services up in a particular order and stopping them all when commanded to do so. However, there are many services which are not direct dependents i.e. the mempool and evidence services should only be working when the consensus service is running. I propose to form more of a hierarchical structure of dependents which forces us to be clear about the relations that one component has to the other. More concretely, I propose the following dependency tree: -![node dependency tree](./images/node-dependency-tree.svg) +![node dependency tree](images/node-dependency-tree.svg) Many of the further discussion topics circle back to this representation of the node. @@ -34,7 +34,7 @@ In a decentralized message passing system, individual services make their decisi Both centralized and decentralized systems rely on the communication of the nodes current height and a judgement on the height of the head of the chain. The latter, working out the head of the chain, is quite a difficult challenge as their is nothing preventing the node from acting maliciously and providing a different height. Currently both blocksync, consensus (and to a certain degree statesync), have parallel systems where peers communicate their height. This could be streamlined with the consensus (or even the p2p layer), broadcasting peer heights and either the node or the other state advancing mechanisms acting accordingly. -Currently, when a node starts, it turns on every service that it is attached to. This means that while a node is syncing up by requesting blocks, it is also receiving transactions and votes, as well as snapshot and block requests. This is a needless use of bandwidth. An implementation of an orchestrator, regardless of whether the system is heirachical or not, should look to be able to open and close channels dynamically and effectively broadcast which services it is running. Integrating this with service discovery may also lead to a better serivce to peers. +Currently, when a node starts, it turns on every service that it is attached to. This means that while a node is syncing up by requesting blocks, it is also receiving transactions and votes, as well as snapshot and block requests. This is a needless use of bandwidth. An implementation of an orchestrator, regardless of whether the system is hierarchical or not, should look to be able to open and close channels dynamically and effectively broadcast which services it is running. Integrating this with service discovery may also lead to a better service to peers. The orchestrator allows for some deal of variablity in how a node is constructed. Does it just run blocksync, shadowing the head of the chain and be highly available for querying. Does it rely on state sync at all? An important question that arises from this dynamicism is we ideally want to encourage nodes to provide as much of their resources as possible so that their is a healthy amount of providers to consumers. Do we make all services compulsory or allow for them to be disabled? Arguably it's possible that a user forks the codebase and rips out the blocksync code because they want to reduce bandwidth so this is more a question of how easy do we want to make this for users. @@ -48,7 +48,7 @@ The block executor is an important component that is currently used by both cons ### The Interprocess communication systems: RPC, P2P, ABCI, and Events The schematic supplied above shows the relations between the different services, the node, the block executor, and the storage layer. Represented as colored dots are the components responsible for different roles of interprocess communication (IPC). These components permeate throughout the code base, seeping into most services. What can provide powerful functionality on one hand can also become a twisted vine, creating messy corner cases and convoluting the protocols themselves. A lot of the thinking around -how we want our IPC systens to function has been summarised in this [RFC](./rfc-002-ipc-ecosystem.md). In this section, I'd like to focus the reader on the relation between the IPC and the node structure. An issue that has frequently risen is that the RPC has control of the components where it strikes me as being more logical for the component to dictate the information that is emitted/available and the knobs it wishes to expose. The RPC is also inextricably tied to the node instance and has situations where it is passed pointers directly to the storage engine and other components. +how we want our IPC systems to function has been summarised in this [RFC](rfc-002-ipc-ecosystem.md). In this section, I'd like to focus the reader on the relation between the IPC and the node structure. An issue that has frequently risen is that the RPC has control of the components where it strikes me as being more logical for the component to dictate the information that is emitted/available and the knobs it wishes to expose. The RPC is also inextricably tied to the node instance and has situations where it is passed pointers directly to the storage engine and other components. I am currently convinced of the approach that the p2p layer takes and would like to see other IPC components follow suit. This would mean that the RPC and events system would be constructed in the node yet would pass the adequate methods to register endpoints and topics to the sub components. For example, @@ -62,7 +62,7 @@ func RegisterTopic(name string) EventPublisher type EventPublisher func (context.Context, types.EventData, []abci.Event) ``` -This would give the components control to the information they want to expose and keep all relevant logic within that package. It accomodates more to a dynamic system where services can switch on and off. Each component would also receive access to the logger and metrics system for introspection and debuggability. +This would give the components control to the information they want to expose and keep all relevant logic within that package. It accommodates more to a dynamic system where services can switch on and off. Each component would also receive access to the logger and metrics system for introspection and debuggability. #### IPC Rubric @@ -70,7 +70,7 @@ I'd like to aim to reach a state where we as a team have either an implicit or e Principally, I think we should look to change our language away from what the actual transport is and more towards what it's being used for and to whom. We call it a peer to peer layer and not the underlying tcp connection. In the same way, we should look to split RPC into an operator interface (RPC Internal), a public interface (RPC External) and a bidirectional ABCI. -### Seperation of consumers and suppliers +### Separation of consumers and suppliers When a service such as blocksync is turned on, it automatically begins requesting blocks to verify and apply them as it also tries to serve them to other peers catching up. We should look to distinguish these two aspects: supplying of information and consuming of information in many of these components. More concretely, I'd suggest: diff --git a/docs/rfc/tendermint-core/rfc-017-abci++-vote-extension-propag.md b/docs/references/rfc/tendermint-core/rfc-017-abci++-vote-extension-propag.md similarity index 98% rename from docs/rfc/tendermint-core/rfc-017-abci++-vote-extension-propag.md rename to docs/references/rfc/tendermint-core/rfc-017-abci++-vote-extension-propag.md index 15d08f7badb..fe6c2ee37e9 100644 --- a/docs/rfc/tendermint-core/rfc-017-abci++-vote-extension-propag.md +++ b/docs/references/rfc/tendermint-core/rfc-017-abci++-vote-extension-propag.md @@ -31,7 +31,7 @@ In the [Discussion](#discussion) section, subsection [Solutions Proposed](#solut worded abstracting away from implementation details, whilst subsections [Feasibility of the Proposed Solutions](#feasibility-of-the-proposed-solutions) and [Current Limitations and Possible Implementations](#current-limitations-and-possible-implementations) -analize the viability of one of the proposed solutions in the context of Tendermint's architecture +analyze the viability of one of the proposed solutions in the context of Tendermint's architecture based on reactors. Finally, [Formalization Work](#formalization-work) briefly discusses the work still needed demonstrate the correctness of the chosen solution. @@ -149,7 +149,7 @@ discussions and need to be addressed. They are (roughly) ordered from easiest to If sets *valseth* and *valseth+1* are disjoint, more than *2nh/3* of validators in height *h* should - have actively participated in conensus in *h*. So, as of height *h*, only a minority of validators + have actively participated in consensus in *h*. So, as of height *h*, only a minority of validators in *h* can be lagging behind, although they could all lag behind from *h+1* on, as they are no longer validators, only full nodes. This situation falls under the assumptions of case (h) below. @@ -369,7 +369,7 @@ These are the solutions proposed in discussions leading up to this RFC. At this point, *all* full nodes, including all validators in *valseth+1*, have advanced to height *h+1* believing they are late, and so, expecting the *hypothetical* leading majority of - validators in *valseth+1* to propose for *h+1*. As a result, the blockhain + validators in *valseth+1* to propose for *h+1*. As a result, the blockchain grinds to a halt. A (rather complex) ad-hoc mechanism would need to be carried out by node operators to roll back all validators to the precommit step of height *h*, round *r*, so that they can regenerate @@ -509,7 +509,7 @@ This solution requires a few changes to the consensus reactor: - upon saving the block for a given height in the block store at decision time, save the corresponding extended commit as well - in the catch-up mechanism, when a node realizes that another peer is more than 2 heights - behind, it uses the extended commit (rather than the canoncial commit as done previously) to + behind, it uses the extended commit (rather than the canonical commit as done previously) to reconstruct the precommit votes with their corresponding extensions The changes to the blocksync reactor are more substantial: @@ -525,12 +525,12 @@ The changes to the blocksync reactor are more substantial: The two main drawbacks of this base implementation are: - the increased size taken by the block store, in particular with big extensions -- the increased bandwith taken by the new format of `BlockResponse` +- the increased bandwidth taken by the new format of `BlockResponse` #### Possible Optimization: Pruning the Extended Commit History If we cannot switch from the consensus reactor back to the blocksync reactor we cannot prune the extended commit backlog in the block store without sacrificing the implementation's correctness. The asynchronous -nature of our distributed system model allows a process to fall behing an arbitrary number of +nature of our distributed system model allows a process to fall behind an arbitrary number of heights, and thus all extended commits need to be kept *just in case* a node that late had previously switched to the consensus reactor. @@ -538,7 +538,7 @@ However, there is a possibility to optimize the base implementation. Every time we could prune from the block store all extended commits that are more than *d* heights in the past. Then, we need to handle two new situations, roughly equivalent to cases (h.1) and (h.2) described above. -- (h.1) A node starts from scratch or recovers after a crash. In thisy case, we need to modify the +- (h.1) A node starts from scratch or recovers after a crash. In this case, we need to modify the blocksync reactor's base implementation. - when receiving a `BlockResponse` message, it MUST accept that the extended commit set to `nil`, - when sending a `BlockResponse` message, if the block store contains the extended commit for that diff --git a/docs/rfc/tendermint-core/rfc-018-bls-agg-exploration.md b/docs/references/rfc/tendermint-core/rfc-018-bls-agg-exploration.md similarity index 99% rename from docs/rfc/tendermint-core/rfc-018-bls-agg-exploration.md rename to docs/references/rfc/tendermint-core/rfc-018-bls-agg-exploration.md index 6de7510ab47..de06e09f7ac 100644 --- a/docs/rfc/tendermint-core/rfc-018-bls-agg-exploration.md +++ b/docs/references/rfc/tendermint-core/rfc-018-bls-agg-exploration.md @@ -60,7 +60,7 @@ elliptic curves over a finite field. With some original curve, you can define tw `G1` and `G2` which are points of the original curve _modulo_ different values. Finally, you define a third group `Gt`, where points from `G1` and `G2` satisfy the property of bilinearity with `Gt`. In this scheme, the function `e` takes -as inputs points in `G1` and `G2` and outputs values in `Gt`. Succintly, given +as inputs points in `G1` and `G2` and outputs values in `Gt`. Succinctly, given some point `P` in `G1` and some point `Q` in `G1`, `e(P, Q) = C` where `C` is in `Gt`. You can efficiently compute the mapping of points in `G1` and `G2` into `Gt`, but you cannot efficiently determine what points were summed and paired to @@ -102,7 +102,7 @@ BLS signatures have already gained traction within several popular projects. Gossip could be updated to aggregate vote signatures during a consensus round. This appears to be of frankly little utility. Creating an aggregated signature incurs overhead, so frequently re-aggregating may incur a significant -overhead. How costly this is is still subject to further investigation and +overhead. How costly this is still subject to further investigation and performance testing. Even if vote signatures were aggregated before gossip, each validator would still @@ -179,7 +179,7 @@ number of operations used to verify a signature does not grow at all with the number of signatures included in the aggregate signature (as long as the signers signed over the same message data as is the case in Tendermint). -It is worth noting that this would also represent a _degredation_ in signature +It is worth noting that this would also represent a _degradation_ in signature verification time for chains with small validator sets. When batch verifying only 32 signatures, our ed25519 library takes .57 milliseconds, whereas BLS would still require the same 1.5 milliseconds. @@ -232,7 +232,7 @@ instead of the full list of multi-signatures as we have them now. Aggregation requires a specific signature algorithm, and our legacy signing schemes cannot be aggregated. In practice, this means that aggregated signatures could be created for a subset of validators using BLS signatures, and validators -with other key types (such as Ed25519) would still have to be be separately +with other key types (such as Ed25519) would still have to be separately propagated in blocks and votes. #### Many HSMs do not support aggregated signatures diff --git a/docs/rfc/tendermint-core/rfc-019-config-version.md b/docs/references/rfc/tendermint-core/rfc-019-config-version.md similarity index 100% rename from docs/rfc/tendermint-core/rfc-019-config-version.md rename to docs/references/rfc/tendermint-core/rfc-019-config-version.md diff --git a/docs/rfc/tendermint-core/rfc-020-onboarding-projects.rst b/docs/references/rfc/tendermint-core/rfc-020-onboarding-projects.rst similarity index 97% rename from docs/rfc/tendermint-core/rfc-020-onboarding-projects.rst rename to docs/references/rfc/tendermint-core/rfc-020-onboarding-projects.rst index d9f883ca034..7a3b3102cb1 100644 --- a/docs/rfc/tendermint-core/rfc-020-onboarding-projects.rst +++ b/docs/references/rfc/tendermint-core/rfc-020-onboarding-projects.rst @@ -164,7 +164,7 @@ covers some of the background and approach. While the changes are in this project are relatively rote, this will provide exposure to lots of different areas of the codebase as well as insight into -how different areas of the codebase interact with eachother, as well as +how different areas of the codebase interact with each other, as well as experience with the test suites and infrastructure. Implement more Expressive ABCI Applications @@ -173,7 +173,7 @@ Implement more Expressive ABCI Applications Tendermint maintains two very simple ABCI applications (a KV application used for basic testing, and slightly more advanced test application used in the end-to-end tests). Writing an application would provide a new engineer with -useful experiences using Tendermint that mirrors the expierence of downstream +useful experiences using Tendermint that mirrors the experience of downstream users. This is more of an exploratory project, but could include providing common @@ -212,11 +212,11 @@ actionable, most users largely ignore the logging or run at very low verbosity. While the log statements in the code do describe useful events, taken as a whole the system is not particularly tractable, and particularly at the Debug level, not useful. One solution to this problem is to identify log -messages that might be (e.g. increment a counter for certian kinds of errors) +messages that might be (e.g. increment a counter for certain kinds of errors) One approach might be to look at various logging statements, particularly debug statements or errors that are logged but not returned, and see if -they're convertable to counters or other metrics. +they're convertible to counters or other metrics. Expose Metrics to Tests +++++++++++++++++++++++ diff --git a/docs/rfc/tendermint-core/rfc-021-socket-protocol.md b/docs/references/rfc/tendermint-core/rfc-021-socket-protocol.md similarity index 99% rename from docs/rfc/tendermint-core/rfc-021-socket-protocol.md rename to docs/references/rfc/tendermint-core/rfc-021-socket-protocol.md index 4b8fd2ab6d3..cfc714d2283 100644 --- a/docs/rfc/tendermint-core/rfc-021-socket-protocol.md +++ b/docs/references/rfc/tendermint-core/rfc-021-socket-protocol.md @@ -235,7 +235,7 @@ design. essential to avoid it. This is a sound principle, but conflates protocol errors with "mechanical" - errors such as timeouts, resoures exhaustion, failed connections, and so on. + errors such as timeouts, resources exhaustion, failed connections, and so on. Because the protocol has no way to distinguish these conditions, the only way for an application to report an error is to panic or crash. diff --git a/docs/rfc/tendermint-core/rfc-023-semi-permanent-testnet.md b/docs/references/rfc/tendermint-core/rfc-023-semi-permanent-testnet.md similarity index 100% rename from docs/rfc/tendermint-core/rfc-023-semi-permanent-testnet.md rename to docs/references/rfc/tendermint-core/rfc-023-semi-permanent-testnet.md diff --git a/docs/rfc/tendermint-core/rfc-024-block-structure-consolidation.md b/docs/references/rfc/tendermint-core/rfc-024-block-structure-consolidation.md similarity index 99% rename from docs/rfc/tendermint-core/rfc-024-block-structure-consolidation.md rename to docs/references/rfc/tendermint-core/rfc-024-block-structure-consolidation.md index 91dec2d63f5..49f91ed1088 100644 --- a/docs/rfc/tendermint-core/rfc-024-block-structure-consolidation.md +++ b/docs/references/rfc/tendermint-core/rfc-024-block-structure-consolidation.md @@ -304,7 +304,7 @@ _each_ block. We could easily save the value and the height at which the value was updated and construct each block using the data that existed at the time. This document does not make any specific recommendations around storage since -that is likely to change with upcoming improvements to to the database infrastructure. +that is likely to change with upcoming improvements to the database infrastructure. However, it's important to note that removing fields from the block for the purposes of 'saving space' may not be that meaningful. We should instead focus our attention of removing fields from the block that are no longer needed diff --git a/docs/rfc/tendermint-core/rfc-025-support-app-side-mempool.md b/docs/references/rfc/tendermint-core/rfc-025-support-app-side-mempool.md similarity index 100% rename from docs/rfc/tendermint-core/rfc-025-support-app-side-mempool.md rename to docs/references/rfc/tendermint-core/rfc-025-support-app-side-mempool.md diff --git a/docs/references/rfc/tendermint-core/rfc-026-p2p-bad-peers-checktx.md b/docs/references/rfc/tendermint-core/rfc-026-p2p-bad-peers-checktx.md new file mode 100644 index 00000000000..8e6c35167b9 --- /dev/null +++ b/docs/references/rfc/tendermint-core/rfc-026-p2p-bad-peers-checktx.md @@ -0,0 +1,436 @@ +# RFC 26: Banning peers based on ResponseCheckTx + +## Changelog +- Nov 4, 2022: Initial draft (jmalicevic) +- Nov 8, 2022: Updated draft (jmalicevic) +- Nov 11, 2022: Updated based on PR comments (jmalicevic) +- Nov 14, 2022: Updated current peer banning mechanisms (jmalicevic) + +## Abstract + +In Tendermint, nodes receive transactions either from external clients via RPC, +or from their peers via p2p. Upon receiving a transaction, a node runs `CheckTx` on it. This is +an application specific check whose return code with a zero value indicates the transaction +has passed this check, and can be added into the mempool. Any non-zero code indicates the transaction +is not valid. Thus, the main role of `CheckTx` is to, as early as possible, prevent invalid transactions +from entering the mempool. + +Note that there are valid scenarios in which a transaction will not +pass this check (including nodes getting different transactions at different times, meaning some +of them might be obsolete at the time of the check; state changes upon block execution etc.). +However, Tendermint users observed that +there are transactions that can never have been or will never be valid. They thus propose +to introduce a special response code for `CheckTx` to indicate this behaviour, and ban the peers +who gossip such transactions. Additionally, users expressed a need for banning peers who +repeatedly send transactions failing `CheckTx`. + +The main goal of this document is to analyse the cases where peers could be banned when they send +transactions failing `CheckTx`, and provide the exact conditions that a peer and transaction have +to satisfy in order to mark the peer as bad. + +This document will also include a proposal for implementing these changes within the mempool, including +potential changes to the existing mempool logic and implementation. + + +## Background + +This work was triggered by issue [#7918](https://github.com/tendermint/tendermint/issues/7918) and a related +discussion in [#2185](https://github.com/tendermint/tendermint/issues/2185). Additionally, +there was a [proposal](https://github.com/tendermint/tendermint/issues/6523) +to disconnect from peers after they send us transactions that constantly fail `CheckTx`. While +the actual implementation of an additional response code for `CheckTx` is straight forward there +are certain correctness aspects to consider. The questions to answer, along with identified risks will be outlined in +the discussion. + +### Existing issues and concerns + +Before diving into the details, we collected a set of issues opened by various users, arguing for +this behaviour and explaining their needs. + +- Celestia: [blacklisting peers that repeatedly send bad tx](https://github.com/celestiaorg/celestia-core/issues/867) + and investigating how [Tendermint treats large Txs](https://github.com/celestiaorg/celestia-core/issues/243) +- BigChainDb: [Handling proposers who propose bad blocks](https://github.com/bigchaindb/BEPs/issues/84) +- IBC relayers: Nodes allow transactions with a wrong `minGas` transaction and gossip them, and other nodes keep rejecting them. (Problem seen with relayers) + +**Acceptable duplicate transactions** + +Banning peers was also mentioned within [IBC-go](https://github.com/cosmos/ibc-go/issues/853#issuecomment-1032211020). However,the crux of the issue is preventing transactions with duplicate payload. While this is indeed undesired behaviour, this is not considered behaviour that should lead to banning a peer or even disconnecting from him. Duplicate transactions are in this case prevented using an application-specific solution. + +### Current state of mempool/p2p interaction + +Transactions received from a peer are handled within the [`Receive`](https://github.com/tendermint/tendermint/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/reactor.go#L158) routine. + +Currently, the mempool triggers a disconnect from a peer in the case of the following errors: + + - [Unknown message type](https://github.com/tendermint/tendermint/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/reactor.go#L184) + +However, disconnecting from a peer is not the same as banning the peer. The p2p layer will close the connection but +the peer can reconnect without any penalty, and if it as a persistent peer, a reconnect will be initiated +from the node. + +### Current support for peer banning + +The p2p layer implements banning peers by marking them +as bad and removing them from the list of peers to connect to for *at least* a predefined amount of time. This is done by calling the `MarkBad` routine implemented by the `Switch`. If the node does not set the amount of time to be banned, a default value is used. +Note that the timing parameter sets the lower bound for when a peer will be unbanned. +But the p2p layer will only try to connect to banned peers if the node is not sufficiently connected. Thus the node has no +explicit control on when a reconnect attempt will be triggered. + +The application can blacklist peers via ABCI if the +[`filterPeers`](../../spec/abci/abci%2B%2B_app_requirements.md#peer-filtering) +config flag is set, by providing a set of peers to ban to Tendermint. + +If the discussion in this RFC deems a different banning mechanism is needed, +the actual implementation and design of this mechanism will be discussed in a separate RFC. +This mechanism should be generic, designed within the p2p layer and simply provide an interface +for reactors to indicate peers to ban and for how long. It should not involve any mempool +specific design considerations. + +## Discussion + +If this feature is to be implemented we need to clearly define the following: +1. What does banning a peer mean: + 1. A peer can be simply disconnected from. + 2. Peer is disconnected from and banned. + 3. Conditions for the peer to be banned. +2. If `CheckTx` signals a peer should be banned, retrieve the ID of peers to ban. +3. Are there possible attack scenarios or unexpected behaviours by allowing this. + +Any further mentions of `banning` will be agnostic to the actual way banning is implemented by the p2p layer. + + +### 1. What does banning a peer mean + +Tendermint recognizes that peers can accept transactions into their mempool as valid but then when the state changes, they can become invalid. +There are also transactions that are received that could never have been valid (for example due to misconfiguration on one node). +We thus differentiate two scenarios - a) where `CheckTx` fails due to reasons already +known and b) where `CheckTx` deems a transaction could never have been valid. + +For the sake of simplicity , in the remainder of the text we will distinguish the failures due to a) as failures +signaled with `ResponseCheckTx.code = 1` and the failures described in b), failures with `ResponseCheckTx.code > 1`, even though +the way we actually mark them in the end might differ. + +For a), a peer sends transactions that **repeatedly** fail CheckTx with `ResponseCheckTx.code = 1`, and is banned or disconnected from to avoid this. +In this case we need to define what repeatedly means. + +For b) we need to understand what is the potential reason a transaction could never have been valid on one node, but passes `CheckTx` on another node. +We need to understand all the possible scenarios in which this can happen: + +1. What happens if a node is misconfigured and allows, for example, very large transactions into the mempool. +This node would then gossip these transactions and they would always fail on other nodes. +Is this a scenario where we want nodes to disconnect from this peer and ban it but do not consider it malicious? +2. Are all other reasons for this to happen sign of malicious behaviour where a node explicitly lies? How can `CheckTx` pass on a valid node, but fail on another valid node with a `ResponseCheckTx.code > 1`? +If such behaviour is only possible when a peer is malicious, should this peer be punished or banned forever? Note that +we cannot know whether a node is a validator in order for it to be punished. Gossiping this behaviour to other peers pro-actively +also entails a different set of problems with it - how do we know we can trust peers who tell us to ban other peers. For these reasons, understanding the actual reason for these failures can be left for future work. + +For now, we will disconnect and ban the peer regardless of the exact reason a transaction +is considered to never be valid. + +#### **Banning for frequent CheckTx failures** + +If a node sends transactions that fail `CheckTx` but could be valid at some point, a peer should not be banned the first time this happens. +Only if this happens frequently enough should this be considered as spam. To define this behaviour we keep track how many times (`numFailures`) a peer +sent us invalid transactions within a time interval (`lastFailure`). This time interval should be reset every `failureResetInterval`ms. + +For each peer, we should have a separate `numFailures` and `lastFailure` variable. There is no need to have one per transaction. + Whenever a transaction fails, if the `now - lastFailure <= failureResetInterval`, we increment the `numFailures` for this particular peer and set the `lastFailure` to `now`. + Otherwise, we set `lastFailure` to `now` and set `numFailures` to 1. + Once the value for `numFailures` for a peer reaches `maxAllowedFailures`, the peer is disconnected from and banned. + +The reason for this logic is as follows: We deem it acceptable if every now and then a peer sends us an invalid transaction. + But if this happens very frequently, then this behaviour can be considered as spamming and we want to disconnect from the peer. + + **Discussion** + + The problem with supporting this scenario is the definition of the above mentioned parameters. It is very hard to estimate, at the Tendermint level, what these parameters should be. A possible solution is + to allow the application to set these parameters. What is unclear, how will the application know that these parameters are not well set if, due to a bug or network problems, transactions start to fail? +The network could end up with all nodes banning everyone. How would an application developer know to debug this, what to look for? + +A possible solution is to ban peers temporarily. In addition to the question on how long is temporarily, setting specific time limits for banning on a peer basis +is currently not supported by the p2p layer. + +*Banning a peer in case of duplicate transactions* + +Currently, a peer can send the same valid (or invalid) transaction [multiple times](https://github.com/tendermint/tendermint/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/clist_mempool.go#L247). Peers do not +gossip transactions to peers that have sent them that same transaction. But there is no check on whether +a node has already sent the same transaction to this peer before. There is also no check whether the transaction +that is being gossiped is currently valid or not (assumint that invalid transactions could become valid). +The transaction broadcast logic simply loops through the mempool and tries to send the transactions currently in the pool. + +If we want to ban peers based on duplicate transactions, we should either add additional checks for the cases above, or +not ban peers for this behaviour at the moment. It would be useful to gather metrics on how often a peer gossips the same +transaction and whether this is cause of significant traffic. + + +#### **Banning for sending *never-valid* transactions** + +If a transaction fails since it could never have been valid, `CheckTx` returns a `ResponseCheckTx.code` +value greater than 1. In this case, the peer should be disconnected from and banned immediately without keeping count on how often +this has happened. + +The question is whether this transaction should be kept track of in the cache? We can still store it in +the cache so that we don't run `CheckTx` on it again, but if this peer is immediately banned, maybe there is no need +to store its information. + +Now, if we want to differentiate further reasons of why this transaction is sent to a node (whether it is a sign of malice or not), +we might need more information on the actual reason for rejection. This could be done by an additional set of response codes provided by the application. + +### 2. Choosing the peer to ban + +Each transaction gossiped contains the ID of the peer that sent that transaction. Upon receiving a transaction, +a node saves the peer ID of the peer(s) that have sent it. As each peer had to have +run `CheckTx` on this transaction before adding it to its own mempool, we can assume this peer +can be held accountable for the validity of transactions it gossips. Invalid transactions are kept only in the mempool +cache and thus not gossiped. +As nodes have to complete a cryptographic handshake at the p2p layer, Tendermint guarantees that a malicious peer +cannot lie about who the sender of the transaction is. + +*Transactions received from users* + +For transactions submitted via `broadcastTxCommit`, the `SenderID` field is empty. + +**Note** Do we have mechanisms in place to handle cases when `broadcastTxCommit` submits +failing transactions (can this be a form of attack)? + +### 3. Attack scenarios + +While an attack by simply banning peers on failing `CheckTx` is hard to imagine, as the incentive for doing so is not clear, there are considerations with regards to the current mempool gossip implementation. + +Should we keep transactions that could never have been valid in the cache? Assuming that receiving such transactions is rare, and the peer that sent them is banned, do we need to occupy space in the mempool cache with these transactions? + +- What if nodes run different versions of Tendermint and banning is not supported in one of the versions? + +- Reserving response codes can be problematic for existing applications that may have reserved these codes for internal purposes withtou being aware that this causes a ban now. + + +## Implementation considerations + +**Indicating a new type of `CheckTx` failure** + +The initial proposal is to reserve a special response code to indicate that the transaction could never have been valid. +Due to concerns of this being a breaking change for applications that have already reserved this code for internal +purposes, there is an alternative implementation: expanding `ResponseCheckTx` with an additional field. +This field `neverValidTx` would be `false` by default. If a transaction could never have been valid, +in addition to indicating this with a non-zero response code from `CheckTx`, the application would set this field value. + +**Adding support for peer banning** + +When a transaction fails `CheckTx`, it is not stored in the mempool but **can** be stored in the cache. If it is in the cache, it cannot be resubmitted again (as it will be discovered in the cache and not checked again). These two scenarios require a different implementation of banning in case `CheckTx` failed. + +In both cases we need to keep track of the peers that sent invalid transactions. If invalid transactions are cached, +we also need to keep track of the `CheckTx` response code for each transaction. Currently the `ResponseCheckTx` code is checked in `resCbFirstTime` of the mempool. +If invalid transactions are kept in the cache, the check is ran only when a transaction is +seen for the first time. Afterwards, the transaction is cached, to avoid running `CheckTx` on transactions already checked. +Thus when a transaction is received from a peer, if it is in the cache, +`CheckTx` is not ran again, but the peers' ID is added to the list of peers who sent this particular transaction. +These transactions are rechecked once a block is committed to verify that they are still valid. + +If invalid transactions are not kept in the cache, they can be resubmitted multiple times, and `CheckTx` will be executed on them upon submission. +Therefore we do not need to remember the previous response codes for these transactions. + +In summary, if we want to support banning peers based on the frequency with which they submit invalid transactions, we need to have **additional datastructures**: +1. One to keep track of past invalid transactions +2. A datastructure to differentiate between valid and invalid *cached* transactions. If the `KeepInvalidTxsInCache` configuration parameter is not set, this datastructure + is not needed. + +We propose two ways to implement peer banning based on the result of `CheckTx`: + +1. Introduce banning when transactions are received +2. Adapt the recheck logic to support this + + + +**Peer banning when transactions are received** + +If a transaction fails `CheckTx` the [first time it is seen](https://github.com/tendermint/tendermint/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/clist_mempool.go#L409), the peer can be banned right there: + +>>mempool/v0/clist_mempool.go#L409 +```golang + +if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { + // Check Tx passed +} else { +// ignore bad transaction + mem.logger.Debug( + "rejected bad transaction", + "tx", types.Tx(tx).Hash(), + "peerID", peerP2PID, + "res", r, + "err", postCheckErr, + ) + mem.metrics.FailedTxs.Add(1) + + mem.banPeer(peerP2PID) + + if !mem.config.KeepInvalidTxsInCache { + // remove from cache (it might be good later) + mem.cache.Remove(tx) + } else { + // If transactins stay in the cache, remember they failed + mem.cache.invalidCachedTx.Store(tx.Key(), true) + } +} + +``` +The `KeepInvalidTxsInCache` configuration parameter defines whether an invalid transaction stays in cache. For *never-valid* +transactions, we could apply a different approach based on what we deem to be the bigger gain: +- As we do not expect to receive frequently and from many peers, and we ban the peer that sent it immediately, we do not store it in the cache to save space. This would mean +that if we did see it again, we'd ran `CheckTx` on it again. + +```golang +if !mem.config.KeepInvalidTxsInCache || r.CheckTx.Code == abci.NeverValid { + // remove from cache (it might be good later or is never valid, we'll most likely don't see it again) + mem.cache.Remove(tx) +} +``` + +- We do keep it in the cache as long as possible to avoid running `CheckTX` on it because we know, for sure, that it will never be valid. As it is rare enough, it +might not take that much space. In this case though, as we ban the sending peer immediately, we can save space by not storing peer information for this transaction. + +The question is which one is more costly, doing `CheckTx` more then once, or keeping an extra entry in the cache? + + + +As said, this code will [never be executed](https://github.com/tendermint/tendermint/blob/ff0f98892f24aac11e46aeff2b6d2c0ad816701a/mempool/v0/clist_mempool.go#L239) for transactions whose signature is found +in the cache. +Instead of remembering the cached transactions, we could have had a valid/invalid bit per transaction within the cache. As transactions themselves do not +store such information and we expect this scenario to be unlikely, instead of increasing the footprint of all transactions in the cache, +we opted to keep a map of transaction signature if the transaction is in the cache, but is invalid. Alternatively, the cache could keep two lists, one for valid, and one for invalid transactions. +This modifies the following pieces of code as follows (this is just a prototype and does not include +some obvious sanity checks): + +```golang + +// New datastructure to keep track of peer failures +type PeerFailure struct { + lastFailure time.Time + numFailures int8 +} + +type LRUTxCache struct { +// Keeping track of invalid transactions within the cache ; + invalidCachedTx map[types.TxKey]bool +} + +type CListMempool struct { + // ..existing fields + peerFailureMap map[nodeID]*PeerFailure + +} +``` + +>mempool/v0/clist_mempool.go#L239 +```golang + +if !mem.cache.Push(tx) { // if the transaction already exists in the cache + // Record a new sender for a tx we've already seen. + // Note it's possible a tx is still in the cache but no longer in the mempool + // (eg. after committing a block, txs are removed from mempool but not cache), + // so we only record the sender for txs still in the mempool. + if e, ok := mem.txsMap.Load(tx.Key()); ok { + memTx := e.(*clist.CElement).Value.(*mempoolTx) + memTx.senders.LoadOrStore(txInfo.SenderID, true) + // TODO: consider punishing peer for dups, + // its non-trivial since invalid txs can become valid, + // but they can spam the same tx with little cost to them atm. + } + + // If transaction was invalid, we need to remember the peer information + if _, ok := mem.cache.invalidCachedTx.Load(tx.Key); ok { + mem.banPeer(peerID) + } + return mempool.ErrTxInCache +} + +``` + + +```golang + +func (mem* ClistMempool) banPeer(peerID NodeID) { + numFails := 0 + // Check whether this peer has sent us transactions that fail + if val, ok := mem.peerFailureMap[peerID]; ok { + lastFailureT := val.lastFailure + numFails = val.numFails + // if the failure was recent enough, update the number of failures and + // ban peer if applicable + if time.Since(lastFailureT) <= failureResetInterval { + if numFails == maxAllowedFailures - 1 { + // Send Ban request to p2p + } + } + } + // Update the time of the last failure + mem.peerFailureMap[peerID] = { time.Now(), numFailures + 1} +} +``` +If transactions with `ResponseCheckTx.code > 1` are not deleted from the cache and we want to ban them on the first offence, +we can skip the second `if` in the code above but call `banPeer` immediately at the end of the function. The function `banPeer` should simply forward the `peerID` to the p2p layer. In fact, we do not need to store any information on this peer as the node will remove it from its peer set. + +**Signaling the ban to p2p** + +As it is the mempool **reactor** that has access to the p2p layer, not the actual mempool implementation, the peer banning function will most likely have to send the peer ID to a channel to inform the reactor of the fact that this peer should be banned. This would require adding a channel for communication into the `CListMempool` on construction, and adding a routine in the mempool reactor that waits on a response via this channel. However, the actual implementation of this is yet to be defined. + +**Implementing peer banning on recheck** + +Currently the recheck logic confirmes whether once **valid** transactions, +, where `ResponseCheckTx.code == 0`, are still valid. + +As this logic loops through the transactions in any case, we can leverage it to check whether we can ban peers. +However, this approach has several downsides: +- It is not timely enough. Recheck is executed after a block is committed, leaving room for a bad peer to send +us transactions the entire time between two blocks. +- If we want to keep track of when peers sent us a traansaction and punish them only if the misbehaviour happens +frequently enough, this approach makes it hard to keep track of when exactly was a transaction submitted. +- Rechecking if optional and node operators can disable it. +- Furthermore, rechecking is a node local configuration parameter. This means that, some nodes might be performing this check, + while others will be unaware of this. + +On the plus side this would avoid adding new logic to the mempool caching mechanism and keeping additional information about +transaction validity. But we would still have to keep the information on peers and the frequency at which they send us bad transactions. + +Transactions that became invalid on recheck should not be cause for peer banning as they have not been gossiped as invalid transactions. + +#### `PreCheck` and`PostCheck` + +The `PreCheck` and `PostCheck` functions are optional functions that can be executed before or after `CheckTx`. +Following the design outlined in this RFC, their responses are not considered for banning. + + +#### Checks outside `CheckTx` + +There are a number of checks that the mempool performs on the transaction, that are not part of `CheckTx` itself. +Those checks, have been mentioned in the user issues described at the beginning of this document: + +- Transaction size +- Proto checks +- Receiving unknown messages via the mempool channel + +The previous code snippets do not incroporate these in peer banning. If we adopt those as valid reasons for banning, we should put the corresponding logic in place. + +### Impacted mempool functionalities + +- Mempool caching: remembering failed transactions and whether they come from banned peers; Removal of transactions from + `invalidCachedTx` when a transaction is removed from cache. +- Handling of transactions failing `CheckTx`: Keeping track of how often transactions from a particular peer have failed + and banning them if the conditions for a ban are met. + +### Impact on ABCI + +- Introduction of new response codes for CheckTx. As previously noted, this might break existing applications if they reserved codes for internal purposes. +- Altering the specification to reflect this change + +### References + + +> Links to external materials needed to follow the discussion may be added here. +> +> In addition, if the discussion in a request for comments leads to any design +> decisions, it may be helpful to add links to the ADR documents here after the +> discussion has settled. + + + +- \ No newline at end of file diff --git a/docs/rfc/tendermint-core/rfc-027-p2p-message-bandwidth-report.md b/docs/references/rfc/tendermint-core/rfc-027-p2p-message-bandwidth-report.md similarity index 98% rename from docs/rfc/tendermint-core/rfc-027-p2p-message-bandwidth-report.md rename to docs/references/rfc/tendermint-core/rfc-027-p2p-message-bandwidth-report.md index eaa99cdef4a..19199f6af5c 100644 --- a/docs/rfc/tendermint-core/rfc-027-p2p-message-bandwidth-report.md +++ b/docs/references/rfc/tendermint-core/rfc-027-p2p-message-bandwidth-report.md @@ -54,25 +54,25 @@ The image below of p2p data collected from the Blockpane validator illustrate the total bandwidth consumption of these three message types. -#### Send: +#### Send: -##### Top 3 Percent: +##### Top 3 Percent: -![](./images/top-3-percent-send.png) +![](images/top-3-percent-send.png) -##### Rate For All Messages: +##### Rate For All Messages: -![](./images/send-rate-all.png) +![](images/send-rate-all.png) -#### Receive: +#### Receive: -##### Top 3 Percent: +##### Top 3 Percent: -![](./images/top-3-percent-receive.png) +![](images/top-3-percent-receive.png) -##### Rate For All Messages: +##### Rate For All Messages: -![](./images/receive-rate-all.png) +![](images/receive-rate-all.png) ### Investigation of Message Usage diff --git a/docs/references/storage/README.md b/docs/references/storage/README.md new file mode 100644 index 00000000000..ae8fb21eb76 --- /dev/null +++ b/docs/references/storage/README.md @@ -0,0 +1,297 @@ +# Overview + +This report summarizes the changes on CometBFT storage between Q3 2023 and Q1 2024, along with all the experiments and benchmarking performed to understand the impact of those changes. + +As of Q3 2023, the CometBFT team has dedicated significant resources addressing a number of storage related concerns: +1. Pruning not working: operators noticed that even when nodes prune data, the storage footprint is increasing. +2. Enabling pruning slows down nodes. Many chains disable pruning due to the impact on block processing time. +3. CometBFT is addressing application level concerns such as transaction indexing. Furthermore, operators have very coarse grained control over what is stored on their node. +4. Comet supports many database backends when ideally we should converge towards one. This requires understanding of the DB features but also the way CometBFT uses the database. +5. The representation of keys CometBFT uses to store block and state data is suboptimal for the way this data is sorted within most kvstores. This work was [started in Tendermint 0.36](https://github.com/tendermint/tendermint/pull/5771) but not completed. We picked up that work and experimented with the proposed data layout. + +All the experiments were performed on `main` after `v1-alpha.1` was released. The experiments on Injective were done on custom branches porting the changes to `0.37.x` with the changes Injective has on their fork of 0.37: +- [Injective testing "v1"](https://github.com/cometbft/cometbft/tree/storage/tmp/injective/v0.37.x-testing-validator) +- [Injective testing "v2"](https://github.com/cometbft/cometbft/tree/storage/tmp/injective/v0.37.x-testing-newlayout-validator) + +We also have non Injective specific backports to 0.37.x based code in the following branches: + +- [Old keylayout](https://github.com/cometbft/cometbft/tree/storage/tmp/v0.37.x-testing-validator) +- [New key layout](https://github.com/cometbft/cometbft/tree/storage/tmp/v0.37.x-testing-validator) + +These branches are however used only for testing and development purposes and are not meant nor designed to be used in production. + +### Releases containing the changes + +- *v1* : Data companion, background pruning, compaction and support for different key layouts +- *v0.38.x-experimental*: Data companion, background pruning (production ready) +- *Validator testing branches based of 0.37.x* - background pruning, compaction, key layout (not production ready). + +## Pre Q1 2024 results +By the end of Q3 we have addressed and documented the second problem by introducing a data companion API. The API allows node operators to extract data out of full nodes or validators, index them in whichever way they find suitable and instruct CometBFT to prune data at a much finer granularity: +- Blocks +- State +- ABCI Results +- The transaction indexer +- The block indexer + +For comparison, until then, CometBFT would only prune the block and state store (not including ABCI results), based on instructions from the application. + +More details on the API itself and how it can be used can be found in the corresponding [ADR](https://github.com/cometbft/cometbft/blob/main/docs/references/architecture/adr-101-data-companion-pull-api.md) and [documentation](https://github.com/cometbft/cometbft/tree/main/docs/explanation/data-companion). + +The rest of this report covers the changes and their impact related to fixing and improving the pruning related points (1 and 3) as well as supporting a new data key layout (point 5). The results are obtained using `goleveldb` as the default backend unless stated otherwise. + +## Q1 goals & summary of results +The expected result for Q1 was fixing the problem of storage growth despite pruning and improving database access times with a more optimal key layout. + +While we did indeed fix the problem of pruning/compaction not working, based on the results we obtained we could not demonstrate a certain benefit of changing the database key representation. + +Without a real world application, when running our test applications, our hypothesis on the impact of ordering was demonstrated by performance improvements and faster compaction times with the new layout. + +The one experiment with a real application (injective) did not back up this theory though. Even though the overall performance was better than the software version used by the application at the moment. + +The block processing time reported by our application were in the range of 600-850ms compared to 100s of ms for the real world application. Furthermore, the application might have different access patterns. Our tests can be seen as testing only CometBFT's interaction with storage, without much interference from the application. + +That is why, in Q1, we introduce an interface with two implementations: the current key layout (a "v1") and a new representation ("v2") sorting the keys by height using ordercode. The new layout is marked as purely experimental. Our hope is that chains will be incentivized to experiment with it and provide us with more real world data. This will also facilitate switching the data layout without breaking changes between releases if we decide to officially support a new data layout. + + + +**Summary of Q1 results:** + +- pruning on its own is inefficient to control storage growth +- we have complemented pruning with a (forced) compaction feature, and this proved effective to control storage growth +- we confirmed that moving pruning + compaction to background mitigates potential performance impact of this feature, by running tests with it on Injective mainnet + - this works as expected, therefore pruning + compaction does not show to impact node performance and we recommend using it +- regarding key layouts: + - our hypothesis was that the new "v2" layout should improve read/write performance on block & state store access + - we obtained contradicting results on this hypothesis locally vs. production settings, concretely: + - in local setting, enabling pruning with the old "v1" key layout _had_ a performance impact; enabling pruning with new layout _had no_ impact + - in mainnet setting the observation was in reverse: using the new layout _introduced a ~10ms latency_ + - it is inconclusive if the new key layout "v2" is beneficial, so we will introduce this as an experimental feature + - we expect to continue working with operator teams to gather data from production, ideally Injective and Osmosis +- pebbleDB: handles compaction without the need for Comet to force it, generally shows better performance with the new layout + +Application developers who use `cometbft-db` as a database backend for their application store should use the new API forcing compaction. This will reduce the storage used by their application in case of pruning. + +# Testing setup + +The experiments were ran in a number of different settings: + 1. We call this setup **Local-1node**: Local runs on one node using a light kvstore application with almost no app state. This setup increases the chances that storage is the bottleneck and enables us to evaluate the changes independent + of the demands of specific applications. Furthermore, we were able to create a larger storage footprint quicker + thus speeding up the experimentation process. + + To evaluate the impact of forced compaction and the different key layouts on both compaction/pruning and performance, we ran the following set of experiments on this setup: + - Current layout - no pruning + - Current layout - pruning, no forced compaction + - Current layout - pruning and forced compaction + - New layout - no pruning + - New layout - pruning, no forced compaction + - New layout - pruning and forced compaction + + We have also experimented with a [third key layout option](https://github.com/cometbft/cometbft/pull/1814), from which we initially expected the most: The new layout combined with insights into the access pattern of CometBFT to order together keys frequently accessed. In all + our experiments, when running CometBFT using this layout was less efficient than the other two and we therefore dismissed it. + + We reduced the `timeout_commit` in this setup to 300ms to speed up execution. The load was generated using `test/loadtime` with the following parameters: `-c 1 -T 3600 -r 1000 -s 8096`, sending 8KB transactions at a rate of 1000txs/s for 1h. + + Each experiment was repeated 3 times to make sure the results are deterministic. + + 2. **e2e-6 node**: CometBFT's e2e application run on a Digital Ocean cluster of 6 nodes. Each node had a different combination of changes: + - Pruning with and without compaction on the current database key layout vs. the same but using the new key layout that uses `ordercode` to sort keys by height. + - No pruning using the current database key layout vs. the new key layout. + + The nodes ran on top of a 11GB database to analyze the effects of pruning but also potentially capture additional impact on performance depending on the key layout. + +3. **production-testing**: The validator team at Informal Staking was kind enough to spend a lot of time with us trying to evaluate our changes on full nodes running on mainnet Injective chains. As their time was limited and they had found initially that pruning, in addition to not working, slows down Injective nodes, we were interested to understand the impact our changes made on their network. Future investigation on mainnet nodes would be required to gather more real-world data on chains with different demands and see if pruning is indeed ineffective and the slow down is reproducible. + + +## **Metrics collected** + +- **Storage footprint** +- **RAM usage** +- **Block processing time** (*cometbft_state_block_processing_time*) This time here indicates the time to execute `FinalizeBlock` while reconstructing the last commit from the database and sending it to the application for processing. +- **Block time**: Computes the time taken for 1 block based on the number of blocks procssed in 1h. Note that for small networks the validators usually keep up and thus their average block times end up being similar. +- **Duration of individual consensus steps** (*cometbft_consensus_step_duration_seconds* aggregated by step) +- **consensus_total_txs** + +During this work we extended CometBFT with two additional storage related metrics: +- *Block store access time* that records the time taken for each method to access the block store +- *State store access time* that records the time taken for each method to access the state store + +## Pruning + +Pruning the blockstore and statestore is a long supported feature by CometBFT. An application can set a `retain_height` - the number of blocks which must be kept - and instruct CometBFT to prune the remaining blocks (taking into account some other constraints). + +## The pruning feature on its own is ineffective in reducing storage footprint +Unfortunately, many users have noticed that, despite the pruning feature based on `retain_height` being enabled, the growth of both the state and block store does not stop. To free up storage, operators copy the database, enforce compaction of the deleted items manually and copy it back. We have talked to operators and some have to do this weekly or every two weeks. + +After some research, we found that some of the database backends can be forced to compact the data. We experimented on it and confirmed those findings. + +That is why we extended `cometbft-db`, [with an API](https://github.com/cometbft/cometbft-db/pull/111) to instruct the database to compact the files. Then we made sure that CometBFT [calls](https://github.com/cometbft/cometbft/pull/1972) this function after blocks are pruned. + +To evaluate whether this was really beneficial, we ran a couple of experiments and recorded the storage used: + +### Local 1 node run of a dummy app that grows the DB to 20GB: + +![local-run-compaction](img/impact_compaction_local.png) + + +### Running CometBFT's e2e application in a mixed network of 6 nodes. +![e2e_storage_usage](img/e2e_storage_usage.png "Storage usage e2e") + + The nodes doing pruning and compaction have a constant footprint compared to the other nodes. + *validator03* and *validator05* prune without compaction. They have a smaller footprint than the + nodes without pruning. The fact that the footprint of *validator05* has a lower footprint than + *validator03* stems from the compaction logic of `goleveldb`. As the keys on *validator03* are sorted + by height, new data is simply appended without the need to reshuffle very old levels with old heights. + On *validator05*, keys are sorted lexicographically leading to `goleveldb` *touching* more levels on insertions. By default, the conditions for triggering compaction are evaluated only when a file is touched. This is the reason why random key order leads to more frequent compaction. (This was also confirmed by [findings](https://github.com/cometbft/cometbft/files/12914649/DB.experiments.pdf) done by our intern in Q3/Q4 2023 on goleveldb without Comet on top, part of the [issue](https://github.com/cometbft/cometbft/issues/64) to understand the database backends and decide which one to optimize and choose.). + + +### Production - Injective mainnet + +#### Pruning without compaction + +![injective-no-compaction](img/injective_no_compaction.png "Injective - pruning without compaction") +#### Pruning with compaction + +![injective-compaction](img/injective_compaction.png "Injective - pruning with compaction") + +## Pruning is slowing nodes down + +While the previous results confirm the storage footprint can be reduced, it is important that this is not impacting the performance of the entire system. + +The most impactful change we have made with regards to that is moving block and state pruning into a background process. Up until v1.x, pruning was done before a node moves on to the next height, blocking +consensus from proceeding. In Q3 2023, we changed this by launching a pruning service that checks in fixed intervals, whether there are blocks to be pruned. This interval is configurable and is `10s` by default. + +### Production - Injective mainnet +The impact of this changes is best demonstrated with the runs by Informal staking comparing 4 Injective nodes with the following setup: + +1. *injective-sentry0* comet="v0.37" , pruning="default", keylayout=old +2. *injective-sentry1* comet="v0.37" , pruning="none" , keylayout=old +3. *injective-pruning* comet="modified" , pruning="600blocks" , keylayout=old +4. *injective-newlayout* comet="modified" , pruning="600blocks" , keylayout=new + +Comet v0.37 is the current 0.37 release used in production where pruning is not happening within a background process. + +We report the time to execute Commit: +![injective-commit](img/injective_commit.png "Injective - commit") + + +The time to complete Commit for pruning done within the same thread, the Commit step takes 412ms vs 286ms when no pruning is activated. Using these numbers as baseline, the new changes for both layout do not degrade performance. The duration of Commit with pruning over the current DB key layout is 253ms, and 260ms on the new layout. + +The graph below plots the block processing time for the 4 nodes. + +![injective-bpt](img/injective_block_processing_time.png "Injective - average block processing time") + +The new changes lead to faster block processing time compared even to the node that has no pruning active. However, the new layout seems to be slightly slower. We will discuss this in more details below. + + +## Database key layout and pruning + +The results above clearly show that pruning is not impacting the nodes performance anymore and could be turned on. The next step was determining whether we should remove the current database key representation from CometBFT and use the new ordering by height, which should be more optimal. (Pure golevelDB benchmarks showed orders of magnitute improvement when keys were written in order vs randomly: 8s vs 16ms - this can be seen in the PDF report on `goleveldb` experiments linked above). +However, while running the same set of experiments locally vs. in production, we obtained contradicting results on the impact of the key layout on these numbers. + +### **Local-1node** +In this setup, we came to the conclusion that, if pruning is turned on, only the version of CometBFT using the new database key layout was not impacted by it. The throughput of CometBFT (measured by num of txs processed within 1h), decreased with pruning (with and without compaction) using the current layout - 500txs/s vs 700 txs/s with the new layout. The compaction operation itself was also much faster than with the old key layout. The block time difference is between 100 and 200ms which for some chains can be significant. +The same was true for additional parameters such as RAM usage (200-300MB). + +We show the findings in the table below. `v1` is the current DB key layout and `v2` is the new key representation leveraging ordercode. + + +| Metric | No pruning v1 | No pruning v2 | Pruning v1 | Pruning v2 | Pruning + compaction v1 | Pruning + compaction v2 +| :---------------- | :------: | ----: | ------: | ----: | ------: | ----: | +| Total tx | 2538767 | 2601857 | 2063870 | 2492327 | 2062080 | 2521171 | +| Tx/s | 705.21 | 722.74 | 573.30 | 692.31 | 572.80 | 700.33 | +| Chain height | 4936 | 5095 | 4277 | 4855 | 4398 | 5104 | +| RAM (MB) | 550 | 470 | 650 | 510 | 660 | 510| +| Block processing time(ms) | 1.9 | 2.1 | 2.2 | 2.1 | 2.0 | 1.9 | +| Block time (s) | 0.73| 0.71 | 0.84 | 0.74| 0.82| 0.71| + +We collected locally periodic heap usage samples via `pprof` and noticed that compaction for the old layout would take ~80MB of RAM vs ~30MB with the new layout. + + +When backporting these changes to the 0.37.x based branch we gave to Informal staking, we obtained similar results when ran locally on the kvstore app. However, this is not what they observed on mainnet. In the graphs above, we see that the new layout, while still improving performance compared to CometBFT v0.37.x, introduced a ~10ms latency in this particular case. According to the operators, this is a big difference for chains like Injective. + +### **e2e - 6 nodes** + +In this experiment, we started a network of 6 validator nodes and 1 seed node. Each node had an initial state with 11GB in its blockstore. The configuration of the nodes is the same one as in the local runs: + + - **validator00**: Current layout - no pruning + - **validator05**: Current layout - pruning, no forced compaction + - **validator02**: Current layout - pruning and forced compaction + - **validator04**: New layout - no pruning + - **validator03**: New layout - pruning, no forced compaction + - **validator01**: New layout - pruning and forced compaction + + Once the nodes synced up to the height in the blockstore, we ran a load of transactions against the network for ~6h. As the run was long, we alternated the nodes to which the load was sent to avoid potential pollution of results by the handling of incoming transactions . + +*Block time* + +As all nodes were validator nodes who were able to most of the time keep up, their block times were very similar (~3ms of difference). We thus looked whether validators were missing blocks and the Commit time to give us an indication of the impact the layout and pruning have. + +*Time to execute Commit* + +![e2e_commitTime](img/e2e_commit_time.png "Commit time e2e") + + +*Missed blocks* +![e2e_val_missed_blocks](img/e2e_val_missed_blocks.png "Blocks missed by a validator") + +The graph above shows the number of missed blocks per validator. *validator02* is doing pruning and compaction using the old layout and keeps missing blocks. The other two validators all use the new layout with *validator03* doing pruning without compaction compared to *validator01* who missed only 1 block while doing pruning and compaction. + +This is something we could not verify in production because the nodes ran by Informal Staking were not validator nodes. + + *Block Store Access time* + + In general, store access times are very low, without pruning they are up to 40ms. The storage device on the Digital Ocean nodes are SSDs but many of our operators use state of the art NVMe devices, thus they could be even lower in production. + Without pruning, the current layout is slightly faster than the new one. However, when pruning is turned on and deletions are performed, the access times grow (to 100s of ms) and using the new layout leads to lower access times. The gap grows slightly as the database size grows (second graph). + + ![e2e_block_store_access_time](img/e2e_block_store_access_time.png "Block store access time e2e") + + + *State Store Access time* + + The conclusions for the state store access times are very similar to those for the blockstore. Note though that in our e2e app the state store does not grow to more than 1GB as we disabled ABCI results saving and the validator set is not updated - which typically leads to increase in state. + + + ![e2e_state_store_access_time](img/e2e_state_store_access_time.png "State store access time e2e") + + *RAM Usage* + The difference in RAM used between the nodes was not very big. Nodes that prune efficiently (with compaction), used 20-40MB more RAM than nodes that did no pruning. + + But *validator04* and *validator00* (no pruning) are using 278MB of RAM . *validator02* (pruning on old layout) uses 330MB of RAM and *validator01*(pruning on new layout) uses 298MB. This is in line with the local runs where pruning on the new layout uses less RAM. + + +### Conclusion on key layout +As demonstrated by the above results, and mentioned at the beginning, `v1.x` will be released with support for the new key layout as a purely experimental feature. + +Without pruning, for a bigger database and block processing times (on runs with our e2e), the new layout lowered the overall block processing time even without pruning. When the block times are very low (in our local setup or on Injective), we did not observe the same benefits. + +Thus, the final decision should be left to the application after testing and understanding their behaviour. + +As the feature is experimental, we do not provide a way to convert the database back into the current format if it is initialized with the new layout. + +The two layouts are not interchange-able, once one is used, a node cannot switch to the other. The version to be used is set in the `config.toml` and defaults to `v1` - the current layout. Once the layout is set, it is written back to the database with `version` as the key. When a node boots up and loads the database initially, if this flag is set, it takes precedense over any configuration file. + +The support for both layouts will allow users to benchmark their applications. If at any point we get clear indications that one layout is better than the other, we will gladly drop support for one of them and provide users with a way to migrate their databases gracefully. + + +## Pebble + +`PebbleDB` was recently added to `cometbft-db` by Notional labs and based on their benchmarks it was superior to goleveldDB. + +We repeated our tests done in **1-node-local** using PebbleDB as the underlying database. While PebbleDB is slightly better in performance (tx/s), the most impressive difference is that PebbleDB seemed to handle compaction very well without a need to enforce it. + +In the graph below, we see the old layout without any compaction and the new layout with and without compaction on the same workload that generated 20GB of data when no pruning is active. + + +![pebble](img/pebble.png "Pebble") + +The table below shows the performance metrics for Pebble: + +| Metric | No pruning v1 | No pruning v2 | Pruning v1 | Pruning v2 | Pruning + compaction v1 | Pruning + compaction v2 +| :---------------- | :------: | ----: | ------: | ----: | ------: | ----: | +| Total tx | 2827232 | 2906186 | 2851298 | 2873765 | 2826235 | 2881003 | +| Tx/s | 785.34 | 807.27 | 792.03 | 798.27 | 785.08 | 800.28 | +| Chain height | 5743 | 5666 | 5553| 5739 | 5551 | 5752 | +| RAM (MB) | 494 | 445 | 456 | 445 | 490 | 461 | +| Block processing time(ms) | 2.1 | 3.9 | 2.1 | 2.1 | 2.1 | 2.1 | +| Block time (s) | 0.63 | 0.64 | 0.65 | 0.63 | 0.65 | 0.63 | \ No newline at end of file diff --git a/docs/references/storage/img/e2e_block_store_access_time.png b/docs/references/storage/img/e2e_block_store_access_time.png new file mode 100644 index 00000000000..8acd1792f9c Binary files /dev/null and b/docs/references/storage/img/e2e_block_store_access_time.png differ diff --git a/docs/references/storage/img/e2e_commit_time.png b/docs/references/storage/img/e2e_commit_time.png new file mode 100644 index 00000000000..d44779a8708 Binary files /dev/null and b/docs/references/storage/img/e2e_commit_time.png differ diff --git a/docs/references/storage/img/e2e_state_store_access_time.png b/docs/references/storage/img/e2e_state_store_access_time.png new file mode 100644 index 00000000000..6990893af89 Binary files /dev/null and b/docs/references/storage/img/e2e_state_store_access_time.png differ diff --git a/docs/references/storage/img/e2e_storage_usage.png b/docs/references/storage/img/e2e_storage_usage.png new file mode 100644 index 00000000000..780004d98ed Binary files /dev/null and b/docs/references/storage/img/e2e_storage_usage.png differ diff --git a/docs/references/storage/img/e2e_val_missed_blocks.png b/docs/references/storage/img/e2e_val_missed_blocks.png new file mode 100644 index 00000000000..e4ee4d3d715 Binary files /dev/null and b/docs/references/storage/img/e2e_val_missed_blocks.png differ diff --git a/docs/references/storage/img/impact_compaction_local.png b/docs/references/storage/img/impact_compaction_local.png new file mode 100644 index 00000000000..42f14b7df89 Binary files /dev/null and b/docs/references/storage/img/impact_compaction_local.png differ diff --git a/docs/references/storage/img/injective_block_processing_time.png b/docs/references/storage/img/injective_block_processing_time.png new file mode 100644 index 00000000000..397de16cae4 Binary files /dev/null and b/docs/references/storage/img/injective_block_processing_time.png differ diff --git a/docs/references/storage/img/injective_commit.png b/docs/references/storage/img/injective_commit.png new file mode 100644 index 00000000000..1adf2cfc02c Binary files /dev/null and b/docs/references/storage/img/injective_commit.png differ diff --git a/docs/references/storage/img/injective_compaction.png b/docs/references/storage/img/injective_compaction.png new file mode 100644 index 00000000000..661d87a1307 Binary files /dev/null and b/docs/references/storage/img/injective_compaction.png differ diff --git a/docs/references/storage/img/injective_no_compaction.png b/docs/references/storage/img/injective_no_compaction.png new file mode 100644 index 00000000000..f85b3dc1d79 Binary files /dev/null and b/docs/references/storage/img/injective_no_compaction.png differ diff --git a/docs/references/storage/img/pebble.png b/docs/references/storage/img/pebble.png new file mode 100644 index 00000000000..86c95e9a648 Binary files /dev/null and b/docs/references/storage/img/pebble.png differ diff --git a/docs/rfc/tendermint-core/README.md b/docs/rfc/tendermint-core/README.md deleted file mode 100644 index 2a164b2c674..00000000000 --- a/docs/rfc/tendermint-core/README.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -order: 1 -parent: - order: false ---- - -# Tendermint Core Requests for Comments - -This document serves as a historical reference for all RFCs that were logged -during the development of Tendermint Core. - -This list is frozen as-is, and new RFCs should be added [here](../). - -## Table of Contents - -- [RFC-000: P2P Roadmap](./rfc-000-p2p-roadmap.rst) -- [RFC-001: Storage Engines](./rfc-001-storage-engine.rst) -- [RFC-002: Interprocess Communication](./rfc-002-ipc-ecosystem.md) -- [RFC-003: Performance Taxonomy](./rfc-003-performance-questions.md) -- [RFC-004: E2E Test Framework Enhancements](./rfc-004-e2e-framework.rst) -- [RFC-005: Event System](./rfc-005-event-system.rst) -- [RFC-006: Event Subscription](./rfc-006-event-subscription.md) -- [RFC-007: Deterministic Proto Byte Serialization](./rfc-007-deterministic-proto-bytes.md) -- [RFC-008: Don't Panic](./rfc-008-do-not-panic.md) -- [RFC-009: Consensus Parameter Upgrades](./rfc-009-consensus-parameter-upgrades.md) -- [RFC-010: P2P Light Client](./rfc-010-p2p-light-client.rst) -- [RFC-011: Delete Gas](./rfc-011-delete-gas.md) -- [RFC-012: Event Indexing Revisited](./rfc-012-custom-indexing.md) -- [RFC-013: ABCI++](./rfc-013-abci++.md) -- [RFC-014: Semantic Versioning](./rfc-014-semantic-versioning.md) -- [RFC-015: ABCI++ Tx Mutation](./rfc-015-abci++-tx-mutation.md) -- [RFC-016: Node Architecture](./rfc-016-node-architecture.md) -- [RFC-017: ABCI++ Vote Extension Propagation](./rfc-017-abci++-vote-extension-propag.md) -- [RFC-018: BLS Signature Aggregation Exploration](./rfc-018-bls-agg-exploration.md) -- [RFC-019: Configuration File Versioning](./rfc-019-config-version.md) -- [RFC-020: Onboarding Projects](./rfc-020-onboarding-projects.rst) -- [RFC-021: The Future of the Socket Protocol](./rfc-021-socket-protocol.md) -- [RFC-023: Semi-permanent Testnet](./rfc-023-semi-permanent-testnet.md) -- [RFC-024: Block Structure Consolidation](./rfc-024-block-structure-consolidation.md) -- [RFC-025: Application Defined Transaction Storage](./rfc-025-support-app-side-mempool.md) -- [RFC-027: P2P Message Bandwidth Report](./rfc-027-p2p-message-bandwidth-report.md) diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md new file mode 100644 index 00000000000..70d1f0e154f --- /dev/null +++ b/docs/tutorials/README.md @@ -0,0 +1,29 @@ +--- +order: 3 +title: CometBFT Tutorials +description: Tutorials +parent: + order: 1 +--- + +## Tutorials + +Are you ready to explore the world of CometBFT, the cutting-edge consensus algorithm that's revolutionizing the +field of distributed systems? You've come to the right place! Our CometBFT Tutorials provide the knowledge +and hands-on experience you need to master this groundbreaking technology. + +## Why Choose CometBFT Tutorials? + +- Comprehensive Learning: Our tutorials cover everything from the basics of consensus algorithms to advanced topics in CometBFT, ensuring that both beginners and experts can benefit. +- Hands-On Experience: We believe in learning by doing. Our tutorials include practical examples and exercises that allow you to implement CometBFT in real-world scenarios. +- Up-to-date Content: We keep our tutorials up-to-date with the latest developments in CometBFT, ensuring that you have access to the most current information and best practices. + +## Get Started Today! + +Whether you're a chain developer, an integrator, an operator, or simply curious about distributed systems, our CometBFT Tutorials are the perfect resource to enhance your knowledge and skills. + +Ready to begin? Start exploring our tutorials now and embark on a learning experience that will empower you to harness the power of CometBFT for your projects and applications. Let's build a more reliable and resilient future together with CometBFT! +- [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/tutorials/go-built-in.md new file mode 100644 index 00000000000..8d3420b3f59 --- /dev/null +++ b/docs/tutorials/go-built-in.md @@ -0,0 +1,892 @@ +--- +order: 2 +--- + +# Creating a built-in application in Go + +## Guide Assumptions + +This guide is designed for beginners who want to get started with a CometBFT +application from scratch. It does not assume that you have any prior +experience with CometBFT. + +CometBFT is a service that provides a Byzantine Fault Tolerant consensus engine +for state-machine replication. The replicated state-machine, or "application", can be written +in any language that can send and receive protocol buffer messages in a client-server model. +Applications written in Go can also use CometBFT as a library and run the service in the same +process as the application. + +By following along this tutorial you will create a CometBFT application called kvstore, +a (very) simple distributed BFT key-value store. +The application will be written in Go and +some understanding of the Go programming language is expected. +If you have never written Go, you may want to go through [Learn X in Y minutes +Where X=Go](https://learnxinyminutes.com/docs/go/) first, to familiarize +yourself with the syntax. + +Note: Please use the latest released version of this guide and of CometBFT. +We strongly advise against using unreleased commits for your development. + +### Built-in app vs external app + +On the one hand, to get maximum performance you can run your application in +the same process as the CometBFT, as long as your application is written in Go. +[Cosmos SDK](https://github.com/cosmos/cosmos-sdk) is written +this way. +This is the approach followed in this tutorial. + +On the other hand, having a separate application might give you better security +guarantees as two processes would be communicating via established binary protocol. +CometBFT will not have access to application's state. +If that is the way you wish to proceed, use the [Creating an application in Go](go.md) guide instead of this one. + +## 1.0 Installing Go + +Verify that you have the latest version of Go installed (refer to the [official guide for installing Go](https://golang.org/doc/install)), , +ou should see an output similar to this one (the `go version` might be a slight different depending on the Go you +have installed and the computer platform): + +```bash +$ go version +go version go1.22.2 darwin/amd64 + +``` + +## 1.1 Installing CometBFT + +Let's install `CometBFT` locally by running the following command: + +```bash +go install github.com/cometbft/cometbft/cmd/cometbft@v1.0 +``` + +Test the installation: + +```bash +$ cometbft version +v1.0.0 +``` + +## 1.2 Creating a new Go project + +We'll start by creating a new Go project and moving into the new directory: + +```bash +mkdir kvstore +cd kvstore +``` + +Inside the `kvstore` directory, create a `main.go` file with the following content: + +```go +package main + +import ( + "fmt" +) + +func main() { + fmt.Println("Hello, CometBFT") +} +``` + +Run the following command: + +```bash +go run main.go +``` + +This should print "Hello, CometBFT" to the standard output. + +```bash +Hello, CometBFT +``` + +We are going to use [Go modules](https://github.com/golang/go/wiki/Modules) for +dependency management, so let's start by including a dependency on the latest version of +CometBFT, `v1.0` in this example. + +Run the commands below to create the go module file (`go.mod`) + +```bash +go mod init kvstore +``` + +This should an output similar to this. + +**NOTE**: No need to run `go mod tidy` at this time, just ignore it for now. +```bash +go: creating new go.mod: module kvstore +go: to add module requirements and sums: + go mod tidy +``` + +go 1.22.2 +Now, lets add `cometbft` as a dependency to our project. Run the `go get` command below: + +```bash +go get github.com/cometbft/cometbft@v1.0 +``` + +**NOTE**: This will add the latest release in the `v1.0` line, so you might a different patch release e.g. `v1.0.0` +or `v1.0.1` + +```bash +go: added github.com/cometbft/cometbft v1.0.0 +``` +` +After running the above commands you will see two generated files, `go.mod` and `go.sum`. +The go.mod file should look similar to: + +```go +module kvstore + +go 1.21.8 + +require github.com/cometbft/cometbft v1.0.0 // indirect +``` + +As you write the kvstore application, you can rebuild the binary by +pulling any new dependencies and recompiling it. + +```bash +go get +go build +``` + +At this point, if you ran the `go build` command above, you should see four files in the directory: + +```bash +$ ls +go.mod go.sum kvstore main.go +``` + +The `kvstore` file is the executable generated. You can run it again to ensure everything still works: + +```bash +$ ./kvstore +Hello, CometBFT +``` + +## 1.3 Writing a CometBFT application + +CometBFT communicates with the application through the Application +BlockChain Interface (`ABCI`). The messages exchanged through the interface are +defined in the ABCI [protobuf +file](https://github.com/cometbft/cometbft/blob/main/proto/cometbft/abci/v1/types.proto). + +We begin by creating the basic scaffolding for an ABCI application by +creating a new type, `KVStoreApplication`, which implements the +methods defined by the [abcitypes.Application](https://github.com/cometbft/cometbft/blob/main/abci/types/application.go) +interface. + +Create a file called `app.go` with the following contents: + +```go +package main + +import ( + abcitypes "github.com/cometbft/cometbft/abci/types" + "context" +) + +type KVStoreApplication struct{} + +var _ abcitypes.Application = (*KVStoreApplication)(nil) + +func NewKVStoreApplication() *KVStoreApplication { + return &KVStoreApplication{} +} + +func (app *KVStoreApplication) Info(_ context.Context, info *abcitypes.InfoRequest) (*abcitypes.InfoResponse, error) { + return &abcitypes.InfoResponse{}, nil +} + +func (app *KVStoreApplication) Query(_ context.Context, req *abcitypes.QueryRequest) (*abcitypes.QueryResponse, error) { + return &abcitypes.QueryResponse{}, nil +} + +func (app *KVStoreApplication) CheckTx(_ context.Context, check *abcitypes.CheckTxRequest) (*abcitypes.CheckTxResponse, error) { + return &abcitypes.CheckTxResponse{Code: 0}, nil +} + +func (app *KVStoreApplication) InitChain(_ context.Context, chain *abcitypes.InitChainRequest) (*abcitypes.InitChainResponse, error) { + return &abcitypes.InitChainResponse{}, nil +} + +func (app *KVStoreApplication) PrepareProposal(_ context.Context, proposal *abcitypes.PrepareProposalRequest) (*abcitypes.PrepareProposalResponse, error) { + return &abcitypes.PrepareProposalResponse{}, nil +} + +func (app *KVStoreApplication) ProcessProposal(_ context.Context, proposal *abcitypes.ProcessProposalRequest) (*abcitypes.ProcessProposalResponse, error) { + return &abcitypes.ProcessProposalResponse{}, nil +} + +func (app *KVStoreApplication) FinalizeBlock(_ context.Context, req *abcitypes.FinalizeBlockRequest) (*abcitypes.FinalizeBlockResponse, error) { + return &abcitypes.FinalizeBlockResponse{}, nil +} + +func (app KVStoreApplication) Commit(_ context.Context, commit *abcitypes.CommitRequest) (*abcitypes.CommitResponse, error) { + return &abcitypes.CommitResponse{}, nil +} + +func (app *KVStoreApplication) ListSnapshots(_ context.Context, snapshots *abcitypes.ListSnapshotsRequest) (*abcitypes.ListSnapshotsResponse, error) { + return &abcitypes.ListSnapshotsResponse{}, nil +} + +func (app *KVStoreApplication) OfferSnapshot(_ context.Context, snapshot *abcitypes.OfferSnapshotRequest) (*abcitypes.OfferSnapshotResponse, error) { + return &abcitypes.OfferSnapshotResponse{}, nil +} + +func (app *KVStoreApplication) LoadSnapshotChunk(_ context.Context, chunk *abcitypes.LoadSnapshotChunkRequest) (*abcitypes.LoadSnapshotChunkResponse, error) { + return &abcitypes.LoadSnapshotChunkResponse{}, nil +} + +func (app *KVStoreApplication) ApplySnapshotChunk(_ context.Context, chunk *abcitypes.ApplySnapshotChunkRequest) (*abcitypes.ApplySnapshotChunkResponse, error) { + return &abcitypes.ApplySnapshotChunkResponse{Result: abcitypes.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil +} + +func (app KVStoreApplication) ExtendVote(_ context.Context, extend *abcitypes.ExtendVoteRequest) (*abcitypes.ExtendVoteResponse, error) { + return &abcitypes.ExtendVoteResponse{}, nil +} + +func (app *KVStoreApplication) VerifyVoteExtension(_ context.Context, verify *abcitypes.VerifyVoteExtensionRequest) (*abcitypes.VerifyVoteExtensionResponse, error) { + return &abcitypes.VerifyVoteExtensionResponse{}, nil +} +``` + +The types used here are defined in the CometBFT library and were added as a dependency +to the project when you ran `go get`. If your IDE is not recognizing the types, go ahead and run the command again. + +```bash +go get github.com/cometbft/cometbft@v1.0 +``` + +Now go back to the `main.go` and modify the `main` function so it matches the following, +where an instance of the `KVStoreApplication` type is created. + +```go +func main() { + fmt.Println("Hello, CometBFT") + + _ = NewKVStoreApplication() +} +``` + +You can recompile and run the application now by running `go get` and `go build`, but it does +not do anything. +So let's revisit the code adding the logic needed to implement our minimal key/value store +and to start it along with the CometBFT Service. + +### 1.3.1 Add a persistent data store + +Our application will need to write its state out to persistent storage so that it +can stop and start without losing all of its data. + +For this tutorial, we will use [BadgerDB](https://github.com/dgraph-io/badger), a +fast embedded key-value store. + +First, add Badger as a dependency of your go module using the `go get` command: + +`go get github.com/dgraph-io/badger/v3` + +Next, let's update the application and its constructor to receive a handle to the database, as follows: + +```go +type KVStoreApplication struct { + db *badger.DB + onGoingBlock *badger.Txn +} + +var _ abcitypes.Application = (*KVStoreApplication)(nil) + +func NewKVStoreApplication(db *badger.DB) *KVStoreApplication { + return &KVStoreApplication{db: db} +} +``` + +The `onGoingBlock` keeps track of the Badger transaction that will update the application's state when a block +is completed. Don't worry about it for now, we'll get to that later. + +Next, update the `import` stanza at the top to include the Badger library: + +```go +import( + "context" + abcitypes "github.com/cometbft/cometbft/abci/types" + "github.com/dgraph-io/badger/v4" +) +``` + +Finally, update the `main.go` file to invoke the updated constructor: + +```go + _ = NewKVStoreApplication(nil) +``` + +### 1.3.2 CheckTx + +When CometBFT receives a new transaction from a client, or from another full node, +CometBFT asks the application if the transaction is acceptable, using the `CheckTx` method. +Invalid transactions will not be shared with other nodes and will not become part of any blocks and, therefore, will not be executed by the application. + +In our application, a transaction is a string with the form `key=value`, indicating a key and value to write to the store. + +The most basic validation check we can perform is to check if the transaction conforms to the `key=value` pattern. +For that, let's add the following helper method to app.go: + +```go +func (app *KVStoreApplication) isValid(tx []byte) uint32 { + // check format + parts := bytes.Split(tx, []byte("=")) + if len(parts) != 2 { + return 1 + } + + return 0 +} +``` + +Now you can rewrite the `CheckTx` method to use the helper function: + +```go +func (app *KVStoreApplication) CheckTx(_ context.Context, check *abcitypes.CheckTxRequest) (*abcitypes.CheckTxResponse, error) { + code := app.isValid(check.Tx) + return &abcitypes.CheckTxResponse{Code: code}, nil +} +``` + +While this `CheckTx` is simple and only validates that the transaction is well-formed, +it is very common for `CheckTx` to make more complex use of the state of an application. +For example, you may refuse to overwrite an existing value, or you can associate +versions to the key/value pairs and allow the caller to specify a version to +perform a conditional update. + +Depending on the checks and on the conditions violated, the function may return +different values, but any response with a non-zero code will be considered invalid +by CometBFT. Our `CheckTx` logic returns 0 to CometBFT when a transaction passes +its validation checks. The specific value of the code is meaningless to CometBFT. +Non-zero codes are logged by CometBFT so applications can provide more specific +information on why the transaction was rejected. + +Note that `CheckTx` does not execute the transaction, it only verifies that the transaction could be executed. We do +not know yet if the rest of the network has agreed to accept this transaction into a block. + +Finally, make sure to add the `bytes` package to the `import` stanza at the top of `app.go`: + +```go +import( + "bytes" + "context" + abcitypes "github.com/cometbft/cometbft/abci/types" + "github.com/dgraph-io/badger/v4" +) +``` + +### 1.3.3 FinalizeBlock + +When the CometBFT consensus engine has decided on the block, the block is transferred to the +application via `FinalizeBlock`. +`FinalizeBlock` is an ABCI method introduced in CometBFT `v0.38.0`. This replaces the functionality provided previously (pre-`v0.38.0`) by the combination of ABCI methods `BeginBlock`, `DeliverTx`, and `EndBlock`. `FinalizeBlock`'s parameters are an aggregation of those in `BeginBlock`, `DeliverTx`, and `EndBlock`. + +This method is responsible for executing the block and returning a response to the consensus engine. +Providing a single `FinalizeBlock` method to signal the finalization of a block simplifies the ABCI interface and increases flexibility in the execution pipeline. + +The `FinalizeBlock` method executes the block, including any necessary transaction processing and state updates, and returns a `FinalizeBlockResponse` object which contains any necessary information about the executed block. + +**Note:** `FinalizeBlock` only prepares the update to be made and does not change the state of the application. The state change is actually committed in a later stage, in the `Commit` phase. + +Note that, to implement these calls in our application we're going to make use of Badger's transaction mechanism. We will always refer to these as Badger transactions, not to confuse them with the transactions included in the blocks delivered by CometBFT, the _application transactions_. + +First, let's create a new Badger transaction during `FinalizeBlock`. All application transactions in the current block will be executed within this Badger transaction. +Next, let's modify `FinalizeBlock` to add the `key` and `value` to the Badger transaction every time our application processes a new application transaction from the list received through `FinalizeBlockRequest`. + +Note that we check the validity of the transaction _again_ during `FinalizeBlock`. + +```go +func (app *KVStoreApplication) FinalizeBlock(_ context.Context, req *abcitypes.FinalizeBlockRequest) (*abcitypes.FinalizeBlockResponse, error) { + var txs = make([]*abcitypes.ExecTxResult, len(req.Txs)) + + app.onGoingBlock = app.db.NewTransaction(true) + for i, tx := range req.Txs { + if code := app.isValid(tx); code != 0 { + log.Printf("Error: invalid transaction index %v", i) + txs[i] = &abcitypes.ExecTxResult{Code: code} + } else { + parts := bytes.SplitN(tx, []byte("="), 2) + key, value := parts[0], parts[1] + log.Printf("Adding key %s with value %s", key, value) + + if err := app.onGoingBlock.Set(key, value); err != nil { + log.Panicf("Error writing to database, unable to execute tx: %v", err) + } + + log.Printf("Successfully added key %s with value %s", key, value) + + // Add an event for the transaction execution. + // Multiple events can be emitted for a transaction, but we are adding only one event + txs[i] = &abcitypes.ExecTxResult{ + Code: 0, + Events: []abcitypes.Event{ + { + Type: "app", + Attributes: []abcitypes.EventAttribute{ + {Key: "key", Value: string(key), Index: true}, + {Key: "value", Value: string(value), Index: true}, + }, + }, + }, + } + } + } + + return &abcitypes.FinalizeBlockResponse{ + TxResults: txs, + }, nil +} +``` + +Transactions are not guaranteed to be valid when they are delivered to an application, even if they were valid when they were proposed. + +This can happen if the application state is used to determine transaction validity. +The application state may have changed between the initial execution of `CheckTx` and the transaction delivery in `FinalizeBlock` in a way that rendered the transaction no longer valid. + +**Note** that `FinalizeBlock` cannot yet commit the Badger transaction we were building during the block execution. + +Other methods, such as `Query`, rely on a consistent view of the application's state, the application should only update its state by committing the Badger transactions when the full block has been delivered and the Commit method is invoked. + +The `Commit` method tells the application to make permanent the effects of +the application transactions. +Let's update the method to terminate the pending Badger transaction and +persist the resulting state: + +```go +func (app KVStoreApplication) Commit(_ context.Context, commit *abcitypes.CommitRequest) (*abcitypes.CommitResponse, error) { + return &abcitypes.CommitResponse{}, app.onGoingBlock.Commit() +} +``` + +Finally, make sure to add the `log` and `errors` libraries to the `import` stanza as well: + +```go +import ( + "context" + "errors" + abcitypes "github.com/cometbft/cometbft/abci/types" + "github.com/dgraph-io/badger/v4" + "log" +) +``` + +You may have noticed that the application we are writing will crash if it receives +an unexpected error from the Badger database during the `FinalizeBlock` or `Commit` methods. +This is not an accident. If the application received an error from the database, there +is no deterministic way for it to make progress so the only safe option is to terminate. +Once the application is restarted, the transactions in the block that failed execution will +be re-executed and should succeed if the Badger error was transient. + +### 1.3.4 Query + +When a client tries to read some information from the `kvstore`, the request will be +handled in the `Query` method. To do this, let's rewrite the `Query` method in `app.go`: + +```go +func (app *KVStoreApplication) Query(_ context.Context, req *abcitypes.QueryRequest) (*abcitypes.QueryResponse, error) { + resp := abcitypes.QueryResponse{Key: req.Data} + + dbErr := app.db.View(func(txn *badger.Txn) error { + item, err := txn.Get(req.Data) + if err != nil { + if !errors.Is(err, badger.ErrKeyNotFound) { + return err + } + resp.Log = "key does not exist" + return nil + } + + return item.Value(func(val []byte) error { + resp.Log = "exists" + resp.Value = val + return nil + }) + }) + if dbErr != nil { + log.Panicf("Error reading database, unable to execute query: %v", dbErr) + } + return &resp, nil +} +``` + +Since it reads only committed data from the store, transactions that are part of a block +that is being processed are not reflected in the query result. + +### 1.3.5 PrepareProposal and ProcessProposal + +`PrepareProposal` and `ProcessProposal` are methods introduced in CometBFT v0.37.0 +to give the application more control over the construction and processing of transaction blocks. + +When CometBFT sees that valid transactions (validated through `CheckTx`) are available to be +included in blocks, it groups some of these transactions and then gives the application a chance +to modify the group by invoking `PrepareProposal`. + +The application is free to modify the group before returning from the call, as long as the resulting set +does not use more bytes than `PrepareProposalRequest.max_tx_bytes` +For example, the application may reorder, add, or even remove transactions from the group to improve the +execution of the block once accepted. + +In the following code, the application simply returns the unmodified group of transactions: + +```go +func (app *KVStoreApplication) PrepareProposal(_ context.Context, proposal *abcitypes.PrepareProposalRequest) (*abcitypes.PrepareProposalResponse, error) { + return &abcitypes.PrepareProposalResponse{Txs: proposal.Txs}, nil +} +``` + +Once a proposed block is received by a node, the proposal is passed to the application to give +its blessing before voting to accept the proposal. + +This mechanism may be used for different reasons, for example to deal with blocks manipulated +by malicious nodes, in which case the block should not be considered valid. + +The following code simply accepts all proposals: + +```go +func (app *KVStoreApplication) ProcessProposal(_ context.Context, proposal *abcitypes.ProcessProposalRequest) (*abcitypes.ProcessProposalResponse, error) { + return &abcitypes.ProcessProposalResponse{Status: abcitypes.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil +} +``` + +## 1.4 Starting an application and a CometBFT instance in the same process + +Now that we have the basic functionality of our application in place, let's put +it all together inside of our `main.go` file. + +Change the contents of your `main.go` file to the following. + +```go +package main + +import ( + "flag" + "fmt" + "github.com/cometbft/cometbft/p2p" + "github.com/cometbft/cometbft/privval" + "github.com/cometbft/cometbft/proxy" + "log" + "os" + "os/signal" + "path/filepath" + "syscall" + + "github.com/dgraph-io/badger/v4" + "github.com/spf13/viper" + cfg "github.com/cometbft/cometbft/config" + cmtflags "github.com/cometbft/cometbft/libs/cli/flags" + cmtlog "github.com/cometbft/cometbft/libs/log" + nm "github.com/cometbft/cometbft/node" +) + +var homeDir string + +func init() { + flag.StringVar(&homeDir, "cmt-home", "", "Path to the CometBFT config directory (if empty, uses $HOME/.cometbft)") +} + +func main() { + flag.Parse() + if homeDir == "" { + homeDir = os.ExpandEnv("$HOME/.cometbft") + } + + config := cfg.DefaultConfig() + config.SetRoot(homeDir) + viper.SetConfigFile(fmt.Sprintf("%s/%s", homeDir, "config/config.toml")) + + if err := viper.ReadInConfig(); err != nil { + log.Fatalf("Reading config: %v", err) + } + if err := viper.Unmarshal(config); err != nil { + log.Fatalf("Decoding config: %v", err) + } + if err := config.ValidateBasic(); err != nil { + log.Fatalf("Invalid configuration data: %v", err) + } + dbPath := filepath.Join(homeDir, "badger") + db, err := badger.Open(badger.DefaultOptions(dbPath)) + + if err != nil { + log.Fatalf("Opening database: %v", err) + } + defer func() { + if err := db.Close(); err != nil { + log.Printf("Closing database: %v", err) + } + }() + + app := NewKVStoreApplication(db) + + pv := privval.LoadFilePV( + config.PrivValidatorKeyFile(), + config.PrivValidatorStateFile(), + ) + + nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) + if err != nil { + log.Fatalf("failed to load node's key: %v", err) + } + + logger := cmtlog.NewTMLogger(cmtlog.NewSyncWriter(os.Stdout)) + logger, err = cmtflags.ParseLogLevel(config.LogLevel, logger, cfg.DefaultLogLevel) + + if err != nil { + log.Fatalf("failed to parse log level: %v", err) + } + + node, err := nm.NewNode( + config, + pv, + nodeKey, + proxy.NewLocalClientCreator(app), + nm.DefaultGenesisDocProviderFunc(config), + cfg.DefaultDBProvider, + nm.DefaultMetricsProvider(config.Instrumentation), + logger, + ) + + if err != nil { + log.Fatalf("Creating node: %v", err) + } + + node.Start() + defer func() { + node.Stop() + node.Wait() + }() + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + <-c +} +``` + +This is a huge blob of code, so let's break it down into pieces. + +First, we use [viper](https://github.com/spf13/viper) to load the CometBFT configuration files, which we will generate later: + +```go +config := cfg.DefaultValidatorConfig() + +config.SetRoot(homeDir) + +viper.SetConfigFile(fmt.Sprintf("%s/%s", homeDir, "config/config.toml")) +if err := viper.ReadInConfig(); err != nil { + log.Fatalf("Reading config: %v", err) +} +if err := viper.Unmarshal(config); err != nil { + log.Fatalf("Decoding config: %v", err) +} +if err := config.ValidateBasic(); err != nil { + log.Fatalf("Invalid configuration data: %v", err) +} +``` + +Next, we initialize the Badger database and create an app instance. + +```go +dbPath := filepath.Join(homeDir, "badger") +db, err := badger.Open(badger.DefaultOptions(dbPath)) +if err != nil { + log.Fatalf("Opening database: %v", err) +} +defer func() { + if err := db.Close(); err != nil { + log.Fatalf("Closing database: %v", err) + } +}() + +app := NewKVStoreApplication(db) +``` + +We use `FilePV`, which is a private validator (i.e. thing which signs consensus +messages). Normally, you would use `SignerRemote` to connect to an external +[HSM](https://kb.certus.one/hsm.html). + +```go +pv := privval.LoadFilePV( + config.PrivValidatorKeyFile(), + config.PrivValidatorStateFile(), +) +``` + +`nodeKey` is needed to identify the node in a p2p network. + +```go +nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile()) +if err != nil { + return nil, fmt.Errorf("failed to load node's key: %w", err) +} +``` + +Now we have everything set up to run the CometBFT node. We construct +a node by passing it the configuration, the logger, a handle to our application and +the genesis information: + +```go +node, err := nm.NewNode( + config, + pv, + nodeKey, + proxy.NewLocalClientCreator(app), + nm.DefaultGenesisDocProviderFunc(config), + cfg.DefaultDBProvider, + nm.DefaultMetricsProvider(config.Instrumentation), + logger) + +if err != nil { + log.Fatalf("Creating node: %v", err) +} +``` + +Finally, we start the node, i.e., the CometBFT service inside our application: + +```go +node.Start() +defer func() { + node.Stop() + node.Wait() +}() +``` + +The additional logic at the end of the file allows the program to catch SIGTERM. This means that the node can shut down gracefully when an operator tries to kill the program: + +```go +c := make(chan os.Signal, 1) +signal.Notify(c, os.Interrupt, syscall.SIGTERM) +<-c +``` + +Try again to build the code to ensure it is all good so far: + +```bash +go build +``` + +If there are no errors, everything worked well so far. But if you get some errors about `missing go.sum entry for module ...`, +you can try to fix them by running the commands below: + +```bash +go mod tidy +go build +``` + +## 1.5 Initializing and Running + +Our application is almost ready to run, but first we'll need to populate the CometBFT configuration files. +The following command will create a `cometbft-home` directory in your project and add a basic set of configuration files in `cometbft-home/config/`. +For more information on what these files contain see [the configuration documentation](https://docs.cometbft.com/v1.0/explanation/core/configuration). + +From the root of your project, run: + +```bash +cometbft init --home /tmp/cometbft-home +``` + +You should see an output similar to the following: + +```bash +I[2023-25-04|09:06:34.444] Generated private validator module=main keyFile=/tmp/cometbft-home/config/priv_validator_key.json stateFile=/tmp/cometbft-home/data/priv_validator_state.json +I[2023-25-04|09:06:34.444] Generated node key module=main path=/tmp/cometbft-home/config/node_key.json +I[2023-25-04|09:06:34.444] Generated genesis file module=main path=/tmp/cometbft-home/config/genesis.json +``` + +Now rebuild the app: + +```bash +go build -mod=mod # use -mod=mod to automatically refresh the dependencies +``` + +Everything is now in place to run your application. Run: + +```bash +./kvstore -cmt-home /tmp/cometbft-home +``` + +The application will start and you should see a continuous output starting with: + +```bash +badger 2023-04-25 09:08:50 INFO: All 0 tables opened in 0s +badger 2023-04-25 09:08:50 INFO: Discard stats nextEmptySlot: 0 +badger 2023-04-25 09:08:50 INFO: Set nextTxnTs to 0 +I[2023-04-25|09:08:50.085] service start module=proxy msg="Starting multiAppConn service" impl=multiAppConn +I[2023-04-25|09:08:50.085] service start module=abci-client connection=query msg="Starting localClient service" impl=localClient +I[2023-04-25|09:08:50.085] service start module=abci-client connection=snapshot msg="Starting localClient service" impl=localClient +... +``` + +More importantly, the application using CometBFT is producing blocks 🎉🎉 and you can see this reflected in the log output in lines like this: + +```bash +I[2023-04-25|09:08:52.147] received proposal module=consensus proposal="Proposal{2/0 (F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C:1:C73D3D1273F2, -1) AD19AE292A45 @ 2023-04-25T12:08:52.143393Z}" +I[2023-04-25|09:08:52.152] received complete proposal block module=consensus height=2 hash=F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C +I[2023-04-25|09:08:52.160] finalizing commit of block module=consensus height=2 hash=F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C root= num_txs=0 +I[2023-04-25|09:08:52.167] executed block module=state height=2 num_valid_txs=0 num_invalid_txs=0 +I[2023-04-25|09:08:52.171] committed state module=state height=2 num_txs=0 app_hash= +``` + +The blocks, as you can see from the `num_valid_txs=0` part, are empty, but let's remedy that next. + +## 1.6 Using the application + +Let's try submitting a transaction to our new application. +Open another terminal window and run the following curl command: + +```bash +curl -s 'localhost:26657/broadcast_tx_commit?tx="cometbft=rocks"' +``` + +If everything went well, you should see a response indicating which height the +transaction was included in the blockchain. + +```bash +{"jsonrpc":"2.0","id":-1,"result":{"check_tx":{"code":0,"data":null,"log":"","info":"","gas_wanted":"0","gas_used":"0","events":[],"codespace":""},"tx_result":{"code":0,"data":null,"log":"","info":"","gas_wanted":"0","gas_used":"0","events":[{"type":"app","attributes":[{"key":"key","value":"cometbft","index":true},{"key":"value","value":"rocks","index":true}]}],"codespace":""},"hash":"71276C4844CE72F6C6C868541D10923259F5F8DA5716B230555B36AD309D6FD1","height":"64"}} +``` + +Finally, let's make sure that transaction really was persisted by the application. +Run the following command: + +```bash +curl -s 'localhost:26657/abci_query?data="cometbft"' +``` + +Let's examine the response object that this request returns. +The request returns a `json` object with a `key` and `value` field set. + +```json +... + "key": "Y29tZXRiZnQ=", + "value": "cm9ja3M=", +... +``` + +Those values don't look like the `key` and `value` we sent to CometBFT. +What's going on here? + +The response contains a `base64` encoded representation of the data we submitted. +To get the original value out of this data, we can use the `base64` command line utility: + +```bash +$ echo "Y29tZXRiZnQ=" | base64 -d +cometbft +$ echo "cm9ja3M=" | base64 -d +rocks +``` +If you want to search for txs, you can leverage `CometBFT` kv indexer by using the `/tx_search` RPC endpoint: +```bash +curl "localhost:26657/tx_search?query=\"app.key='cometbft'\"" +``` +The events (`abcitypes.Event`) added in `FinalizeBlock` are indexed by CometBFT (assuming the `kv` indexer is enabled in the CometBFT's configuration). + + +## Outro + +Hope you could run everything smoothly. If you have any difficulties running through this tutorial, reach out to us via [discord](https://discord.com/invite/cosmosnetwork) or open a new [issue](https://github.com/cometbft/cometbft/issues/new/choose) on Github. diff --git a/docs/tutorials/go.md b/docs/tutorials/go.md new file mode 100644 index 00000000000..7c7fb78114e --- /dev/null +++ b/docs/tutorials/go.md @@ -0,0 +1,807 @@ +--- +order: 1 +--- + +# Creating an application in Go + +## Guide Assumptions + +This guide is designed for beginners who want to get started with a CometBFT +application from scratch. It does not assume that you have any prior +experience with CometBFT. + +CometBFT is a service that provides a Byzantine Fault Tolerant consensus engine +for state-machine replication. The replicated state-machine, or "application", can be written +in any language that can send and receive protocol buffer messages in a client-server model. +Applications written in Go can also use CometBFT as a library and run the service in the same +process as the application. + +By following along this tutorial you will create a CometBFT application called kvstore, +a (very) simple distributed BFT key-value store. +The application will be written in Go and +some understanding of the Go programming language is expected. +If you have never written Go, you may want to go through [Learn X in Y minutes +Where X=Go](https://learnxinyminutes.com/docs/go/) first, to familiarize +yourself with the syntax. + +Note: Please use the latest released version of this guide and of CometBFT. +We strongly advise against using unreleased commits for your development. + +### Built-in app vs external app + +On the one hand, to get maximum performance you can run your application in +the same process as the CometBFT, as long as your application is written in Go. +[Cosmos SDK](https://github.com/cosmos/cosmos-sdk) is written +this way. +If that is the way you wish to proceed, use the [Creating a built-in application in Go](go-built-in.md) guide instead of this one. + +On the other hand, having a separate application might give you better security +guarantees as two processes would be communicating via established binary protocol. +CometBFT will not have access to application's state. +This is the approach followed in this tutorial. + +## 1.0 Installing Go + +Verify that you have the latest version of Go installed (refer to the [official guide for installing Go](https://golang.org/doc/install)), you should see an output similar to this one (the `go version` might be a slight different depending on the Go you have installed and the computer platform): + +```bash +$ go version +go version go1.22.2 darwin/amd64 +``` + +## 1.1 Installing CometBFT + +Let's install `CometBFT` locally by running the following command: + +```bash +go install github.com/cometbft/cometbft/cmd/cometbft@v1.0 +``` + +Test the installation: + +```bash +$ cometbft version +v1.0.0 +``` + +## 1.2 Creating a new Go project + +We'll start by creating a new Go project and moving into the new directory: + +```bash +mkdir kvstore +cd kvstore +``` + +Inside the `kvstore` directory, create a `main.go` file with the following content: + +```go +package main + +import ( + "fmt" +) + +func main() { + fmt.Println("Hello, CometBFT") +} +``` + +Run the following command: + +```bash +go run main.go +``` + +This should print "Hello, CometBFT" to the standard output. + +```bash +Hello, CometBFT +``` + +We are going to use [Go modules](https://github.com/golang/go/wiki/Modules) for +dependency management, so let's start by including a dependency on the latest version of +CometBFT, `v1.0` in this example. + +Run the commands below to create the go module file (`go.mod`) + +```bash +go mod init kvstore +```` + +This should an output similar to this. + +**NOTE**: No need to run `go mod tidy` at this time, just ignore it for now. +```bash +go: creating new go.mod: module kvstore +go: to add module requirements and sums: + go mod tidy +``` + +Now, lets add `cometbft` as a dependency to our project. Run the `go get` command below: + +```bash +go get github.com/cometbft/cometbft@v1.0 +``` + +**NOTE**: This will add the latest release in the `v1.0` line, so you might a different patch release e.g. `v1.0.0` +or `v1.0.1` + +```bash +go: added github.com/cometbft/cometbft v1.0.0 +``` + +After running the above commands you will see two generated files, `go.mod` and `go.sum`. +The go.mod file should look similar to: + +```go +module kvstore + +go 1.22.2 + + +require github.com/cometbft/cometbft v1.0.0 // indirect +``` + +As you write the kvstore application, you can rebuild the binary by +pulling any new dependencies and recompiling it. + +```bash +go get +go build +``` + +At this point, if you ran the `go build` command above, you should see four files in the directory: + +```bash +$ ls +go.mod go.sum kvstore main.go +``` + +The `kvstore` file is the executable generated. You can run it again to ensure everything still works: + +```bash +$ ./kvstore +Hello, CometBFT +``` + +## 1.3 Writing a CometBFT application + +Now, let's start adding some logic to our application. + +CometBFT communicates with the application through the Application +BlockChain Interface (`ABCI`). The messages exchanged through the interface are +defined in the ABCI [protobuf +file](https://github.com/cometbft/cometbft/blob/main/proto/cometbft/abci/v1/types.proto). + +We begin by creating the basic scaffolding for an ABCI application by +creating a new type, `KVStoreApplication`, which implements the +methods defined by the [abcitypes.Application](https://github.com/cometbft/cometbft/blob/main/abci/types/application.go) interface. + +Create a file called `app.go` with the following contents: + +```go +package main + +import ( + abcitypes "github.com/cometbft/cometbft/abci/types" + "context" +) + +type KVStoreApplication struct{} + +var _ abcitypes.Application = (*KVStoreApplication)(nil) + +func NewKVStoreApplication() *KVStoreApplication { + return &KVStoreApplication{} +} + +func (app *KVStoreApplication) Info(_ context.Context, info *abcitypes.InfoRequest) (*abcitypes.InfoResponse, error) { + return &abcitypes.InfoResponse{}, nil +} + +func (app *KVStoreApplication) Query(_ context.Context, req *abcitypes.QueryRequest) (*abcitypes.QueryResponse, error) { + return &abcitypes.QueryResponse{}, nil +} + +func (app *KVStoreApplication) CheckTx(_ context.Context, check *abcitypes.CheckTxRequest) (*abcitypes.CheckTxResponse, error) { + return &abcitypes.CheckTxResponse{Code: 0}, nil +} + +func (app *KVStoreApplication) InitChain(_ context.Context, chain *abcitypes.InitChainRequest) (*abcitypes.InitChainResponse, error) { + return &abcitypes.InitChainResponse{}, nil +} + +func (app *KVStoreApplication) PrepareProposal(_ context.Context, proposal *abcitypes.PrepareProposalRequest) (*abcitypes.PrepareProposalResponse, error) { + return &abcitypes.PrepareProposalResponse{}, nil +} + +func (app *KVStoreApplication) ProcessProposal(_ context.Context, proposal *abcitypes.ProcessProposalRequest) (*abcitypes.ProcessProposalResponse, error) { + return &abcitypes.ProcessProposalResponse{}, nil +} + +func (app *KVStoreApplication) FinalizeBlock(_ context.Context, req *abcitypes.FinalizeBlockRequest) (*abcitypes.FinalizeBlockResponse, error) { + return &abcitypes.FinalizeBlockResponse{}, nil +} + +func (app KVStoreApplication) Commit(_ context.Context, commit *abcitypes.CommitRequest) (*abcitypes.CommitResponse, error) { + return &abcitypes.CommitResponse{}, nil +} + +func (app *KVStoreApplication) ListSnapshots(_ context.Context, snapshots *abcitypes.ListSnapshotsRequest) (*abcitypes.ListSnapshotsResponse, error) { + return &abcitypes.ListSnapshotsResponse{}, nil +} + +func (app *KVStoreApplication) OfferSnapshot(_ context.Context, snapshot *abcitypes.OfferSnapshotRequest) (*abcitypes.OfferSnapshotResponse, error) { + return &abcitypes.OfferSnapshotResponse{}, nil +} + +func (app *KVStoreApplication) LoadSnapshotChunk(_ context.Context, chunk *abcitypes.LoadSnapshotChunkRequest) (*abcitypes.LoadSnapshotChunkResponse, error) { + return &abcitypes.LoadSnapshotChunkResponse{}, nil +} + +func (app *KVStoreApplication) ApplySnapshotChunk(_ context.Context, chunk *abcitypes.ApplySnapshotChunkRequest) (*abcitypes.ApplySnapshotChunkResponse, error) { + return &abcitypes.ApplySnapshotChunkResponse{Result: abcitypes.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil +} + +func (app KVStoreApplication) ExtendVote(_ context.Context, extend *abcitypes.ExtendVoteRequest) (*abcitypes.ExtendVoteResponse, error) { + return &abcitypes.ExtendVoteResponse{}, nil +} + +func (app *KVStoreApplication) VerifyVoteExtension(_ context.Context, verify *abcitypes.VerifyVoteExtensionRequest) (*abcitypes.VerifyVoteExtensionResponse, error) { + return &abcitypes.VerifyVoteExtensionResponse{}, nil +} +``` + +The types used here are defined in the CometBFT library and were added as a dependency +to the project when you ran `go get`. If your IDE is not recognizing the types, go ahead and run the command again. + +```bash +go get github.com/cometbft/cometbft@v1.0 +``` + +Now go back to the `main.go` and modify the `main` function so it matches the following, +where an instance of the `KVStoreApplication` type is created. + +```go +func main() { + fmt.Println("Hello, CometBFT") + + _ = NewKVStoreApplication() +} +``` + +You can recompile and run the application now by running `go get` and `go build`, but it does +not do anything. +So let's revisit the code adding the logic needed to implement our minimal key/value store +and to start it along with the CometBFT Service. + +### 1.3.1 Add a persistent data store + +Our application will need to write its state out to persistent storage so that it +can stop and start without losing all of its data. + +For this tutorial, we will use [BadgerDB](https://github.com/dgraph-io/badger), a +a fast embedded key-value store. + +First, add Badger as a dependency of your go module using the `go get` command: + +`go get github.com/dgraph-io/badger/v4` + +Next, let's update the application and its constructor to receive a handle to the database, as follows: + +```go +type KVStoreApplication struct { + db *badger.DB + onGoingBlock *badger.Txn +} + +var _ abcitypes.Application = (*KVStoreApplication)(nil) + +func NewKVStoreApplication(db *badger.DB) *KVStoreApplication { + return &KVStoreApplication{db: db} +} +``` + +The `onGoingBlock` keeps track of the Badger transaction that will update the application's state when a block +is completed. Don't worry about it for now, we'll get to that later. + +Next, update the `import` stanza at the top to include the Badger library: + +```go +import ( + "context" + abcitypes "github.com/cometbft/cometbft/abci/types" + "github.com/dgraph-io/badger/v4" +) +``` + +Finally, update the `main.go` file to invoke the updated constructor: + +```go +_ = NewKVStoreApplication(nil) +``` + +### 1.3.2 CheckTx + +When CometBFT receives a new transaction from a client, or from another full node, +CometBFT asks the application if the transaction is acceptable, using the `CheckTx` method. +Invalid transactions will not be shared with other nodes and will not become part of any blocks and, therefore, will not be executed by the application. + +In our application, a transaction is a string with the form `key=value`, indicating a key and value to write to the store. + +The most basic validation check we can perform is to check if the transaction conforms to the `key=value` pattern. +For that, let's add the following helper method to app.go: + +```go +func (app *KVStoreApplication) isValid(tx []byte) uint32 { + // check format + parts := bytes.Split(tx, []byte("=")) + if len(parts) != 2 { + return 1 + } + return 0 +} +``` + +Now you can rewrite the `CheckTx` method to use the helper function: + +```go +func (app *KVStoreApplication) CheckTx(_ context.Context, check *abcitypes.CheckTxRequest) (*abcitypes.CheckTxResponse, error) { + code := app.isValid(check.Tx) + return &abcitypes.CheckTxResponse{Code: code}, nil +} +``` + +While this `CheckTx` is simple and only validates that the transaction is well-formed, +it is very common for `CheckTx` to make more complex use of the state of an application. +For example, you may refuse to overwrite an existing value, or you can associate +versions to the key/value pairs and allow the caller to specify a version to +perform a conditional update. + +Depending on the checks and on the conditions violated, the function may return +different values, but any response with a non-zero code will be considered invalid +by CometBFT. Our `CheckTx` logic returns 0 to CometBFT when a transaction passes +its validation checks. The specific value of the code is meaningless to CometBFT. +Non-zero codes are logged by CometBFT so applications can provide more specific +information on why the transaction was rejected. + +Note that `CheckTx` does not execute the transaction, it only verifies that the transaction could be executed. We do +not know yet if the rest of the network has agreed to accept this transaction into a block. + +Finally, make sure to add the bytes package to the `import` stanza at the top of `app.go`: + +```go +import ( + "bytes" + "context" + abcitypes "github.com/cometbft/cometbft/abci/types" + "github.com/dgraph-io/badger/v4" +) +``` + +### 1.3.3 FinalizeBlock + +When the CometBFT consensus engine has decided on the block, the block is transferred to the +application via the `FinalizeBlock` method. +`FinalizeBlock` is an ABCI method introduced in CometBFT `v0.38.0`. This replaces the functionality provided previously (pre-`v0.38.0`) by the combination of ABCI methods `BeginBlock`, `DeliverTx`, and `EndBlock`. +`FinalizeBlock`'s parameters are an aggregation of those in `BeginBlock`, `DeliverTx`, and `EndBlock`. + +This method is responsible for executing the block and returning a response to the consensus engine. +Providing a single `FinalizeBlock` method to signal the finalization of a block simplifies the ABCI interface and increases flexibility in the execution pipeline. + +The `FinalizeBlock` method executes the block, including any necessary transaction processing and state updates, and returns a `FinalizeBlockResponse` object which contains any necessary information about the executed block. + +**Note:** `FinalizeBlock` only prepares the update to be made and does not change the state of the application. The state change is actually committed in a later stage, in the `Commit` phase. + +Note that, to implement these calls in our application we're going to make use of Badger's transaction mechanism. We will always refer to these as Badger transactions, not to confuse them with the transactions included in the blocks delivered by CometBFT, the _application transactions_. + +First, let's create a new Badger transaction during `FinalizeBlock`. All application transactions in the current block will be executed within this Badger transaction. +Next, let's modify `FinalizeBlock` to add the `key` and `value` to the database transaction every time our application processes a new application transaction from the list received through `FinalizeBlockRequest`. + +Note that we check the validity of the transaction _again_ during `FinalizeBlock`. + +```go +func (app *KVStoreApplication) FinalizeBlock(_ context.Context, req *abcitypes.FinalizeBlockRequest) (*abcitypes.FinalizeBlockResponse, error) { + var txs = make([]*abcitypes.ExecTxResult, len(req.Txs)) + + app.onGoingBlock = app.db.NewTransaction(true) + for i, tx := range req.Txs { + if code := app.isValid(tx); code != 0 { + log.Printf("Error in tx in if") + txs[i] = &abcitypes.ExecTxResult{Code: code} + } else { + parts := bytes.SplitN(tx, []byte("="), 2) + key, value := parts[0], parts[1] + log.Printf("Adding key %s with value %s", key, value) + + if err := app.onGoingBlock.Set(key, value); err != nil { + log.Panicf("Error writing to database, unable to execute tx: %v", err) + } + log.Printf("Successfully added key %s with value %s", key, value) + + // Add an event for the transaction execution. + // Multiple events can be emitted for a transaction, but we are adding only one event + txs[i] = &abcitypes.ExecTxResult{ + Code: 0, + Events: []abcitypes.Event{ + { + Type: "app", + Attributes: []abcitypes.EventAttribute{ + {Key: "key", Value: string(key), Index: true}, + {Key: "value", Value: string(value), Index: true}, + }, + }, + }, + } + } + } + + return &abcitypes.FinalizeBlockResponse{ + TxResults: txs, + }, nil +} +``` + +Transactions are not guaranteed to be valid when they are delivered to an application, even if they were valid when they were proposed. + +This can happen if the application state is used to determine transaction validity. The application state may have changed between the initial execution of `CheckTx` and the transaction delivery in `FinalizeBlock` in a way that rendered the transaction no longer valid. + +**Note** that `FinalizeBlock` cannot yet commit the Badger transaction we were building during the block execution. + +Other methods, such as `Query`, rely on a consistent view of the application's state, the application should only update its state by committing the Badger transactions when the full block has been delivered and the `Commit` method is invoked. + +The `Commit` method tells the application to make permanent the effects of the application transactions. +Let's update the method to terminate the pending Badger transaction and persist the resulting state: + +```go +func (app KVStoreApplication) Commit(_ context.Context, commit *abcitypes.CommitRequest) (*abcitypes.CommitResponse, error) { + return &abcitypes.CommitResponse{}, app.onGoingBlock.Commit() +} +``` + +Finally, make sure to add the `log` and `errors` libraries to the `import` stanza as well: + +```go +import ( + "bytes" + "context" + "errors" + abcitypes "github.com/cometbft/cometbft/abci/types" + "github.com/dgraph-io/badger/v4" + "log" +) +``` + +You may have noticed that the application we are writing will crash if it receives +an unexpected error from the Badger database during the `FinalizeBlock` or `Commit` methods. +This is not an accident. If the application received an error from the database, there +is no deterministic way for it to make progress so the only safe option is to terminate. + +### 1.3.4 Query + +When a client tries to read some information from the `kvstore`, the request will be +handled in the `Query` method. To do this, let's rewrite the `Query` method in `app.go`: + +```go +func (app *KVStoreApplication) Query(_ context.Context, req *abcitypes.QueryRequest) (*abcitypes.QueryResponse, error) { + resp := abcitypes.QueryResponse{Key: req.Data} + + dbErr := app.db.View(func(txn *badger.Txn) error { + item, err := txn.Get(req.Data) + if err != nil { + if !errors.Is(err, badger.ErrKeyNotFound) { + return err + } + resp.Log = "key does not exist" + return nil + } + + return item.Value(func(val []byte) error { + resp.Log = "exists" + resp.Value = val + return nil + }) + }) + if dbErr != nil { + log.Panicf("Error reading database, unable to execute query: %v", dbErr) + } + return &resp, nil +} +``` + +Since it reads only committed data from the store, transactions that are part of a block +that is being processed are not reflected in the query result. + +### 1.3.5 PrepareProposal and ProcessProposal + +`PrepareProposal` and `ProcessProposal` are methods introduced in CometBFT v0.37.0 +to give the application more control over the construction and processing of transaction blocks. + +When CometBFT sees that valid transactions (validated through `CheckTx`) are available to be +included in blocks, it groups some of these transactions and then gives the application a chance +to modify the group by invoking `PrepareProposal`. + +The application is free to modify the group before returning from the call, as long as the resulting set +does not use more bytes than `PrepareProposalRequest.max_tx_bytes'. +For example, the application may reorder, add, or even remove transactions from the group to improve the +execution of the block once accepted. + +In the following code, the application simply returns the unmodified group of transactions: + +```go +func (app *KVStoreApplication) PrepareProposal(_ context.Context, proposal *abcitypes.PrepareProposalRequest) (*abcitypes.PrepareProposalResponse, error) { + return &abcitypes.PrepareProposalResponse{Txs: proposal.Txs}, nil +} +``` + +Once a proposed block is received by a node, the proposal is passed to the +application to determine its validity before voting to accept the proposal. + +This mechanism may be used for different reasons, for example to deal with blocks manipulated +by malicious nodes, in which case the block should not be considered valid. + +The following code simply accepts all proposals: + +```go +func (app *KVStoreApplication) ProcessProposal(_ context.Context, proposal *abcitypes.ProcessProposalRequest) (*abcitypes.ProcessProposalResponse, error) { + return &abcitypes.ProcessProposalResponse{Status: abcitypes.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil +} +``` + +## 1.4 Starting an application and a CometBFT instance + +Now that we have the basic functionality of our application in place, let's put +it all together inside of our `main.go` file. + +Change the contents of your `main.go` file to the following. + +```go +package main + +import ( + "flag" + "fmt" + abciserver "github.com/cometbft/cometbft/abci/server" + "log" + "os" + "os/signal" + "path/filepath" + "syscall" + + "github.com/dgraph-io/badger/v4" + cmtlog "github.com/cometbft/cometbft/libs/log" +) + +var homeDir string +var socketAddr string + +func init() { + flag.StringVar(&homeDir, "kv-home", "", "Path to the kvstore directory (if empty, uses $HOME/.kvstore)") + flag.StringVar(&socketAddr, "socket-addr", "unix://example.sock", "Unix domain socket address (if empty, uses \"unix://example.sock\"") +} + +func main() { + flag.Parse() + if homeDir == "" { + homeDir = os.ExpandEnv("$HOME/.kvstore") + } + + dbPath := filepath.Join(homeDir, "badger") + db, err := badger.Open(badger.DefaultOptions(dbPath)) + if err != nil { + log.Fatalf("Opening database: %v", err) + } + + defer func() { + if err := db.Close(); err != nil { + log.Fatalf("Closing database: %v", err) + } + }() + + app := NewKVStoreApplication(db) + logger := cmtlog.NewTMLogger(cmtlog.NewSyncWriter(os.Stdout)) + + server := abciserver.NewSocketServer(socketAddr, app) + server.SetLogger(logger) + + if err := server.Start(); err != nil { + fmt.Fprintf(os.Stderr, "error starting socket server: %v", err) + + os.Exit(1) + } + defer server.Stop() + + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + <-c +} +``` + +This is a huge blob of code, so let's break it down into pieces. + +First, we initialize the Badger database and create an app instance: + +```go +dbPath := filepath.Join(homeDir, "badger") +db, err := badger.Open(badger.DefaultOptions(dbPath)) +if err != nil { + log.Fatalf("Opening database: %v", err) +} +defer func() { + if err := db.Close(); err != nil { + log.Fatalf("Closing database: %v", err) + } +}() + +app := NewKVStoreApplication(db) +``` + +Then we start the ABCI server and add some signal handling to gracefully stop +it upon receiving SIGTERM or Ctrl-C. CometBFT will act as a client, +which connects to our server and send us transactions and other messages. + +```go +server := abciserver.NewSocketServer(socketAddr, app) +server.SetLogger(logger) + +if err := server.Start(); err != nil { + fmt.Fprintf(os.Stderr, "error starting socket server: %v", err) + os.Exit(1) +} +defer server.Stop() + +c := make(chan os.Signal, 1) +signal.Notify(c, os.Interrupt, syscall.SIGTERM) +<-c +``` + +Try again to build the code to ensure it is all good so far: + +```bash +go build +``` + +If there are no errors, everything worked well so far. But if you get some errors about `missing go.sum entry for module ...`, +you can try to fix them by running the commands below: + +```bash +go mod tidy +go build +``` + +## 1.5 Initializing and Running + +Our application is almost ready to run, but first we'll need to populate the CometBFT configuration files. +The following command will create a `cometbft-home` directory in your project and add a basic set of configuration files in `cometbft-home/config/`. +For more information on what these files contain see [the configuration documentation](https://docs.cometbft.com/v1.0/explanation/core/configuration). + +From the root of your project, run: + +```bash +cometbft init --home /tmp/cometbft-home +``` + +You should see an output similar to the following: + +```bash +I[2023-04-25|09:06:34.444] Generated private validator module=main keyFile=/tmp/cometbft-home/config/priv_validator_key.json stateFile=/tmp/cometbft-home/data/priv_validator_state.json +I[2023-04-25|09:06:34.444] Generated node key module=main path=/tmp/cometbft-home/config/node_key.json +I[2023-04-25|09:06:34.444] Generated genesis file module=main path=/tmp/cometbft-home/config/genesis.json +``` + +Now rebuild the app: + +```bash +go build -mod=mod # use -mod=mod to automatically refresh the dependencies +``` + +Everything is now in place to run your application. Run: + +```bash +./kvstore -kv-home /tmp/badger-home +``` + +The application will start and you should see an output similar to the following: + +```bash +badger 2023-04-25 17:01:28 INFO: All 0 tables opened in 0s +badger 2023-04-25 17:01:28 INFO: Discard stats nextEmptySlot: 0 +badger 2023-04-25 17:01:28 INFO: Set nextTxnTs to 0 +I[2023-04-25|17:01:28.726] service start msg="Starting ABCIServer service" impl=ABCIServer +I[2023-04-25|17:01:28.726] Waiting for new connection... +``` + +Then we need to start CometBFT service and point it to our application. + +Open a new terminal window and cd into the same folder where the app is running (this is important because when you run the `kvstore` command above +a file will be created `example.sock` and you need to run `cometbft` in the same folder so that they can communicate via sockets) + +Then execute the following command: + +```bash +cometbft node --home /tmp/cometbft-home --proxy_app=unix://example.sock +``` + +This should start the full node and connect to our ABCI application, which will be +reflected in the application output. + +```sh +I[2023-04-25|17:07:08.124] service start msg="Starting ABCIServer service" impl=ABCIServer +I[2023-04-25|17:07:08.124] Waiting for new connection... +I[2023-04-25|17:08:12.702] Accepted a new connection +I[2023-04-25|17:08:12.703] Waiting for new connection... +I[2023-04-25|17:08:12.703] Accepted a new connection +I[2023-04-25|17:08:12.703] Waiting for new connection... +``` + +Also, the application using CometBFT Core is producing blocks 🎉🎉 and you can see this reflected in the log output of the service in lines like this: + +```bash +I[2023-04-25|09:08:52.147] received proposal module=consensus proposal="Proposal{2/0 (F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C:1:C73D3D1273F2, -1) AD19AE292A45 @ 2023-04-25T12:08:52.143393Z}" +I[2023-04-25|09:08:52.147] received proposal module=consensus proposal="Proposal{2/0 (F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C:1:C73D3D1273F2, -1) AD19AE292A45 @ 2023-04-25T12:08:52.143393Z}" +I[2023-04-25|09:08:52.152] received complete proposal block module=consensus height=2 hash=F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C +I[2023-04-25|09:08:52.160] finalizing commit of block module=consensus height=2 hash=F518444C0E348270436A73FD0F0B9DFEA758286BEB29482F1E3BEA75330E825C root= num_txs=0 +I[2023-04-25|09:08:52.167] executed block module=state height=2 num_valid_txs=0 num_invalid_txs=0 +I[2023-04-25|09:08:52.171] committed state module=state height=2 num_txs=0 app_hash= +``` + +The blocks, as you can see from the `num_valid_txs=0` part, are empty, but let's remedy that next. + +## 1.6 Using the application + +Let's try submitting a transaction to our new application. +Open another terminal window and run the following curl command: + +```bash +curl -s 'localhost:26657/broadcast_tx_commit?tx="cometbft=rocks"' +``` + +If everything went well, you should see a response indicating which height the +transaction was included in the blockchain. + +```bash +{"jsonrpc":"2.0","id":-1,"result":{"check_tx":{"code":0,"data":null,"log":"","info":"","gas_wanted":"0","gas_used":"0","events":[],"codespace":""},"tx_result":{"code":0,"data":null,"log":"","info":"","gas_wanted":"0","gas_used":"0","events":[{"type":"app","attributes":[{"key":"key","value":"cometbft","index":true},{"key":"value","value":"rocks","index":true}]}],"codespace":""},"hash":"71276C4844CE72F6C6C868541D10923259F5F8DA5716B230555B36AD309D6FD1","height":"64"}} +``` + +Finally, let's make sure that transaction really was persisted by the application. +Run the following command: + +```bash +curl -s 'localhost:26657/abci_query?data="cometbft"' +``` + +Let's examine the response object that this request returns. +The request returns a `json` object with a `key` and `value` field set. + +```json +... + "key": "Y29tZXRiZnQ=", + "value": "cm9ja3M=", +... +``` + +Those values don't look like the `key` and `value` we sent to CometBFT. +What's going on here? + +The response contains a `base64` encoded representation of the data we submitted. +To get the original value out of this data, we can use the `base64` command line utility: + +```bash +$ echo "Y29tZXRiZnQ=" | base64 -d +cometbft +$ echo "cm9ja3M=" | base64 -d +rocks +``` + +If you want to search for txs, you can leverage `CometBFT` kv indexer by using the `/tx_search` RPC endpoint: + +```bash +curl "localhost:26657/tx_search?query=\"app.key='cometbft'\"" +``` + +The events (`abcitypes.Event`) added in `FinalizeBlock` are indexed by CometBFT (assuming the `kv` indexer is enabled in the CometBFT's configuration). + +## Outro + +Hope you could run everything smoothly. If you have any difficulties running through this tutorial, reach out to us via [discord](https://discord.com/invite/cosmosnetwork) or open a new [issue](https://github.com/cometbft/cometbft/issues/new/choose) on Github. diff --git a/docs/guides/install.md b/docs/tutorials/install.md similarity index 61% rename from docs/guides/install.md rename to docs/tutorials/install.md index 366c0c90a27..022edbd61fd 100644 --- a/docs/guides/install.md +++ b/docs/tutorials/install.md @@ -4,6 +4,20 @@ order: 3 # Install CometBFT +## From Go Package + +Install the latest version of CometBFT's Go package: + +```sh +go install github.com/cometbft/cometbft/cmd/cometbft@latest +``` + +Install a specific version of CometBFT's Go package: + +```sh +go install github.com/cometbft/cometbft/cmd/cometbft@v0.38 +``` + ## From Binary To download pre-built binaries, see the [releases page](https://github.com/cometbft/cometbft/releases). @@ -51,15 +65,6 @@ running: cometbft version ``` -## Run - -To start a one-node blockchain with a simple in-process application: - -```sh -cometbft init -cometbft node --proxy_app=kvstore -``` - ## Reinstall If you already have CometBFT installed, and you make updates, simply @@ -75,46 +80,46 @@ git pull origin main make install ``` -## Compile with CLevelDB support +## Compile with RocksDB support -Install [LevelDB](https://github.com/google/leveldb) (minimum version is 1.7). +Install [RocksDB](https://github.com/facebook/rocksdb/blob/main/INSTALL.md). -Install LevelDB with snappy (optionally). Below are commands for Ubuntu: +Ubuntu: ```sh sudo apt-get update -sudo apt install build-essential - -sudo apt-get install libsnappy-dev - -wget https://github.com/google/leveldb/archive/v1.20.tar.gz && \ - tar -zxvf v1.20.tar.gz && \ - cd leveldb-1.20/ && \ - make && \ - sudo cp -r out-static/lib* out-shared/lib* /usr/local/lib/ && \ - cd include/ && \ - sudo cp -r leveldb /usr/local/include/ && \ - sudo ldconfig && \ - rm -f v1.20.tar.gz + +git clone https://github.com/facebook/rocksdb.git +cd rocksdb + +DEBUG_LEVEL=0 make shared_lib install-shared + +export LD_LIBRARY_PATH=/usr/local/lib +``` + +OSX: + +```sh +brew install rocksdb ``` -Set a database backend to `cleveldb`: +Set a database backend to `rocksdb`: ```toml # config/config.toml -db_backend = "cleveldb" +db_backend = "rocksdb" ``` To install CometBFT, run: ```sh -CGO_LDFLAGS="-lsnappy" make install COMETBFT_BUILD_OPTIONS=cleveldb +make install COMETBFT_BUILD_OPTIONS=rocksdb ``` or run: ```sh -CGO_LDFLAGS="-lsnappy" make build COMETBFT_BUILD_OPTIONS=cleveldb +make build COMETBFT_BUILD_OPTIONS=rocksdb ``` which puts the binary in `./build`. diff --git a/docs/guides/quick-start.md b/docs/tutorials/quick-start.md similarity index 76% rename from docs/guides/quick-start.md rename to docs/tutorials/quick-start.md index b0eecf25187..f2f0131f3fe 100644 --- a/docs/guides/quick-start.md +++ b/docs/tutorials/quick-start.md @@ -11,7 +11,7 @@ works and want to get started right away, continue. ## Install -See the [install guide](./install.md). +See the [install guide](install.md). ## Initialization @@ -95,7 +95,7 @@ First create four Ubuntu cloud machines. The following was tested on Digital Ocean Ubuntu 16.04 x64 (3GB/1CPU, 20GB SSD). We'll refer to their respective IP addresses below as IP1, IP2, IP3, IP4. -Then, `ssh` into each machine and install CometBFT following the [instructions](./install.md). +Then, `ssh` into each machine and install CometBFT following the [instructions](install.md). Next, use the `cometbft testnet` command to create four directories of config files (found in `./mytestnet`) and copy each directory to the relevant machine in the cloud, so that each machine has `$HOME/mytestnet/node[0-3]` directory. @@ -108,6 +108,46 @@ cometbft show_node_id --home ./mytestnet/node2 cometbft show_node_id --home ./mytestnet/node3 ``` +Here's a handy Bash script to compile the persistent peers string, which will +be needed for our next step: + +```bash +#!/bin/bash + +# Check if the required argument is provided +if [ $# -eq 0 ]; then + echo "Usage: $0 ..." + exit 1 +fi + +# Command to run on each IP +BASE_COMMAND="cometbft show_node_id --home ./mytestnet/node" + +# Initialize an array to store results +PERSISTENT_PEERS="" + +# Iterate through provided IPs +for i in "${!@}"; do + IP="${!i}" + NODE_IDX=$((i - 1)) # Adjust for zero-based indexing + + echo "Getting ID of $IP (node $NODE_IDX)..." + + # Run the command on the current IP and capture the result + ID=$($BASE_COMMAND$NODE_IDX) + + # Store the result in the array + PERSISTENT_PEERS+="$ID@$IP:26656" + + # Add a comma if not the last IP + if [ $i -lt $# ]; then + PERSISTENT_PEERS+="," + fi +done + +echo "$PERSISTENT_PEERS" +``` + Finally, from each machine, run: ```sh @@ -119,6 +159,6 @@ cometbft node --home ./mytestnet/node3 --proxy_app=kvstore --p2p.persistent_peer Note that after the third node is started, blocks will start to stream in because >2/3 of validators (defined in the `genesis.json`) have come online. -Persistent peers can also be specified in the `config.toml`. See [here](../core/configuration.md) for more information about configuration options. +Persistent peers can also be specified in the `config.toml`. See [here](../explanation/core/configuration.md) for more information about configuration options. Transactions can then be sent as covered in the single, local node example above. diff --git a/go.mod b/go.mod index da6f0c7de42..bd75c896fa6 100644 --- a/go.mod +++ b/go.mod @@ -1,296 +1,159 @@ module github.com/cometbft/cometbft -go 1.20 +go 1.22.2 require ( - github.com/BurntSushi/toml v1.2.1 - github.com/adlio/schema v1.3.3 + github.com/BurntSushi/toml v1.3.2 + github.com/adlio/schema v1.3.4 github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/fortytw2/leaktest v1.3.0 - github.com/go-kit/kit v0.12.0 + github.com/go-kit/kit v0.13.0 github.com/go-kit/log v0.2.1 github.com/go-logfmt/logfmt v0.6.0 - github.com/golang/protobuf v1.5.3 - github.com/golangci/golangci-lint v1.52.0 + github.com/golang/protobuf v1.5.4 // indirect github.com/google/orderedcode v0.0.1 - github.com/gorilla/websocket v1.5.0 - github.com/informalsystems/tm-load-test v1.3.0 - github.com/lib/pq v1.10.7 + github.com/gorilla/websocket v1.5.1 + github.com/lib/pq v1.10.9 github.com/libp2p/go-buffer-pool v0.1.0 github.com/minio/highwayhash v1.0.2 github.com/ory/dockertest v3.3.5+incompatible github.com/pkg/errors v0.9.1 - 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.42.0 + github.com/prometheus/client_golang v1.19.0 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.52.2 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 - github.com/rs/cors v1.8.3 + github.com/rs/cors v1.10.1 github.com/sasha-s/go-deadlock v0.3.1 github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa - 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.7.0 - golang.org/x/net v0.8.0 - google.golang.org/grpc v1.54.0 + github.com/spf13/cobra v1.8.0 + github.com/spf13/viper v1.18.2 + github.com/stretchr/testify v1.9.0 + golang.org/x/crypto v0.22.0 + golang.org/x/net v0.24.0 + google.golang.org/grpc v1.63.2 ) -require ( - github.com/bufbuild/buf v1.15.1 - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 -) +require github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 require ( - github.com/Masterminds/semver/v3 v3.2.0 + github.com/Masterminds/semver/v3 v3.2.1 github.com/btcsuite/btcd/btcec/v2 v2.3.2 - 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.6.1 + github.com/btcsuite/btcd/btcutil v1.1.5 + github.com/cometbft/cometbft-db v0.12.0 + github.com/cometbft/cometbft-load-test v0.1.0 + github.com/cometbft/cometbft/api v1.0.0-alpha.2 + github.com/cosmos/crypto v0.0.0-20240309083813-82ed2537802e + github.com/cosmos/gogoproto v1.4.12 + github.com/go-git/go-git/v5 v5.12.0 + github.com/goccmack/goutil v1.2.3 github.com/gofrs/uuid v4.4.0+incompatible - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.6.0 + github.com/minio/sha256-simd v1.0.1 github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae - 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.30.0 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa + golang.org/x/sync v0.7.0 + gonum.org/v1/gonum v0.15.0 + google.golang.org/protobuf v1.33.0 ) require ( - 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect - 4d63.com/gochecknoglobals v0.2.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 + dario.cat/mergo v1.0.0 // 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 - github.com/Masterminds/semver v1.5.0 // indirect - github.com/Microsoft/go-winio v0.6.0 // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/Microsoft/go-winio v0.6.1 // 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-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.5.1 // indirect - github.com/ashanbrown/makezero v1.1.1 // indirect + github.com/ProtonMail/go-crypto v1.0.0 // 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.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.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/cloudflare/circl v1.3.7 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v1.1.0 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // 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.10.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 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/badger/v4 v4.2.0 // 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 v23.0.1+incompatible // indirect - github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v23.0.1+incompatible // indirect - github.com/docker/docker-credential-helpers v0.7.0 // indirect + github.com/docker/cli v24.0.7+incompatible // indirect + github.com/docker/docker v24.0.7+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/esimonov/ifshort v1.0.4 // indirect - github.com/ettle/strcase v0.1.1 // indirect - 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.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.7.0 // indirect - github.com/go-git/gcfg v1.5.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.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 - github.com/go-toolsmith/strparse v1.1.0 // indirect - github.com/go-toolsmith/typep v1.1.0 // indirect - 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/fsnotify/fsnotify v1.7.0 // indirect + github.com/getsentry/sentry-go v0.18.0 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.0.0 // indirect + github.com/golang/glog v1.2.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect - github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect - github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect - github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect - github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect - github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect - github.com/golangci/misspell v0.4.0 // indirect - github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect - github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect 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-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 - github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/google/flatbuffers v2.0.8+incompatible // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - 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/imdario/mergo v0.3.15 // 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/julz/importas v0.1.0 // 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.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 - github.com/kyoh86/exportloopref v0.1.11 // indirect - github.com/ldez/gomoddirectives v0.2.3 // indirect - github.com/ldez/tagliatelle v0.4.0 // indirect - github.com/leonklingele/grouper v1.1.1 // indirect - github.com/lufeee/execinquery v1.2.1 // indirect + github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/cpuid/v2 v2.2.3 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/linxGnu/grocksdb v1.8.14 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/maratori/testableexamples v1.0.0 // 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.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/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.9.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/onsi/gomega v1.28.1 // 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/opencontainers/image-spec v1.1.0-rc5 // indirect + github.com/opencontainers/runc v1.1.12 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // 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.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-20210819130434-b3f0c404a727 // indirect - github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // 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 - github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect - github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.23.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/satori/go.uuid v1.2.0 // indirect - github.com/securego/gosec/v2 v2.15.0 // indirect - github.com/sergi/go-diff v1.2.0 // indirect - github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - github.com/sivchari/containedctx v1.0.2 // indirect - 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.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 - github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/skeema/knownhosts v1.2.2 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect - github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - 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.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.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 - github.com/uudashr/gocognit v1.0.6 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/yagipy/maintidx v1.0.0 // indirect - 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.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.10.0 // indirect - go.uber.org/zap v1.24.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 + go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect + go.opencensus.io v0.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // 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.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 - mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect +) + +retract ( + // a regression was introduced + v0.38.4 + // a breaking change was introduced + v0.38.3 + // superseeded by v0.38.3 because of ASA-2024-001 + [v0.38.0, v0.38.2] ) diff --git a/go.sum b/go.sum index 4e0c853dbf3..cd9b5f9ccc8 100644 --- a/go.sum +++ b/go.sum @@ -1,131 +1,52 @@ -4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= -4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= -4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= -4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -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.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= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 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= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7IAzX8QezqtFV9m0MUHFJgts= -github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/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-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= -github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= +github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= -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/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/schema v1.3.4 h1:8K+41sfQkxfT6a79aLBxx+dBKcid6Raw2JPk5COqeqE= +github.com/adlio/schema v1.3.4/go.mod h1:gFMaHYzLkZRfaIqZ5u96LLXPt+DdXSFWUwtr6YBz0kk= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= -github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= -github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -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.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= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= -github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= -github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= -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.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= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -135,229 +56,138 @@ 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.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= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -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.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= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= -github.com/cloudflare/circl v1.3.1 h1:4OVCZRL62ijwEwxnF6I7hLwxvIYi3VaZt8TflkqtrtA= -github.com/cloudflare/circl v1.3.1/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo= -github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v1.1.0 h1:pcFh8CdCIt2kmEpK0OIatq67Ln9uGDYY3d5XnE0LJG4= +github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/cometbft/cometbft-db v0.12.0 h1:v77/z0VyfSU7k682IzZeZPFZrQAKiQwkqGN0QzAjMi0= +github.com/cometbft/cometbft-db v0.12.0/go.mod h1:aX2NbCrjNVd2ZajYxt1BsiFf/Z+TQ2MN0VxdicheYuw= +github.com/cometbft/cometbft-load-test v0.1.0 h1:Axw5oVXlQqZLVUHVxmULSfEtpEuaUMmoeM560hvBAmw= +github.com/cometbft/cometbft-load-test v0.1.0/go.mod h1:QEXKZ2L5SH1gEw6DRSKYpd3nDCWrzIejaHxwYdgKtkc= +github.com/cometbft/cometbft/api v1.0.0-alpha.2 h1:pw6k48EnA/FjxBP2/gCyDGnSdCNjB5yPFd2du/9rNoE= +github.com/cometbft/cometbft/api v1.0.0-alpha.2/go.mod h1:H52lgJKkSPeVpTcKr9a4nrSpyr6s1B352SWa6ajNHv0= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= -github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cosmos/gogoproto v1.4.6 h1:Ee7z15dWJaGlgM2rWrK8N2IX7PQcuccu8oG68jp5RL4= -github.com/cosmos/gogoproto v1.4.6/go.mod h1:VS/ASYmPgv6zkPKLjR9EB91lwbLHOzaGCirmKKhncfI= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cosmos/crypto v0.0.0-20240309083813-82ed2537802e h1:Zk4OsfLBN+0WOfH15Hg/aAYsSP7IuZQC6RZjewPuITw= +github.com/cosmos/crypto v0.0.0-20240309083813-82ed2537802e/go.mod h1:0KOK/XVzL5lj9x+NyJ7lWuJYl6F0Wd7JMVYM06bVQsc= +github.com/cosmos/gogoproto v1.4.12 h1:vB6Lbe/rtnYGjQuFxkPiPYiCybqFT8QvLipDZP8JpFE= +github.com/cosmos/gogoproto v1.4.12/go.mod h1:LnZob1bXRdUoqMMtwYlcR3wjiElmlC+FkjaZRv1/eLY= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -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.10.1 h1:eheNA3ljF6SxnPD/vE4lCBusVHmV3Rs3dkKvFrJ7MR0= -github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= -github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA= -github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= -github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= -github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= +github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= +github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= 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 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.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/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= +github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= -github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= -github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= -github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -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.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= -github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= -github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= -github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= -github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -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.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.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.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= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= -github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= +github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= +github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -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.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= -github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= -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.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= -github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= -github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= -github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/goccmack/goutil v1.2.3 h1:acIQAjDl8RLs64e11yFHoPgE3wmvTDbniDZrXq3/GxA= +github.com/goccmack/goutil v1.2.3/go.mod h1:dPBoKv07AeI2DGYE3ECrSLOLpGaBIBGCUCGKHclOPyU= 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= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -366,958 +196,346 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -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/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= -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.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= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= -github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= -github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -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= -github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k= -github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -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-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/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= -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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -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.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= -github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= -github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= -github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= -github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -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= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/informalsystems/tm-load-test v1.3.0 h1:FGjKy7vBw6mXNakt+wmNWKggQZRsKkEYpaFk/zR64VA= -github.com/informalsystems/tm-load-test v1.3.0/go.mod h1:OQ5AQ9TbT5hKWBNIwsMjn6Bf4O0U4b1kRc+0qZlQJKw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 h1:2uT3aivO7NVpUPGcQX7RbHijHMyWix/yCnIrCWc+5co= -github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -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.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= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -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/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= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/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.5.0 h1:bV1DTdi38Hi4pG4OVWa7Kap0hi0o7EczuK6wQt9zPOM= -github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= 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= -github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= -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.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.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= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -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/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 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.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= -github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= -github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= -github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= -github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= -github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= -github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1c= -github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= -github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= -github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= -github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/linxGnu/grocksdb v1.8.14 h1:HTgyYalNwBSG/1qCQUIott44wU5b2Y9Kr3z7SK5OfGQ= +github.com/linxGnu/grocksdb v1.8.14/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= 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.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= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -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.3.1 h1:OlQkcH40IB2cGuprTPcjB0iIUddgVZgGmDX3IAMR8D4= -github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= 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= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 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/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/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -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= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= -github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= -github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACpzmGME= -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.9.0 h1:Sm0zX5QfjJzkeCjEp+t6d3Ha0jwvoDjleP9XCsrEzOA= -github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= 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= github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= +github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= -github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= +github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/ory/dockertest/v3 v3.9.1 h1:v4dkG+dlu76goxMiTT2j8zV7s4oPPEppKT8K8p2f1kY= -github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= -github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/ory/dockertest/v3 v3.9.1/go.mod h1:42Ir9hmvaAPm0Mgibk6mBPi7SFvTXxEcnztDYOJ//uM= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= 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/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= 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= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= -github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pointlander/compress v1.1.1-0.20190518213731-ff44bd196cc3 h1:hUmXhbljNFtrH5hzV9kiRoddZ5nfPTq3K0Sb2hYYiqE= -github.com/pointlander/compress v1.1.1-0.20190518213731-ff44bd196cc3/go.mod h1:q5NXNGzqj5uPnVuhGkZfmgHqNUhf15VLi6L9kW0VEc0= -github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4 h1:RHHRCZeaNyBXdYPMjZNH8/XHDBH38TZzw8izrW7dmBE= -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.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= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -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.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= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= -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-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/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.52.2 h1:LW8Vk7BccEdONfrJBDffQGRtpSzi5CQaRZGtboOO2ck= +github.com/prometheus/common v0.52.2/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -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.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= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= -github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= -github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= -github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= -github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= -github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= -github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= -github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0= -github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/securego/gosec/v2 v2.15.0 h1:v4Ym7FF58/jlykYmmhZ7mTm7FQvN/setNm++0fgIAtw= -github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= -github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= -github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= -github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= -github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= -github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= -github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= -github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0= -github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= 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.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= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= -github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= -github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= -github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm07ysF0U6JQXczc= -github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= 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.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= -github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= -github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= -github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -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.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= -github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= -github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= -github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= -github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -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.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= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= -github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= -github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= -github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= -gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -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.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.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= +go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 h1:qxen9oVGzDdIRP6ejyAJc760RwW4SnVDiTYTzwnXuxo= +go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5/go.mod h1:eW0HG9/oHQhvRCvb1/pIXW4cOvtDqeQK+XSi3TnwaXY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 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= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -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-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/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/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= 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/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/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -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.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/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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/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/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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= -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/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/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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/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= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -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= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -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-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= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -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-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-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-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= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -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/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/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.12.0 h1:xKuo6hzt+gMav00meVPUlXwSdoEJP46BR+wdxQEFK2o= -gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1326,22 +544,13 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -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= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1352,35 +561,14 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -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.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= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -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/go.work b/go.work new file mode 100644 index 00000000000..32800c1cff0 --- /dev/null +++ b/go.work @@ -0,0 +1,6 @@ +go 1.22.2 + +use ( + . + ./api +) diff --git a/libs/async/async.go b/internal/async/async.go similarity index 86% rename from libs/async/async.go rename to internal/async/async.go index e716821b633..8729a8ad7b2 100644 --- a/libs/async/async.go +++ b/internal/async/async.go @@ -6,16 +6,16 @@ import ( "sync/atomic" ) -//---------------------------------------- +// ---------------------------------------- // Task // val: the value returned after task execution. // err: the error returned during task completion. // abort: tells Parallel to return, whether or not all tasks have completed. -type Task func(i int) (val interface{}, abort bool, err error) +type Task func(i int) (val any, abort bool, err error) type TaskResult struct { - Value interface{} + Value any Error error } @@ -54,7 +54,7 @@ func (trs *TaskResultSet) LatestResult(index int) (TaskResult, bool) { // Writes results to trs.results without waiting for all tasks to complete. func (trs *TaskResultSet) Reap() *TaskResultSet { for i := 0; i < len(trs.results); i++ { - var trch = trs.chz[i] + trch := trs.chz[i] select { case result, ok := <-trch: if ok { @@ -78,7 +78,7 @@ func (trs *TaskResultSet) Reap() *TaskResultSet { // Like Reap() but waits until all tasks have returned or panic'd. func (trs *TaskResultSet) Wait() *TaskResultSet { for i := 0; i < len(trs.results); i++ { - var trch = trs.chz[i] + trch := trs.chz[i] result, ok := <-trch if ok { // Write result. @@ -96,7 +96,7 @@ func (trs *TaskResultSet) Wait() *TaskResultSet { // Returns the firstmost (by task index) error as // discovered by all previous Reap() calls. -func (trs *TaskResultSet) FirstValue() interface{} { +func (trs *TaskResultSet) FirstValue() any { for _, result := range trs.results { if result.Value != nil { return result.Value @@ -116,7 +116,7 @@ func (trs *TaskResultSet) FirstError() error { return nil } -//---------------------------------------- +// ---------------------------------------- // Parallel // Run tasks in parallel, with ability to abort early. @@ -125,9 +125,9 @@ func (trs *TaskResultSet) FirstError() error { // concurrent quit-like primitives, passed implicitly via Task closures. (e.g. // it's not Parallel's concern how you quit/abort your tasks). func Parallel(tasks ...Task) (trs *TaskResultSet, ok bool) { - var taskResultChz = make([]TaskResultCh, len(tasks)) // To return. - var taskDoneCh = make(chan bool, len(tasks)) // A "wait group" channel, early abort if any true received. - var numPanics = new(int32) // Keep track of panics to set ok=false later. + taskResultChz := make([]TaskResultCh, len(tasks)) // To return. + taskDoneCh := make(chan bool, len(tasks)) // A "wait group" channel, early abort if any true received. + numPanics := new(int32) // Keep track of panics to set ok=false later. // We will set it to false iff any tasks panic'd or returned abort. ok = true @@ -136,7 +136,7 @@ func Parallel(tasks ...Task) (trs *TaskResultSet, ok bool) { // When the task is complete, it will appear in the // respective taskResultCh (associated by task index). for i, task := range tasks { - var taskResultCh = make(chan TaskResult, 1) // Capacity for 1 result. + taskResultCh := make(chan TaskResult, 1) // Capacity for 1 result. taskResultChz[i] = taskResultCh go func(i int, task Task, taskResultCh chan TaskResult) { // Recovery @@ -155,7 +155,7 @@ func Parallel(tasks ...Task) (trs *TaskResultSet, ok bool) { } }() // Run the task. - var val, abort, err = task(i) + val, abort, err := task(i) // Send val/err to taskResultCh. // NOTE: Below this line, nothing must panic/ taskResultCh <- TaskResult{val, err} diff --git a/libs/async/async_test.go b/internal/async/async_test.go similarity index 70% rename from libs/async/async_test.go rename to internal/async/async_test.go index 4faead4443e..5609a9100fb 100644 --- a/libs/async/async_test.go +++ b/internal/async/async_test.go @@ -8,26 +8,26 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParallel(t *testing.T) { - // Create tasks. - var counter = new(int32) - var tasks = make([]Task, 100*1000) + counter := new(int32) + tasks := make([]Task, 100*1000) for i := 0; i < len(tasks); i++ { - tasks[i] = func(i int) (res interface{}, abort bool, err error) { + tasks[i] = func(i int) (res any, abort bool, err error) { atomic.AddInt32(counter, 1) return -1 * i, false, nil } } // Run in parallel. - var trs, ok = Parallel(tasks...) + trs, ok := Parallel(tasks...) assert.True(t, ok) // Verify. - assert.Equal(t, int(*counter), len(tasks), "Each task should have incremented the counter already") + assert.Len(t, tasks, int(*counter), "Each task should have incremented the counter already") var failedTasks int for i := 0; i < len(tasks); i++ { taskResult, ok := trs.LatestResult(i) @@ -46,44 +46,43 @@ func TestParallel(t *testing.T) { // Good! // } } - assert.Equal(t, failedTasks, 0, "No task should have failed") - assert.Nil(t, trs.FirstError(), "There should be no errors") + assert.Equal(t, 0, failedTasks, "No task should have failed") + require.NoError(t, trs.FirstError(), "There should be no errors") assert.Equal(t, 0, trs.FirstValue(), "First value should be 0") } func TestParallelAbort(t *testing.T) { - - var flow1 = make(chan struct{}, 1) - var flow2 = make(chan struct{}, 1) - var flow3 = make(chan struct{}, 1) // Cap must be > 0 to prevent blocking. - var flow4 = make(chan struct{}, 1) + flow1 := make(chan struct{}, 1) + flow2 := make(chan struct{}, 1) + flow3 := make(chan struct{}, 1) // Cap must be > 0 to prevent blocking. + flow4 := make(chan struct{}, 1) // Create tasks. - var tasks = []Task{ - func(i int) (res interface{}, abort bool, err error) { - assert.Equal(t, i, 0) + tasks := []Task{ + func(i int) (res any, abort bool, err error) { + assert.Equal(t, 0, i) flow1 <- struct{}{} return 0, false, nil }, - func(i int) (res interface{}, abort bool, err error) { - assert.Equal(t, i, 1) + func(i int) (res any, abort bool, err error) { + assert.Equal(t, 1, i) flow2 <- <-flow1 return 1, false, errors.New("some error") }, - func(i int) (res interface{}, abort bool, err error) { - assert.Equal(t, i, 2) + func(i int) (res any, abort bool, err error) { + assert.Equal(t, 2, i) flow3 <- <-flow2 return 2, true, nil }, - func(i int) (res interface{}, abort bool, err error) { - assert.Equal(t, i, 3) + func(i int) (res any, abort bool, err error) { + assert.Equal(t, 3, i) <-flow4 return 3, false, nil }, } // Run in parallel. - var taskResultSet, ok = Parallel(tasks...) + taskResultSet, ok := Parallel(tasks...) assert.False(t, ok, "ok should be false since we aborted task #2.") // Verify task #3. @@ -104,22 +103,21 @@ func TestParallelAbort(t *testing.T) { } func TestParallelRecover(t *testing.T) { - // Create tasks. - var tasks = []Task{ - func(i int) (res interface{}, abort bool, err error) { + tasks := []Task{ + func(_ int) (res any, abort bool, err error) { return 0, false, nil }, - func(i int) (res interface{}, abort bool, err error) { + func(_ int) (res any, abort bool, err error) { return 1, false, errors.New("some error") }, - func(i int) (res interface{}, abort bool, err error) { + func(_ int) (res any, abort bool, err error) { panic(2) }, } // Run in parallel. - var taskResultSet, ok = Parallel(tasks...) + taskResultSet, ok := Parallel(tasks...) assert.False(t, ok, "ok should be false since we panic'd in task #2.") // Verify task #0, #1, #2. @@ -128,9 +126,11 @@ func TestParallelRecover(t *testing.T) { checkResult(t, taskResultSet, 2, nil, nil, fmt.Errorf("panic in task %v", 2).Error()) } -// Wait for result +// Wait for result. func checkResult(t *testing.T, taskResultSet *TaskResultSet, index int, - val interface{}, err error, pnk interface{}) { + val any, err error, pnk any, +) { + t.Helper() taskResult, ok := taskResultSet.LatestResult(index) taskName := fmt.Sprintf("Task #%v", index) assert.True(t, ok, "TaskResultCh unexpectedly closed for %v", taskName) @@ -141,12 +141,13 @@ func checkResult(t *testing.T, taskResultSet *TaskResultSet, index int, case pnk != nil: assert.Contains(t, taskResult.Error.Error(), pnk, taskName) default: - assert.Nil(t, taskResult.Error, taskName) + require.NoError(t, taskResult.Error, taskName) } } -// Wait for timeout (no result) +// Wait for timeout (no result). func waitTimeout(t *testing.T, taskResultCh TaskResultCh, taskName string) { + t.Helper() select { case _, ok := <-taskResultCh: if !ok { diff --git a/libs/autofile/README.md b/internal/autofile/README.md similarity index 100% rename from libs/autofile/README.md rename to internal/autofile/README.md diff --git a/libs/autofile/autofile.go b/internal/autofile/autofile.go similarity index 96% rename from libs/autofile/autofile.go rename to internal/autofile/autofile.go index b67af20e150..a5656f1d67c 100644 --- a/libs/autofile/autofile.go +++ b/internal/autofile/autofile.go @@ -8,7 +8,7 @@ import ( "syscall" "time" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) /* AutoFile usage @@ -35,7 +35,7 @@ if err != nil { const ( autoFileClosePeriod = 1000 * time.Millisecond - autoFilePerms = os.FileMode(0600) + autoFilePerms = os.FileMode(0o600) ) // AutoFile automatically closes and re-opens file for writing. The file is @@ -133,12 +133,12 @@ func (af *AutoFile) Write(b []byte) (n int, err error) { if af.file == nil { if err = af.openFile(); err != nil { - return + return 0, err } } n, err = af.file.Write(b) - return + return n, err } // Sync commits the current contents of the file to stable storage. Typically, diff --git a/libs/autofile/autofile_test.go b/internal/autofile/autofile_test.go similarity index 98% rename from libs/autofile/autofile_test.go rename to internal/autofile/autofile_test.go index 2713e5482a0..d651f225ab5 100644 --- a/libs/autofile/autofile_test.go +++ b/internal/autofile/autofile_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmtos "github.com/cometbft/cometbft/libs/os" + cmtos "github.com/cometbft/cometbft/internal/os" ) func TestSIGHUP(t *testing.T) { diff --git a/libs/autofile/cmd/logjack.go b/internal/autofile/cmd/logjack.go similarity index 87% rename from libs/autofile/cmd/logjack.go rename to internal/autofile/cmd/logjack.go index f6be50332de..f13b1a9ecf8 100644 --- a/libs/autofile/cmd/logjack.go +++ b/internal/autofile/cmd/logjack.go @@ -8,16 +8,18 @@ import ( "strconv" "strings" - auto "github.com/cometbft/cometbft/libs/autofile" - cmtos "github.com/cometbft/cometbft/libs/os" + auto "github.com/cometbft/cometbft/internal/autofile" + cmtos "github.com/cometbft/cometbft/internal/os" ) -const Version = "0.0.1" -const readBufferSize = 1024 // 1KB at a time +const ( + Version = "0.0.1" + readBufferSize = 1024 // 1KB at a time +) -// Parse command-line options +// Parse command-line options. func parseFlags() (headPath string, chopSize int64, limitSize int64, version bool) { - var flagSet = flag.NewFlagSet(os.Args[0], flag.ExitOnError) + flagSet := flag.NewFlagSet(os.Args[0], flag.ExitOnError) var chopSizeStr, limitSizeStr string flagSet.StringVar(&headPath, "head", "logjack.out", "Destination (head) file.") flagSet.StringVar(&chopSizeStr, "chop", "100M", "Move file if greater than this") @@ -29,12 +31,12 @@ func parseFlags() (headPath string, chopSize int64, limitSize int64, version boo } chopSize = parseBytesize(chopSizeStr) limitSize = parseBytesize(limitSizeStr) - return + return headPath, chopSize, limitSize, version } type fmtLogger struct{} -func (fmtLogger) Info(msg string, keyvals ...interface{}) { +func (fmtLogger) Info(msg string, keyvals ...any) { strs := make([]string, len(keyvals)) for i, kv := range keyvals { strs[i] = fmt.Sprintf("%v", kv) @@ -78,10 +80,9 @@ func main() { } if err == io.EOF { os.Exit(0) - } else { - fmt.Println("logjack errored") - os.Exit(1) } + fmt.Println("logjack errored") + os.Exit(1) } _, err = group.Write(buf[:n]) if err != nil { diff --git a/libs/autofile/group.go b/internal/autofile/group.go similarity index 97% rename from libs/autofile/group.go rename to internal/autofile/group.go index 057957915af..411f78f9b8b 100644 --- a/libs/autofile/group.go +++ b/internal/autofile/group.go @@ -13,7 +13,7 @@ import ( "sync" "time" - "github.com/cometbft/cometbft/libs/service" + "github.com/cometbft/cometbft/internal/service" ) const ( @@ -200,7 +200,7 @@ func (g *Group) MinIndex() int { // returns the number of bytes written. If nn < len(p), it also returns an // error explaining why the write is short. // NOTE: Writes are buffered so they don't write synchronously -// TODO: Make it halt if space is unavailable +// TODO: Make it halt if space is unavailable. func (g *Group) Write(p []byte) (nn int, err error) { g.mtx.Lock() defer g.mtx.Unlock() @@ -209,7 +209,7 @@ func (g *Group) Write(p []byte) (nn int, err error) { // WriteLine writes line into the current head of the group. It also appends "\n". // NOTE: Writes are buffered so they don't write synchronously -// TODO: Make it halt if space is unavailable +// TODO: Make it halt if space is unavailable. func (g *Group) WriteLine(line string) error { g.mtx.Lock() defer g.mtx.Unlock() @@ -353,7 +353,7 @@ func (g *Group) ReadGroupInfo() GroupInfo { } // Index includes the head. -// CONTRACT: caller should have called g.mtx.Lock +// CONTRACT: caller should have called g.mtx.Lock. func (g *Group) readGroupInfo() GroupInfo { groupDir := filepath.Dir(g.Head.Path) headBase := filepath.Base(g.Head.Path) @@ -417,7 +417,7 @@ func filePathForIndex(headPath string, index int, maxIndex int) string { return fmt.Sprintf("%v.%03d", headPath, index) } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- // GroupReader provides an interface for reading from a Group. type GroupReader struct { @@ -496,7 +496,7 @@ func (gr *GroupReader) Read(p []byte) (n int, err error) { } // IF index > gr.Group.maxIndex, returns io.EOF -// CONTRACT: caller should hold gr.mtx +// CONTRACT: caller should hold gr.mtx. func (gr *GroupReader) openFile(index int) error { // Lock on Group to ensure that head doesn't move in the meanwhile. gr.Group.mtx.Lock() diff --git a/libs/autofile/group_test.go b/internal/autofile/group_test.go similarity index 86% rename from libs/autofile/group_test.go rename to internal/autofile/group_test.go index e2813b6c972..dbc53e3f06d 100644 --- a/libs/autofile/group_test.go +++ b/internal/autofile/group_test.go @@ -9,14 +9,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmtos "github.com/cometbft/cometbft/libs/os" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtos "github.com/cometbft/cometbft/internal/os" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) func createTestGroupWithHeadSizeLimit(t *testing.T, headSizeLimit int64) *Group { + t.Helper() testID := cmtrand.Str(12) testDir := "_test_" + testID - err := cmtos.EnsureDir(testDir, 0700) + err := cmtos.EnsureDir(testDir, 0o700) require.NoError(t, err, "Error creating dir") headPath := testDir + "/myfile" @@ -28,14 +29,16 @@ func createTestGroupWithHeadSizeLimit(t *testing.T, headSizeLimit int64) *Group } func destroyTestGroup(t *testing.T, g *Group) { + t.Helper() g.Close() err := os.RemoveAll(g.Dir) require.NoError(t, err, "Error removing test Group directory") } -func assertGroupInfo(t *testing.T, gInfo GroupInfo, minIndex, maxIndex int, totalSize, headSize int64) { - assert.Equal(t, minIndex, gInfo.MinIndex) +func assertGroupInfo(t *testing.T, gInfo GroupInfo, maxIndex int, totalSize, headSize int64) { + t.Helper() + assert.Equal(t, 0, gInfo.MinIndex) assert.Equal(t, maxIndex, gInfo.MaxIndex) assert.Equal(t, totalSize, gInfo.TotalSize) assert.Equal(t, headSize, gInfo.HeadSize) @@ -45,7 +48,7 @@ func TestCheckHeadSizeLimit(t *testing.T) { g := createTestGroupWithHeadSizeLimit(t, 1000*1000) // At first, there are no files. - assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 0, 0) + assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 0) // Write 1000 bytes 999 times. for i := 0; i < 999; i++ { @@ -54,11 +57,11 @@ func TestCheckHeadSizeLimit(t *testing.T) { } err := g.FlushAndSync() require.NoError(t, err) - assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 999000, 999000) + assertGroupInfo(t, g.ReadGroupInfo(), 0, 999000, 999000) // Even calling checkHeadSizeLimit manually won't rotate it. g.checkHeadSizeLimit() - assertGroupInfo(t, g.ReadGroupInfo(), 0, 0, 999000, 999000) + assertGroupInfo(t, g.ReadGroupInfo(), 0, 999000, 999000) // Write 1000 more bytes. err = g.WriteLine(cmtrand.Str(999)) @@ -68,7 +71,7 @@ func TestCheckHeadSizeLimit(t *testing.T) { // Calling checkHeadSizeLimit this time rolls it. g.checkHeadSizeLimit() - assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 1000000, 0) + assertGroupInfo(t, g.ReadGroupInfo(), 1, 1000000, 0) // Write 1000 more bytes. err = g.WriteLine(cmtrand.Str(999)) @@ -78,7 +81,7 @@ func TestCheckHeadSizeLimit(t *testing.T) { // Calling checkHeadSizeLimit does nothing. g.checkHeadSizeLimit() - assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 1001000, 1000) + assertGroupInfo(t, g.ReadGroupInfo(), 1, 1001000, 1000) // Write 1000 bytes 999 times. for i := 0; i < 999; i++ { @@ -87,22 +90,22 @@ func TestCheckHeadSizeLimit(t *testing.T) { } err = g.FlushAndSync() require.NoError(t, err) - assertGroupInfo(t, g.ReadGroupInfo(), 0, 1, 2000000, 1000000) + assertGroupInfo(t, g.ReadGroupInfo(), 1, 2000000, 1000000) // Calling checkHeadSizeLimit rolls it again. g.checkHeadSizeLimit() - assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2000000, 0) + assertGroupInfo(t, g.ReadGroupInfo(), 2, 2000000, 0) // Write 1000 more bytes. _, err = g.Head.Write([]byte(cmtrand.Str(999) + "\n")) require.NoError(t, err, "Error appending to head") err = g.FlushAndSync() require.NoError(t, err) - assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2001000, 1000) + assertGroupInfo(t, g.ReadGroupInfo(), 2, 2001000, 1000) // Calling checkHeadSizeLimit does nothing. g.checkHeadSizeLimit() - assertGroupInfo(t, g.ReadGroupInfo(), 0, 2, 2001000, 1000) + assertGroupInfo(t, g.ReadGroupInfo(), 2, 2001000, 1000) // Cleanup destroyTestGroup(t, g) @@ -151,14 +154,14 @@ func TestRotateFile(t *testing.T) { // Read g.Head.Path+"000" body1, err := os.ReadFile(g.Head.Path + ".000") - assert.NoError(t, err, "Failed to read first rolled file") + require.NoError(t, err, "Failed to read first rolled file: %v", err) if string(body1) != "Line 1\nLine 2\nLine 3\n" { t.Errorf("got unexpected contents: [%v]", string(body1)) } // Read g.Head.Path body2, err := os.ReadFile(g.Head.Path) - assert.NoError(t, err, "Failed to read first rolled file") + require.NoError(t, err, "Failed to read first rolled file: %v", err) if string(body2) != "Line 4\nLine 5\nLine 6\n" { t.Errorf("got unexpected contents: [%v]", string(body2)) } @@ -186,7 +189,7 @@ func TestWrite(t *testing.T) { require.NoError(t, err, "failed to create reader") _, err = gr.Read(read) - assert.NoError(t, err, "failed to read data") + require.NoError(t, err, "failed to read data: %v", err) assert.Equal(t, written, read) // Cleanup @@ -216,7 +219,7 @@ func TestGroupReaderRead(t *testing.T) { require.NoError(t, err, "failed to create reader") n, err := gr.Read(read) - assert.NoError(t, err, "failed to read data") + require.NoError(t, err, "failed to read data: %v", err) assert.Equal(t, totalWrittenLength, n, "not enough bytes read") professorPlusFrankenstein := professor professorPlusFrankenstein = append(professorPlusFrankenstein, frankenstein...) diff --git a/libs/bits/bit_array.go b/internal/bits/bit_array.go similarity index 93% rename from libs/bits/bit_array.go rename to internal/bits/bit_array.go index 358e37be8df..73f483022b2 100644 --- a/libs/bits/bit_array.go +++ b/internal/bits/bit_array.go @@ -7,9 +7,9 @@ import ( "strings" "sync" + cmtprotobits "github.com/cometbft/cometbft/api/cometbft/libs/bits/v1" + cmtrand "github.com/cometbft/cometbft/internal/rand" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtprotobits "github.com/cometbft/cometbft/proto/tendermint/libs/bits" ) // BitArray is a thread-safe implementation of a bit array. @@ -31,7 +31,7 @@ func NewBitArray(bits int) *BitArray { } } -// Size returns the number of bits in the bitarray +// Size returns the number of bits in the bitarray. func (bA *BitArray) Size() int { if bA == nil { return 0 @@ -40,7 +40,7 @@ func (bA *BitArray) Size() int { } // GetIndex returns the bit at index i within the bit array. -// The behavior is undefined if i >= bA.Bits +// The behavior is undefined if i >= bA.Bits. func (bA *BitArray) GetIndex(i int) bool { if bA == nil { return false @@ -58,7 +58,7 @@ func (bA *BitArray) getIndex(i int) bool { } // SetIndex sets the bit at index i within the bit array. -// The behavior is undefined if i >= bA.Bits +// The behavior is undefined if i >= bA.Bits. func (bA *BitArray) SetIndex(i int, v bool) bool { if bA == nil { return false @@ -178,7 +178,7 @@ func (bA *BitArray) not() *BitArray { // Sub subtracts the two bit-arrays bitwise, without carrying the bits. // Note that carryless subtraction of a - b is (a and not b). // The output is the same as bA, regardless of o's size. -// If bA is longer than o, o is right padded with zeroes +// If bA is longer than o, o is right padded with zeroes. func (bA *BitArray) Sub(o *BitArray) *BitArray { if bA == nil || o == nil { // TODO: Decide if we should do 1's complement here? @@ -202,7 +202,7 @@ func (bA *BitArray) Sub(o *BitArray) *BitArray { return c } -// IsEmpty returns true iff all bits in the bit array are 0 +// IsEmpty returns true iff all bits in the bit array are 0. func (bA *BitArray) IsEmpty() bool { if bA == nil { return true // should this be opposite? @@ -409,16 +409,27 @@ func (bA *BitArray) UnmarshalJSON(bz []byte) error { // Construct new BitArray and copy over. numBits := len(bits) bA2 := NewBitArray(numBits) + if bA2 == nil { + // Treat it as if we encountered the case: b == "null" + bA.Bits = 0 + bA.Elems = nil + return nil + } + for i := 0; i < numBits; i++ { if bits[i] == 'x' { bA2.SetIndex(i, true) } } - *bA = *bA2 //nolint:govet + + // Instead of *bA = *bA2 + bA.Bits = bA2.Bits + bA.Elems = make([]uint64, len(bA2.Elems)) + copy(bA.Elems, bA2.Elems) return nil } -// ToProto converts BitArray to protobuf +// ToProto converts BitArray to protobuf. func (bA *BitArray) ToProto() *cmtprotobits.BitArray { if bA == nil || len(bA.Elems) == 0 { return nil @@ -433,6 +444,7 @@ func (bA *BitArray) ToProto() *cmtprotobits.BitArray { // FromProto sets a protobuf BitArray to the given pointer. func (bA *BitArray) FromProto(protoBitArray *cmtprotobits.BitArray) { if protoBitArray == nil { + //nolint:wastedassign bA = nil return } diff --git a/libs/bits/bit_array_test.go b/internal/bits/bit_array_test.go similarity index 86% rename from libs/bits/bit_array_test.go rename to internal/bits/bit_array_test.go index 4694da9a919..0907c14cf6b 100644 --- a/libs/bits/bit_array_test.go +++ b/internal/bits/bit_array_test.go @@ -9,28 +9,27 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) -func randBitArray(bits int) (*BitArray, []byte) { +func randBitArray(bits int) *BitArray { src := cmtrand.Bytes((bits + 7) / 8) bA := NewBitArray(bits) for i := 0; i < len(src); i++ { for j := 0; j < 8; j++ { if i*8+j >= bits { - return bA, src + return bA } setBit := src[i]&(1< 0 bA.SetIndex(i*8+j, setBit) } } - return bA, src + return bA } func TestAnd(t *testing.T) { - - bA1, _ := randBitArray(51) - bA2, _ := randBitArray(31) + bA1 := randBitArray(51) + bA2 := randBitArray(31) bA3 := bA1.And(bA2) var bNil *BitArray @@ -53,9 +52,8 @@ func TestAnd(t *testing.T) { } func TestOr(t *testing.T) { - - bA1, _ := randBitArray(51) - bA2, _ := randBitArray(31) + bA1 := randBitArray(51) + bA2 := randBitArray(31) bA3 := bA1.Or(bA2) bNil := (*BitArray)(nil) @@ -97,13 +95,14 @@ func TestSub(t *testing.T) { for _, tc := range testCases { var bA *BitArray err := json.Unmarshal([]byte(tc.initBA), &bA) - require.Nil(t, err) + require.NoError(t, err) var o *BitArray err = json.Unmarshal([]byte(tc.subtractingBA), &o) - require.Nil(t, err) + require.NoError(t, err) - got, _ := json.Marshal(bA.Sub(o)) + got, err := json.Marshal(bA.Sub(o)) + require.NoError(t, err) require.Equal( t, tc.expectedBA, @@ -143,7 +142,7 @@ func TestPickRandom(t *testing.T) { } } -func TestBytes(t *testing.T) { +func TestBytes(_ *testing.T) { bA := NewBitArray(4) bA.SetIndex(0, true) check := func(bA *BitArray, bz []byte) { @@ -188,9 +187,9 @@ func TestEmptyFull(t *testing.T) { } } -func TestUpdateNeverPanics(t *testing.T) { +func TestUpdateNeverPanics(_ *testing.T) { newRandBitArray := func(n int) *BitArray { - ba, _ := randBitArray(n) + ba := randBitArray(n) return ba } pairs := []struct { @@ -210,7 +209,7 @@ func TestUpdateNeverPanics(t *testing.T) { } } -func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { +func TestNewBitArrayNeverCrashesOnNegatives(_ *testing.T) { bitList := []int{-127, -128, -1 << 31} for _, bits := range bitList { _ = NewBitArray(bits) @@ -218,7 +217,6 @@ func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { } func TestJSONMarshalUnmarshal(t *testing.T) { - bA1 := NewBitArray(0) bA2 := NewBitArray(1) @@ -288,3 +286,18 @@ func TestBitArrayProtoBuf(t *testing.T) { } } } + +// Tests that UnmarshalJSON doesn't crash when no bits are passed into the JSON. +// See issue https://github.com/cometbft/cometbft/issues/2658 +func TestUnmarshalJSONDoesntCrashOnZeroBits(t *testing.T) { + type indexCorpus struct { + BitArray *BitArray `json:"ba"` + Index int `json:"i"` + } + + ic := new(indexCorpus) + blob := []byte(`{"BA":""}`) + err := json.Unmarshal(blob, ic) + require.NoError(t, err) + require.Equal(t, ic.BitArray, &BitArray{Bits: 0, Elems: nil}) +} diff --git a/internal/blocksync/errors.go b/internal/blocksync/errors.go new file mode 100644 index 00000000000..bafe2d1ac41 --- /dev/null +++ b/internal/blocksync/errors.go @@ -0,0 +1,51 @@ +package blocksync + +import ( + "errors" + "fmt" + + "github.com/cosmos/gogoproto/proto" +) + +// ErrNilMessage is returned when provided message is empty. +var ErrNilMessage = errors.New("message cannot be nil") + +// ErrInvalidBase is returned when peer informs of a status with invalid height. +type ErrInvalidHeight struct { + Height int64 + Reason string +} + +func (e ErrInvalidHeight) Error() string { + return fmt.Sprintf("invalid height %v: %s", e.Height, e.Reason) +} + +// ErrInvalidBase is returned when peer informs of a status with invalid base. +type ErrInvalidBase struct { + Base int64 + Reason string +} + +func (e ErrInvalidBase) Error() string { + return fmt.Sprintf("invalid base %v: %s", e.Base, e.Reason) +} + +type ErrUnknownMessageType struct { + Msg proto.Message +} + +func (e ErrUnknownMessageType) Error() string { + return fmt.Sprintf("unknown message type %T", e.Msg) +} + +type ErrReactorValidation struct { + Err error +} + +func (e ErrReactorValidation) Error() string { + return fmt.Sprintf("reactor validation error: %v", e.Err) +} + +func (e ErrReactorValidation) Unwrap() error { + return e.Err +} diff --git a/blocksync/metrics.gen.go b/internal/blocksync/metrics.gen.go similarity index 100% rename from blocksync/metrics.gen.go rename to internal/blocksync/metrics.gen.go diff --git a/blocksync/metrics.go b/internal/blocksync/metrics.go similarity index 93% rename from blocksync/metrics.go rename to internal/blocksync/metrics.go index f120b4f7c44..7e4b1d9cd8a 100644 --- a/blocksync/metrics.go +++ b/internal/blocksync/metrics.go @@ -1,8 +1,9 @@ package blocksync import ( - "github.com/cometbft/cometbft/types" "github.com/go-kit/kit/metrics" + + "github.com/cometbft/cometbft/types" ) const ( @@ -11,7 +12,7 @@ const ( MetricsSubsystem = "blocksync" ) -//go:generate go run ../scripts/metricsgen -struct=Metrics +//go:generate go run ../../scripts/metricsgen -struct=Metrics // Metrics contains metrics exposed by this package. type Metrics struct { diff --git a/blocksync/msgs.go b/internal/blocksync/msgs.go similarity index 51% rename from blocksync/msgs.go rename to internal/blocksync/msgs.go index 447748ecb92..97d5bdd1bf9 100644 --- a/blocksync/msgs.go +++ b/internal/blocksync/msgs.go @@ -1,17 +1,16 @@ package blocksync import ( - "errors" "fmt" "github.com/cosmos/gogoproto/proto" - bcproto "github.com/cometbft/cometbft/proto/tendermint/blocksync" + bcproto "github.com/cometbft/cometbft/api/cometbft/blocksync/v1" "github.com/cometbft/cometbft/types" ) const ( - // NOTE: keep up to date with bcproto.BlockResponse + // NOTE: keep up to date with bcproto.BlockResponse. BlockResponseMessagePrefixSize = 4 BlockResponseMessageFieldKeySize = 1 MaxMsgSize = types.MaxBlockSizeBytes + @@ -22,37 +21,36 @@ const ( // ValidateMsg validates a message. func ValidateMsg(pb proto.Message) error { if pb == nil { - return errors.New("message cannot be nil") + return ErrNilMessage } switch msg := pb.(type) { case *bcproto.BlockRequest: if msg.Height < 0 { - return errors.New("negative Height") + return ErrInvalidHeight{Height: msg.Height, Reason: "negative height"} } case *bcproto.BlockResponse: - _, err := types.BlockFromProto(msg.Block) - if err != nil { - return err - } + // Avoid double-calling `types.BlockFromProto` for performance reasons. + // See https://github.com/cometbft/cometbft/issues/1964 + return nil case *bcproto.NoBlockResponse: if msg.Height < 0 { - return errors.New("negative Height") + return ErrInvalidHeight{Height: msg.Height, Reason: "negative height"} } case *bcproto.StatusResponse: if msg.Base < 0 { - return errors.New("negative Base") + return ErrInvalidBase{Base: msg.Base, Reason: "negative base"} } if msg.Height < 0 { - return errors.New("negative Height") + return ErrInvalidHeight{Height: msg.Height, Reason: "negative height"} } if msg.Base > msg.Height { - return fmt.Errorf("base %v cannot be greater than height %v", msg.Base, msg.Height) + return ErrInvalidHeight{Height: msg.Height, Reason: fmt.Sprintf("base %v cannot be greater than height", msg.Base)} } case *bcproto.StatusRequest: return nil default: - return fmt.Errorf("unknown message type %T", msg) + return ErrUnknownMessageType{Msg: msg} } return nil } diff --git a/blocksync/msgs_test.go b/internal/blocksync/msgs_test.go similarity index 66% rename from blocksync/msgs_test.go rename to internal/blocksync/msgs_test.go index 1100771e8a4..3fb1704bf70 100644 --- a/blocksync/msgs_test.go +++ b/internal/blocksync/msgs_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/cometbft/cometbft/blocksync" - bcproto "github.com/cometbft/cometbft/proto/tendermint/blocksync" + bcproto "github.com/cometbft/cometbft/api/cometbft/blocksync/v1" + "github.com/cometbft/cometbft/internal/blocksync" "github.com/cometbft/cometbft/types" ) @@ -56,7 +56,7 @@ func TestBcNoBlockResponseMessageValidateBasic(t *testing.T) { func TestBcStatusRequestMessageValidateBasic(t *testing.T) { request := bcproto.StatusRequest{} - assert.NoError(t, blocksync.ValidateMsg(&request)) + require.NoError(t, blocksync.ValidateMsg(&request)) } func TestBcStatusResponseMessageValidateBasic(t *testing.T) { @@ -93,26 +93,44 @@ func TestBlocksyncMessageVectors(t *testing.T) { expBytes string }{ {"BlockRequestMessage", &bcproto.Message{Sum: &bcproto.Message_BlockRequest{ - BlockRequest: &bcproto.BlockRequest{Height: 1}}}, "0a020801"}, - {"BlockRequestMessage", &bcproto.Message{Sum: &bcproto.Message_BlockRequest{ - BlockRequest: &bcproto.BlockRequest{Height: math.MaxInt64}}}, - "0a0a08ffffffffffffffff7f"}, + BlockRequest: &bcproto.BlockRequest{Height: 1}, + }}, "0a020801"}, + { + "BlockRequestMessage", &bcproto.Message{Sum: &bcproto.Message_BlockRequest{ + BlockRequest: &bcproto.BlockRequest{Height: math.MaxInt64}, + }}, + "0a0a08ffffffffffffffff7f", + }, {"BlockResponseMessage", &bcproto.Message{Sum: &bcproto.Message_BlockResponse{ - BlockResponse: &bcproto.BlockResponse{Block: bpb}}}, "1a700a6e0a5b0a02080b1803220b088092b8c398feffffff012a0212003a20c4da88e876062aa1543400d50d0eaa0dac88096057949cfb7bca7f3a48c04bf96a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855120d0a0b48656c6c6f20576f726c641a00"}, - {"NoBlockResponseMessage", &bcproto.Message{Sum: &bcproto.Message_NoBlockResponse{ - NoBlockResponse: &bcproto.NoBlockResponse{Height: 1}}}, "12020801"}, + BlockResponse: &bcproto.BlockResponse{Block: bpb}, + }}, "1a700a6e0a5b0a02080b1803220b088092b8c398feffffff012a0212003a20c4da88e876062aa1543400d50d0eaa0dac88096057949cfb7bca7f3a48c04bf96a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855120d0a0b48656c6c6f20576f726c641a00"}, {"NoBlockResponseMessage", &bcproto.Message{Sum: &bcproto.Message_NoBlockResponse{ - NoBlockResponse: &bcproto.NoBlockResponse{Height: math.MaxInt64}}}, - "120a08ffffffffffffffff7f"}, - {"StatusRequestMessage", &bcproto.Message{Sum: &bcproto.Message_StatusRequest{ - StatusRequest: &bcproto.StatusRequest{}}}, - "2200"}, - {"StatusResponseMessage", &bcproto.Message{Sum: &bcproto.Message_StatusResponse{ - StatusResponse: &bcproto.StatusResponse{Height: 1, Base: 2}}}, - "2a0408011002"}, - {"StatusResponseMessage", &bcproto.Message{Sum: &bcproto.Message_StatusResponse{ - StatusResponse: &bcproto.StatusResponse{Height: math.MaxInt64, Base: math.MaxInt64}}}, - "2a1408ffffffffffffffff7f10ffffffffffffffff7f"}, + NoBlockResponse: &bcproto.NoBlockResponse{Height: 1}, + }}, "12020801"}, + { + "NoBlockResponseMessage", &bcproto.Message{Sum: &bcproto.Message_NoBlockResponse{ + NoBlockResponse: &bcproto.NoBlockResponse{Height: math.MaxInt64}, + }}, + "120a08ffffffffffffffff7f", + }, + { + "StatusRequestMessage", &bcproto.Message{Sum: &bcproto.Message_StatusRequest{ + StatusRequest: &bcproto.StatusRequest{}, + }}, + "2200", + }, + { + "StatusResponseMessage", &bcproto.Message{Sum: &bcproto.Message_StatusResponse{ + StatusResponse: &bcproto.StatusResponse{Height: 1, Base: 2}, + }}, + "2a0408011002", + }, + { + "StatusResponseMessage", &bcproto.Message{Sum: &bcproto.Message_StatusResponse{ + StatusResponse: &bcproto.StatusResponse{Height: math.MaxInt64, Base: math.MaxInt64}, + }}, + "2a1408ffffffffffffffff7f10ffffffffffffffff7f", + }, } for _, tc := range testCases { diff --git a/blocksync/pool.go b/internal/blocksync/pool.go similarity index 51% rename from blocksync/pool.go rename to internal/blocksync/pool.go index 522c3e68178..0a810cc22f3 100644 --- a/blocksync/pool.go +++ b/internal/blocksync/pool.go @@ -4,13 +4,13 @@ import ( "errors" "fmt" "math" - "sync/atomic" + "sort" "time" - flow "github.com/cometbft/cometbft/libs/flowrate" + flow "github.com/cometbft/cometbft/internal/flowrate" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/types" ) @@ -28,25 +28,33 @@ eg, L = latency = 0.1s */ const ( - requestIntervalMS = 2 - maxTotalRequesters = 600 - maxPendingRequests = maxTotalRequesters maxPendingRequestsPerPeer = 20 requestRetrySeconds = 30 // Minimum recv rate to ensure we're receiving blocks from a peer fast - // enough. If a peer is not sending us data at at least that rate, we - // consider them to have timedout and we disconnect. + // enough. If a peer is not sending us data at least that rate, we consider + // them to have timed out, and we disconnect. // - // Assuming a DSL connection (not a good choice) 128 Kbps (upload) ~ 15 KB/s, - // sending data across atlantic ~ 7.5 KB/s. - minRecvRate = 7680 - - // Maximum difference between current and new block's height. - maxDiffBetweenCurrentAndReceivedBlockHeight = 100 + // Based on the experiments with [Osmosis](https://osmosis.zone/), the + // minimum rate could be as high as 500 KB/s. However, we're setting it to + // 128 KB/s for now to be conservative. + minRecvRate = 128 * 1024 // 128 KB/s + + // peerConnWait is the time that must have elapsed since the pool routine + // was created before we start making requests. This is to give the peer + // routine time to connect to peers. + peerConnWait = 3 * time.Second + + // If we're within minBlocksForSingleRequest blocks of the pool's height, we + // send 2 parallel requests to 2 peers for the same block. If we're further + // away, we send a single request. + minBlocksForSingleRequest = 50 ) -var peerTimeout = 15 * time.Second // not const so we can override with tests +var ( + requestInterval = 10 * time.Millisecond // timeout between requests + peerTimeout = 15 * time.Second // not const so we can override with tests +) /* Peers self report their heights when we join the block pool. @@ -56,13 +64,14 @@ var peerTimeout = 15 * time.Second // not const so we can override with tests Requests are continuously made for blocks of higher heights until the limit is reached. If most of the requests have no available peers, and we - are not at peer limits, we can probably switch to consensus reactor + are not at peer limits, we can probably switch to consensus reactor. */ // BlockPool keeps track of the block sync peers, block requests and block responses. type BlockPool struct { service.BaseService - startTime time.Time + startTime time.Time + startHeight int64 mtx cmtsync.Mutex // block requests @@ -70,10 +79,8 @@ type BlockPool struct { height int64 // the lowest key in requesters. // peers peers map[p2p.ID]*bpPeer - maxPeerHeight int64 // the biggest reported height - - // atomic - numPending int32 // number of requests pending assignment or block response + sortedPeers []*bpPeer // sorted by curRate, highest first + maxPeerHeight int64 // the biggest reported height requestsCh chan<- BlockRequest errorsCh chan<- peerError @@ -85,9 +92,9 @@ func NewBlockPool(start int64, requestsCh chan<- BlockRequest, errorsCh chan<- p bp := &BlockPool{ peers: make(map[p2p.ID]*bpPeer), - requesters: make(map[int64]*bpRequester), - height: start, - numPending: 0, + requesters: make(map[int64]*bpRequester), + height: start, + startHeight: start, requestsCh: requestsCh, errorsCh: errorsCh, @@ -99,33 +106,44 @@ func NewBlockPool(start int64, requestsCh chan<- BlockRequest, errorsCh chan<- p // OnStart implements service.Service by spawning requesters routine and recording // pool's start time. func (pool *BlockPool) OnStart() error { - go pool.makeRequestersRoutine() pool.startTime = time.Now() + go pool.makeRequestersRoutine() return nil } -// spawns requesters as needed func (pool *BlockPool) makeRequestersRoutine() { for { if !pool.IsRunning() { - break + return + } + + // Check if we are within peerConnWait seconds of start time + // This gives us some time to connect to peers before starting a wave of requests + if time.Since(pool.startTime) < peerConnWait { + // Calculate the duration to sleep until peerConnWait seconds have passed since pool.startTime + sleepDuration := peerConnWait - time.Since(pool.startTime) + time.Sleep(sleepDuration) } - _, numPending, lenRequesters := pool.GetStatus() + pool.mtx.Lock() + var ( + maxRequestersCreated = len(pool.requesters) >= len(pool.peers)*maxPendingRequestsPerPeer + + nextHeight = pool.height + int64(len(pool.requesters)) + maxPeerHeightReached = nextHeight > pool.maxPeerHeight + ) + pool.mtx.Unlock() + switch { - case numPending >= maxPendingRequests: - // sleep for a bit. - time.Sleep(requestIntervalMS * time.Millisecond) - // check for timed out peers - pool.removeTimedoutPeers() - case lenRequesters >= maxTotalRequesters: - // sleep for a bit. - time.Sleep(requestIntervalMS * time.Millisecond) - // check for timed out peers + case maxRequestersCreated: // If we have enough requesters, wait for them to finish. + time.Sleep(requestInterval) pool.removeTimedoutPeers() + case maxPeerHeightReached: // If we're caught up, wait for a bit so reactor could finish or a higher height is reported. + time.Sleep(requestInterval) default: - // request for more blocks. - pool.makeNextRequester() + pool.makeNextRequester(nextHeight) + // Sleep for a bit to make the requests more ordered. + time.Sleep(requestInterval) } } } @@ -147,32 +165,28 @@ func (pool *BlockPool) removeTimedoutPeers() { "minRate", fmt.Sprintf("%d KB/s", minRecvRate/1024)) peer.didTimeout = true } + + peer.curRate = curRate } + if peer.didTimeout { pool.removePeer(peer.id) } } -} -// GetStatus returns pool's height, numPending requests and the number of -// requesters. -func (pool *BlockPool) GetStatus() (height int64, numPending int32, lenRequesters int) { - pool.mtx.Lock() - defer pool.mtx.Unlock() - - return pool.height, atomic.LoadInt32(&pool.numPending), len(pool.requesters) + pool.sortPeers() } // IsCaughtUp returns true if this node is caught up, false - otherwise. // TODO: relax conditions, prevent abuse. -func (pool *BlockPool) IsCaughtUp() bool { +func (pool *BlockPool) IsCaughtUp() (isCaughtUp bool, height, maxPeerHeight int64) { pool.mtx.Lock() defer pool.mtx.Unlock() // Need at least 1 peer to be considered caught up. if len(pool.peers) == 0 { pool.Logger.Debug("Blockpool has no peers") - return false + return false, pool.height, pool.maxPeerHeight } // Some conditions to determine if we're caught up. @@ -182,8 +196,8 @@ func (pool *BlockPool) IsCaughtUp() bool { // to verify the LastCommit. receivedBlockOrTimedOut := pool.height > 0 || time.Since(pool.startTime) > 5*time.Second ourChainIsLongestAmongPeers := pool.maxPeerHeight == 0 || pool.height >= (pool.maxPeerHeight-1) - isCaughtUp := receivedBlockOrTimedOut && ourChainIsLongestAmongPeers - return isCaughtUp + isCaughtUp = receivedBlockOrTimedOut && ourChainIsLongestAmongPeers + return isCaughtUp, pool.height, pool.maxPeerHeight } // PeekTwoBlocks returns blocks at pool.height and pool.height+1. We need to @@ -204,48 +218,64 @@ func (pool *BlockPool) PeekTwoBlocks() (first, second *types.Block, firstExtComm if r := pool.requesters[pool.height+1]; r != nil { second = r.getBlock() } - return + return first, second, firstExtCommit } -// PopRequest pops the first block at pool.height. -// It must have been validated by the second Commit from PeekTwoBlocks. -// TODO(thane): (?) and its corresponding ExtendedCommit. +// PopRequest removes the requester at pool.height and increments pool.height. func (pool *BlockPool) PopRequest() { pool.mtx.Lock() defer pool.mtx.Unlock() - if r := pool.requesters[pool.height]; r != nil { - /* The block can disappear at any time, due to removePeer(). - if r := pool.requesters[pool.height]; r == nil || r.block == nil { - PanicSanity("PopRequest() requires a valid block") - } - */ - if err := r.Stop(); err != nil { - pool.Logger.Error("Error stopping requester", "err", err) - } - delete(pool.requesters, pool.height) - pool.height++ - } else { + r := pool.requesters[pool.height] + if r == nil { panic(fmt.Sprintf("Expected requester to pop, got nothing at height %v", pool.height)) } + + if err := r.Stop(); err != nil { + pool.Logger.Error("Error stopping requester", "err", err) + } + delete(pool.requesters, pool.height) + pool.height++ + + // Notify the next minBlocksForSingleRequest requesters about new height, so + // they can potentially request a block from the second peer. + for i := int64(0); i < minBlocksForSingleRequest && i < int64(len(pool.requesters)); i++ { + pool.requesters[pool.height+i].newHeight(pool.height) + } } -// RedoRequest invalidates the block at pool.height, -// Remove the peer and redo request from others. +// RemovePeerAndRedoAllPeerRequests retries the request at the given height and +// all the requests made to the same peer. The peer is removed from the pool. // Returns the ID of the removed peer. -func (pool *BlockPool) RedoRequest(height int64) p2p.ID { +func (pool *BlockPool) RemovePeerAndRedoAllPeerRequests(height int64) p2p.ID { pool.mtx.Lock() defer pool.mtx.Unlock() request := pool.requesters[height] - peerID := request.getPeerID() - if peerID != p2p.ID("") { - // RemovePeer will redo all requesters associated with this peer. - pool.removePeer(peerID) - } + peerID := request.gotBlockFromPeerID() + // RemovePeer will redo all requesters associated with this peer. + pool.removePeer(peerID) return peerID } +// RedoRequestFrom retries the request at the given height. It does not remove the +// peer. +func (pool *BlockPool) RedoRequestFrom(height int64, peerID p2p.ID) { + pool.mtx.Lock() + defer pool.mtx.Unlock() + + if requester, ok := pool.requesters[height]; ok { // If we requested this block + if requester.didRequestFrom(peerID) { // From this specific peer + requester.redo(peerID) + } + } +} + +// Deprecated: use RemovePeerAndRedoAllPeerRequests instead. +func (pool *BlockPool) RedoRequest(height int64) p2p.ID { + return pool.RemovePeerAndRedoAllPeerRequests(height) +} + // AddBlock validates that the block comes from the peer it was expected from // and calls the requester to store it. // @@ -260,44 +290,49 @@ func (pool *BlockPool) AddBlock(peerID p2p.ID, block *types.Block, extCommit *ty defer pool.mtx.Unlock() if extCommit != nil && block.Height != extCommit.Height { - return fmt.Errorf("heights don't match, not adding block (block height: %d, commit height: %d)", block.Height, extCommit.Height) + err := fmt.Errorf("block height %d != extCommit height %d", block.Height, extCommit.Height) + // Peer sent us an invalid block => remove it. + pool.sendError(err, peerID) + return err } requester := pool.requesters[block.Height] if requester == nil { - pool.Logger.Info( - "peer sent us a block we didn't expect", - "peer", - peerID, - "curHeight", - pool.height, - "blockHeight", - block.Height) - diff := pool.height - block.Height - if diff < 0 { - diff *= -1 - } - if diff > maxDiffBetweenCurrentAndReceivedBlockHeight { - pool.sendError(errors.New("peer sent us a block we didn't expect with a height too far ahead/behind"), peerID) + // Because we're issuing 2nd requests for closer blocks, it's possible to + // receive a block we've already processed from a second peer. Hence, we + // can't punish it. But if the peer sent us a block we clearly didn't + // request, we disconnect. + if block.Height > pool.height || block.Height < pool.startHeight { + err := fmt.Errorf("peer sent us block #%d we didn't expect (current height: %d, start height: %d)", + block.Height, pool.height, pool.startHeight) + pool.sendError(err, peerID) + return err } - return fmt.Errorf("peer sent us a block we didn't expect (peer: %s, current height: %d, block height: %d)", peerID, pool.height, block.Height) + + return fmt.Errorf("got an already committed block #%d (possibly from the slow peer %s)", block.Height, peerID) } - if requester.setBlock(block, extCommit, peerID) { - atomic.AddInt32(&pool.numPending, -1) - peer := pool.peers[peerID] - if peer != nil { - peer.decrPending(blockSize) - } - } else { - err := errors.New("requester is different or block already exists") + if !requester.setBlock(block, extCommit, peerID) { + err := fmt.Errorf("requested block #%d from %v, not %s", block.Height, requester.requestedFrom(), peerID) pool.sendError(err, peerID) - return fmt.Errorf("%w (peer: %s, requester: %s, block height: %d)", err, peerID, requester.getPeerID(), block.Height) + return err + } + + peer := pool.peers[peerID] + if peer != nil { + peer.decrPending(blockSize) } return nil } +// Height returns the pool's height. +func (pool *BlockPool) Height() int64 { + pool.mtx.Lock() + defer pool.mtx.Unlock() + return pool.height +} + // MaxPeerHeight returns the highest reported height. func (pool *BlockPool) MaxPeerHeight() int64 { pool.mtx.Lock() @@ -318,6 +353,9 @@ func (pool *BlockPool) SetPeerRange(peerID p2p.ID, base int64, height int64) { peer = newBPPeer(pool, peerID, base, height) peer.setLogger(pool.Logger.With("peer", peerID)) pool.peers[peerID] = peer + // no need to sort because curRate is 0 at start. + // just add to the beginning so it's picked first by pickIncrAvailablePeer. + pool.sortedPeers = append([]*bpPeer{peer}, pool.sortedPeers...) } if height > pool.maxPeerHeight { @@ -336,7 +374,7 @@ func (pool *BlockPool) RemovePeer(peerID p2p.ID) { func (pool *BlockPool) removePeer(peerID p2p.ID) { for _, requester := range pool.requesters { - if requester.getPeerID() == peerID { + if requester.didRequestFrom(peerID) { requester.redo(peerID) } } @@ -348,6 +386,12 @@ func (pool *BlockPool) removePeer(peerID p2p.ID) { } delete(pool.peers, peerID) + for i, p := range pool.sortedPeers { + if p.id == peerID { + pool.sortedPeers = append(pool.sortedPeers[:i], pool.sortedPeers[i+1:]...) + break + } + } // Find a new peer with the biggest height and update maxPeerHeight if the // peer's height was the biggest. @@ -370,11 +414,14 @@ func (pool *BlockPool) updateMaxPeerHeight() { // Pick an available peer with the given height available. // If no peers are available, returns nil. -func (pool *BlockPool) pickIncrAvailablePeer(height int64) *bpPeer { +func (pool *BlockPool) pickIncrAvailablePeer(height int64, excludePeerID p2p.ID) *bpPeer { pool.mtx.Lock() defer pool.mtx.Unlock() - for _, peer := range pool.peers { + for _, peer := range pool.sortedPeers { + if peer.id == excludePeerID { + continue + } if peer.didTimeout { pool.removePeer(peer.id) continue @@ -388,33 +435,30 @@ func (pool *BlockPool) pickIncrAvailablePeer(height int64) *bpPeer { peer.incrPending() return peer } + return nil } -func (pool *BlockPool) makeNextRequester() { - pool.mtx.Lock() - defer pool.mtx.Unlock() - - nextHeight := pool.height + pool.requestersLen() - if nextHeight > pool.maxPeerHeight { - return - } +// Sort peers by curRate, highest first. +// +// CONTRACT: pool.mtx must be locked. +func (pool *BlockPool) sortPeers() { + sort.Slice(pool.sortedPeers, func(i, j int) bool { + return pool.sortedPeers[i].curRate > pool.sortedPeers[j].curRate + }) +} +func (pool *BlockPool) makeNextRequester(nextHeight int64) { + pool.mtx.Lock() request := newBPRequester(pool, nextHeight) - pool.requesters[nextHeight] = request - atomic.AddInt32(&pool.numPending, 1) + pool.mtx.Unlock() - err := request.Start() - if err != nil { + if err := request.Start(); err != nil { request.Logger.Error("Error starting request", "err", err) } } -func (pool *BlockPool) requestersLen() int64 { - return int64(len(pool.requesters)) -} - func (pool *BlockPool) sendRequest(height int64, peerID p2p.ID) { if !pool.IsRunning() { return @@ -437,7 +481,7 @@ func (pool *BlockPool) debug() string { defer pool.mtx.Unlock() str := "" - nextHeight := pool.height + pool.requestersLen() + nextHeight := pool.height + int64(len(pool.requesters)) for h := pool.height; h < nextHeight; h++ { if pool.requesters[h] == nil { str += fmt.Sprintf("H(%v):X ", h) @@ -450,10 +494,11 @@ func (pool *BlockPool) debug() string { return str } -//------------------------------------- +// ------------------------------------- type bpPeer struct { didTimeout bool + curRate int64 numPending int32 height int64 base int64 @@ -524,30 +569,44 @@ func (peer *bpPeer) onTimeout() { peer.didTimeout = true } -//------------------------------------- +// ------------------------------------- +// bpRequester requests a block from a peer. +// +// If the height is within minBlocksForSingleRequest blocks of the pool's +// height, it will send an additional request to another peer. This is to avoid +// a situation where blocksync is stuck because of a single slow peer. Note +// that it's okay to send a single request when the requested height is far +// from the pool's height. If the peer is slow, it will timeout and be replaced +// with another peer. type bpRequester struct { service.BaseService - pool *BlockPool - height int64 - gotBlockCh chan struct{} - redoCh chan p2p.ID // redo may send multitime, add peerId to identify repeat - mtx cmtsync.Mutex - peerID p2p.ID - block *types.Block - extCommit *types.ExtendedCommit + pool *BlockPool + height int64 + gotBlockCh chan struct{} + redoCh chan p2p.ID // redo may got multiple messages, add peerId to identify repeat + newHeightCh chan int64 + + mtx cmtsync.Mutex + peerID p2p.ID + secondPeerID p2p.ID // alternative peer to request from (if close to pool's height) + gotBlockFrom p2p.ID + block *types.Block + extCommit *types.ExtendedCommit } func newBPRequester(pool *BlockPool, height int64) *bpRequester { bpr := &bpRequester{ - pool: pool, - height: height, - gotBlockCh: make(chan struct{}, 1), - redoCh: make(chan p2p.ID, 1), + pool: pool, + height: height, + gotBlockCh: make(chan struct{}, 1), + redoCh: make(chan p2p.ID, 1), + newHeightCh: make(chan int64, 1), - peerID: "", - block: nil, + peerID: "", + secondPeerID: "", + block: nil, } bpr.BaseService = *service.NewBaseService(nil, "bpRequester", bpr) return bpr @@ -558,15 +617,21 @@ func (bpr *bpRequester) OnStart() error { return nil } -// Returns true if the peer matches and block doesn't already exist. +// Returns true if the peer(s) match and block doesn't already exist. func (bpr *bpRequester) setBlock(block *types.Block, extCommit *types.ExtendedCommit, peerID p2p.ID) bool { bpr.mtx.Lock() - if bpr.block != nil || bpr.peerID != peerID { + if bpr.peerID != peerID && bpr.secondPeerID != peerID { bpr.mtx.Unlock() return false } + if bpr.block != nil { + bpr.mtx.Unlock() + return true // getting a block from both peers is not an error + } + bpr.block = block bpr.extCommit = extCommit + bpr.gotBlockFrom = peerID bpr.mtx.Unlock() select { @@ -588,24 +653,54 @@ func (bpr *bpRequester) getExtendedCommit() *types.ExtendedCommit { return bpr.extCommit } -func (bpr *bpRequester) getPeerID() p2p.ID { +// Returns the IDs of peers we've requested a block from. +func (bpr *bpRequester) requestedFrom() []p2p.ID { bpr.mtx.Lock() defer bpr.mtx.Unlock() - return bpr.peerID + peerIDs := make([]p2p.ID, 0, 2) + if bpr.peerID != "" { + peerIDs = append(peerIDs, bpr.peerID) + } + if bpr.secondPeerID != "" { + peerIDs = append(peerIDs, bpr.secondPeerID) + } + return peerIDs } -// This is called from the requestRoutine, upon redo(). -func (bpr *bpRequester) reset() { +// Returns true if we've requested a block from the given peer. +func (bpr *bpRequester) didRequestFrom(peerID p2p.ID) bool { bpr.mtx.Lock() defer bpr.mtx.Unlock() + return bpr.peerID == peerID || bpr.secondPeerID == peerID +} - if bpr.block != nil { - atomic.AddInt32(&bpr.pool.numPending, 1) +// Returns the ID of the peer who sent us the block. +func (bpr *bpRequester) gotBlockFromPeerID() p2p.ID { + bpr.mtx.Lock() + defer bpr.mtx.Unlock() + return bpr.gotBlockFrom +} + +// Removes the block (IF we got it from the given peer) and resets the peer. +func (bpr *bpRequester) reset(peerID p2p.ID) (removedBlock bool) { + bpr.mtx.Lock() + defer bpr.mtx.Unlock() + + // Only remove the block if we got it from that peer. + if bpr.gotBlockFrom == peerID { + bpr.block = nil + bpr.extCommit = nil + bpr.gotBlockFrom = "" + removedBlock = true } - bpr.peerID = "" - bpr.block = nil - bpr.extCommit = nil + if bpr.peerID == peerID { + bpr.peerID = "" + } else { + bpr.secondPeerID = "" + } + + return removedBlock } // Tells bpRequester to pick another peer and try again. @@ -618,34 +713,81 @@ func (bpr *bpRequester) redo(peerID p2p.ID) { } } +func (bpr *bpRequester) pickPeerAndSendRequest() { + bpr.mtx.Lock() + secondPeerID := bpr.secondPeerID + bpr.mtx.Unlock() + + var peer *bpPeer +PICK_PEER_LOOP: + for { + if !bpr.IsRunning() || !bpr.pool.IsRunning() { + return + } + peer = bpr.pool.pickIncrAvailablePeer(bpr.height, secondPeerID) + if peer == nil { + bpr.Logger.Debug("No peers currently available; will retry shortly", "height", bpr.height) + time.Sleep(requestInterval) + continue PICK_PEER_LOOP + } + break PICK_PEER_LOOP + } + bpr.mtx.Lock() + bpr.peerID = peer.id + bpr.mtx.Unlock() + + bpr.pool.sendRequest(bpr.height, peer.id) +} + +// Picks a second peer and sends a request to it. If the second peer is already +// set, does nothing. +func (bpr *bpRequester) pickSecondPeerAndSendRequest() (picked bool) { + bpr.mtx.Lock() + if bpr.secondPeerID != "" { + bpr.mtx.Unlock() + return false + } + peerID := bpr.peerID + bpr.mtx.Unlock() + + secondPeer := bpr.pool.pickIncrAvailablePeer(bpr.height, peerID) + if secondPeer != nil { + bpr.mtx.Lock() + bpr.secondPeerID = secondPeer.id + bpr.mtx.Unlock() + + bpr.pool.sendRequest(bpr.height, secondPeer.id) + return true + } + + return false +} + +// Informs the requester of a new pool's height. +func (bpr *bpRequester) newHeight(height int64) { + select { + case bpr.newHeightCh <- height: + default: + } +} + // Responsible for making more requests as necessary -// Returns only when a block is found (e.g. AddBlock() is called) +// Returns only when a block is found (e.g. AddBlock() is called). func (bpr *bpRequester) requestRoutine() { + gotBlock := false + OUTER_LOOP: for { - // Pick a peer to send request to. - var peer *bpPeer - PICK_PEER_LOOP: - for { - if !bpr.IsRunning() || !bpr.pool.IsRunning() { - return - } - peer = bpr.pool.pickIncrAvailablePeer(bpr.height) - if peer == nil { - bpr.Logger.Debug("No peers currently available; will retry shortly", "height", bpr.height) - time.Sleep(requestIntervalMS * time.Millisecond) - continue PICK_PEER_LOOP - } - break PICK_PEER_LOOP + bpr.pickPeerAndSendRequest() + + poolHeight := bpr.pool.Height() + if bpr.height-poolHeight < minBlocksForSingleRequest { + bpr.pickSecondPeerAndSendRequest() } - bpr.mtx.Lock() - bpr.peerID = peer.id - bpr.mtx.Unlock() - to := time.NewTimer(requestRetrySeconds * time.Second) - // Send request and wait. - bpr.pool.sendRequest(bpr.height, peer.id) - WAIT_LOOP: + retryTimer := time.NewTimer(requestRetrySeconds * time.Second) + defer retryTimer.Stop() + for { select { case <-bpr.pool.Quit(): @@ -655,29 +797,50 @@ OUTER_LOOP: return case <-bpr.Quit(): return - case <-to.C: - bpr.Logger.Debug("Retrying block request after timeout", "height", bpr.height, "peer", bpr.peerID) - // Simulate a redo - bpr.reset() - continue OUTER_LOOP + case <-retryTimer.C: + if !gotBlock { + bpr.Logger.Debug("Retrying block request(s) after timeout", "height", bpr.height, "peer", bpr.peerID, "secondPeerID", bpr.secondPeerID) + bpr.reset(bpr.peerID) + bpr.reset(bpr.secondPeerID) + continue OUTER_LOOP + } case peerID := <-bpr.redoCh: - if peerID == bpr.peerID { - bpr.reset() + if bpr.didRequestFrom(peerID) { + removedBlock := bpr.reset(peerID) + if removedBlock { + gotBlock = false + } + } + // If both peers returned NoBlockResponse or bad block, reschedule both + // requests. If not, wait for the other peer. + if len(bpr.requestedFrom()) == 0 { + retryTimer.Stop() continue OUTER_LOOP - } else { - continue WAIT_LOOP + } + case newHeight := <-bpr.newHeightCh: + if !gotBlock && bpr.height-newHeight < minBlocksForSingleRequest { + // The operation is a noop if the second peer is already set. The cost is checking a mutex. + // + // If the second peer was just set, reset the retryTimer to give the + // second peer a chance to respond. + if picked := bpr.pickSecondPeerAndSendRequest(); picked { + if !retryTimer.Stop() { //nolint:revive // suppress max-control-nesting linter + <-retryTimer.C + } + retryTimer.Reset(requestRetrySeconds * time.Second) + } } case <-bpr.gotBlockCh: + gotBlock = true // We got a block! // Continue the for-loop and wait til Quit. - continue WAIT_LOOP } } } } // BlockRequest stores a block request identified by the block Height and the PeerID responsible for -// delivering the block +// delivering the block. type BlockRequest struct { Height int64 PeerID p2p.ID diff --git a/blocksync/pool_test.go b/internal/blocksync/pool_test.go similarity index 84% rename from blocksync/pool_test.go rename to internal/blocksync/pool_test.go index c5bfab46b5a..573afba88ff 100644 --- a/blocksync/pool_test.go +++ b/internal/blocksync/pool_test.go @@ -1,15 +1,15 @@ package blocksync import ( - "fmt" + "strconv" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/libs/log" - cmtrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/types" ) @@ -40,7 +40,7 @@ func (p testPeer) runInputRoutine() { } // Request desired, pretend like we got the block immediately. -func (p testPeer) simulateInput(input inputData) { +func (testPeer) simulateInput(input inputData) { block := &types.Block{Header: types.Header{Height: input.request.Height}} extCommit := &types.ExtendedCommit{ Height: input.request.Height, @@ -81,10 +81,13 @@ func makePeers(numPeers int, minHeight, maxHeight int64) testPeers { } func TestBlockPoolBasic(t *testing.T) { - start := int64(42) - peers := makePeers(10, start+1, 1000) - errorsCh := make(chan peerError, 1000) - requestsCh := make(chan BlockRequest, 1000) + var ( + start = int64(42) + peers = makePeers(10, start, 1000) + errorsCh = make(chan peerError) + requestsCh = make(chan BlockRequest) + ) + pool := NewBlockPool(start, requestsCh, errorsCh) pool.SetLogger(log.TestingLogger()) @@ -99,16 +102,13 @@ func TestBlockPoolBasic(t *testing.T) { } }) + for _, peer := range peers { + pool.SetPeerRange(peer.id, peer.base, peer.height) + } + peers.start() defer peers.stop() - // Introduce each peer. - go func() { - for _, peer := range peers { - pool.SetPeerRange(peer.id, peer.base, peer.height) - } - }() - // Start a goroutine to pull blocks go func() { for { @@ -119,7 +119,7 @@ func TestBlockPoolBasic(t *testing.T) { if first != nil && second != nil { pool.PopRequest() } else { - time.Sleep(1 * time.Second) + time.Sleep(10 * time.Millisecond) } } }() @@ -134,23 +134,30 @@ func TestBlockPoolBasic(t *testing.T) { if request.Height == 300 { return // Done! } - peers[request.PeerID].inputChan <- inputData{t, pool, request} + case <-time.After(10 * time.Second): + t.Error("Timed out waiting for block requests") + return } } } func TestBlockPoolTimeout(t *testing.T) { - start := int64(42) - peers := makePeers(10, start+1, 1000) - errorsCh := make(chan peerError, 1000) - requestsCh := make(chan BlockRequest, 1000) + var ( + start = int64(42) + peers = makePeers(10, start, 1000) + errorsCh = make(chan peerError) + requestsCh = make(chan BlockRequest) + ) + pool := NewBlockPool(start, requestsCh, errorsCh) pool.SetLogger(log.TestingLogger()) + err := pool.Start() if err != nil { t.Error(err) } + t.Cleanup(func() { if err := pool.Stop(); err != nil { t.Error(err) @@ -158,16 +165,9 @@ func TestBlockPoolTimeout(t *testing.T) { }) for _, peer := range peers { - t.Logf("Peer %v", peer.id) + pool.SetPeerRange(peer.id, peer.base, peer.height) } - // Introduce each peer. - go func() { - for _, peer := range peers { - pool.SetPeerRange(peer.id, peer.base, peer.height) - } - }() - // Start a goroutine to pull blocks go func() { for { @@ -178,7 +178,7 @@ func TestBlockPoolTimeout(t *testing.T) { if first != nil && second != nil { pool.PopRequest() } else { - time.Sleep(1 * time.Second) + time.Sleep(10 * time.Millisecond) } } }() @@ -199,6 +199,9 @@ func TestBlockPoolTimeout(t *testing.T) { } case request := <-requestsCh: t.Logf("Pulled new BlockRequest %+v", request) + case <-time.After(10 * time.Second): + t.Error("Timed out waiting for block requests") + return } } } @@ -206,7 +209,7 @@ func TestBlockPoolTimeout(t *testing.T) { func TestBlockPoolRemovePeer(t *testing.T) { peers := make(testPeers, 10) for i := 0; i < 10; i++ { - peerID := p2p.ID(fmt.Sprintf("%d", i+1)) + peerID := p2p.ID(strconv.Itoa(i + 1)) height := int64(i + 1) peers[peerID] = testPeer{peerID, 0, height, make(chan inputData)} } diff --git a/blocksync/reactor.go b/internal/blocksync/reactor.go similarity index 75% rename from blocksync/reactor.go rename to internal/blocksync/reactor.go index b67c2d844c4..2767f39f27d 100644 --- a/blocksync/reactor.go +++ b/internal/blocksync/reactor.go @@ -3,29 +3,30 @@ package blocksync import ( "fmt" "reflect" + "sync" "time" + bcproto "github.com/cometbft/cometbft/api/cometbft/blocksync/v1" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/p2p" - bcproto "github.com/cometbft/cometbft/proto/tendermint/blocksync" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" ) const ( - // BlocksyncChannel is a channel for blocks and status updates (`BlockStore` height) + // BlocksyncChannel is a channel for blocks and status updates (`BlockStore` height). BlocksyncChannel = byte(0x40) trySyncIntervalMS = 10 // stop syncing when last block's time is // within this much of the system time. - // stopSyncingDurationMinutes = 10 + // stopSyncingDurationMinutes = 10. - // ask for best height every 10s + // ask for best height every 10s. statusUpdateIntervalSeconds = 10 - // check if we should switch to consensus reactor + // check if we should switch to consensus reactor. switchToConsensusIntervalSeconds = 1 ) @@ -35,6 +36,11 @@ type consensusReactor interface { SwitchToConsensus(state sm.State, skipWAL bool) } +type mempoolReactor interface { + // for when we finish doing block sync or state sync + EnableInOutTxs() +} + type peerError struct { err error peerID p2p.ID @@ -51,10 +57,11 @@ type Reactor struct { // immutable initialState sm.State - blockExec *sm.BlockExecutor - store sm.BlockStore - pool *BlockPool - blockSync bool + blockExec *sm.BlockExecutor + store sm.BlockStore + pool *BlockPool + blockSync bool + poolRoutineWg sync.WaitGroup requestsCh <-chan BlockRequest errorsCh <-chan peerError @@ -66,19 +73,31 @@ type Reactor struct { // NewReactor returns new reactor instance. func NewReactor(state sm.State, blockExec *sm.BlockExecutor, store *store.BlockStore, - blockSync bool, metrics *Metrics) *Reactor { - - if state.LastBlockHeight != store.Height() { - panic(fmt.Sprintf("state (%v) and store (%v) height mismatch", state.LastBlockHeight, - store.Height())) + blockSync bool, metrics *Metrics, offlineStateSyncHeight int64, +) *Reactor { + storeHeight := store.Height() + if storeHeight == 0 { + // If state sync was performed offline and the stores were bootstrapped to height H + // the state store's lastHeight will be H while blockstore's Height and Base are still 0 + // 1. This scenario should not lead to a panic in this case, which is indicated by + // having a OfflineStateSyncHeight > 0 + // 2. We need to instruct the blocksync reactor to start fetching blocks from H+1 + // instead of 0. + storeHeight = offlineStateSyncHeight + } + if state.LastBlockHeight != storeHeight { + panic(fmt.Sprintf("state (%v) and store (%v) height mismatch, stores were left in an inconsistent state", state.LastBlockHeight, + storeHeight)) } - requestsCh := make(chan BlockRequest, maxTotalRequesters) + // It's okay to block since sendRequest is called from a separate goroutine + // (bpRequester#requestRoutine; 1 per each peer). + requestsCh := make(chan BlockRequest) const capacity = 1000 // must be bigger than peers count errorsCh := make(chan peerError, capacity) // so we don't block in #Receive#pool.AddBlock - startHeight := store.Height() + 1 + startHeight := storeHeight + 1 if startHeight == 1 { startHeight = state.InitialHeight } @@ -111,7 +130,11 @@ func (bcR *Reactor) OnStart() error { if err != nil { return err } - go bcR.poolRoutine(false) + bcR.poolRoutineWg.Add(1) + go func() { + defer bcR.poolRoutineWg.Done() + bcR.poolRoutine(false) + }() } return nil } @@ -126,7 +149,11 @@ func (bcR *Reactor) SwitchToBlockSync(state sm.State) error { if err != nil { return err } - go bcR.poolRoutine(true) + bcR.poolRoutineWg.Add(1) + go func() { + defer bcR.poolRoutineWg.Done() + bcR.poolRoutine(true) + }() return nil } @@ -136,11 +163,12 @@ func (bcR *Reactor) OnStop() { if err := bcR.pool.Stop(); err != nil { bcR.Logger.Error("Error stopping pool", "err", err) } + bcR.poolRoutineWg.Wait() } } -// GetChannels implements Reactor -func (bcR *Reactor) GetChannels() []*p2p.ChannelDescriptor { +// GetChannels implements Reactor. +func (*Reactor) GetChannels() []*p2p.ChannelDescriptor { return []*p2p.ChannelDescriptor{ { ID: BlocksyncChannel, @@ -169,16 +197,14 @@ func (bcR *Reactor) AddPeer(peer p2p.Peer) { } // RemovePeer implements Reactor by removing peer from the pool. -func (bcR *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) { +func (bcR *Reactor) RemovePeer(peer p2p.Peer, _ any) { bcR.pool.RemovePeer(peer.ID()) } // respondToPeer loads a block and sends it to the requesting peer, // if we have it. Otherwise, we'll respond saying we don't have it. -func (bcR *Reactor) respondToPeer(msg *bcproto.BlockRequest, - src p2p.Peer) (queued bool) { - - block := bcR.store.LoadBlock(msg.Height) +func (bcR *Reactor) respondToPeer(msg *bcproto.BlockRequest, src p2p.Peer) (queued bool) { + block, _ := bcR.store.LoadBlock(msg.Height) if block == nil { bcR.Logger.Info("Peer asking for a block we don't have", "src", src, "height", msg.Height) return src.TrySend(p2p.Envelope{ @@ -193,7 +219,7 @@ func (bcR *Reactor) respondToPeer(msg *bcproto.BlockRequest, return false } var extCommit *types.ExtendedCommit - if state.ConsensusParams.ABCI.VoteExtensionsEnabled(msg.Height) { + if state.ConsensusParams.Feature.VoteExtensionsEnabled(msg.Height) { extCommit = bcR.store.LoadBlockExtendedCommit(msg.Height) if extCommit == nil { bcR.Logger.Error("found block in store with no extended commit", "block", block) @@ -232,7 +258,8 @@ func (bcR *Reactor) Receive(e p2p.Envelope) { case *bcproto.BlockResponse: bi, err := types.BlockFromProto(msg.Block) if err != nil { - bcR.Logger.Error("Block content is invalid", "err", err) + bcR.Logger.Error("Peer sent us invalid block", "peer", e.Src, "msg", e.Message, "err", err) + bcR.Switch.StopPeerForError(e.Src, err) return } var extCommit *types.ExtendedCommit @@ -243,12 +270,13 @@ func (bcR *Reactor) Receive(e p2p.Envelope) { bcR.Logger.Error("failed to convert extended commit from proto", "peer", e.Src, "err", err) + bcR.Switch.StopPeerForError(e.Src, err) return } } if err := bcR.pool.AddBlock(e.Src.ID(), bi, extCommit, msg.Block.Size()); err != nil { - bcR.Logger.Error("failed to add block", "err", err) + bcR.Logger.Error("failed to add block", "peer", e.Src, "err", err) } case *bcproto.StatusRequest: // Send peer our state. @@ -264,6 +292,7 @@ func (bcR *Reactor) Receive(e p2p.Envelope) { bcR.pool.SetPeerRange(e.Src.ID(), msg.Base, msg.Height) case *bcproto.NoBlockResponse: bcR.Logger.Debug("Peer does not have requested block", "peer", e.Src, "height", msg.Height) + bcR.pool.RedoRequestFrom(msg.Height, e.Src.ID()) default: bcR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg))) } @@ -327,7 +356,6 @@ func (bcR *Reactor) poolRoutine(stateSynced bool) { case <-statusUpdateTicker.C: // ask for status updates go bcR.BroadcastStatusRequest() - } } }() @@ -336,10 +364,8 @@ FOR_LOOP: for { select { case <-switchToConsensusTicker.C: - height, numPending, lenRequesters := bcR.pool.GetStatus() outbound, inbound, _ := bcR.Switch.NumPeers() - bcR.Logger.Debug("Consensus ticker", "numPending", numPending, "total", lenRequesters, - "outbound", outbound, "inbound", inbound, "lastHeight", state.LastBlockHeight) + bcR.Logger.Debug("Consensus ticker", "outbound", outbound, "inbound", inbound, "lastHeight", state.LastBlockHeight) // The "if" statement below is a bit confusing, so here is a breakdown // of its logic and purpose: @@ -359,10 +385,8 @@ FOR_LOOP: // if we did not blocksync any block. // missingExtension := true - if state.LastBlockHeight == 0 || - !state.ConsensusParams.ABCI.VoteExtensionsEnabled(state.LastBlockHeight) || - blocksSynced > 0 || - initialCommitHasExtensions { + voteExtensionsDisabled := state.LastBlockHeight > 0 && !state.ConsensusParams.Feature.VoteExtensionsEnabled(state.LastBlockHeight) + if state.LastBlockHeight == 0 || voteExtensionsDisabled || blocksSynced > 0 || initialCommitHasExtensions { missingExtension = false } @@ -370,20 +394,23 @@ FOR_LOOP: if missingExtension { bcR.Logger.Info( "no extended commit yet", - "height", height, "last_block_height", state.LastBlockHeight, - "initial_height", state.InitialHeight, - "max_peer_height", bcR.pool.MaxPeerHeight(), + "vote_extensions_disabled", voteExtensionsDisabled, + "blocks_synced", blocksSynced, + "initial_commit_has_extensions", initialCommitHasExtensions, ) continue FOR_LOOP } - if bcR.pool.IsCaughtUp() { - bcR.Logger.Info("Time to switch to consensus reactor!", "height", height) + + if isCaughtUp, height, _ := bcR.pool.IsCaughtUp(); isCaughtUp { + bcR.Logger.Info("Time to switch to consensus mode!", "height", height) if err := bcR.pool.Stop(); err != nil { bcR.Logger.Error("Error stopping pool", "err", err) } - conR, ok := bcR.Switch.Reactor("CONSENSUS").(consensusReactor) - if ok { + if memR, ok := bcR.Switch.Reactor("MEMPOOL").(mempoolReactor); ok { + memR.EnableInOutTxs() + } + if conR, ok := bcR.Switch.Reactor("CONSENSUS").(consensusReactor); ok { conR.SwitchToConsensus(state, blocksSynced > 0 || stateSynced) } // else { @@ -424,11 +451,18 @@ FOR_LOOP: // Panicking because this is an obvious bug in the block pool, which is totally under our control panic(fmt.Errorf("heights of first and second block are not consecutive; expected %d, got %d", state.LastBlockHeight, first.Height)) } - if extCommit == nil && state.ConsensusParams.ABCI.VoteExtensionsEnabled(first.Height) { + if extCommit == nil && state.ConsensusParams.Feature.VoteExtensionsEnabled(first.Height) { // See https://github.com/tendermint/tendermint/pull/8433#discussion_r866790631 panic(fmt.Errorf("peeked first block without extended commit at height %d - possible node store corruption", first.Height)) } + // Before priming didProcessCh for another check on the next + // iteration, break the loop if the BlockPool or the Reactor itself + // has quit. This avoids case ambiguity of the outer select when two + // channels are ready. + if !bcR.IsRunning() || !bcR.pool.IsRunning() { + break FOR_LOOP + } // Try again quickly next loop. didProcessCh <- struct{}{} @@ -455,29 +489,27 @@ FOR_LOOP: } if err == nil { // if vote extensions were required at this height, ensure they exist. - if state.ConsensusParams.ABCI.VoteExtensionsEnabled(first.Height) { + if state.ConsensusParams.Feature.VoteExtensionsEnabled(first.Height) { err = extCommit.EnsureExtensions(true) - } else { - if extCommit != nil { - err = fmt.Errorf("received non-nil extCommit for height %d (extensions disabled)", first.Height) - } + } else if extCommit != nil { + err = fmt.Errorf("received non-nil extCommit for height %d (extensions disabled)", first.Height) } } if err != nil { bcR.Logger.Error("Error in validation", "err", err) - peerID := bcR.pool.RedoRequest(first.Height) + peerID := bcR.pool.RemovePeerAndRedoAllPeerRequests(first.Height) peer := bcR.Switch.Peers().Get(peerID) if peer != nil { // NOTE: we've already removed the peer's request, but we // still need to clean up the rest. - bcR.Switch.StopPeerForError(peer, fmt.Errorf("Reactor validation error: %v", err)) + bcR.Switch.StopPeerForError(peer, ErrReactorValidation{Err: err}) } - peerID2 := bcR.pool.RedoRequest(second.Height) + peerID2 := bcR.pool.RemovePeerAndRedoAllPeerRequests(second.Height) peer2 := bcR.Switch.Peers().Get(peerID2) if peer2 != nil && peer2 != peer { // NOTE: we've already removed the peer's request, but we // still need to clean up the rest. - bcR.Switch.StopPeerForError(peer2, fmt.Errorf("Reactor validation error: %v", err)) + bcR.Switch.StopPeerForError(peer2, ErrReactorValidation{Err: err}) } continue FOR_LOOP } @@ -485,7 +517,7 @@ FOR_LOOP: bcR.pool.PopRequest() // TODO: batch saves so we dont persist to disk every block - if state.ConsensusParams.ABCI.VoteExtensionsEnabled(first.Height) { + if state.ConsensusParams.Feature.VoteExtensionsEnabled(first.Height) { bcR.store.SaveBlockWithExtendedCommit(first, firstParts, extCommit) } else { // We use LastCommit here instead of extCommit. extCommit is not @@ -497,7 +529,7 @@ FOR_LOOP: // TODO: same thing for app - but we would need a way to // get the hash without persisting the state - state, err = bcR.blockExec.ApplyBlock(state, firstID, first) + state, err = bcR.blockExec.ApplyVerifiedBlock(state, firstID, first) if err != nil { // TODO This is bad, are we zombie? panic(fmt.Sprintf("Failed to process committed block (%d:%X): %v", first.Height, first.Hash(), err)) @@ -506,9 +538,9 @@ FOR_LOOP: blocksSynced++ if blocksSynced%100 == 0 { + _, height, maxPeerHeight := bcR.pool.IsCaughtUp() lastRate = 0.9*lastRate + 0.1*(100/time.Since(lastHundred).Seconds()) - bcR.Logger.Info("Block Sync Rate", "height", bcR.pool.height, - "max_peer_height", bcR.pool.MaxPeerHeight(), "blocks/s", lastRate) + bcR.Logger.Info("Block Sync Rate", "height", height, "max_peer_height", maxPeerHeight, "blocks/s", lastRate) lastHundred = time.Now() } @@ -516,6 +548,8 @@ FOR_LOOP: case <-bcR.Quit(): break FOR_LOOP + case <-bcR.pool.Quit(): + break FOR_LOOP } } } diff --git a/blocksync/reactor_test.go b/internal/blocksync/reactor_test.go similarity index 86% rename from blocksync/reactor_test.go rename to internal/blocksync/reactor_test.go index 8363e9f5941..6fcdfadb98b 100644 --- a/blocksync/reactor_test.go +++ b/internal/blocksync/reactor_test.go @@ -12,28 +12,28 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" cfg "github.com/cometbft/cometbft/config" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" mpmocks "github.com/cometbft/cometbft/mempool/mocks" "github.com/cometbft/cometbft/p2p" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" ) var config *cfg.Config -func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.GenesisDoc, []types.PrivValidator) { +func randGenesisDoc() (*types.GenesisDoc, []types.PrivValidator) { + minPower := int64(30) + numValidators := 1 validators := make([]types.GenesisValidator, numValidators) privValidators := make([]types.PrivValidator, numValidators) for i := 0; i < numValidators; i++ { - val, privVal := types.RandValidator(randPower, minPower) + val, privVal := types.RandValidator(false, minPower) validators[i] = types.GenesisValidator{ PubKey: val.PubKey, Power: val.VotingPower, @@ -43,7 +43,7 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G sort.Sort(types.PrivValidatorsByAddress(privValidators)) consPar := types.DefaultConsensusParams() - consPar.ABCI.VoteExtensionsEnableHeight = 1 + consPar.Feature.VoteExtensionsEnableHeight = 1 return &types.GenesisDoc{ GenesisTime: cmttime.Now(), ChainID: test.DefaultTestChainID, @@ -64,6 +64,7 @@ func newReactor( privVals []types.PrivValidator, maxBlockHeight int64, ) ReactorPair { + t.Helper() if len(privVals) != 1 { panic("only support one validator") } @@ -140,9 +141,9 @@ func newReactor( idx, thisBlock.Header.Height, 0, - cmtproto.PrecommitType, + types.PrecommitType, blockID, - time.Now(), + cmttime.Now(), ) if err != nil { panic(err) @@ -162,7 +163,7 @@ func newReactor( blockStore.SaveBlockWithExtendedCommit(thisBlock, thisParts, seenExtCommit) } - bcReactor := NewReactor(state.Copy(), blockExec, blockStore, fastSync, NopMetrics()) + bcReactor := NewReactor(state.Copy(), blockExec, blockStore, fastSync, NopMetrics(), 0) bcReactor.SetLogger(logger.With("module", "blocksync")) return ReactorPair{bcReactor, proxyApp} @@ -171,7 +172,7 @@ func newReactor( func TestNoBlockResponse(t *testing.T) { config = test.ResetTestRoot("blocksync_reactor_test") defer os.RemoveAll(config.RootDir) - genDoc, privVals := randGenesisDoc(1, false, 30) + genDoc, privVals := randGenesisDoc() maxBlockHeight := int64(65) @@ -205,7 +206,7 @@ func TestNoBlockResponse(t *testing.T) { } for { - if reactorPairs[1].reactor.pool.IsCaughtUp() { + if isCaughtUp, _, _ := reactorPairs[1].reactor.pool.IsCaughtUp(); isCaughtUp { break } @@ -215,11 +216,11 @@ func TestNoBlockResponse(t *testing.T) { assert.Equal(t, maxBlockHeight, reactorPairs[0].reactor.store.Height()) for _, tt := range tests { - block := reactorPairs[1].reactor.store.LoadBlock(tt.height) + block, _ := reactorPairs[1].reactor.store.LoadBlock(tt.height) if tt.existent { - assert.True(t, block != nil) + assert.NotNil(t, block) } else { - assert.True(t, block == nil) + assert.Nil(t, block) } } } @@ -232,12 +233,12 @@ func TestNoBlockResponse(t *testing.T) { func TestBadBlockStopsPeer(t *testing.T) { config = test.ResetTestRoot("blocksync_reactor_test") defer os.RemoveAll(config.RootDir) - genDoc, privVals := randGenesisDoc(1, false, 30) + genDoc, privVals := randGenesisDoc() maxBlockHeight := int64(148) // Other chain needs a different validator set - otherGenDoc, otherPrivVals := randGenesisDoc(1, false, 30) + otherGenDoc, otherPrivVals := randGenesisDoc() otherChain := newReactor(t, log.TestingLogger(), otherGenDoc, otherPrivVals, maxBlockHeight) defer func() { @@ -273,7 +274,7 @@ func TestBadBlockStopsPeer(t *testing.T) { time.Sleep(1 * time.Second) caughtUp := true for _, r := range reactorPairs { - if !r.reactor.pool.IsCaughtUp() { + if isCaughtUp, _, _ := r.reactor.pool.IsCaughtUp(); !isCaughtUp { caughtUp = false } } @@ -290,9 +291,9 @@ func TestBadBlockStopsPeer(t *testing.T) { reactorPairs[3].reactor.store = otherChain.reactor.store lastReactorPair := newReactor(t, log.TestingLogger(), genDoc, privVals, 0) - reactorPairs = append(reactorPairs, lastReactorPair) + reactorPairs = append(reactorPairs, lastReactorPair) //nolint:makezero // when initializing with 0, the test breaks. - switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(i int, s *p2p.Switch) *p2p.Switch { + switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(_ int, s *p2p.Switch) *p2p.Switch { s.AddReactor("BLOCKSYNC", reactorPairs[len(reactorPairs)-1].reactor) return s }, p2p.Connect2Switches)...) @@ -302,14 +303,15 @@ func TestBadBlockStopsPeer(t *testing.T) { } for { - if lastReactorPair.reactor.pool.IsCaughtUp() || lastReactorPair.reactor.Switch.Peers().Size() == 0 { + isCaughtUp, _, _ := lastReactorPair.reactor.pool.IsCaughtUp() + if isCaughtUp || lastReactorPair.reactor.Switch.Peers().Size() == 0 { break } time.Sleep(1 * time.Second) } - assert.True(t, lastReactorPair.reactor.Switch.Peers().Size() < len(reactorPairs)-1) + assert.Less(t, lastReactorPair.reactor.Switch.Peers().Size(), len(reactorPairs)-1) } func TestCheckSwitchToConsensusLastHeightZero(t *testing.T) { @@ -317,7 +319,7 @@ func TestCheckSwitchToConsensusLastHeightZero(t *testing.T) { config = test.ResetTestRoot("blocksync_reactor_test") defer os.RemoveAll(config.RootDir) - genDoc, privVals := randGenesisDoc(1, false, 30) + genDoc, privVals := randGenesisDoc() reactorPairs := make([]ReactorPair, 1, 2) reactorPairs[0] = newReactor(t, log.TestingLogger(), genDoc, privVals, 0) @@ -335,7 +337,7 @@ func TestCheckSwitchToConsensusLastHeightZero(t *testing.T) { var switches []*p2p.Switch for _, r := range reactorPairs { - switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(i int, s *p2p.Switch) *p2p.Switch { + switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(_ int, s *p2p.Switch) *p2p.Switch { s.AddReactor("BLOCKSYNC", r.reactor) return s }, p2p.Connect2Switches)...) @@ -351,7 +353,7 @@ func TestCheckSwitchToConsensusLastHeightZero(t *testing.T) { time.Sleep(20 * time.Millisecond) caughtUp := true for _, r := range reactorPairs { - if !r.reactor.pool.IsCaughtUp() { + if isCaughtUp, _, _ := r.reactor.pool.IsCaughtUp(); !isCaughtUp { caughtUp = false break } @@ -362,9 +364,8 @@ func TestCheckSwitchToConsensusLastHeightZero(t *testing.T) { if time.Since(startTime) > 90*time.Second { msg := "timeout: reactors didn't catch up;" for i, r := range reactorPairs { - h, p, lr := r.reactor.pool.GetStatus() - c := r.reactor.pool.IsCaughtUp() - msg += fmt.Sprintf(" reactor#%d (h %d, p %d, lr %d, c %t);", i, h, p, lr, c) + c, h, maxH := r.reactor.pool.IsCaughtUp() + msg += fmt.Sprintf(" reactor#%d (h %d, maxH %d, c %t);", i, h, maxH, c) } require.Fail(t, msg) } diff --git a/internal/blocksync/types.go b/internal/blocksync/types.go new file mode 100644 index 00000000000..b24a5c8945a --- /dev/null +++ b/internal/blocksync/types.go @@ -0,0 +1,14 @@ +package blocksync + +import ( + cmtbs "github.com/cometbft/cometbft/api/cometbft/blocksync/v1" + "github.com/cometbft/cometbft/types" +) + +var ( + _ types.Wrapper = &cmtbs.StatusRequest{} + _ types.Wrapper = &cmtbs.StatusResponse{} + _ types.Wrapper = &cmtbs.NoBlockResponse{} + _ types.Wrapper = &cmtbs.BlockResponse{} + _ types.Wrapper = &cmtbs.BlockRequest{} +) diff --git a/libs/clist/bench_test.go b/internal/clist/bench_test.go similarity index 100% rename from libs/clist/bench_test.go rename to internal/clist/bench_test.go diff --git a/libs/clist/clist.go b/internal/clist/clist.go similarity index 92% rename from libs/clist/clist.go rename to internal/clist/clist.go index b18306490f9..8d39bf37b0f 100644 --- a/libs/clist/clist.go +++ b/internal/clist/clist.go @@ -15,7 +15,7 @@ import ( "fmt" "sync" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) // MaxLength is the max allowed number of elements a linked list is @@ -51,7 +51,7 @@ type CElement struct { nextWaitCh chan struct{} removed bool - Value interface{} // immutable + Value any // immutable } // Blocking implementation of Next(). @@ -166,7 +166,7 @@ func (e *CElement) SetNext(newNext *CElement) { // If a WaitGroup is reused to wait for several independent sets of // events, new Add calls must happen after all previous Wait calls have // returned. - e.nextWg = waitGroup1() // WaitGroups are difficult to re-use. + e.nextWg = waitGroup1() // WaitGroups are difficult to reuse. e.nextWaitCh = make(chan struct{}) } if oldNext == nil && newNext != nil { @@ -177,14 +177,14 @@ func (e *CElement) SetNext(newNext *CElement) { } // NOTE: This function needs to be safe for -// concurrent goroutines waiting on prevWg +// concurrent goroutines waiting on prevWg. func (e *CElement) SetPrev(newPrev *CElement) { e.mtx.Lock() oldPrev := e.prev e.prev = newPrev if oldPrev != nil && newPrev == nil { - e.prevWg = waitGroup1() // WaitGroups are difficult to re-use. + e.prevWg = waitGroup1() // WaitGroups are difficult to reuse. e.prevWaitCh = make(chan struct{}) } if oldPrev == nil && newPrev != nil { @@ -211,7 +211,7 @@ func (e *CElement) SetRemoved() { e.mtx.Unlock() } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- // CList represents a linked list. // The zero value for CList is an empty list ready to use. @@ -223,7 +223,7 @@ type CList struct { waitCh chan struct{} head *CElement // first element tail *CElement // last element - len int // list length + curLen int // list length maxLen int // max list length } @@ -234,7 +234,7 @@ func (l *CList) Init() *CList { l.waitCh = make(chan struct{}) l.head = nil l.tail = nil - l.len = 0 + l.curLen = 0 l.mtx.Unlock() return l } @@ -252,9 +252,9 @@ func newWithMax(maxLength int) *CList { func (l *CList) Len() int { l.mtx.RLock() - len := l.len + curLen := l.curLen l.mtx.RUnlock() - return len + return curLen } func (l *CList) Front() *CElement { @@ -313,7 +313,7 @@ func (l *CList) WaitChan() <-chan struct{} { } // Panics if list grows beyond its max length. -func (l *CList) PushBack(v interface{}) *CElement { +func (l *CList) PushBack(v any) *CElement { l.mtx.Lock() // Construct a new element @@ -329,14 +329,14 @@ func (l *CList) PushBack(v interface{}) *CElement { } // Release waiters on FrontWait/BackWait maybe - if l.len == 0 { + if l.curLen == 0 { l.wg.Done() close(l.waitCh) } - if l.len >= l.maxLen { + if l.curLen >= l.maxLen { panic(fmt.Sprintf("clist: maximum length list reached %d", l.maxLen)) } - l.len++ + l.curLen++ // Modify the tail if l.tail == nil { @@ -353,7 +353,7 @@ func (l *CList) PushBack(v interface{}) *CElement { // CONTRACT: Caller must call e.DetachPrev() and/or e.DetachNext() to avoid memory leaks. // NOTE: As per the contract of CList, removed elements cannot be added back. -func (l *CList) Remove(e *CElement) interface{} { +func (l *CList) Remove(e *CElement) any { l.mtx.Lock() prev := e.Prev() @@ -373,13 +373,13 @@ func (l *CList) Remove(e *CElement) interface{} { } // If we're removing the only item, make CList FrontWait/BackWait wait. - if l.len == 1 { - l.wg = waitGroup1() // WaitGroups are difficult to re-use. + if l.curLen == 1 { + l.wg = waitGroup1() // WaitGroups are difficult to reuse. l.waitCh = make(chan struct{}) } // Update l.len - l.len-- + l.curLen-- // Connect next/prev and set head/tail if prev == nil { @@ -403,5 +403,5 @@ func (l *CList) Remove(e *CElement) interface{} { func waitGroup1() (wg *sync.WaitGroup) { wg = &sync.WaitGroup{} wg.Add(1) - return + return wg } diff --git a/libs/clist/clist_test.go b/internal/clist/clist_test.go similarity index 80% rename from libs/clist/clist_test.go rename to internal/clist/clist_test.go index 9cff7e34f2c..64a267ff09d 100644 --- a/libs/clist/clist_test.go +++ b/internal/clist/clist_test.go @@ -3,13 +3,13 @@ package clist import ( "fmt" "runtime" - "sync/atomic" + "sync" "testing" "time" "github.com/stretchr/testify/assert" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) func TestPanicOnMaxLength(t *testing.T) { @@ -63,75 +63,65 @@ func TestSmall(t *testing.T) { if l.Len() != 0 { t.Error("Expected len 0, got ", l.Len()) } - } -// This test is quite hacky because it relies on SetFinalizer -// which isn't guaranteed to run at all. -// -//nolint:unused,deadcode -func _TestGCFifo(t *testing.T) { +// This test was quite hacky because it relies on SetFinalizer +// it has been made less hacky (I think) by using a WaitGroup. +func TestGCFifo(t *testing.T) { + t.Helper() if runtime.GOARCH != "amd64" { t.Skipf("Skipping on non-amd64 machine") } const numElements = 1000000 l := New() - gcCount := new(uint64) - // SetFinalizer doesn't work well with circular structures, - // so we construct a trivial non-circular structure to - // track. + // Use a WaitGroup to wait for all finalizers to run. + var wg sync.WaitGroup + wg.Add(numElements) + type value struct { Int int } - done := make(chan struct{}) for i := 0; i < numElements; i++ { v := new(value) v.Int = i l.PushBack(v) - runtime.SetFinalizer(v, func(v *value) { - atomic.AddUint64(gcCount, 1) + runtime.SetFinalizer(v, func(_ *value) { + wg.Done() }) } for el := l.Front(); el != nil; { + next := el.Next() l.Remove(el) - // oldEl := el - el = el.Next() - // oldEl.DetachPrev() - // oldEl.DetachNext() + el = next } - runtime.GC() - time.Sleep(time.Second * 3) - runtime.GC() - time.Sleep(time.Second * 3) - _ = done + // Wait for all finalizers to run. + wg.Wait() - if *gcCount != numElements { - t.Errorf("expected gcCount to be %v, got %v", numElements, - *gcCount) + if l.Len() != 0 { + t.Errorf("expected list to be empty, got %v elements", l.Len()) } } // This test is quite hacky because it relies on SetFinalizer // which isn't guaranteed to run at all. -// -//nolint:unused,deadcode -func _TestGCRandom(t *testing.T) { +func TestGCRandom(t *testing.T) { + t.Helper() if runtime.GOARCH != "amd64" { t.Skipf("Skipping on non-amd64 machine") } const numElements = 1000000 l := New() - gcCount := 0 - // SetFinalizer doesn't work well with circular structures, - // so we construct a trivial non-circular structure to - // track. + // Use a WaitGroup to wait for all finalizers to run. + var wg sync.WaitGroup + wg.Add(numElements) + type value struct { Int int } @@ -140,8 +130,8 @@ func _TestGCRandom(t *testing.T) { v := new(value) v.Int = i l.PushBack(v) - runtime.SetFinalizer(v, func(v *value) { - gcCount++ + runtime.SetFinalizer(v, func(_ *value) { + wg.Done() }) } @@ -156,17 +146,15 @@ func _TestGCRandom(t *testing.T) { _ = el.Next() } - runtime.GC() - time.Sleep(time.Second * 3) + // Wait for all finalizers to run. + wg.Wait() - if gcCount != numElements { - t.Errorf("expected gcCount to be %v, got %v", numElements, - gcCount) + if l.Len() != 0 { + t.Errorf("expected list to be empty, got %v elements", l.Len()) } } func TestScanRightDeleteRandom(t *testing.T) { - const numElements = 1000 const numTimes = 100 const numScanners = 10 @@ -222,7 +210,6 @@ func TestScanRightDeleteRandom(t *testing.T) { if i%100000 == 0 { fmt.Printf("Pushed %vK elements so far...\n", i/1000) } - } // Stop scanners diff --git a/libs/cmap/cmap.go b/internal/cmap/cmap.go similarity index 69% rename from libs/cmap/cmap.go rename to internal/cmap/cmap.go index 2169c02fe96..d3eee666ebf 100644 --- a/libs/cmap/cmap.go +++ b/internal/cmap/cmap.go @@ -1,28 +1,28 @@ package cmap import ( - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) -// CMap is a goroutine-safe map +// CMap is a goroutine-safe map. type CMap struct { - m map[string]interface{} + m map[string]any l cmtsync.Mutex } func NewCMap() *CMap { return &CMap{ - m: make(map[string]interface{}), + m: make(map[string]any), } } -func (cm *CMap) Set(key string, value interface{}) { +func (cm *CMap) Set(key string, value any) { cm.l.Lock() cm.m[key] = value cm.l.Unlock() } -func (cm *CMap) Get(key string) interface{} { +func (cm *CMap) Get(key string) any { cm.l.Lock() val := cm.m[key] cm.l.Unlock() @@ -51,7 +51,7 @@ func (cm *CMap) Size() int { func (cm *CMap) Clear() { cm.l.Lock() - cm.m = make(map[string]interface{}) + cm.m = make(map[string]any) cm.l.Unlock() } @@ -66,9 +66,9 @@ func (cm *CMap) Keys() []string { return keys } -func (cm *CMap) Values() []interface{} { +func (cm *CMap) Values() []any { cm.l.Lock() - items := make([]interface{}, 0, len(cm.m)) + items := make([]any, 0, len(cm.m)) for _, v := range cm.m { items = append(items, v) } diff --git a/libs/cmap/cmap_test.go b/internal/cmap/cmap_test.go similarity index 94% rename from libs/cmap/cmap_test.go rename to internal/cmap/cmap_test.go index bab78da965e..bc507bce5a4 100644 --- a/libs/cmap/cmap_test.go +++ b/internal/cmap/cmap_test.go @@ -17,8 +17,8 @@ func TestIterateKeysWithValues(t *testing.T) { // Testing size assert.Equal(t, 10, cmap.Size()) - assert.Equal(t, 10, len(cmap.Keys())) - assert.Equal(t, 10, len(cmap.Values())) + assert.Len(t, cmap.Keys(), 10) + assert.Len(t, cmap.Values(), 10) // Iterating Keys, checking for matching Value for _, key := range cmap.Keys() { diff --git a/consensus/README.md b/internal/consensus/README.md similarity index 100% rename from consensus/README.md rename to internal/consensus/README.md diff --git a/consensus/byzantine_test.go b/internal/consensus/byzantine_test.go similarity index 84% rename from consensus/byzantine_test.go rename to internal/consensus/byzantine_test.go index 6365e48911a..b9a7002e9da 100644 --- a/consensus/byzantine_test.go +++ b/internal/consensus/byzantine_test.go @@ -13,28 +13,26 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abcicli "github.com/cometbft/cometbft/abci/client" abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/evidence" + cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1" + "github.com/cometbft/cometbft/internal/evidence" + "github.com/cometbft/cometbft/internal/service" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" mempl "github.com/cometbft/cometbft/mempool" - "github.com/cometbft/cometbft/proxy" - "github.com/cometbft/cometbft/p2p" - cmtcons "github.com/cometbft/cometbft/proto/tendermint/consensus" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/store" + "github.com/cometbft/cometbft/proxy" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" ) -//---------------------------------------------- +// ---------------------------------------------- // byzantine failures -// Byzantine node sends two different prevotes (nil and blockID) to the same validator +// Byzantine node sends two different prevotes (nil and blockID) to the same validator. func TestByzantinePrevoteEquivocation(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -46,7 +44,7 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { tickerFunc := newMockTickerFunc(true) appFunc := newKVStore - genDoc, privVals := randGenesisDoc(nValidators, false, 30, nil) + genDoc, privVals := randGenesisDoc(nValidators, 30, nil, cmttime.Now()) css := make([]*State, nValidators) for i := 0; i < nValidators; i++ { @@ -58,10 +56,10 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { state, _ := stateStore.LoadFromDBOrGenesisDoc(genDoc) thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i)) defer os.RemoveAll(thisConfig.RootDir) - ensureDir(path.Dir(thisConfig.Consensus.WalFile()), 0o700) // dir for wal + ensureDir(path.Dir(thisConfig.Consensus.WalFile())) // dir for wal app := appFunc() vals := types.TM2PB.ValidatorUpdates(state.Validators) - _, err := app.InitChain(context.Background(), &abci.RequestInitChain{Validators: vals}) + _, err := app.InitChain(context.Background(), &abci.InitChainRequest{Validators: vals}) require.NoError(t, err) blockDB := dbm.NewMemDB() @@ -145,11 +143,11 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { // allow first height to happen normally so that byzantine validator is no longer proposer if height == prevoteHeight { bcs.Logger.Info("Sending two votes") - prevote1, err := bcs.signVote(cmtproto.PrevoteType, bcs.ProposalBlock.Hash(), bcs.ProposalBlockParts.Header()) + prevote1, err := bcs.signVote(types.PrevoteType, bcs.ProposalBlock.Hash(), bcs.ProposalBlockParts.Header(), bcs.ProposalBlock) require.NoError(t, err) - prevote2, err := bcs.signVote(cmtproto.PrevoteType, nil, types.PartSetHeader{}) + prevote2, err := bcs.signVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) require.NoError(t, err) - peerList := reactors[byzantineNode].Switch.Peers().List() + peerList := reactors[byzantineNode].Switch.Peers().Copy() bcs.Logger.Info("Getting peer list", "peers", peerList) // send two votes to all peers (1st to one half, 2nd to another half) for i, peer := range peerList { @@ -192,7 +190,8 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { extCommit = &types.ExtendedCommit{} case lazyProposer.LastCommit.HasTwoThirdsMajority(): // Make the commit from LastCommit - veHeightParam := types.ABCIParams{VoteExtensionsEnableHeight: height} + // Vote extensions are enabled by default for test units + veHeightParam := lazyProposer.state.ConsensusParams.Feature extCommit = lazyProposer.LastCommit.MakeExtendedCommit(veHeightParam) default: // This shouldn't happen. lazyProposer.Logger.Error("enterPropose: Cannot propose anything: No commit for the previous block") @@ -205,7 +204,7 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { if lazyProposer.privValidatorPubKey == nil { // If this node is a validator & proposer in the current round, it will // miss the opportunity to create a block. - lazyProposer.Logger.Error(fmt.Sprintf("enterPropose: %v", errPubKeyIsNotSet)) + lazyProposer.Logger.Error(fmt.Sprintf("enterPropose: %v", ErrPubKeyIsNotSet)) return } proposerAddr := lazyProposer.privValidatorPubKey.Address() @@ -224,16 +223,16 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { // Make proposal propBlockID := types.BlockID{Hash: block.Hash(), PartSetHeader: blockParts.Header()} - proposal := types.NewProposal(height, round, lazyProposer.ValidRound, propBlockID) + proposal := types.NewProposal(height, round, lazyProposer.ValidRound, propBlockID, block.Header.Time) p := proposal.ToProto() if err := lazyProposer.privValidator.SignProposal(lazyProposer.state.ChainID, p); err == nil { proposal.Signature = p.Signature // send proposal and block parts on internal msg queue - lazyProposer.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""}) + lazyProposer.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, "", cmttime.Now()}) for i := 0; i < int(blockParts.Total()); i++ { part := blockParts.GetPart(i) - lazyProposer.sendInternalMessage(msgInfo{&BlockPartMessage{lazyProposer.Height, lazyProposer.Round, part}, ""}) + lazyProposer.sendInternalMessage(msgInfo{&BlockPartMessage{lazyProposer.Height, lazyProposer.Round, part}, "", time.Time{}}) } lazyProposer.Logger.Info("Signed proposal", "height", height, "round", round, "proposal", proposal) lazyProposer.Logger.Debug(fmt.Sprintf("Signed proposal block: %v", block)) @@ -296,16 +295,16 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { // byzantine validator sends conflicting proposals into A and B, // and prevotes/precommits on both of them. // B sees a commit, A doesn't. -// Heal partition and ensure A sees the commit +// Heal partition and ensure A sees the commit. func TestByzantineConflictingProposalsWithPartition(t *testing.T) { - N := 4 + n := 4 logger := consensusLogger().With("test", "byzantine") ctx, cancel := context.WithCancel(context.Background()) defer cancel() app := newKVStore - css, cleanup := randConsensusNet(t, N, "consensus_byzantine_test", newMockTickerFunc(false), app) + css, cleanup := randConsensusNet(t, n, "consensus_byzantine_test", newMockTickerFunc(false), app) defer cleanup() // give the byzantine validator a normal ticker @@ -313,23 +312,21 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { ticker.SetLogger(css[0].Logger) css[0].SetTimeoutTicker(ticker) - switches := make([]*p2p.Switch, N) + switches := make([]*p2p.Switch, n) p2pLogger := logger.With("module", "p2p") - for i := 0; i < N; i++ { + for i := 0; i < n; i++ { switches[i] = p2p.MakeSwitch( config.P2P, i, - "foo", "1.0.0", - func(i int, sw *p2p.Switch) *p2p.Switch { + func(_ int, sw *p2p.Switch) *p2p.Switch { return sw }) switches[i].SetLogger(p2pLogger.With("validator", i)) } - blocksSubs := make([]types.Subscription, N) - reactors := make([]p2p.Reactor, N) - for i := 0; i < N; i++ { - + blocksSubs := make([]types.Subscription, n) + reactors := make([]p2p.Reactor, n) + for i := 0; i < n; i++ { // enable txs so we can create different proposals assertMempool(css[i].txNotifier).EnableTxsAvailable() // make first val byzantine @@ -337,14 +334,13 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { // NOTE: Now, test validators are MockPV, which by default doesn't // do any safety checks. css[i].privValidator.(types.MockPV).DisableChecks() - css[i].decideProposal = func(j int32) func(int64, int32) { - return func(height int64, round int32) { - byzantineDecideProposalFunc(ctx, t, height, round, css[j], switches[j]) - } - }(int32(i)) + j := i + css[i].decideProposal = func(height int64, round int32) { + byzantineDecideProposalFunc(ctx, t, height, round, css[j], switches[j]) + } // We are setting the prevote function to do nothing because the prevoting // and precommitting are done alongside the proposal. - css[i].doPrevote = func(height int64, round int32) {} + css[i].doPrevote = func(_ int64, _ int32) {} } eventBus := css[i].eventBus @@ -382,7 +378,7 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { } }() - p2p.MakeConnectedSwitches(config.P2P, N, func(i int, s *p2p.Switch) *p2p.Switch { + p2p.MakeConnectedSwitches(config.P2P, n, func(i int, _ *p2p.Switch) *p2p.Switch { // ignore new switch s, we already made ours switches[i].AddReactor("CONSENSUS", reactors[i]) return switches[i] @@ -396,7 +392,7 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { // start the non-byz state machines. // note these must be started before the byz - for i := 1; i < N; i++ { + for i := 1; i < n; i++ { cr := reactors[i].(*Reactor) cr.SwitchToConsensus(cr.conS.GetState(), false) } @@ -409,7 +405,7 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { // byz proposer sends one block to peers[0] // and the other block to peers[1] and peers[2]. // note peers and switches order don't match. - peers := switches[0].Peers().List() + peers := switches[0].Peers().Copy() // partition A ind0 := getSwitchIndex(switches, peers[0]) @@ -429,7 +425,7 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { // wait till everyone makes the first new block // (one of them already has) wg := new(sync.WaitGroup) - for i := 1; i < N-1; i++ { + for i := 1; i < n-1; i++ { wg.Add(1) go func(j int) { <-blocksSubs[j].Out() @@ -455,20 +451,18 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { } } -//------------------------------- +// ------------------------------- // byzantine consensus functions -func byzantineDecideProposalFunc(ctx context.Context, t *testing.T, height int64, round int32, cs *State, sw *p2p.Switch) { +func byzantineDecideProposalFunc(_ context.Context, t *testing.T, height int64, round int32, cs *State, sw *p2p.Switch) { + t.Helper() // byzantine user should create two proposals and try to split the vote. // Avoid sending on internalMsgQueue and running consensus state. // Create a new proposal block from state/txs from the mempool. - block1, err := cs.createProposalBlock(ctx) - require.NoError(t, err) - blockParts1, err := block1.MakePartSet(types.BlockPartSizeBytes) - require.NoError(t, err) - polRound, propBlockID := cs.ValidRound, types.BlockID{Hash: block1.Hash(), PartSetHeader: blockParts1.Header()} - proposal1 := types.NewProposal(height, round, polRound, propBlockID) + block1, blockParts1, propBlockID := createProposalBlock(t, cs) + polRound := cs.ValidRound + proposal1 := types.NewProposal(height, round, polRound, propBlockID, block1.Time) p1 := proposal1.ToProto() if err := cs.privValidator.SignProposal(cs.state.ChainID, p1); err != nil { t.Error(err) @@ -477,15 +471,12 @@ func byzantineDecideProposalFunc(ctx context.Context, t *testing.T, height int64 proposal1.Signature = p1.Signature // some new transactions come in (this ensures that the proposals are different) - deliverTxsRange(t, cs, 0, 1) + deliverTxsRange(t, cs, 1) // Create a new proposal block from state/txs from the mempool. - block2, err := cs.createProposalBlock(ctx) - require.NoError(t, err) - blockParts2, err := block2.MakePartSet(types.BlockPartSizeBytes) - require.NoError(t, err) - polRound, propBlockID = cs.ValidRound, types.BlockID{Hash: block2.Hash(), PartSetHeader: blockParts2.Header()} - proposal2 := types.NewProposal(height, round, polRound, propBlockID) + block2, blockParts2, propBlockID := createProposalBlock(t, cs) + polRound = cs.ValidRound + proposal2 := types.NewProposal(height, round, polRound, propBlockID, block2.Time) p2 := proposal2.ToProto() if err := cs.privValidator.SignProposal(cs.state.ChainID, p2); err != nil { t.Error(err) @@ -495,15 +486,16 @@ func byzantineDecideProposalFunc(ctx context.Context, t *testing.T, height int64 block1Hash := block1.Hash() block2Hash := block2.Hash() + require.NotEqual(t, block1Hash, block2Hash) // broadcast conflicting proposals/block parts to peers - peers := sw.Peers().List() + peers := sw.Peers().Copy() t.Logf("Byzantine: broadcasting conflicting proposals to %d peers", len(peers)) for i, peer := range peers { if i < len(peers)/2 { - go sendProposalAndParts(height, round, cs, peer, proposal1, block1Hash, blockParts1) + go sendProposalAndParts(height, round, cs, peer, proposal1, block1, block1Hash, blockParts1) } else { - go sendProposalAndParts(height, round, cs, peer, proposal2, block2Hash, blockParts2) + go sendProposalAndParts(height, round, cs, peer, proposal2, block2, block2Hash, blockParts2) } } } @@ -514,6 +506,7 @@ func sendProposalAndParts( cs *State, peer p2p.Peer, proposal *types.Proposal, + block *types.Block, blockHash []byte, parts *types.PartSet, ) { @@ -542,8 +535,8 @@ func sendProposalAndParts( // votes cs.mtx.Lock() - prevote, _ := cs.signVote(cmtproto.PrevoteType, blockHash, parts.Header()) - precommit, _ := cs.signVote(cmtproto.PrecommitType, blockHash, parts.Header()) + prevote, _ := cs.signVote(types.PrevoteType, blockHash, parts.Header(), nil) + precommit, _ := cs.signVote(types.PrecommitType, blockHash, parts.Header(), block) cs.mtx.Unlock() peer.Send(p2p.Envelope{ ChannelID: VoteChannel, @@ -555,7 +548,7 @@ func sendProposalAndParts( }) } -//---------------------------------------- +// ---------------------------------------- // byzantine consensus reactor type ByzantineReactor struct { @@ -583,16 +576,18 @@ func (br *ByzantineReactor) AddPeer(peer p2p.Peer) { // Send our state to peer. // If we're syncing, broadcast a RoundStepMessage later upon SwitchToConsensus(). - if !br.reactor.waitSync { + if !br.reactor.WaitSync() { br.reactor.sendNewRoundStepMessage(peer) } } -func (br *ByzantineReactor) RemovePeer(peer p2p.Peer, reason interface{}) { +func (br *ByzantineReactor) RemovePeer(peer p2p.Peer, reason any) { br.reactor.RemovePeer(peer, reason) } +// Receive forwards all messages to the underlying reactor. func (br *ByzantineReactor) Receive(e p2p.Envelope) { br.reactor.Receive(e) } -func (br *ByzantineReactor) InitPeer(peer p2p.Peer) p2p.Peer { return peer } + +func (*ByzantineReactor) InitPeer(peer p2p.Peer) p2p.Peer { return peer } diff --git a/consensus/common_test.go b/internal/consensus/common_test.go similarity index 76% rename from consensus/common_test.go rename to internal/consensus/common_test.go index 95effc131dd..02f53c59767 100644 --- a/consensus/common_test.go +++ b/internal/consensus/common_test.go @@ -3,6 +3,7 @@ package consensus import ( "bytes" "context" + "errors" "fmt" "os" "path" @@ -17,25 +18,24 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abcicli "github.com/cometbft/cometbft/abci/client" "github.com/cometbft/cometbft/abci/example/kvstore" abci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" cfg "github.com/cometbft/cometbft/config" - cstypes "github.com/cometbft/cometbft/consensus/types" + cstypes "github.com/cometbft/cometbft/internal/consensus/types" + cmtos "github.com/cometbft/cometbft/internal/os" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/internal/test" cmtbytes "github.com/cometbft/cometbft/libs/bytes" "github.com/cometbft/cometbft/libs/log" - cmtos "github.com/cometbft/cometbft/libs/os" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - cmtsync "github.com/cometbft/cometbft/libs/sync" mempl "github.com/cometbft/cometbft/mempool" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/privval" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -48,15 +48,15 @@ const ( // test. type cleanupFunc func() -// genesis, chain_id, priv_val +// genesis, chain_id, priv_val. var ( config *cfg.Config // NOTE: must be reset for each _test.go file consensusReplayConfig *cfg.Config ensureTimeout = time.Millisecond * 200 ) -func ensureDir(dir string, mode os.FileMode) { - if err := cmtos.EnsureDir(dir, mode); err != nil { +func ensureDir(dir string) { + if err := cmtos.EnsureDir(dir, 0o700); err != nil { panic(err) } } @@ -65,13 +65,14 @@ func ResetConfig(name string) *cfg.Config { return test.ResetTestRoot(name) } -//------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- // validator stub (a kvstore consensus peer we control) type validatorStub struct { Index int32 // Validator index. NOTE: we don't assume validator set changes. Height int64 Round int32 + clock cmttime.Source types.PrivValidator VotingPower int64 lastVote *types.Vote @@ -84,15 +85,25 @@ func newValidatorStub(privValidator types.PrivValidator, valIndex int32) *valida Index: valIndex, PrivValidator: privValidator, VotingPower: testMinPower, + clock: cmttime.DefaultSource{}, } } +func signProposal(t *testing.T, proposal *types.Proposal, chainID string, vss *validatorStub) { + t.Helper() + p := proposal.ToProto() + err := vss.SignProposal(chainID, p) + require.NoError(t, err) + proposal.Signature = p.Signature +} + func (vs *validatorStub) signVote( - voteType cmtproto.SignedMsgType, - hash []byte, - header types.PartSetHeader, + voteType types.SignedMsgType, + chainID string, + blockID types.BlockID, voteExtension []byte, extEnabled bool, + timestamp time.Time, ) (*types.Vote, error) { pubKey, err := vs.PrivValidator.GetPubKey() if err != nil { @@ -102,14 +113,14 @@ func (vs *validatorStub) signVote( Type: voteType, Height: vs.Height, Round: vs.Round, - BlockID: types.BlockID{Hash: hash, PartSetHeader: header}, - Timestamp: cmttime.Now(), + BlockID: blockID, + Timestamp: timestamp, ValidatorAddress: pubKey.Address(), ValidatorIndex: vs.Index, Extension: voteExtension, } v := vote.ToProto() - if err = vs.PrivValidator.SignVote(test.DefaultTestChainID, v); err != nil { + if err = vs.PrivValidator.SignVote(chainID, v, true); err != nil { return nil, fmt.Errorf("sign vote failed: %w", err) } @@ -131,20 +142,21 @@ func (vs *validatorStub) signVote( return vote, err } -// Sign vote for type/hash/header -func signVote(vs *validatorStub, voteType cmtproto.SignedMsgType, hash []byte, header types.PartSetHeader, extEnabled bool) *types.Vote { +// Sign vote for type/hash/header. +func signVoteWithTimestamp(vs *validatorStub, voteType types.SignedMsgType, chainID string, + blockID types.BlockID, extEnabled bool, timestamp time.Time, +) *types.Vote { var ext []byte // Only non-nil precommits are allowed to carry vote extensions. if extEnabled { - if voteType != cmtproto.PrecommitType { - panic(fmt.Errorf("vote type is not precommit but extensions enabled")) + if voteType != types.PrecommitType { + panic(errors.New("vote type is not precommit but extensions enabled")) } - if len(hash) != 0 || !header.IsZero() { + if len(blockID.Hash) != 0 || !blockID.PartSetHeader.IsZero() { ext = []byte("extension") } } - v, err := vs.signVote(voteType, hash, header, ext, extEnabled) - + v, err := vs.signVote(voteType, chainID, blockID, ext, extEnabled, timestamp) if err != nil { panic(fmt.Errorf("failed to sign vote: %v", err)) } @@ -154,16 +166,20 @@ func signVote(vs *validatorStub, voteType cmtproto.SignedMsgType, hash []byte, h return v } +func signVote(vs *validatorStub, voteType types.SignedMsgType, chainID string, blockID types.BlockID, extEnabled bool) *types.Vote { + return signVoteWithTimestamp(vs, voteType, chainID, blockID, extEnabled, vs.clock.Now()) +} + func signVotes( - voteType cmtproto.SignedMsgType, - hash []byte, - header types.PartSetHeader, + voteType types.SignedMsgType, + chainID string, + blockID types.BlockID, extEnabled bool, vss ...*validatorStub, ) []*types.Vote { votes := make([]*types.Vote, len(vss)) for i, vs := range vss { - votes[i] = signVote(vs, voteType, hash, header, extEnabled) + votes[i] = signVote(vs, voteType, chainID, blockID, extEnabled) } return votes } @@ -171,6 +187,7 @@ func signVotes( func incrementHeight(vss ...*validatorStub) { for _, vs := range vss { vs.Height++ + vs.Round = 0 } } @@ -210,7 +227,7 @@ func (vss ValidatorStubsByPower) Swap(i, j int) { vss[j].Index = int32(j) } -//------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- // Functions for transitioning the consensus state func startTestRound(cs *State, height int64, round int32) { @@ -218,20 +235,38 @@ func startTestRound(cs *State, height int64, round int32) { cs.startRoutines(0) } +func createProposalBlockWithTime(t *testing.T, cs *State, time time.Time) (*types.Block, *types.PartSet, types.BlockID) { + t.Helper() + block, err := cs.createProposalBlock(context.Background()) + if !time.IsZero() { + block.Time = cmttime.Canonical(time) + } + assert.NoError(t, err) + blockParts, err := block.MakePartSet(types.BlockPartSizeBytes) + assert.NoError(t, err) + blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: blockParts.Header()} + return block, blockParts, blockID +} + +func createProposalBlock(t *testing.T, cs *State) (*types.Block, *types.PartSet, types.BlockID) { + t.Helper() + return createProposalBlockWithTime(t, cs, time.Time{}) +} + // Create proposal block from cs1 but sign it with vs. func decideProposal( - ctx context.Context, + _ context.Context, t *testing.T, cs1 *State, vs *validatorStub, height int64, round int32, ) (*types.Proposal, *types.Block) { + t.Helper() + cs1.mtx.Lock() - block, err := cs1.createProposalBlock(ctx) - require.NoError(t, err) - blockParts, err := block.MakePartSet(types.BlockPartSizeBytes) - require.NoError(t, err) + block, _, propBlockID := createProposalBlock(t, cs1) + validRound := cs1.ValidRound chainID := cs1.state.ChainID cs1.mtx.Unlock() @@ -240,8 +275,7 @@ func decideProposal( } // Make proposal - polRound, propBlockID := validRound, types.BlockID{Hash: block.Hash(), PartSetHeader: blockParts.Header()} - proposal := types.NewProposal(height, round, polRound, propBlockID) + proposal := types.NewProposal(height, round, validRound, propBlockID, block.Header.Time) p := proposal.ToProto() if err := vs.SignProposal(chainID, p); err != nil { panic(err) @@ -260,17 +294,18 @@ func addVotes(to *State, votes ...*types.Vote) { func signAddVotes( to *State, - voteType cmtproto.SignedMsgType, - hash []byte, - header types.PartSetHeader, + voteType types.SignedMsgType, + chainID string, + blockID types.BlockID, extEnabled bool, vss ...*validatorStub, ) { - votes := signVotes(voteType, hash, header, extEnabled, vss...) + votes := signVotes(voteType, chainID, blockID, extEnabled, vss...) addVotes(to, votes...) } func validatePrevote(t *testing.T, cs *State, round int32, privVal *validatorStub, blockHash []byte) { + t.Helper() prevotes := cs.Votes.Prevotes(round) pubKey, err := privVal.GetPubKey() require.NoError(t, err) @@ -284,13 +319,16 @@ func validatePrevote(t *testing.T, cs *State, round int32, privVal *validatorStu panic(fmt.Sprintf("Expected prevote to be for nil, got %X", vote.BlockID.Hash)) } } else { - if !bytes.Equal(vote.BlockID.Hash, blockHash) { + if vote.BlockID.Hash == nil { + panic(fmt.Sprintf("Expected prevote to be for %X, got ", blockHash)) + } else if !bytes.Equal(vote.BlockID.Hash, blockHash) { panic(fmt.Sprintf("Expected prevote to be for %X, got %X", blockHash, vote.BlockID.Hash)) } } } func validateLastPrecommit(t *testing.T, cs *State, privVal *validatorStub, blockHash []byte) { + t.Helper() votes := cs.LastCommit pv, err := privVal.GetPubKey() require.NoError(t, err) @@ -313,6 +351,7 @@ func validatePrecommit( votedBlockHash, lockedBlockHash []byte, ) { + t.Helper() precommits := cs.Votes.Precommits(thisRound) pv, err := privVal.GetPubKey() require.NoError(t, err) @@ -371,7 +410,25 @@ func subscribeToVoter(cs *State, addr []byte) <-chan cmtpubsub.Message { return ch } -//------------------------------------------------------------------------------- +func subscribeToVoterBuffered(cs *State, addr []byte) <-chan cmtpubsub.Message { + votesSub, err := cs.eventBus.Subscribe(context.Background(), testSubscriber, types.EventQueryVote, 10) + if err != nil { + panic(fmt.Sprintf("failed to subscribe %s to %v with outcapacity 10", testSubscriber, types.EventQueryVote)) + } + ch := make(chan cmtpubsub.Message, 10) + go func() { + for msg := range votesSub.Out() { + vote := msg.Data().(types.EventDataVote) + // we only fire for our own votes + if bytes.Equal(addr, vote.Vote.ValidatorAddress) { + ch <- msg + } + } + }() + return ch +} + +// ------------------------------------------------------------------------------- // consensus states func newState(state sm.State, pv types.PrivValidator, app abci.Application) *State { @@ -448,7 +505,7 @@ func newStateWithConfigAndBlockStore( func loadPrivValidator(config *cfg.Config) *privval.FilePV { privValidatorKeyFile := config.PrivValidatorKeyFile() - ensureDir(filepath.Dir(privValidatorKeyFile), 0o700) + ensureDir(filepath.Dir(privValidatorKeyFile)) privValidatorStateFile := config.PrivValidatorStateFile() privValidator := privval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile) privValidator.Reset() @@ -465,9 +522,10 @@ func randStateWithAppWithHeight( height int64, ) (*State, []*validatorStub) { c := test.ConsensusParams() - c.ABCI.VoteExtensionsEnableHeight = height + c.Feature.VoteExtensionsEnableHeight = height return randStateWithAppImpl(nValidators, app, c) } + func randStateWithApp(nValidators int, app abci.Application) (*State, []*validatorStub) { c := test.ConsensusParams() return randStateWithAppImpl(nValidators, app, c) @@ -477,9 +535,18 @@ func randStateWithAppImpl( nValidators int, app abci.Application, consensusParams *types.ConsensusParams, +) (*State, []*validatorStub) { + return randStateWithAppImplGenesisTime(nValidators, app, consensusParams, cmttime.Now()) +} + +func randStateWithAppImplGenesisTime( + nValidators int, + app abci.Application, + consensusParams *types.ConsensusParams, + genesisTime time.Time, ) (*State, []*validatorStub) { // Get State - state, privVals := randGenesisState(nValidators, false, 10, consensusParams) + state, privVals := randGenesisStateWithTime(nValidators, consensusParams, genesisTime) vss := make([]*validatorStub, nValidators) @@ -494,14 +561,13 @@ func randStateWithAppImpl( return cs, vss } -//------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- func ensureNoNewEvent(ch <-chan cmtpubsub.Message, timeout time.Duration, errorMessage string, ) { select { case <-time.After(timeout): - break case <-ch: panic(errorMessage) } @@ -521,13 +587,6 @@ func ensureNoNewRoundStep(stepCh <-chan cmtpubsub.Message) { "We should be stuck waiting, not receiving NewRoundStep event") } -func ensureNoNewUnlock(unlockCh <-chan cmtpubsub.Message) { - ensureNoNewEvent( - unlockCh, - ensureTimeout, - "We should be stuck waiting, not receiving Unlock event") -} - func ensureNoNewTimeout(stepCh <-chan cmtpubsub.Message, timeout int64) { timeoutDuration := time.Duration(timeout*10) * time.Nanosecond ensureNoNewEvent( @@ -581,25 +640,6 @@ func ensureNewTimeout(timeoutCh <-chan cmtpubsub.Message, height int64, round in "Timeout expired while waiting for NewTimeout event") } -func ensureNewProposal(proposalCh <-chan cmtpubsub.Message, height int64, round int32) { - select { - case <-time.After(ensureTimeout): - panic("Timeout expired while waiting for NewProposal event") - case msg := <-proposalCh: - proposalEvent, ok := msg.Data().(types.EventDataCompleteProposal) - if !ok { - panic(fmt.Sprintf("expected a EventDataCompleteProposal, got %T. Wrong subscription channel?", - msg.Data())) - } - if proposalEvent.Height != height { - panic(fmt.Sprintf("expected height %v, got %v", height, proposalEvent.Height)) - } - if proposalEvent.Round != round { - panic(fmt.Sprintf("expected round %v, got %v", round, proposalEvent.Round)) - } - } -} - func ensureNewValidBlock(validBlockCh <-chan cmtpubsub.Message, height int64, round int32) { ensureNewEvent(validBlockCh, height, round, ensureTimeout, "Timeout expired while waiting for NewValidBlock event") @@ -640,14 +680,19 @@ func ensureNewBlockHeader(blockCh <-chan cmtpubsub.Message, height int64, blockH } } -func ensureNewUnlock(unlockCh <-chan cmtpubsub.Message, height int64, round int32) { - ensureNewEvent(unlockCh, height, round, ensureTimeout, - "Timeout expired while waiting for NewUnlock event") +func ensureLock(lockCh <-chan cmtpubsub.Message, height int64, round int32) { + ensureNewEvent(lockCh, height, round, ensureTimeout, + "Timeout expired while waiting for LockValue event") } -func ensureProposal(proposalCh <-chan cmtpubsub.Message, height int64, round int32, propID types.BlockID) { +func ensureRelock(relockCh <-chan cmtpubsub.Message, height int64, round int32) { + ensureNewEvent(relockCh, height, round, ensureTimeout, + "Timeout expired while waiting for RelockValue event") +} + +func ensureProposalWithTimeout(proposalCh <-chan cmtpubsub.Message, height int64, round int32, propID *types.BlockID, timeout time.Duration) { select { - case <-time.After(ensureTimeout): + case <-time.After(timeout): panic("Timeout expired while waiting for NewProposal event") case msg := <-proposalCh: proposalEvent, ok := msg.Data().(types.EventDataCompleteProposal) @@ -661,22 +706,33 @@ func ensureProposal(proposalCh <-chan cmtpubsub.Message, height int64, round int if proposalEvent.Round != round { panic(fmt.Sprintf("expected round %v, got %v", round, proposalEvent.Round)) } - if !proposalEvent.BlockID.Equals(propID) { - panic(fmt.Sprintf("Proposed block does not match expected block (%v != %v)", proposalEvent.BlockID, propID)) + if propID != nil { + if !proposalEvent.BlockID.Equals(*propID) { + panic(fmt.Sprintf("Proposed block does not match expected block (%v != %v)", proposalEvent.BlockID, *propID)) + } } } } +func ensureProposal(proposalCh <-chan cmtpubsub.Message, height int64, round int32, propID types.BlockID) { + ensureProposalWithTimeout(proposalCh, height, round, &propID, ensureTimeout) +} + +// For the propose, as we do not know the blockID in advance. +func ensureNewProposal(proposalCh <-chan cmtpubsub.Message, height int64, round int32) { + ensureProposalWithTimeout(proposalCh, height, round, nil, ensureTimeout) +} + func ensurePrecommit(voteCh <-chan cmtpubsub.Message, height int64, round int32) { - ensureVote(voteCh, height, round, cmtproto.PrecommitType) + ensureVote(voteCh, height, round, types.PrecommitType) } func ensurePrevote(voteCh <-chan cmtpubsub.Message, height int64, round int32) { - ensureVote(voteCh, height, round, cmtproto.PrevoteType) + ensureVote(voteCh, height, round, types.PrevoteType) } func ensureVote(voteCh <-chan cmtpubsub.Message, height int64, round int32, - voteType cmtproto.SignedMsgType, + voteType types.SignedMsgType, ) { select { case <-time.After(ensureTimeout): @@ -702,15 +758,15 @@ func ensureVote(voteCh <-chan cmtpubsub.Message, height int64, round int32, func ensurePrevoteMatch(t *testing.T, voteCh <-chan cmtpubsub.Message, height int64, round int32, hash []byte) { t.Helper() - ensureVoteMatch(t, voteCh, height, round, hash, cmtproto.PrevoteType) + ensureVoteMatch(t, voteCh, height, round, hash, types.PrevoteType) } func ensurePrecommitMatch(t *testing.T, voteCh <-chan cmtpubsub.Message, height int64, round int32, hash []byte) { t.Helper() - ensureVoteMatch(t, voteCh, height, round, hash, cmtproto.PrecommitType) + ensureVoteMatch(t, voteCh, height, round, hash, types.PrecommitType) } -func ensureVoteMatch(t *testing.T, voteCh <-chan cmtpubsub.Message, height int64, round int32, hash []byte, voteType cmtproto.SignedMsgType) { +func ensureVoteMatch(t *testing.T, voteCh <-chan cmtpubsub.Message, height int64, round int32, hash []byte, voteType types.SignedMsgType) { t.Helper() select { case <-time.After(ensureTimeout): @@ -732,14 +788,6 @@ func ensureVoteMatch(t *testing.T, voteCh <-chan cmtpubsub.Message, height int64 } } -func ensurePrecommitTimeout(ch <-chan cmtpubsub.Message) { - select { - case <-time.After(ensureTimeout): - panic("Timeout expired while waiting for the Precommit to Timeout") - case <-ch: - } -} - func ensureNewEventOnChannel(ch <-chan cmtpubsub.Message) { select { case <-time.After(ensureTimeout * 12 / 10): // 20% leniency for goroutine scheduling uncertainty @@ -748,13 +796,13 @@ func ensureNewEventOnChannel(ch <-chan cmtpubsub.Message) { } } -//------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- // consensus nets // consensusLogger is a TestingLogger which uses a different // color for each validator ("validator" key must exist). func consensusLogger() log.Logger { - return log.TestingLoggerWithColorFn(func(keyvals ...interface{}) term.FgBgColor { + return log.TestingLoggerWithColorFn(func(keyvals ...any) term.FgBgColor { for i := 0; i < len(keyvals)-1; i += 2 { if keyvals[i] == "validator" { return term.FgBgColor{Fg: term.Color(uint8(keyvals[i+1].(int) + 1))} @@ -765,9 +813,10 @@ func consensusLogger() log.Logger { } func randConsensusNet(t *testing.T, nValidators int, testName string, tickerFunc func() TimeoutTicker, - appFunc func() abci.Application, configOpts ...func(*cfg.Config)) ([]*State, cleanupFunc) { + appFunc func() abci.Application, configOpts ...func(*cfg.Config), +) ([]*State, cleanupFunc) { t.Helper() - genDoc, privVals := randGenesisDoc(nValidators, false, 30, nil) + genDoc, privVals := randGenesisDoc(nValidators, 30, nil, cmttime.Now()) css := make([]*State, nValidators) logger := consensusLogger() configRootDirs := make([]string, 0, nValidators) @@ -782,10 +831,10 @@ func randConsensusNet(t *testing.T, nValidators int, testName string, tickerFunc for _, opt := range configOpts { opt(thisConfig) } - ensureDir(filepath.Dir(thisConfig.Consensus.WalFile()), 0o700) // dir for wal + ensureDir(filepath.Dir(thisConfig.Consensus.WalFile())) // dir for wal app := appFunc() vals := types.TM2PB.ValidatorUpdates(state.Validators) - _, err := app.InitChain(context.Background(), &abci.RequestInitChain{Validators: vals}) + _, err := app.InitChain(context.Background(), &abci.InitChainRequest{Validators: vals}) require.NoError(t, err) css[i] = newStateWithConfigAndBlockStore(thisConfig, state, privVals[i], app, stateDB) @@ -799,7 +848,7 @@ func randConsensusNet(t *testing.T, nValidators int, testName string, tickerFunc } } -// nPeers = nValidators + nNotValidator +// nPeers = nValidators + nNotValidator. func randConsensusNetWithPeers( t *testing.T, nValidators, @@ -808,8 +857,9 @@ func randConsensusNetWithPeers( tickerFunc func() TimeoutTicker, appFunc func(string) abci.Application, ) ([]*State, *types.GenesisDoc, *cfg.Config, cleanupFunc) { + t.Helper() c := test.ConsensusParams() - genDoc, privVals := randGenesisDoc(nValidators, false, testMinPower, c) + genDoc, privVals := randGenesisDoc(nValidators, testMinPower, c, cmttime.Now()) css := make([]*State, nPeers) logger := consensusLogger() var peer0Config *cfg.Config @@ -823,7 +873,7 @@ func randConsensusNetWithPeers( state, _ := stateStore.LoadFromDBOrGenesisDoc(genDoc) thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i)) configRootDirs = append(configRootDirs, thisConfig.RootDir) - ensureDir(filepath.Dir(thisConfig.Consensus.WalFile()), 0o700) // dir for wal + ensureDir(filepath.Dir(thisConfig.Consensus.WalFile())) // dir for wal if i == 0 { peer0Config = thisConfig } @@ -849,7 +899,7 @@ func randConsensusNetWithPeers( // simulate handshake, receive app version. If don't do this, replay test will fail state.Version.Consensus.App = kvstore.AppVersion } - _, err := app.InitChain(context.Background(), &abci.RequestInitChain{Validators: vals}) + _, err := app.InitChain(context.Background(), &abci.InitChainRequest{Validators: vals}) require.NoError(t, err) css[i] = newStateWithConfig(thisConfig, state, privVal, app) @@ -869,17 +919,18 @@ func getSwitchIndex(switches []*p2p.Switch, peer p2p.Peer) int { return i } } - panic("didnt find peer in switches") + panic("didn't find peer in switches") } -//------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- // genesis func randGenesisDoc(numValidators int, - randPower bool, minPower int64, consensusParams *types.ConsensusParams, + genesisTime time.Time, ) (*types.GenesisDoc, []types.PrivValidator) { + randPower := false validators := make([]types.GenesisValidator, numValidators) privValidators := make([]types.PrivValidator, numValidators) for i := 0; i < numValidators; i++ { @@ -892,8 +943,12 @@ func randGenesisDoc(numValidators int, } sort.Sort(types.PrivValidatorsByAddress(privValidators)) + if consensusParams == nil { + consensusParams = test.ConsensusParams() + } + return &types.GenesisDoc{ - GenesisTime: cmttime.Now(), + GenesisTime: genesisTime, InitialHeight: 1, ChainID: test.DefaultTestChainID, Validators: validators, @@ -902,30 +957,40 @@ func randGenesisDoc(numValidators int, } func randGenesisState( + numValidators int, //nolint: unparam + consensusParams *types.ConsensusParams, //nolint: unparam +) (sm.State, []types.PrivValidator) { + if consensusParams == nil { + consensusParams = test.ConsensusParams() + } + return randGenesisStateWithTime(numValidators, consensusParams, cmttime.Now()) +} + +func randGenesisStateWithTime( numValidators int, - randPower bool, - minPower int64, consensusParams *types.ConsensusParams, + genesisTime time.Time, ) (sm.State, []types.PrivValidator) { - genDoc, privValidators := randGenesisDoc(numValidators, randPower, minPower, consensusParams) + minPower := int64(10) + genDoc, privValidators := randGenesisDoc(numValidators, minPower, consensusParams, genesisTime) s0, _ := sm.MakeGenesisState(genDoc) return s0, privValidators } -//------------------------------------ +// ------------------------------------ // mock ticker func newMockTickerFunc(onlyOnce bool) func() TimeoutTicker { return func() TimeoutTicker { return &mockTicker{ - c: make(chan timeoutInfo, 10), + c: make(chan timeoutInfo, 100), onlyOnce: onlyOnce, } } } // mock ticker only fires on RoundStepNewHeight -// and only once if onlyOnce=true +// and only once if onlyOnce=true. type mockTicker struct { c chan timeoutInfo @@ -934,11 +999,11 @@ type mockTicker struct { fired bool } -func (m *mockTicker) Start() error { +func (*mockTicker) Start() error { return nil } -func (m *mockTicker) Stop() error { +func (*mockTicker) Stop() error { return nil } diff --git a/internal/consensus/errors.go b/internal/consensus/errors.go new file mode 100644 index 00000000000..fe26c84bff7 --- /dev/null +++ b/internal/consensus/errors.go @@ -0,0 +1,45 @@ +package consensus + +import ( + "errors" + "fmt" +) + +var ( + ErrNilMessage = errors.New("message is nil") + ErrPeerStateHeightRegression = errors.New("error peer state height regression") + ErrPeerStateInvalidStartTime = errors.New("error peer state invalid startTime") + ErrCommitQuorumNotMet = errors.New("extended commit does not have +2/3 majority") + ErrNilPrivValidator = errors.New("entered createProposalBlock with privValidator being nil") + ErrProposalWithoutPreviousCommit = errors.New("propose step; cannot propose anything without commit for the previous block") +) + +// Consensus sentinel errors. +var ( + ErrInvalidProposalSignature = errors.New("error invalid proposal signature") + ErrInvalidProposalPOLRound = errors.New("error invalid proposal POL round") + ErrAddingVote = errors.New("error adding vote") + ErrSignatureFoundInPastBlocks = errors.New("found signature from the same key") + ErrPubKeyIsNotSet = errors.New("pubkey is not set. Look for \"Can't get private validator pubkey\" errors") + ErrProposalTooManyParts = errors.New("proposal block has too many parts") +) + +type ErrConsensusMessageNotRecognized struct { + Message any +} + +func (e ErrConsensusMessageNotRecognized) Error() string { + return fmt.Sprintf("consensus: message not recognized: %T", e.Message) +} + +type ErrDenyMessageOverflow struct { + Err error +} + +func (e ErrDenyMessageOverflow) Error() string { + return "denying message due to possible overflow: " + e.Err.Error() +} + +func (e ErrDenyMessageOverflow) Unwrap() error { + return e.Err +} diff --git a/consensus/invalid_test.go b/internal/consensus/invalid_test.go similarity index 73% rename from consensus/invalid_test.go rename to internal/consensus/invalid_test.go index dd5f8f2ceca..1ef066ba79b 100644 --- a/consensus/invalid_test.go +++ b/internal/consensus/invalid_test.go @@ -4,24 +4,23 @@ import ( "testing" "time" + cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1" cfg "github.com/cometbft/cometbft/config" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/libs/bytes" "github.com/cometbft/cometbft/libs/log" - cmtrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/p2p" - cmtcons "github.com/cometbft/cometbft/proto/tendermint/consensus" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" ) -//---------------------------------------------- +// ---------------------------------------------- // byzantine failures // one byz val sends a precommit for a random block at each height -// Ensure a testnet makes blocks +// Ensure a testnet makes blocks. func TestReactorInvalidPrecommit(t *testing.T) { - N := 4 - css, cleanup := randConsensusNet(t, N, "consensus_reactor_test", newMockTickerFunc(true), newKVStore, + n := 4 + css, cleanup := randConsensusNet(t, n, "consensus_reactor_test", newMockTickerFunc(true), newKVStore, func(c *cfg.Config) { c.Consensus.TimeoutPropose = 3000 * time.Millisecond c.Consensus.TimeoutPrevote = 1000 * time.Millisecond @@ -29,18 +28,17 @@ func TestReactorInvalidPrecommit(t *testing.T) { }) defer cleanup() - for i := 0; i < N; i++ { + for i := 0; i < n; i++ { ticker := NewTimeoutTicker() ticker.SetLogger(css[i].Logger) css[i].SetTimeoutTicker(ticker) - } - reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N) + reactors, blocksSubs, eventBuses := startConsensusNet(t, css, n) defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses) // this val sends a random precommit at each height - byzValIdx := N - 1 + byzValIdx := n - 1 byzVal := css[byzValIdx] byzR := reactors[byzValIdx] @@ -48,21 +46,22 @@ func TestReactorInvalidPrecommit(t *testing.T) { // and otherwise disable the priv validator byzVal.mtx.Lock() pv := byzVal.privValidator - byzVal.doPrevote = func(height int64, round int32) { - invalidDoPrevoteFunc(t, height, round, byzVal, byzR.Switch, pv) + byzVal.doPrevote = func(int64, int32) { + invalidDoPrevoteFunc(t, byzVal, byzR.Switch, pv) } byzVal.mtx.Unlock() // wait for a bunch of blocks // TODO: make this tighter by ensuring the halt happens by block 2 for i := 0; i < 10; i++ { - timeoutWaitGroup(t, N, func(j int) { + timeoutWaitGroup(n, func(j int) { <-blocksSubs[j].Out() - }, css) + }) } } -func invalidDoPrevoteFunc(t *testing.T, height int64, round int32, cs *State, sw *p2p.Switch, pv types.PrivValidator) { +func invalidDoPrevoteFunc(t *testing.T, cs *State, sw *p2p.Switch, pv types.PrivValidator) { + t.Helper() // routine to: // - precommit for a random block // - send precommit to all peers @@ -80,19 +79,22 @@ func invalidDoPrevoteFunc(t *testing.T, height int64, round int32, cs *State, sw // precommit a random block blockHash := bytes.HexBytes(cmtrand.Bytes(32)) + timestamp := cs.voteTime(cs.Height) + precommit := &types.Vote{ ValidatorAddress: addr, ValidatorIndex: valIndex, Height: cs.Height, Round: cs.Round, - Timestamp: cs.voteTime(), - Type: cmtproto.PrecommitType, + Timestamp: timestamp, + Type: types.PrecommitType, BlockID: types.BlockID{ Hash: blockHash, - PartSetHeader: types.PartSetHeader{Total: 1, Hash: cmtrand.Bytes(32)}}, + PartSetHeader: types.PartSetHeader{Total: 1, Hash: cmtrand.Bytes(32)}, + }, } p := precommit.ToProto() - err = cs.privValidator.SignVote(cs.state.ChainID, p) + err = cs.privValidator.SignVote(cs.state.ChainID, p, true) if err != nil { t.Error(err) } @@ -100,7 +102,7 @@ func invalidDoPrevoteFunc(t *testing.T, height int64, round int32, cs *State, sw precommit.ExtensionSignature = p.ExtensionSignature cs.privValidator = nil // disable priv val so we don't do normal votes - peers := sw.Peers().List() + peers := sw.Peers().Copy() for _, peer := range peers { cs.Logger.Info("Sending bad vote", "block", blockHash, "peer", peer) peer.Send(p2p.Envelope{ diff --git a/consensus/mempool_test.go b/internal/consensus/mempool_test.go similarity index 81% rename from consensus/mempool_test.go rename to internal/consensus/mempool_test.go index 405ba194b67..fdea1adac86 100644 --- a/consensus/mempool_test.go +++ b/internal/consensus/mempool_test.go @@ -2,8 +2,8 @@ package consensus import ( "context" - "fmt" "os" + "strconv" "testing" "time" @@ -11,16 +11,15 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/abci/example/kvstore" abci "github.com/cometbft/cometbft/abci/types" + sm "github.com/cometbft/cometbft/internal/state" mempl "github.com/cometbft/cometbft/mempool" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" ) -// for testing +// for testing. func assertMempool(txn txNotifier) mempl.Mempool { return txn.(mempl.Mempool) } @@ -29,9 +28,9 @@ func TestMempoolNoProgressUntilTxsAvailable(t *testing.T) { config := ResetConfig("consensus_mempool_txs_available_test") defer os.RemoveAll(config.RootDir) config.Consensus.CreateEmptyBlocks = false - state, privVals := randGenesisState(1, false, 10, nil) + state, privVals := randGenesisState(1, nil) app := kvstore.NewInMemoryApplication() - resp, err := app.Info(context.Background(), proxy.RequestInfo) + resp, err := app.Info(context.Background(), proxy.InfoRequest) require.NoError(t, err) state.AppHash = resp.LastBlockAppHash cs := newStateWithConfig(config, state, privVals[0], app) @@ -42,7 +41,7 @@ func TestMempoolNoProgressUntilTxsAvailable(t *testing.T) { ensureNewEventOnChannel(newBlockCh) // first block gets committed ensureNoNewEventOnChannel(newBlockCh) - deliverTxsRange(t, cs, 0, 1) + deliverTxsRange(t, cs, 1) ensureNewEventOnChannel(newBlockCh) // commit txs ensureNewEventOnChannel(newBlockCh) // commit updated app hash ensureNoNewEventOnChannel(newBlockCh) @@ -53,9 +52,9 @@ func TestMempoolProgressAfterCreateEmptyBlocksInterval(t *testing.T) { defer os.RemoveAll(config.RootDir) config.Consensus.CreateEmptyBlocksInterval = ensureTimeout - state, privVals := randGenesisState(1, false, 10, nil) + state, privVals := randGenesisState(1, nil) app := kvstore.NewInMemoryApplication() - resp, err := app.Info(context.Background(), proxy.RequestInfo) + resp, err := app.Info(context.Background(), proxy.InfoRequest) require.NoError(t, err) state.AppHash = resp.LastBlockAppHash cs := newStateWithConfig(config, state, privVals[0], app) @@ -74,21 +73,21 @@ func TestMempoolProgressInHigherRound(t *testing.T) { config := ResetConfig("consensus_mempool_txs_available_test") defer os.RemoveAll(config.RootDir) config.Consensus.CreateEmptyBlocks = false - state, privVals := randGenesisState(1, false, 10, nil) + state, privVals := randGenesisState(1, nil) cs := newStateWithConfig(config, state, privVals[0], kvstore.NewInMemoryApplication()) assertMempool(cs.txNotifier).EnableTxsAvailable() height, round := cs.Height, cs.Round newBlockCh := subscribe(cs.eventBus, types.EventQueryNewBlock) newRoundCh := subscribe(cs.eventBus, types.EventQueryNewRound) timeoutCh := subscribe(cs.eventBus, types.EventQueryTimeoutPropose) - cs.setProposal = func(proposal *types.Proposal) error { + cs.setProposal = func(proposal *types.Proposal, recvTime time.Time) error { if cs.Height == 2 && cs.Round == 0 { // dont set the proposal in round 0 so we timeout and // go to next round cs.Logger.Info("Ignoring set proposal at height 2, round 0") return nil } - return cs.defaultSetProposal(proposal) + return cs.defaultSetProposal(proposal, recvTime) } startTestRound(cs, height, round) @@ -99,7 +98,7 @@ func TestMempoolProgressInHigherRound(t *testing.T) { round = 0 ensureNewRound(newRoundCh, height, round) // first round at next height - deliverTxsRange(t, cs, 0, 1) // we deliver txs, but dont set a proposal so we get the next round + deliverTxsRange(t, cs, 1) // we deliver txs, but dont set a proposal so we get the next round ensureNewTimeout(timeoutCh, height, round, cs.config.TimeoutPropose.Nanoseconds()) round++ // moving to the next round @@ -107,16 +106,19 @@ func TestMempoolProgressInHigherRound(t *testing.T) { ensureNewEventOnChannel(newBlockCh) // now we can commit the block } -func deliverTxsRange(t *testing.T, cs *State, start, end int) { +func deliverTxsRange(t *testing.T, cs *State, end int) { + t.Helper() + start := 0 // Deliver some txs. for i := start; i < end; i++ { - err := assertMempool(cs.txNotifier).CheckTx(kvstore.NewTx(fmt.Sprintf("%d", i), "true"), nil, mempl.TxInfo{}) + reqRes, err := assertMempool(cs.txNotifier).CheckTx(kvstore.NewTx(strconv.Itoa(i), "true")) require.NoError(t, err) + require.False(t, reqRes.Response.GetCheckTx().IsErr()) } } func TestMempoolTxConcurrentWithCommit(t *testing.T) { - state, privVals := randGenesisState(1, false, 10, nil) + state, privVals := randGenesisState(1, nil) blockDB := dbm.NewMemDB() stateStore := sm.NewStore(blockDB, sm.StoreOptions{DiscardABCIResponses: false}) cs := newStateWithConfigAndBlockStore(config, state, privVals[0], kvstore.NewInMemoryApplication(), blockDB) @@ -125,7 +127,7 @@ func TestMempoolTxConcurrentWithCommit(t *testing.T) { newBlockEventsCh := subscribe(cs.eventBus, types.EventQueryNewBlockEvents) const numTxs int64 = 3000 - go deliverTxsRange(t, cs, 0, int(numTxs)) + go deliverTxsRange(t, cs, int(numTxs)) startTestRound(cs, cs.Height, cs.Round) for n := int64(0); n < numTxs; { @@ -141,7 +143,7 @@ func TestMempoolTxConcurrentWithCommit(t *testing.T) { } func TestMempoolRmBadTx(t *testing.T) { - state, privVals := randGenesisState(1, false, 10, nil) + state, privVals := randGenesisState(1, nil) app := kvstore.NewInMemoryApplication() blockDB := dbm.NewMemDB() stateStore := sm.NewStore(blockDB, sm.StoreOptions{DiscardABCIResponses: false}) @@ -151,12 +153,12 @@ func TestMempoolRmBadTx(t *testing.T) { // increment the counter by 1 txBytes := kvstore.NewTx("key", "value") - res, err := app.FinalizeBlock(context.Background(), &abci.RequestFinalizeBlock{Txs: [][]byte{txBytes}}) + res, err := app.FinalizeBlock(context.Background(), &abci.FinalizeBlockRequest{Txs: [][]byte{txBytes}}) require.NoError(t, err) assert.False(t, res.TxResults[0].IsErr()) - assert.True(t, len(res.AppHash) > 0) + assert.NotEmpty(t, res.AppHash) - _, err = app.Commit(context.Background(), &abci.RequestCommit{}) + _, err = app.Commit(context.Background(), &abci.CommitRequest{}) require.NoError(t, err) emptyMempoolCh := make(chan struct{}) @@ -166,17 +168,16 @@ func TestMempoolRmBadTx(t *testing.T) { // CheckTx should not err, but the app should return a bad abci code // and the tx should get removed from the pool invalidTx := []byte("invalidTx") - err := assertMempool(cs.txNotifier).CheckTx(invalidTx, func(r *abci.ResponseCheckTx) { - if r.Code != kvstore.CodeTypeInvalidTxFormat { - t.Errorf("expected checktx to return invalid format, got %v", r) - return - } - checkTxRespCh <- struct{}{} - }, mempl.TxInfo{}) + reqRes, err := assertMempool(cs.txNotifier).CheckTx(invalidTx) if err != nil { t.Errorf("error after CheckTx: %v", err) return } + if reqRes.Response.GetCheckTx().Code != kvstore.CodeTypeInvalidTxFormat { + t.Errorf("expected checktx to return invalid format, got %v", reqRes.Response) + return + } + checkTxRespCh <- struct{}{} // check for the tx for { diff --git a/consensus/metrics.gen.go b/internal/consensus/metrics.gen.go similarity index 75% rename from consensus/metrics.gen.go rename to internal/consensus/metrics.gen.go index a986b6bfeb5..6940855953a 100644 --- a/consensus/metrics.gen.go +++ b/internal/consensus/metrics.gen.go @@ -106,6 +106,12 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "block_size_bytes", Help: "Size of the block.", }, labels).With(labelsAndValues...), + ChainSizeBytes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "chain_size_bytes", + Help: "Size of the chain in bytes.", + }, labels).With(labelsAndValues...), TotalTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, @@ -124,6 +130,18 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "block_parts", Help: "Number of block parts transmitted by each peer.", }, append(labels, "peer_id")).With(labelsAndValues...), + DuplicateBlockPart: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "duplicate_block_part", + Help: "Number of times we received a duplicate block part", + }, labels).With(labelsAndValues...), + DuplicateVote: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "duplicate_vote", + Help: "Number of times we received a duplicate vote", + }, labels).With(labelsAndValues...), StepDurationSeconds: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, @@ -180,37 +198,49 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "late_votes", Help: "LateVotes stores the number of votes that were received by this node that correspond to earlier heights and rounds than this node is currently in.", }, append(labels, "vote_type")).With(labelsAndValues...), + ProposalTimestampDifference: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "proposal_timestamp_difference", + Help: "Difference in seconds between the local time when a proposal message is received and the timestamp in the proposal message.", + + Buckets: []float64{-1.5, -1.0, -0.5, -0.2, 0, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 4.0, 8.0}, + }, append(labels, "is_timely")).With(labelsAndValues...), } } func NopMetrics() *Metrics { return &Metrics{ - Height: discard.NewGauge(), - ValidatorLastSignedHeight: discard.NewGauge(), - Rounds: discard.NewGauge(), - RoundDurationSeconds: discard.NewHistogram(), - Validators: discard.NewGauge(), - ValidatorsPower: discard.NewGauge(), - ValidatorPower: discard.NewGauge(), - ValidatorMissedBlocks: discard.NewGauge(), - MissingValidators: discard.NewGauge(), - MissingValidatorsPower: discard.NewGauge(), - ByzantineValidators: discard.NewGauge(), - ByzantineValidatorsPower: discard.NewGauge(), - BlockIntervalSeconds: discard.NewHistogram(), - NumTxs: discard.NewGauge(), - BlockSizeBytes: discard.NewGauge(), - TotalTxs: discard.NewGauge(), - CommittedHeight: discard.NewGauge(), - BlockParts: discard.NewCounter(), - StepDurationSeconds: discard.NewHistogram(), - BlockGossipPartsReceived: discard.NewCounter(), - QuorumPrevoteDelay: discard.NewGauge(), - FullPrevoteDelay: discard.NewGauge(), - VoteExtensionReceiveCount: discard.NewCounter(), - ProposalReceiveCount: discard.NewCounter(), - ProposalCreateCount: discard.NewCounter(), - RoundVotingPowerPercent: discard.NewGauge(), - LateVotes: discard.NewCounter(), + Height: discard.NewGauge(), + ValidatorLastSignedHeight: discard.NewGauge(), + Rounds: discard.NewGauge(), + RoundDurationSeconds: discard.NewHistogram(), + Validators: discard.NewGauge(), + ValidatorsPower: discard.NewGauge(), + ValidatorPower: discard.NewGauge(), + ValidatorMissedBlocks: discard.NewGauge(), + MissingValidators: discard.NewGauge(), + MissingValidatorsPower: discard.NewGauge(), + ByzantineValidators: discard.NewGauge(), + ByzantineValidatorsPower: discard.NewGauge(), + BlockIntervalSeconds: discard.NewHistogram(), + NumTxs: discard.NewGauge(), + BlockSizeBytes: discard.NewGauge(), + ChainSizeBytes: discard.NewCounter(), + TotalTxs: discard.NewGauge(), + CommittedHeight: discard.NewGauge(), + BlockParts: discard.NewCounter(), + DuplicateBlockPart: discard.NewCounter(), + DuplicateVote: discard.NewCounter(), + StepDurationSeconds: discard.NewHistogram(), + BlockGossipPartsReceived: discard.NewCounter(), + QuorumPrevoteDelay: discard.NewGauge(), + FullPrevoteDelay: discard.NewGauge(), + VoteExtensionReceiveCount: discard.NewCounter(), + ProposalReceiveCount: discard.NewCounter(), + ProposalCreateCount: discard.NewCounter(), + RoundVotingPowerPercent: discard.NewGauge(), + LateVotes: discard.NewCounter(), + ProposalTimestampDifference: discard.NewHistogram(), } } diff --git a/consensus/metrics.go b/internal/consensus/metrics.go similarity index 70% rename from consensus/metrics.go rename to internal/consensus/metrics.go index ab2b78d476d..596a9a01cfe 100644 --- a/consensus/metrics.go +++ b/internal/consensus/metrics.go @@ -6,8 +6,9 @@ import ( "github.com/go-kit/kit/metrics" - cstypes "github.com/cometbft/cometbft/consensus/types" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cstypes "github.com/cometbft/cometbft/internal/consensus/types" + "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" ) const ( @@ -16,7 +17,7 @@ const ( MetricsSubsystem = "consensus" ) -//go:generate go run ../scripts/metricsgen -struct=Metrics +//go:generate go run ../../scripts/metricsgen -struct=Metrics // Metrics contains metrics exposed by this package. type Metrics struct { @@ -30,7 +31,7 @@ type Metrics struct { Rounds metrics.Gauge // Histogram of round duration. - RoundDurationSeconds metrics.Histogram `metrics_buckettype:"exprange" metrics_bucketsizes:"0.1, 100, 8"` + RoundDurationSeconds metrics.Histogram `metrics_bucketsizes:"0.1, 100, 8" metrics_buckettype:"exprange"` // Number of validators. Validators metrics.Gauge @@ -56,6 +57,8 @@ type Metrics struct { NumTxs metrics.Gauge // Size of the block. BlockSizeBytes metrics.Gauge + // Size of the chain in bytes. + ChainSizeBytes metrics.Counter // Total number of transactions. TotalTxs metrics.Gauge // The latest block height. @@ -64,8 +67,14 @@ type Metrics struct { // Number of block parts transmitted by each peer. BlockParts metrics.Counter `metrics_labels:"peer_id"` + // Number of times we received a duplicate block part + DuplicateBlockPart metrics.Counter + + // Number of times we received a duplicate vote + DuplicateVote metrics.Counter + // Histogram of durations for each step in the consensus protocol. - StepDurationSeconds metrics.Histogram `metrics_labels:"step" metrics_buckettype:"exprange" metrics_bucketsizes:"0.1, 100, 8"` + StepDurationSeconds metrics.Histogram `metrics_bucketsizes:"0.1, 100, 8" metrics_buckettype:"exprange" metrics_labels:"step"` stepStart time.Time // Number of block parts received by the node, separated by whether the part @@ -81,13 +90,13 @@ type Metrics struct { // be above 2/3 of the total voting power of the network defines the endpoint // the endpoint of the interval. Subtract the proposal timestamp from this endpoint // to obtain the quorum delay. - //metrics:Interval in seconds between the proposal timestamp and the timestamp of the earliest prevote that achieved a quorum. + // metrics:Interval in seconds between the proposal timestamp and the timestamp of the earliest prevote that achieved a quorum. QuorumPrevoteDelay metrics.Gauge `metrics_labels:"proposer_address"` // FullPrevoteDelay is the interval in seconds between the proposal // timestamp and the timestamp of the latest prevote in a round where 100% // of the voting power on the network issued prevotes. - //metrics:Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted. + // metrics:Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted. FullPrevoteDelay metrics.Gauge `metrics_labels:"proposer_address"` // VoteExtensionReceiveCount is the number of vote extensions received by this @@ -116,6 +125,21 @@ type Metrics struct { // correspond to earlier heights and rounds than this node is currently // in. LateVotes metrics.Counter `metrics_labels:"vote_type"` + + // ProposalTimestampDifference is the difference between the local time + // of the validator at the time it receives a proposal message, and the + // timestamp of the received proposal message. + // + // The value of this metric is not expected to be negative, as it would + // mean that the proposal's timestamp is in the future. This indicates + // that the proposer's and this node's clocks are desynchronized. + // + // A positive value of this metric reflects the message delay from the + // proposer to this node, for the delivery of a Proposal message. This + // metric thus should drive the definition of values for the consensus + // parameter SynchronyParams.MessageDelay, used by the PBTS algorithm. + // metrics:Difference in seconds between the local time when a proposal message is received and the timestamp in the proposal message. + ProposalTimestampDifference metrics.Histogram `metrics_bucketsizes:"-1.5, -1.0, -0.5, -0.2, 0, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 4.0, 8.0" metrics_labels:"is_timely"` } func (m *Metrics) MarkProposalProcessed(accepted bool) { @@ -134,7 +158,7 @@ func (m *Metrics) MarkVoteExtensionReceived(accepted bool) { m.VoteExtensionReceiveCount.With("status", status).Add(1) } -func (m *Metrics) MarkVoteReceived(vt cmtproto.SignedMsgType, power, totalPower int64) { +func (m *Metrics) MarkVoteReceived(vt types.SignedMsgType, power, totalPower int64) { p := float64(power) / float64(totalPower) n := strings.ToLower(strings.TrimPrefix(vt.String(), "SIGNED_MSG_TYPE_")) m.RoundVotingPowerPercent.With("vote_type", n).Add(p) @@ -142,28 +166,28 @@ func (m *Metrics) MarkVoteReceived(vt cmtproto.SignedMsgType, power, totalPower func (m *Metrics) MarkRound(r int32, st time.Time) { m.Rounds.Set(float64(r)) - roundTime := time.Since(st).Seconds() + roundTime := cmttime.Since(st).Seconds() m.RoundDurationSeconds.Observe(roundTime) - pvt := cmtproto.PrevoteType + pvt := types.PrevoteType pvn := strings.ToLower(strings.TrimPrefix(pvt.String(), "SIGNED_MSG_TYPE_")) m.RoundVotingPowerPercent.With("vote_type", pvn).Set(0) - pct := cmtproto.PrecommitType + pct := types.PrecommitType pcn := strings.ToLower(strings.TrimPrefix(pct.String(), "SIGNED_MSG_TYPE_")) m.RoundVotingPowerPercent.With("vote_type", pcn).Set(0) } -func (m *Metrics) MarkLateVote(vt cmtproto.SignedMsgType) { +func (m *Metrics) MarkLateVote(vt types.SignedMsgType) { n := strings.ToLower(strings.TrimPrefix(vt.String(), "SIGNED_MSG_TYPE_")) m.LateVotes.With("vote_type", n).Add(1) } func (m *Metrics) MarkStep(s cstypes.RoundStepType) { if !m.stepStart.IsZero() { - stepTime := time.Since(m.stepStart).Seconds() + stepTime := cmttime.Since(m.stepStart).Seconds() stepName := strings.TrimPrefix(s.String(), "RoundStep") m.StepDurationSeconds.With("step", stepName).Observe(stepTime) } - m.stepStart = time.Now() + m.stepStart = cmttime.Now() } diff --git a/consensus/msgs.go b/internal/consensus/msgs.go similarity index 70% rename from consensus/msgs.go rename to internal/consensus/msgs.go index e8c1e2cddeb..5506c540624 100644 --- a/consensus/msgs.go +++ b/internal/consensus/msgs.go @@ -1,97 +1,105 @@ package consensus import ( - "errors" "fmt" + "time" "github.com/cosmos/gogoproto/proto" - cstypes "github.com/cometbft/cometbft/consensus/types" - "github.com/cometbft/cometbft/libs/bits" + cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/internal/bits" + cstypes "github.com/cometbft/cometbft/internal/consensus/types" cmtmath "github.com/cometbft/cometbft/libs/math" "github.com/cometbft/cometbft/p2p" - cmtcons "github.com/cometbft/cometbft/proto/tendermint/consensus" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" ) -// MsgToProto takes a consensus message type and returns the proto defined consensus message. -// // TODO: This needs to be removed, but WALToProto depends on this. -func MsgToProto(msg Message) (proto.Message, error) { +// Takes a consensus message type and returns the proto defined consensus message, +// wrapped in the discriminating Message container. +func MsgToWrappedProto(msg Message) (cmtcons.Message, error) { + pb := cmtcons.Message{} if msg == nil { - return nil, errors.New("consensus: message is nil") + return pb, ErrNilMessage } - var pb proto.Message switch msg := msg.(type) { case *NewRoundStepMessage: - pb = &cmtcons.NewRoundStep{ + pb.Sum = &cmtcons.Message_NewRoundStep{NewRoundStep: &cmtcons.NewRoundStep{ Height: msg.Height, Round: msg.Round, Step: uint32(msg.Step), SecondsSinceStartTime: msg.SecondsSinceStartTime, LastCommitRound: msg.LastCommitRound, - } + }} case *NewValidBlockMessage: pbPartSetHeader := msg.BlockPartSetHeader.ToProto() pbBits := msg.BlockParts.ToProto() - pb = &cmtcons.NewValidBlock{ + pb.Sum = &cmtcons.Message_NewValidBlock{NewValidBlock: &cmtcons.NewValidBlock{ Height: msg.Height, Round: msg.Round, BlockPartSetHeader: pbPartSetHeader, BlockParts: pbBits, IsCommit: msg.IsCommit, - } + }} case *ProposalMessage: pbP := msg.Proposal.ToProto() - pb = &cmtcons.Proposal{ + pb.Sum = &cmtcons.Message_Proposal{Proposal: &cmtcons.Proposal{ Proposal: *pbP, - } + }} case *ProposalPOLMessage: pbBits := msg.ProposalPOL.ToProto() - pb = &cmtcons.ProposalPOL{ + pb.Sum = &cmtcons.Message_ProposalPol{ProposalPol: &cmtcons.ProposalPOL{ Height: msg.Height, ProposalPolRound: msg.ProposalPOLRound, ProposalPol: *pbBits, - } + }} case *BlockPartMessage: parts, err := msg.Part.ToProto() if err != nil { - return nil, fmt.Errorf("msg to proto error: %w", err) + return pb, cmterrors.ErrMsgToProto{MessageName: "Part", Err: err} } - pb = &cmtcons.BlockPart{ + pb.Sum = &cmtcons.Message_BlockPart{BlockPart: &cmtcons.BlockPart{ Height: msg.Height, Round: msg.Round, Part: *parts, - } + }} case *VoteMessage: vote := msg.Vote.ToProto() - pb = &cmtcons.Vote{ + pb.Sum = &cmtcons.Message_Vote{Vote: &cmtcons.Vote{ Vote: vote, - } + }} case *HasVoteMessage: - pb = &cmtcons.HasVote{ + pb.Sum = &cmtcons.Message_HasVote{HasVote: &cmtcons.HasVote{ Height: msg.Height, Round: msg.Round, Type: msg.Type, Index: msg.Index, - } + }} + + case *HasProposalBlockPartMessage: + pb.Sum = &cmtcons.Message_HasProposalBlockPart{HasProposalBlockPart: &cmtcons.HasProposalBlockPart{ + Height: msg.Height, + Round: msg.Round, + Index: msg.Index, + }} case *VoteSetMaj23Message: bi := msg.BlockID.ToProto() - pb = &cmtcons.VoteSetMaj23{ + pb.Sum = &cmtcons.Message_VoteSetMaj23{VoteSetMaj23: &cmtcons.VoteSetMaj23{ Height: msg.Height, Round: msg.Round, Type: msg.Type, BlockID: bi, - } + }} case *VoteSetBitsMessage: bi := msg.BlockID.ToProto() @@ -108,19 +116,19 @@ func MsgToProto(msg Message) (proto.Message, error) { vsb.Votes = *bits } - pb = vsb + pb.Sum = &cmtcons.Message_VoteSetBits{VoteSetBits: vsb} default: - return nil, fmt.Errorf("consensus: message not recognized: %T", msg) + return pb, ErrConsensusMessageNotRecognized{msg} } return pb, nil } -// MsgFromProto takes a consensus proto message and returns the native go type +// MsgFromProto takes a consensus proto message and returns the native go type. func MsgFromProto(p proto.Message) (Message, error) { if p == nil { - return nil, errors.New("consensus: nil message") + return nil, ErrNilMessage } var pb Message @@ -129,7 +137,7 @@ func MsgFromProto(p proto.Message) (Message, error) { rs, err := cmtmath.SafeConvertUint8(int64(msg.Step)) // deny message based on possible overflow if err != nil { - return nil, fmt.Errorf("denying message due to possible overflow: %w", err) + return nil, ErrDenyMessageOverflow{err} } pb = &NewRoundStepMessage{ Height: msg.Height, @@ -141,7 +149,7 @@ func MsgFromProto(p proto.Message) (Message, error) { case *cmtcons.NewValidBlock: pbPartSetHeader, err := types.PartSetHeaderFromProto(&msg.BlockPartSetHeader) if err != nil { - return nil, fmt.Errorf("parts to proto error: %w", err) + return nil, cmterrors.ErrMsgToProto{MessageName: "BlockPartSetHeader", Err: err} } pbBits := new(bits.BitArray) @@ -157,7 +165,7 @@ func MsgFromProto(p proto.Message) (Message, error) { case *cmtcons.Proposal: pbP, err := types.ProposalFromProto(&msg.Proposal) if err != nil { - return nil, fmt.Errorf("proposal msg to proto error: %w", err) + return nil, cmterrors.ErrMsgToProto{MessageName: "Proposal", Err: err} } pb = &ProposalMessage{ @@ -174,7 +182,7 @@ func MsgFromProto(p proto.Message) (Message, error) { case *cmtcons.BlockPart: parts, err := types.PartFromProto(&msg.Part) if err != nil { - return nil, fmt.Errorf("blockpart msg to proto error: %w", err) + return nil, cmterrors.ErrMsgToProto{MessageName: "Part", Err: err} } pb = &BlockPartMessage{ Height: msg.Height, @@ -186,7 +194,7 @@ func MsgFromProto(p proto.Message) (Message, error) { // call below. vote, err := types.VoteFromProto(msg.Vote) if err != nil { - return nil, fmt.Errorf("vote msg to proto error: %w", err) + return nil, cmterrors.ErrMsgToProto{MessageName: "Vote", Err: err} } pb = &VoteMessage{ @@ -199,10 +207,16 @@ func MsgFromProto(p proto.Message) (Message, error) { Type: msg.Type, Index: msg.Index, } + case *cmtcons.HasProposalBlockPart: + pb = &HasProposalBlockPartMessage{ + Height: msg.Height, + Round: msg.Round, + Index: msg.Index, + } case *cmtcons.VoteSetMaj23: bi, err := types.BlockIDFromProto(&msg.BlockID) if err != nil { - return nil, fmt.Errorf("voteSetMaj23 msg to proto error: %w", err) + return nil, cmterrors.ErrMsgToProto{MessageName: "VoteSetMaj23", Err: err} } pb = &VoteSetMaj23Message{ Height: msg.Height, @@ -213,7 +227,7 @@ func MsgFromProto(p proto.Message) (Message, error) { case *cmtcons.VoteSetBits: bi, err := types.BlockIDFromProto(&msg.BlockID) if err != nil { - return nil, fmt.Errorf("voteSetBits msg to proto error: %w", err) + return nil, cmterrors.ErrMsgToProto{MessageName: "VoteSetBits", Err: err} } bits := new(bits.BitArray) bits.FromProto(&msg.Votes) @@ -226,7 +240,7 @@ func MsgFromProto(p proto.Message) (Message, error) { Votes: bits, } default: - return nil, fmt.Errorf("consensus: message not recognized: %T", msg) + return nil, ErrConsensusMessageNotRecognized{msg} } if err := pb.ValidateBasic(); err != nil { @@ -236,7 +250,7 @@ func MsgFromProto(p proto.Message) (Message, error) { return pb, nil } -// WALToProto takes a WAL message and return a proto walMessage and error +// WALToProto takes a WAL message and return a proto walMessage and error. func WALToProto(msg WALMessage) (*cmtcons.WALMessage, error) { var pb cmtcons.WALMessage @@ -252,19 +266,24 @@ func WALToProto(msg WALMessage) (*cmtcons.WALMessage, error) { }, } case msgInfo: - consMsg, err := MsgToProto(msg.Msg) + cm, err := MsgToWrappedProto(msg.Msg) if err != nil { return nil, err } - if w, ok := consMsg.(p2p.Wrapper); ok { - consMsg = w.Wrap() + + var rtp *time.Time + if !msg.ReceiveTime.IsZero() { + // Only record the `ReceiveTime` if explicitly set. + rt := msg.ReceiveTime + rtp = &rt } - cm := consMsg.(*cmtcons.Message) + pb = cmtcons.WALMessage{ Sum: &cmtcons.WALMessage_MsgInfo{ MsgInfo: &cmtcons.MsgInfo{ - Msg: *cm, - PeerID: string(msg.PeerID), + Msg: cm, + PeerID: string(msg.PeerID), + ReceiveTime: rtp, }, }, } @@ -294,10 +313,10 @@ func WALToProto(msg WALMessage) (*cmtcons.WALMessage, error) { return &pb, nil } -// WALFromProto takes a proto wal message and return a consensus walMessage and error +// WALFromProto takes a proto wal message and return a consensus walMessage and error. func WALFromProto(msg *cmtcons.WALMessage) (WALMessage, error) { if msg == nil { - return nil, errors.New("nil WAL message") + return nil, ErrNilMessage } var pb WALMessage @@ -315,18 +334,23 @@ func WALFromProto(msg *cmtcons.WALMessage) (WALMessage, error) { } walMsg, err := MsgFromProto(um) if err != nil { - return nil, fmt.Errorf("msgInfo from proto error: %w", err) + return nil, cmterrors.ErrMsgFromProto{MessageName: "MsgInfo", Err: err} } - pb = msgInfo{ + msgInfo := msgInfo{ Msg: walMsg, PeerID: p2p.ID(msg.MsgInfo.PeerID), } + if msg.MsgInfo.ReceiveTime != nil { + msgInfo.ReceiveTime = *msg.MsgInfo.ReceiveTime + } + pb = msgInfo + case *cmtcons.WALMessage_TimeoutInfo: tis, err := cmtmath.SafeConvertUint8(int64(msg.TimeoutInfo.Step)) // deny message based on possible overflow if err != nil { - return nil, fmt.Errorf("denying message due to possible overflow: %w", err) + return nil, ErrDenyMessageOverflow{err} } pb = timeoutInfo{ Duration: msg.TimeoutInfo.Duration, diff --git a/consensus/msgs_test.go b/internal/consensus/msgs_test.go similarity index 52% rename from consensus/msgs_test.go rename to internal/consensus/msgs_test.go index b27650c6a58..b05898829dd 100644 --- a/consensus/msgs_test.go +++ b/internal/consensus/msgs_test.go @@ -10,13 +10,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto/merkle" - "github.com/cometbft/cometbft/libs/bits" - cmtrand "github.com/cometbft/cometbft/libs/rand" + "github.com/cometbft/cometbft/internal/bits" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/p2p" - cmtcons "github.com/cometbft/cometbft/proto/tendermint/consensus" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" ) func TestMsgToProto(t *testing.T) { @@ -47,12 +48,12 @@ func TestMsgToProto(t *testing.T) { require.NoError(t, err) proposal := types.Proposal{ - Type: cmtproto.ProposalType, + Type: types.ProposalType, Height: 1, - Round: 1, + Round: 2, POLRound: 1, BlockID: bi, - Timestamp: time.Now(), + Timestamp: cmttime.Now(), Signature: cmtrand.Bytes(20), } pbProposal := proposal.ToProto() @@ -64,9 +65,9 @@ func TestMsgToProto(t *testing.T) { 0, 1, 0, - cmtproto.PrecommitType, + types.PrecommitType, bi, - time.Now(), + cmttime.Now(), ) pbVote := vote.ToProto() @@ -76,110 +77,129 @@ func TestMsgToProto(t *testing.T) { want proto.Message wantErr bool }{ - {"successful NewRoundStepMessage", &NewRoundStepMessage{ - Height: 2, - Round: 1, - Step: 1, - SecondsSinceStartTime: 1, - LastCommitRound: 2, - }, &cmtcons.NewRoundStep{ - Height: 2, - Round: 1, - Step: 1, - SecondsSinceStartTime: 1, - LastCommitRound: 2, - }, - - false}, + { + "successful NewRoundStepMessage", &NewRoundStepMessage{ + Height: 2, + Round: 1, + Step: 1, + SecondsSinceStartTime: 1, + LastCommitRound: 2, + }, &cmtcons.NewRoundStep{ + Height: 2, + Round: 1, + Step: 1, + SecondsSinceStartTime: 1, + LastCommitRound: 2, + }, - {"successful NewValidBlockMessage", &NewValidBlockMessage{ - Height: 1, - Round: 1, - BlockPartSetHeader: psh, - BlockParts: bits, - IsCommit: false, - }, &cmtcons.NewValidBlock{ - Height: 1, - Round: 1, - BlockPartSetHeader: pbPsh, - BlockParts: pbBits, - IsCommit: false, + false, }, - false}, - {"successful BlockPartMessage", &BlockPartMessage{ - Height: 100, - Round: 1, - Part: &parts, - }, &cmtcons.BlockPart{ - Height: 100, - Round: 1, - Part: *pbParts, + { + "successful NewValidBlockMessage", &NewValidBlockMessage{ + Height: 1, + Round: 1, + BlockPartSetHeader: psh, + BlockParts: bits, + IsCommit: false, + }, &cmtcons.NewValidBlock{ + Height: 1, + Round: 1, + BlockPartSetHeader: pbPsh, + BlockParts: pbBits, + IsCommit: false, + }, + + false, }, + { + "successful BlockPartMessage", &BlockPartMessage{ + Height: 100, + Round: 1, + Part: &parts, + }, &cmtcons.BlockPart{ + Height: 100, + Round: 1, + Part: *pbParts, + }, - false}, - {"successful ProposalPOLMessage", &ProposalPOLMessage{ - Height: 1, - ProposalPOLRound: 1, - ProposalPOL: bits, - }, &cmtcons.ProposalPOL{ - Height: 1, - ProposalPolRound: 1, - ProposalPol: *pbBits, + false, }, - false}, - {"successful ProposalMessage", &ProposalMessage{ - Proposal: &proposal, - }, &cmtcons.Proposal{ - Proposal: *pbProposal, + { + "successful ProposalPOLMessage", &ProposalPOLMessage{ + Height: 1, + ProposalPOLRound: 1, + ProposalPOL: bits, + }, &cmtcons.ProposalPOL{ + Height: 1, + ProposalPolRound: 1, + ProposalPol: *pbBits, + }, + false, }, + { + "successful ProposalMessage", &ProposalMessage{ + Proposal: &proposal, + }, &cmtcons.Proposal{ + Proposal: *pbProposal, + }, - false}, - {"successful VoteMessage", &VoteMessage{ - Vote: vote, - }, &cmtcons.Vote{ - Vote: pbVote, + false, }, + { + "successful VoteMessage", &VoteMessage{ + Vote: vote, + }, &cmtcons.Vote{ + Vote: pbVote, + }, - false}, - {"successful VoteSetMaj23", &VoteSetMaj23Message{ - Height: 1, - Round: 1, - Type: 1, - BlockID: bi, - }, &cmtcons.VoteSetMaj23{ - Height: 1, - Round: 1, - Type: 1, - BlockID: pbBi, + false, }, + { + "successful VoteSetMaj23", &VoteSetMaj23Message{ + Height: 1, + Round: 1, + Type: 1, + BlockID: bi, + }, &cmtcons.VoteSetMaj23{ + Height: 1, + Round: 1, + Type: 1, + BlockID: pbBi, + }, - false}, - {"successful VoteSetBits", &VoteSetBitsMessage{ - Height: 1, - Round: 1, - Type: 1, - BlockID: bi, - Votes: bits, - }, &cmtcons.VoteSetBits{ - Height: 1, - Round: 1, - Type: 1, - BlockID: pbBi, - Votes: *pbBits, + false, }, + { + "successful VoteSetBits", &VoteSetBitsMessage{ + Height: 1, + Round: 1, + Type: 1, + BlockID: bi, + Votes: bits, + }, &cmtcons.VoteSetBits{ + Height: 1, + Round: 1, + Type: 1, + BlockID: pbBi, + Votes: *pbBits, + }, - false}, + false, + }, {"failure", nil, &cmtcons.Message{}, true}, } for _, tt := range testsCases { tt := tt t.Run(tt.testName, func(t *testing.T) { - pb, err := MsgToProto(tt.msg) - if tt.wantErr == true { - assert.Equal(t, err != nil, tt.wantErr) + wpb, err := MsgToWrappedProto(tt.msg) + if tt.wantErr { + assert.Equal(t, tt.wantErr, err != nil) return } + require.NoError(t, err) + pb, err := wpb.Unwrap() + require.NoError(t, err) assert.EqualValues(t, tt.want, pb, tt.testName) msg, err := MsgFromProto(pb) @@ -196,7 +216,6 @@ func TestMsgToProto(t *testing.T) { } func TestWALMsgProto(t *testing.T) { - parts := types.Part{ Index: 1, Bytes: []byte("test"), @@ -209,12 +228,14 @@ func TestWALMsgProto(t *testing.T) { } pbParts, err := parts.ToProto() require.NoError(t, err) + now := cmttime.Now() testsCases := []struct { - testName string - msg WALMessage - want *cmtcons.WALMessage - wantErr bool + testName string + msg WALMessage + want *cmtcons.WALMessage + wantErr bool + equalValues bool // False for msgInfo, since equalValues does not see nil and time{} as equivalent }{ {"successful EventDataRoundState", types.EventDataRoundState{ Height: 2, @@ -228,7 +249,7 @@ func TestWALMsgProto(t *testing.T) { Step: "ronies", }, }, - }, false}, + }, false, true}, {"successful msgInfo", msgInfo{ Msg: &BlockPartMessage{ Height: 100, @@ -251,7 +272,55 @@ func TestWALMsgProto(t *testing.T) { PeerID: "string", }, }, - }, false}, + }, false, false}, + {"successful msgInfo with receive time", msgInfo{ + Msg: &BlockPartMessage{ + Height: 100, + Round: 1, + Part: &parts, + }, + PeerID: p2p.ID("string"), + }, &cmtcons.WALMessage{ + Sum: &cmtcons.WALMessage_MsgInfo{ + MsgInfo: &cmtcons.MsgInfo{ + Msg: cmtcons.Message{ + Sum: &cmtcons.Message_BlockPart{ + BlockPart: &cmtcons.BlockPart{ + Height: 100, + Round: 1, + Part: *pbParts, + }, + }, + }, + PeerID: "string", + ReceiveTime: &time.Time{}, + }, + }, + }, false, false}, + {"successful msgInfo with receive time explicit", msgInfo{ + Msg: &BlockPartMessage{ + Height: 100, + Round: 1, + Part: &parts, + }, + PeerID: p2p.ID("string"), + }, &cmtcons.WALMessage{ + Sum: &cmtcons.WALMessage_MsgInfo{ + MsgInfo: &cmtcons.MsgInfo{ + Msg: cmtcons.Message{ + Sum: &cmtcons.Message_BlockPart{ + BlockPart: &cmtcons.BlockPart{ + Height: 100, + Round: 1, + Part: *pbParts, + }, + }, + }, + PeerID: "string", + ReceiveTime: &now, + }, + }, + }, false, false}, {"successful timeoutInfo", timeoutInfo{ Duration: time.Duration(100), Height: 1, @@ -266,7 +335,7 @@ func TestWALMsgProto(t *testing.T) { Step: 1, }, }, - }, false}, + }, false, true}, {"successful EndHeightMessage", EndHeightMessage{ Height: 1, }, &cmtcons.WALMessage{ @@ -275,18 +344,21 @@ func TestWALMsgProto(t *testing.T) { Height: 1, }, }, - }, false}, - {"failure", nil, &cmtcons.WALMessage{}, true}, + }, false, true}, + {"failure", nil, &cmtcons.WALMessage{}, true, true}, } for _, tt := range testsCases { tt := tt t.Run(tt.testName, func(t *testing.T) { pb, err := WALToProto(tt.msg) - if tt.wantErr == true { - assert.Equal(t, err != nil, tt.wantErr) + if tt.wantErr { + assert.Equal(t, tt.wantErr, err != nil) return } - assert.EqualValues(t, tt.want, pb, tt.testName) + + if tt.equalValues { + assert.EqualValues(t, tt.want, pb, tt.testName) + } msg, err := WALFromProto(pb) @@ -331,7 +403,7 @@ func TestConsMsgsVectors(t *testing.T) { require.NoError(t, err) proposal := types.Proposal{ - Type: cmtproto.ProposalType, + Type: types.ProposalType, Height: 1, Round: 1, POLRound: 1, @@ -347,7 +419,7 @@ func TestConsMsgsVectors(t *testing.T) { Height: 1, Round: 0, Timestamp: date, - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, BlockID: bi, } vpb := v.ToProto() @@ -373,37 +445,69 @@ func TestConsMsgsVectors(t *testing.T) { SecondsSinceStartTime: math.MaxInt64, LastCommitRound: math.MaxInt32, }}}, "0a2608ffffffffffffffff7f10ffffffff0718ffffffff0f20ffffffffffffffff7f28ffffffff07"}, - {"NewValidBlock", &cmtcons.Message{Sum: &cmtcons.Message_NewValidBlock{ - NewValidBlock: &cmtcons.NewValidBlock{ - Height: 1, Round: 1, BlockPartSetHeader: pbPsh, BlockParts: pbBits, IsCommit: false}}}, - "1231080110011a24080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d22050801120100"}, - {"Proposal", &cmtcons.Message{Sum: &cmtcons.Message_Proposal{Proposal: &cmtcons.Proposal{Proposal: *pbProposal}}}, - "1a720a7008201001180120012a480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d320608c0b89fdc053a146164645f6d6f72655f6578636c616d6174696f6e"}, - {"ProposalPol", &cmtcons.Message{Sum: &cmtcons.Message_ProposalPol{ - ProposalPol: &cmtcons.ProposalPOL{Height: 1, ProposalPolRound: 1}}}, - "2206080110011a00"}, - {"BlockPart", &cmtcons.Message{Sum: &cmtcons.Message_BlockPart{ - BlockPart: &cmtcons.BlockPart{Height: 1, Round: 1, Part: *pbParts}}}, - "2a36080110011a3008011204746573741a26080110011a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d"}, - {"Vote_without_ext", &cmtcons.Message{Sum: &cmtcons.Message_Vote{ - Vote: &cmtcons.Vote{Vote: vpb}}}, - "32700a6e0802100122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a0608c0b89fdc0532146164645f6d6f72655f6578636c616d6174696f6e3801"}, - {"Vote_with_ext", &cmtcons.Message{Sum: &cmtcons.Message_Vote{ - Vote: &cmtcons.Vote{Vote: vextPb}}}, - "327b0a790802100122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a0608c0b89fdc0532146164645f6d6f72655f6578636c616d6174696f6e38014a09657874656e73696f6e"}, - {"HasVote", &cmtcons.Message{Sum: &cmtcons.Message_HasVote{ - HasVote: &cmtcons.HasVote{Height: 1, Round: 1, Type: cmtproto.PrevoteType, Index: 1}}}, - "3a080801100118012001"}, - {"HasVote", &cmtcons.Message{Sum: &cmtcons.Message_HasVote{ - HasVote: &cmtcons.HasVote{Height: math.MaxInt64, Round: math.MaxInt32, - Type: cmtproto.PrevoteType, Index: math.MaxInt32}}}, - "3a1808ffffffffffffffff7f10ffffffff07180120ffffffff07"}, - {"VoteSetMaj23", &cmtcons.Message{Sum: &cmtcons.Message_VoteSetMaj23{ - VoteSetMaj23: &cmtcons.VoteSetMaj23{Height: 1, Round: 1, Type: cmtproto.PrevoteType, BlockID: pbBi}}}, - "425008011001180122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d"}, - {"VoteSetBits", &cmtcons.Message{Sum: &cmtcons.Message_VoteSetBits{ - VoteSetBits: &cmtcons.VoteSetBits{Height: 1, Round: 1, Type: cmtproto.PrevoteType, BlockID: pbBi, Votes: *pbBits}}}, - "4a5708011001180122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a050801120100"}, + { + "NewValidBlock", &cmtcons.Message{Sum: &cmtcons.Message_NewValidBlock{ + NewValidBlock: &cmtcons.NewValidBlock{ + Height: 1, Round: 1, BlockPartSetHeader: pbPsh, BlockParts: pbBits, IsCommit: false, + }, + }}, + "1231080110011a24080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d22050801120100", + }, + { + "Proposal", &cmtcons.Message{Sum: &cmtcons.Message_Proposal{Proposal: &cmtcons.Proposal{Proposal: *pbProposal}}}, + "1a720a7008201001180120012a480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d320608c0b89fdc053a146164645f6d6f72655f6578636c616d6174696f6e", + }, + { + "ProposalPol", &cmtcons.Message{Sum: &cmtcons.Message_ProposalPol{ + ProposalPol: &cmtcons.ProposalPOL{Height: 1, ProposalPolRound: 1}, + }}, + "2206080110011a00", + }, + { + "BlockPart", &cmtcons.Message{Sum: &cmtcons.Message_BlockPart{ + BlockPart: &cmtcons.BlockPart{Height: 1, Round: 1, Part: *pbParts}, + }}, + "2a36080110011a3008011204746573741a26080110011a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d", + }, + { + "Vote_without_ext", &cmtcons.Message{Sum: &cmtcons.Message_Vote{ + Vote: &cmtcons.Vote{Vote: vpb}, + }}, + "32700a6e0802100122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a0608c0b89fdc0532146164645f6d6f72655f6578636c616d6174696f6e3801", + }, + { + "Vote_with_ext", &cmtcons.Message{Sum: &cmtcons.Message_Vote{ + Vote: &cmtcons.Vote{Vote: vextPb}, + }}, + "327b0a790802100122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a0608c0b89fdc0532146164645f6d6f72655f6578636c616d6174696f6e38014a09657874656e73696f6e", + }, + { + "HasVote", &cmtcons.Message{Sum: &cmtcons.Message_HasVote{ + HasVote: &cmtcons.HasVote{Height: 1, Round: 1, Type: types.PrevoteType, Index: 1}, + }}, + "3a080801100118012001", + }, + { + "HasVote", &cmtcons.Message{Sum: &cmtcons.Message_HasVote{ + HasVote: &cmtcons.HasVote{ + Height: math.MaxInt64, Round: math.MaxInt32, + Type: types.PrevoteType, Index: math.MaxInt32, + }, + }}, + "3a1808ffffffffffffffff7f10ffffffff07180120ffffffff07", + }, + { + "VoteSetMaj23", &cmtcons.Message{Sum: &cmtcons.Message_VoteSetMaj23{ + VoteSetMaj23: &cmtcons.VoteSetMaj23{Height: 1, Round: 1, Type: types.PrevoteType, BlockID: pbBi}, + }}, + "425008011001180122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d", + }, + { + "VoteSetBits", &cmtcons.Message{Sum: &cmtcons.Message_VoteSetBits{ + VoteSetBits: &cmtcons.VoteSetBits{Height: 1, Round: 1, Type: types.PrevoteType, BlockID: pbBi, Votes: *pbBits}, + }}, + "4a5708011001180122480a206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d1224080112206164645f6d6f72655f6578636c616d6174696f6e5f6d61726b735f636f64652d2a050801120100", + }, } for _, tc := range testCases { diff --git a/internal/consensus/pbts_test.go b/internal/consensus/pbts_test.go new file mode 100644 index 00000000000..9af8d2ec0c6 --- /dev/null +++ b/internal/consensus/pbts_test.go @@ -0,0 +1,770 @@ +package consensus + +import ( + "bytes" + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/cometbft/cometbft/abci/example/kvstore" + abci "github.com/cometbft/cometbft/abci/types" + abcimocks "github.com/cometbft/cometbft/abci/types/mocks" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + "github.com/cometbft/cometbft/internal/test" + "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" + cmttimemocks "github.com/cometbft/cometbft/types/time/mocks" +) + +const ( + // blockTimeIota is used in the test harness as the time between + // blocks when not otherwise specified. + blockTimeIota = time.Millisecond +) + +// pbtsTestHarness constructs a CometBFT network that can be used for testing the +// implementation of the Proposer-Based timestamps algorithm. +// It runs a series of consensus heights and captures timing of votes and events. +type pbtsTestHarness struct { + // configuration options set by the user of the test harness. + pbtsTestConfiguration + + // The timestamp of the first block produced by the network. + firstBlockTime time.Time + + // The CometBFT consensus state machine being run during + // a run of the pbtsTestHarness. + observedState *State + + // A stub for signing votes and messages using the key + // from the observedState. + observedValidator *validatorStub + + // A list of simulated validators that interact with the observedState and are + // fully controlled by the test harness. + otherValidators []*validatorStub + + // The mock time source used by all of the validator stubs in the test harness. + // This mock clock allows the test harness to produce votes and blocks with arbitrary + // timestamps. + validatorClock *cmttimemocks.Source + + chainID string + + // channels for verifying that the observed validator completes certain actions. + ensureProposalCh, roundCh, blockCh, ensureVoteCh <-chan cmtpubsub.Message + + // channel of events from the observed validator annotated with the timestamp + // the event was received. + eventCh <-chan timestampedEvent + + currentHeight int64 + currentRound int32 +} + +type pbtsTestConfiguration struct { + // The timestamp consensus parameters to be used by the state machine under test. + synchronyParams types.SynchronyParams + + // The setting to use for the TimeoutPropose configuration parameter. + timeoutPropose time.Duration + + // The genesis time + genesisTime time.Time + + // The times offset from height 1 block time of the block proposed at height 2. + height2ProposedBlockOffset time.Duration + + // The time offset from height 1 block time at which the proposal at height 2 should be delivered. + height2ProposalTimeDeliveryOffset time.Duration + + // The time offset from height 1 block time of the block proposed at height 4. + // At height 4, the proposed block and the deliver offsets are the same so + // that timely-ness does not affect height 4. + height4ProposedBlockOffset time.Duration +} + +func newPBTSTestHarness(ctx context.Context, t *testing.T, tc pbtsTestConfiguration) pbtsTestHarness { + t.Helper() + const validators = 4 + cfg := test.ResetTestRoot("newPBTSTestHarness") + clock := new(cmttimemocks.Source) + + if tc.genesisTime.IsZero() { + tc.genesisTime = cmttime.Now() + } + + if tc.height4ProposedBlockOffset == 0 { + // Set a default height4ProposedBlockOffset. + // Use a proposed block time that is greater than the time that the + // block at height 2 was delivered. Height 3 is not relevant for testing + // and always occurs blockTimeIota before height 4. If not otherwise specified, + // height 4 therefore occurs 2*blockTimeIota after height 2. + tc.height4ProposedBlockOffset = tc.height2ProposalTimeDeliveryOffset + 2*blockTimeIota + } + cfg.Consensus.TimeoutPropose = tc.timeoutPropose + consensusParams := types.DefaultConsensusParams() + consensusParams.Synchrony = tc.synchronyParams + consensusParams.Feature.PbtsEnableHeight = 1 + + state, privVals := randGenesisStateWithTime(validators, consensusParams, tc.genesisTime) + cs := newStateWithConfig(cfg, state, privVals[0], kvstore.NewInMemoryApplication()) + vss := make([]*validatorStub, validators) + for i := 0; i < validators; i++ { + vss[i] = newValidatorStub(privVals[i], int32(i)) + } + incrementHeight(vss[1:]...) + + for _, vs := range vss { + vs.clock = clock + } + pubKey, err := vss[0].PrivValidator.GetPubKey() + require.NoError(t, err) + + eventCh := timestampedCollector(ctx, t, cs.eventBus) + + return pbtsTestHarness{ + pbtsTestConfiguration: tc, + observedValidator: vss[0], + observedState: cs, + otherValidators: vss[1:], + validatorClock: clock, + currentHeight: 1, + chainID: cs.state.ChainID, + roundCh: subscribe(cs.eventBus, types.EventQueryNewRound), + ensureProposalCh: subscribe(cs.eventBus, types.EventQueryCompleteProposal), + blockCh: subscribe(cs.eventBus, types.EventQueryNewBlock), + ensureVoteCh: subscribeToVoterBuffered(cs, pubKey.Address()), + eventCh: eventCh, + } +} + +func (p *pbtsTestHarness) observedValidatorProposerHeight(t *testing.T, previousBlockTime time.Time) (heightResult, time.Time) { + t.Helper() + p.validatorClock.On("Now").Return(p.genesisTime.Add(p.height2ProposedBlockOffset)).Times(2 * len(p.otherValidators)) + + ensureNewRound(p.roundCh, p.currentHeight, p.currentRound) + + timeout := cmttime.Until(previousBlockTime.Add(ensureTimeout)) + if timeout < ensureTimeout { + timeout = ensureTimeout + } + ensureProposalWithTimeout(p.ensureProposalCh, p.currentHeight, p.currentRound, nil, timeout) + + rs := p.observedState.GetRoundState() + bid := types.BlockID{Hash: rs.ProposalBlock.Hash(), PartSetHeader: rs.ProposalBlockParts.Header()} + ensurePrevote(p.ensureVoteCh, p.currentHeight, p.currentRound) + signAddVotes(p.observedState, types.PrevoteType, p.chainID, bid, false, p.otherValidators...) + + ensurePrecommit(p.ensureVoteCh, p.currentHeight, p.currentRound) + signAddVotes(p.observedState, types.PrecommitType, p.chainID, bid, false, p.otherValidators...) + + ensureNewBlock(p.blockCh, p.currentHeight) + + vk, err := p.observedValidator.GetPubKey() + require.NoError(t, err) + res := collectHeightResults(t, p.eventCh, p.currentHeight, vk.Address()) + + p.currentHeight++ + incrementHeight(p.otherValidators...) + return res, rs.ProposalBlock.Time +} + +func (p *pbtsTestHarness) height2(ctx context.Context, t *testing.T) heightResult { + t.Helper() + signer := p.otherValidators[0].PrivValidator + return p.nextHeight(ctx, t, signer, + p.firstBlockTime.Add(p.height2ProposalTimeDeliveryOffset), + p.firstBlockTime.Add(p.height2ProposedBlockOffset), + p.firstBlockTime.Add(p.height2ProposedBlockOffset+10*blockTimeIota)) +} + +func (p *pbtsTestHarness) intermediateHeights(ctx context.Context, t *testing.T) { + t.Helper() + signer := p.otherValidators[1].PrivValidator + p.nextHeight(ctx, t, signer, + p.firstBlockTime.Add(p.height2ProposedBlockOffset+10*blockTimeIota), + p.firstBlockTime.Add(p.height2ProposedBlockOffset+10*blockTimeIota), + p.firstBlockTime.Add(p.height4ProposedBlockOffset)) + + signer = p.otherValidators[2].PrivValidator + p.nextHeight(ctx, t, signer, + p.firstBlockTime.Add(p.height4ProposedBlockOffset), + p.firstBlockTime.Add(p.height4ProposedBlockOffset), + cmttime.Now()) +} + +func (p *pbtsTestHarness) height5(t *testing.T) (heightResult, time.Time) { + t.Helper() + return p.observedValidatorProposerHeight(t, p.firstBlockTime.Add(p.height4ProposedBlockOffset)) +} + +func (p *pbtsTestHarness) nextHeight( + ctx context.Context, + t *testing.T, + proposer types.PrivValidator, + deliverTime, proposedTime, nextProposedTime time.Time, +) heightResult { + t.Helper() + + p.validatorClock.On("Now").Return(nextProposedTime).Times(2 * len(p.otherValidators)) + + ensureNewRound(p.roundCh, p.currentHeight, p.currentRound) + + b, err := p.observedState.createProposalBlock(ctx) + require.NoError(t, err) + require.Equal(t, b.Height, p.currentHeight) + b.Time = proposedTime + + k, err := proposer.GetPubKey() + require.NoError(t, err) + b.Header.ProposerAddress = k.Address() + ps, err := b.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) + bid := types.BlockID{Hash: b.Hash(), PartSetHeader: ps.Header()} + prop := types.NewProposal(p.currentHeight, 0, -1, bid, proposedTime) + tp := prop.ToProto() + + err = proposer.SignProposal(p.chainID, tp) + require.NoError(t, err) + + time.Sleep(cmttime.Until(deliverTime)) + prop.Signature = tp.Signature + err = p.observedState.SetProposalAndBlock(prop, ps, "peerID") + require.NoError(t, err) + ensureProposal(p.ensureProposalCh, p.currentHeight, 0, bid) + + ensurePrevote(p.ensureVoteCh, p.currentHeight, p.currentRound) + signAddVotes(p.observedState, types.PrevoteType, p.chainID, bid, false, p.otherValidators...) + + ensurePrecommit(p.ensureVoteCh, p.currentHeight, p.currentRound) + signAddVotes(p.observedState, types.PrecommitType, p.chainID, bid, false, p.otherValidators...) + + vk, err := p.observedValidator.GetPubKey() + require.NoError(t, err) + res := collectHeightResults(t, p.eventCh, p.currentHeight, vk.Address()) + ensureNewBlock(p.blockCh, p.currentHeight) + + p.currentHeight++ + incrementHeight(p.otherValidators...) + return res +} + +func timestampedCollector(ctx context.Context, t *testing.T, eb *types.EventBus) <-chan timestampedEvent { + t.Helper() + + // Since eventCh is not read until the end of each height, it must be large + // enough to hold all of the events produced during a single height. + eventCh := make(chan timestampedEvent, 100) + + const tsCollectorClient = "timestampedCollector" + proposalSub, err := eb.Subscribe(ctx, tsCollectorClient, types.EventQueryCompleteProposal) + require.NoError(t, err) + // We set a capacity of since there are several votes produced. + // With capacity 1 (default) the tests deadlock sometimes. + voteSub, err := eb.Subscribe(ctx, tsCollectorClient, types.EventQueryVote, 10) + require.NoError(t, err) + + go func(ctx context.Context, t *testing.T) { + t.Helper() + for { + var msg cmtpubsub.Message + select { + case <-ctx.Done(): + return + case msg = <-proposalSub.Out(): + case msg = <-voteSub.Out(): + } + eventCh <- timestampedEvent{ + ts: cmttime.Now(), + m: msg, + } + } + }(ctx, t) + + return eventCh +} + +func collectHeightResults(t *testing.T, eventCh <-chan timestampedEvent, height int64, address []byte) heightResult { + t.Helper() + var res heightResult + for event := range eventCh { + require.False(t, event.ts.IsZero()) + switch v := event.m.Data().(type) { + case types.EventDataVote: + if v.Vote.Height > height { + t.Fatalf("received prevote from unexpected height, expected: %d, saw: %d", height, v.Vote.Height) + } + if !bytes.Equal(address, v.Vote.ValidatorAddress) { + continue + } + if v.Vote.Type != types.PrevoteType { + continue + } + if res.prevote != nil { + t.Fatalf("received duplicate prevote, previous %v, current %v", res.prevote, v.Vote) + } + res.prevote = v.Vote + res.prevoteIssuedAt = event.ts + + case types.EventDataCompleteProposal: + if v.Height > height { + t.Fatalf("received proposal from unexpected height, expected: %d, saw: %d", height, v.Height) + } + res.proposalIssuedAt = event.ts + } + if res.isComplete() { + return res + } + } + t.Fatalf("complete height result never seen for height %d", height) //nolint:revive // this is part of an unreachable code test + + panic("unreachable") +} + +type timestampedEvent struct { + ts time.Time + m cmtpubsub.Message +} + +func (p *pbtsTestHarness) run(ctx context.Context, t *testing.T) resultSet { + t.Helper() + startTestRound(p.observedState, p.currentHeight, p.currentRound) + + r1, proposalBlockTime := p.observedValidatorProposerHeight(t, p.genesisTime) + p.firstBlockTime = proposalBlockTime + r2 := p.height2(ctx, t) + p.intermediateHeights(ctx, t) + r5, _ := p.height5(t) + return resultSet{ + genesisHeight: r1, + height2: r2, + height5: r5, + } +} + +type resultSet struct { + genesisHeight heightResult + height2 heightResult + height5 heightResult +} + +type heightResult struct { + proposalIssuedAt time.Time + prevote *types.Vote + prevoteIssuedAt time.Time +} + +func (hr heightResult) isComplete() bool { + return !hr.proposalIssuedAt.IsZero() && !hr.prevoteIssuedAt.IsZero() && hr.prevote != nil +} + +// TestProposerWaitsForGenesisTime tests that a proposer will not propose a block +// until after the genesis time has passed. The test sets the genesis time in the +// future and then ensures that the observed validator waits to propose a block. +func TestPBTSProposerWaitsForGenesisTime(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // create a genesis time far (enough) in the future. + initialTime := cmttime.Now().Add(800 * time.Millisecond) + cfg := pbtsTestConfiguration{ + synchronyParams: types.SynchronyParams{ + Precision: 10 * time.Millisecond, + MessageDelay: 10 * time.Millisecond, + }, + timeoutPropose: 10 * time.Millisecond, + genesisTime: initialTime, + height2ProposalTimeDeliveryOffset: 10 * time.Millisecond, + height2ProposedBlockOffset: 10 * time.Millisecond, + height4ProposedBlockOffset: 30 * time.Millisecond, + } + + pbtsTest := newPBTSTestHarness(ctx, t, cfg) + results := pbtsTest.run(ctx, t) + + // ensure that the proposal was issued after the genesis time. + assert.True(t, results.genesisHeight.proposalIssuedAt.After(cfg.genesisTime)) +} + +// TestProposerWaitsForPreviousBlock tests that the proposer of a block waits until +// the block time of the previous height has passed to propose the next block. +// The test harness ensures that the observed validator will be the proposer at +// height 1 and height 5. The test sets the block time of height 4 in the future +// and then verifies that the observed validator waits until after the block time +// of height 4 to propose a block at height 5. +func TestPBTSProposerWaitsForPreviousBlock(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + initialTime := cmttime.Now().Add(time.Millisecond * 50) + cfg := pbtsTestConfiguration{ + synchronyParams: types.SynchronyParams{ + Precision: 100 * time.Millisecond, + MessageDelay: 500 * time.Millisecond, + }, + timeoutPropose: 50 * time.Millisecond, + genesisTime: initialTime, + height2ProposalTimeDeliveryOffset: 150 * time.Millisecond, + height2ProposedBlockOffset: 100 * time.Millisecond, + height4ProposedBlockOffset: 800 * time.Millisecond, + } + + pbtsTest := newPBTSTestHarness(ctx, t, cfg) + results := pbtsTest.run(ctx, t) + + // the observed validator is the proposer at height 5. + // ensure that the observed validator did not propose a block until after + // the time configured for height 4. + assert.True(t, results.height5.proposalIssuedAt.After(pbtsTest.firstBlockTime.Add(cfg.height4ProposedBlockOffset))) + + // Ensure that the validator issued a prevote for a non-nil block. + assert.NotNil(t, results.height5.prevote.BlockID.Hash) +} + +func TestPBTSProposerWaitTime(t *testing.T) { + genesisTime, err := time.Parse(time.RFC3339, "2019-03-13T23:00:00Z") + require.NoError(t, err) + testCases := []struct { + name string + previousBlockTime time.Time + localTime time.Time + expectedWait time.Duration + }{ + { + name: "block time greater than local time", + previousBlockTime: genesisTime.Add(5 * time.Nanosecond), + localTime: genesisTime.Add(1 * time.Nanosecond), + expectedWait: 4 * time.Nanosecond, + }, + { + name: "local time greater than block time", + previousBlockTime: genesisTime.Add(1 * time.Nanosecond), + localTime: genesisTime.Add(5 * time.Nanosecond), + expectedWait: 0, + }, + { + name: "both times equal", + previousBlockTime: genesisTime.Add(5 * time.Nanosecond), + localTime: genesisTime.Add(5 * time.Nanosecond), + expectedWait: 0, + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + mockSource := new(cmttimemocks.Source) + mockSource.On("Now").Return(testCase.localTime) + + ti := proposerWaitTime(mockSource, testCase.previousBlockTime) + assert.Equal(t, testCase.expectedWait, ti) + }) + } +} + +func TestPBTSTimelyProposal(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + initialTime := cmttime.Now() + + cfg := pbtsTestConfiguration{ + synchronyParams: types.SynchronyParams{ + Precision: 10 * time.Millisecond, + MessageDelay: 140 * time.Millisecond, + }, + timeoutPropose: 40 * time.Millisecond, + genesisTime: initialTime, + height2ProposedBlockOffset: 15 * time.Millisecond, + height2ProposalTimeDeliveryOffset: 30 * time.Millisecond, + } + + pbtsTest := newPBTSTestHarness(ctx, t, cfg) + results := pbtsTest.run(ctx, t) + require.NotNil(t, results.height2.prevote.BlockID.Hash) +} + +func TestPBTSTooFarInThePastProposal(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // localtime > proposedBlockTime + MsgDelay + Precision + cfg := pbtsTestConfiguration{ + synchronyParams: types.SynchronyParams{ + Precision: 1 * time.Millisecond, + MessageDelay: 10 * time.Millisecond, + }, + timeoutPropose: 50 * time.Millisecond, + height2ProposedBlockOffset: 15 * time.Millisecond, + height2ProposalTimeDeliveryOffset: 27 * time.Millisecond, + } + + pbtsTest := newPBTSTestHarness(ctx, t, cfg) + results := pbtsTest.run(ctx, t) + + require.Nil(t, results.height2.prevote.BlockID.Hash) +} + +func TestPBTSTooFarInTheFutureProposal(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // localtime < proposedBlockTime - Precision + cfg := pbtsTestConfiguration{ + synchronyParams: types.SynchronyParams{ + Precision: 1 * time.Millisecond, + MessageDelay: 10 * time.Millisecond, + }, + timeoutPropose: 50 * time.Millisecond, + height2ProposedBlockOffset: 100 * time.Millisecond, + height2ProposalTimeDeliveryOffset: 10 * time.Millisecond, + height4ProposedBlockOffset: 150 * time.Millisecond, + } + + pbtsTest := newPBTSTestHarness(ctx, t, cfg) + results := pbtsTest.run(ctx, t) + + require.Nil(t, results.height2.prevote.BlockID.Hash) +} + +// TestPBTSEnableHeight tests the transition between BFT Time and PBTS. +// The test runs multiple heights. BFT Time is used until the configured +// PbtsEnableHeight. During some of these heights, the timestamp of votes +// is shifted to the future to increase block timestamps. PBTS is enabled +// at pbtsSetHeight, via FinalizeBlock. From this point, some nodes select +// timestamps using PBTS, which is not yet enabled. When PbtsEnableHeight +// is reached, some nodes propose bad timestamps. At the end, only blocks +// proposed by the tested node are accepted, as they are not tweaked. +func TestPBTSEnableHeight(t *testing.T) { + numValidators := 4 + election := func(h int64, r int32) int { + return (int(h-1) + int(r)) % numValidators + } + + c := test.ConsensusParams() + c.Feature.PbtsEnableHeight = 0 // Start with PBTS disabled + + app := abcimocks.NewApplication(t) + app.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ProcessProposalResponse{ + Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT, + }, nil) + app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{}, nil) + app.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ExtendVoteResponse{}, nil) + app.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.VerifyVoteExtensionResponse{ + Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT, + }, nil) + app.On("Commit", mock.Anything, mock.Anything).Return(&abci.CommitResponse{}, nil).Maybe() + + cs, vss := randStateWithAppImpl(numValidators, app, c) + height, round, chainID := cs.Height, cs.Round, cs.state.ChainID + + proposalCh := subscribe(cs.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs.eventBus, types.EventQueryNewRound) + voteCh := subscribe(cs.eventBus, types.EventQueryVote) + + lastHeight := height + 4 + pbtsSetHeight := height + 2 + pbtsEnableHeight := height + 3 + + startTestRound(cs, height, round) + for height <= lastHeight { + var block *types.Block + var blockID types.BlockID + + ensureNewRound(newRoundCh, height, round) + proposer := election(height, round) + pbtsEnabled := (height >= pbtsEnableHeight) + rejectProposal := false + + // Propose step + if proposer == 0 { + // Wait until we receive our own proposal + // This may take longer when switching to PBTS since + // BFT Time timestamps are shifted to the future. + ensureProposalWithTimeout(proposalCh, height, round, nil, 2*time.Second) + rs := cs.GetRoundState() + block, _ = rs.ProposalBlock, rs.ProposalBlockParts + blockID = rs.Proposal.BlockID + } else { + var ts time.Time + var blockParts *types.PartSet + + if height >= pbtsSetHeight && height < pbtsEnableHeight { + // Use PBTS logic while PBTS is not yet activated + ts = cmttime.Now() + rejectProposal = true + } else if height >= pbtsEnableHeight { + // Shift timestamp to the future 2*PRECISION => not timely + ts = cmttime.Now().Add(2 * c.Synchrony.Precision) + rejectProposal = true + } + block, blockParts, blockID = createProposalBlockWithTime(t, cs, ts) + proposal := types.NewProposal(height, round, -1, blockID, block.Header.Time) + // BFT Time should not care about Proposal's timestamps + if height < pbtsSetHeight { + proposal.Timestamp = cmttime.Now() + } + signProposal(t, proposal, chainID, vss[proposer]) + err := cs.SetProposalAndBlock(proposal, blockParts, "p") + require.NoError(t, err) + ensureProposal(proposalCh, height, round, blockID) + } + + delta := cmttime.Since(block.Time) + t.Log("BLOCK", height, round, "PROPOSER", proposer, "PBTS", pbtsEnabled, + "TIMESTAMP", block.Time, delta, "ACCEPTED", !rejectProposal) + + // Accept proposal and decide, or reject proposal and move to next round + myVote := blockID.Hash + lockedRound := round + if rejectProposal { + myVote = nil + lockedRound = int32(-1) + } else { // We are deciding, enable FinalizeBlock mock + res := &abci.FinalizeBlockResponse{} + // Enable PBTS from pbtsEnableHeight via consensus params + if height == pbtsSetHeight { + params := types.DefaultConsensusParams() + params.Feature.VoteExtensionsEnableHeight = 1 + params.Feature.PbtsEnableHeight = pbtsEnableHeight + paramsProto := params.ToProto() + res.ConsensusParamUpdates = ¶msProto + } + app.On("FinalizeBlock", mock.Anything, mock.Anything). + Return(res, nil).Once() + } + + // Prevote step + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs, round, vss[0], myVote) + for _, vs := range vss[2:] { + signAddVotes(cs, types.PrevoteType, chainID, blockID, false, vs) + ensurePrevote(voteCh, height, round) + } + + // Precommit step + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs, round, lockedRound, vss[0], myVote, myVote) + for _, vs := range vss[2:] { + ts := cmttime.Now() + // Shift the next block timestamp while running BFT Time + if height >= pbtsSetHeight-1 && height < pbtsEnableHeight { + ts = ts.Add(time.Second) + } + vote := signVoteWithTimestamp(vs, types.PrecommitType, chainID, blockID, true, ts) + cs.peerMsgQueue <- msgInfo{Msg: &VoteMessage{vote}} + ensurePrecommit(voteCh, height, round) + } + + if myVote != nil { + height, round = height+1, 0 + incrementHeight(vss[1:]...) + } else { + round = round + 1 + incrementRound(vss[1:]...) + } + } + // Last call to FinalizeBlock + ensureNewRound(newRoundCh, height, round) +} + +// TestPbtsAdaptiveMessageDelay tests whether proposals with timestamps in the +// past are eventually accepted by validators. The test runs multiple rounds. +// Rounds where the tested node is the proposer are skipped. Rounds with other +// proposers uses a Proposal with a tweaked timestamp, which is too far in the +// past. After a maximum number of rounds, if PBTS validation is adaptive, the +// synchronous parameters will be large enough to accept the proposal. +func TestPbtsAdaptiveMessageDelay(t *testing.T) { + numValidators := 4 + election := func(h int64, r int32) int { + return (int(h-1) + int(r)) % numValidators + } + + c := test.ConsensusParams() + app := kvstore.NewInMemoryApplication() + genesisTime := cmttime.Now().Add(-10 * time.Second) + cs, vss := randStateWithAppImplGenesisTime(numValidators, app, c, genesisTime) + + myPubKey, err := vss[0].GetPubKey() + require.NoError(t, err) + myAddress := myPubKey.Address() + + proposalCh := subscribe(cs.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs.eventBus, types.EventQueryNewRound) + voteCh := subscribe(cs.eventBus, types.EventQueryVote) + + height, round := cs.Height, cs.Round + chainID := cs.state.ChainID + + originMaxDelta := c.Synchrony.Precision + c.Synchrony.MessageDelay + + maximumRound := round + 10 + startTestRound(cs, height, round) + + for ; round < maximumRound; round++ { + var vote types.BlockID + assert.True(t, vote.IsNil()) // default is vote nil + + t.Log("Starting round", round) + ensureNewRound(newRoundCh, height, round) + proposer := election(height, round) + ac := c.Synchrony.InRound(round) + maxDelta := ac.Precision + ac.MessageDelay + + if proposer != 0 { + shift := originMaxDelta + c.Synchrony.MessageDelay/2 + ts := cmttime.Now().Add(-shift) + if ts.Before(genesisTime) { + ts = genesisTime + } + + // Create block and proposal with the tweaked timestamp + block, blockParts, blockID := createProposalBlockWithTime(t, cs, ts) + proposal := types.NewProposal(height, round, -1, blockID, block.Header.Time) + signProposal(t, proposal, chainID, vss[proposer]) + + require.NoError(t, cs.SetProposalAndBlock(proposal, blockParts, "p")) + maxReceiveTime := cmttime.Now() + + ensureProposal(proposalCh, height, round, blockID) + ensurePrevote(voteCh, height, round) + vote = cs.Votes.Prevotes(round).GetByAddress(myAddress).BlockID + + delta := maxReceiveTime.Sub(ts) + t.Log("Proposal timestamp", ts.Format(time.StampMicro), + "maximum receive time", maxReceiveTime.Format(time.StampMicro), + "delta", delta, + "maximum allowed delta", maxDelta) + t.Logf("Round %d, expected timely=%v, got timely=%v\n", + round, (delta < maxDelta), !vote.IsNil()) + } else { + // The node will accept its own proposal. + // Just make everyone to vote nil and skip the round. + ensureNewProposal(proposalCh, height, round) + ensurePrevote(voteCh, height, round) + } + + for _, vs := range vss[2:] { + signAddVotes(cs, types.PrevoteType, chainID, vote, false, vs) + ensurePrevote(voteCh, height, round) + } + ensurePrecommit(voteCh, height, round) + + for _, vs := range vss[2:] { + signAddVotes(cs, types.PrecommitType, chainID, vote, true, vs) + ensurePrecommit(voteCh, height, round) + } + + if !vote.IsNil() { + // Decide, so we are good! + ensureNewRound(newRoundCh, height+1, 0) + t.Log("Decided at round", round) + return + } + // No decision, new round required + incrementRound(vss[1:]...) + } + t.Error("Did not decide after round", round) +} diff --git a/consensus/reactor.go b/internal/consensus/reactor.go similarity index 78% rename from consensus/reactor.go rename to internal/consensus/reactor.go index 1d7655ae26b..dd44e4a230d 100644 --- a/consensus/reactor.go +++ b/internal/consensus/reactor.go @@ -1,23 +1,24 @@ package consensus import ( - "errors" "fmt" "reflect" "sync" + "sync/atomic" "time" - cstypes "github.com/cometbft/cometbft/consensus/types" - "github.com/cometbft/cometbft/libs/bits" - cmtevents "github.com/cometbft/cometbft/libs/events" + cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1" + "github.com/cometbft/cometbft/internal/bits" + cstypes "github.com/cometbft/cometbft/internal/consensus/types" + cmtevents "github.com/cometbft/cometbft/internal/events" + cmtrand "github.com/cometbft/cometbft/internal/rand" + sm "github.com/cometbft/cometbft/internal/state" + cmtsync "github.com/cometbft/cometbft/internal/sync" cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/p2p" - cmtcons "github.com/cometbft/cometbft/proto/tendermint/consensus" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -33,7 +34,7 @@ const ( votesToContributeToBecomeGoodPeer = 10000 ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Reactor defines a reactor for the consensus service. type Reactor struct { @@ -41,26 +42,29 @@ type Reactor struct { conS *State - mtx cmtsync.RWMutex - waitSync bool + waitSync atomic.Bool eventBus *types.EventBus - rs *cstypes.RoundState + + rsMtx cmtsync.Mutex + rs *cstypes.RoundState Metrics *Metrics } type ReactorOption func(*Reactor) -// NewReactor returns a new Reactor with the given -// consensusState. +// NewReactor returns a new Reactor with the given consensusState. func NewReactor(consensusState *State, waitSync bool, options ...ReactorOption) *Reactor { conR := &Reactor{ conS: consensusState, - waitSync: waitSync, + waitSync: atomic.Bool{}, rs: consensusState.GetRoundState(), Metrics: NopMetrics(), } conR.BaseReactor = *p2p.NewBaseReactor("Consensus", conR) + if waitSync { + conR.waitSync.Store(true) + } for _, option := range options { option(conR) @@ -72,7 +76,9 @@ func NewReactor(consensusState *State, waitSync bool, options ...ReactorOption) // OnStart implements BaseService by subscribing to events, which later will be // broadcasted to other peers and starting state if we're not in block sync. func (conR *Reactor) OnStart() error { - conR.Logger.Info("Reactor ", "waitSync", conR.WaitSync()) + if conR.WaitSync() { + conR.Logger.Info("Starting reactor in sync mode: consensus protocols will start once sync completes") + } // start routine that computes peer statistics for evaluating peer quality go conR.peerStatsRoutine() @@ -102,27 +108,34 @@ func (conR *Reactor) OnStop() { } } -// SwitchToConsensus switches from block_sync mode to consensus mode. -// It resets the state, turns off block_sync, and starts the consensus state-machine +// SwitchToConsensus switches from block sync or state sync mode to consensus +// mode. func (conR *Reactor) SwitchToConsensus(state sm.State, skipWAL bool) { conR.Logger.Info("SwitchToConsensus") - // We have no votes, so reconstruct LastCommit from SeenCommit. - if state.LastBlockHeight > 0 { - conR.conS.reconstructLastCommit(state) - } + // reset the state + func() { + // We need to lock, as we are not entering consensus state from State's `handleMsg` or `handleTimeout` + conR.conS.mtx.Lock() + defer conR.conS.mtx.Unlock() + // We have no votes, so reconstruct LastCommit from SeenCommit + if state.LastBlockHeight > 0 { + conR.conS.reconstructLastCommit(state) + } - // NOTE: The line below causes broadcastNewRoundStepRoutine() to broadcast a - // NewRoundStepMessage. - conR.conS.updateToState(state) + // NOTE: The line below causes broadcastNewRoundStepRoutine() to broadcast a + // NewRoundStepMessage. + conR.conS.updateToState(state) + }() - conR.mtx.Lock() - conR.waitSync = false - conR.mtx.Unlock() + // stop waiting for syncing to finish + conR.waitSync.Store(false) if skipWAL { conR.conS.doWALCatchup = false } + + // start the consensus protocol err := conR.conS.Start() if err != nil { panic(fmt.Sprintf(`Failed to start consensus state: %v @@ -135,8 +148,8 @@ conR: } } -// GetChannels implements Reactor -func (conR *Reactor) GetChannels() []*p2p.ChannelDescriptor { +// GetChannels implements Reactor. +func (*Reactor) GetChannels() []*p2p.ChannelDescriptor { // TODO optimize return []*p2p.ChannelDescriptor{ { @@ -205,7 +218,7 @@ func (conR *Reactor) AddPeer(peer p2p.Peer) { } // RemovePeer is a noop. -func (conR *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) { +func (conR *Reactor) RemovePeer(p2p.Peer, any) { if !conR.IsRunning() { return } @@ -222,7 +235,7 @@ func (conR *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) { // Messages affect either a peer state or the consensus state. // Peer state updates can happen in parallel, but processing of // proposals, block parts, and votes are ordered by the receiveRoutine -// NOTE: blocks on consensus state for proposals, block parts, and votes +// NOTE: blocks on consensus state for proposals, block parts, and votes. func (conR *Reactor) Receive(e p2p.Envelope) { if !conR.IsRunning() { conR.Logger.Debug("Receive", "src", e.Src, "chId", e.ChannelID) @@ -266,6 +279,8 @@ func (conR *Reactor) Receive(e p2p.Envelope) { ps.ApplyNewValidBlockMessage(msg) case *HasVoteMessage: ps.ApplyHasVoteMessage(msg) + case *HasProposalBlockPartMessage: + ps.ApplyHasProposalBlockPartMessage(msg) case *VoteSetMaj23Message: cs := conR.conS cs.mtx.Lock() @@ -284,9 +299,9 @@ func (conR *Reactor) Receive(e p2p.Envelope) { // (and consequently shows which we don't have) var ourVotes *bits.BitArray switch msg.Type { - case cmtproto.PrevoteType: + case types.PrevoteType: ourVotes = votes.Prevotes(msg.Round).BitArrayByBlockID(msg.BlockID) - case cmtproto.PrecommitType: + case types.PrecommitType: ourVotes = votes.Precommits(msg.Round).BitArrayByBlockID(msg.BlockID) default: panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?") @@ -316,13 +331,13 @@ func (conR *Reactor) Receive(e p2p.Envelope) { switch msg := msg.(type) { case *ProposalMessage: ps.SetHasProposal(msg.Proposal) - conR.conS.peerMsgQueue <- msgInfo{msg, e.Src.ID()} + conR.conS.peerMsgQueue <- msgInfo{msg, e.Src.ID(), cmttime.Now()} case *ProposalPOLMessage: ps.ApplyProposalPOLMessage(msg) case *BlockPartMessage: ps.SetHasProposalBlockPart(msg.Height, msg.Round, int(msg.Part.Index)) conR.Metrics.BlockParts.With("peer_id", string(e.Src.ID())).Add(1) - conR.conS.peerMsgQueue <- msgInfo{msg, e.Src.ID()} + conR.conS.peerMsgQueue <- msgInfo{msg, e.Src.ID(), time.Time{}} default: conR.Logger.Error(fmt.Sprintf("Unknown message type %v", reflect.TypeOf(msg))) } @@ -342,7 +357,7 @@ func (conR *Reactor) Receive(e p2p.Envelope) { ps.EnsureVoteBitArrays(height-1, lastCommitSize) ps.SetHasVote(msg.Vote) - cs.peerMsgQueue <- msgInfo{msg, e.Src.ID()} + cs.peerMsgQueue <- msgInfo{msg, e.Src.ID(), time.Time{}} default: // don't punish (leave room for soft upgrades) @@ -364,9 +379,9 @@ func (conR *Reactor) Receive(e p2p.Envelope) { if height == msg.Height { var ourVotes *bits.BitArray switch msg.Type { - case cmtproto.PrevoteType: + case types.PrevoteType: ourVotes = votes.Prevotes(msg.Round).BitArrayByBlockID(msg.BlockID) - case cmtproto.PrecommitType: + case types.PrecommitType: ourVotes = votes.Precommits(msg.Round).BitArrayByBlockID(msg.BlockID) default: panic("Bad VoteSetBitsMessage field Type. Forgot to add a check in ValidateBasic?") @@ -393,12 +408,10 @@ func (conR *Reactor) SetEventBus(b *types.EventBus) { // WaitSync returns whether the consensus reactor is waiting for state/block sync. func (conR *Reactor) WaitSync() bool { - conR.mtx.RLock() - defer conR.mtx.RUnlock() - return conR.waitSync + return conR.waitSync.Load() } -//-------------------------------------- +// -------------------------------------- // subscribeToBroadcastEvents subscribes for new round steps and votes // using internal pubsub defined on state to broadcast @@ -409,23 +422,29 @@ func (conR *Reactor) subscribeToBroadcastEvents() { func(data cmtevents.EventData) { conR.broadcastNewRoundStepMessage(data.(*cstypes.RoundState)) }); err != nil { - conR.Logger.Error("Error adding listener for events", "err", err) + conR.Logger.Error("Error adding listener for events (NewRoundStep)", "err", err) } if err := conR.conS.evsw.AddListenerForEvent(subscriber, types.EventValidBlock, func(data cmtevents.EventData) { conR.broadcastNewValidBlockMessage(data.(*cstypes.RoundState)) }); err != nil { - conR.Logger.Error("Error adding listener for events", "err", err) + conR.Logger.Error("Error adding listener for events (ValidBlock)", "err", err) } if err := conR.conS.evsw.AddListenerForEvent(subscriber, types.EventVote, func(data cmtevents.EventData) { conR.broadcastHasVoteMessage(data.(*types.Vote)) }); err != nil { - conR.Logger.Error("Error adding listener for events", "err", err) + conR.Logger.Error("Error adding listener for events (Vote)", "err", err) } + if err := conR.conS.evsw.AddListenerForEvent(subscriber, types.EventProposalBlockPart, + func(data cmtevents.EventData) { + conR.broadcastHasProposalBlockPartMessage(data.(*BlockPartMessage)) + }); err != nil { + conR.Logger.Error("Error adding listener for events (ProposalBlockPart)", "err", err) + } } func (conR *Reactor) unsubscribeFromBroadcastEvents() { @@ -470,7 +489,7 @@ func (conR *Reactor) broadcastHasVoteMessage(vote *types.Vote) { }) /* // TODO: Make this broadcast more selective. - for _, peer := range conR.Switch.Peers().List() { + for _, peer := range conR.Switch.Peers().Copy() { ps, ok := peer.Get(PeerStateKey).(*PeerState) if !ok { panic(fmt.Sprintf("Peer %v has no state", peer)) @@ -492,15 +511,28 @@ func (conR *Reactor) broadcastHasVoteMessage(vote *types.Vote) { */ } +// Broadcasts HasProposalBlockPartMessage to peers that care. +func (conR *Reactor) broadcastHasProposalBlockPartMessage(partMsg *BlockPartMessage) { + msg := &cmtcons.HasProposalBlockPart{ + Height: partMsg.Height, + Round: partMsg.Round, + Index: int32(partMsg.Part.Index), + } + conR.Switch.Broadcast(p2p.Envelope{ + ChannelID: StateChannel, + Message: msg, + }) +} + func makeRoundStepMessage(rs *cstypes.RoundState) (nrsMsg *cmtcons.NewRoundStep) { nrsMsg = &cmtcons.NewRoundStep{ Height: rs.Height, Round: rs.Round, Step: uint32(rs.Step), - SecondsSinceStartTime: int64(time.Since(rs.StartTime).Seconds()), + SecondsSinceStartTime: int64(cmttime.Since(rs.StartTime).Seconds()), LastCommitRound: rs.LastCommit.GetRound(), } - return + return nrsMsg } func (conR *Reactor) sendNewRoundStepMessage(peer p2p.Peer) { @@ -520,15 +552,15 @@ func (conR *Reactor) updateRoundStateRoutine() { return } rs := conR.conS.GetRoundState() - conR.mtx.Lock() + conR.rsMtx.Lock() conR.rs = rs - conR.mtx.Unlock() + conR.rsMtx.Unlock() } } func (conR *Reactor) getRoundState() *cstypes.RoundState { - conR.mtx.RLock() - defer conR.mtx.RUnlock() + conR.rsMtx.Lock() + defer conR.rsMtx.Unlock() return conR.rs } @@ -541,6 +573,15 @@ OUTER_LOOP: if !peer.IsRunning() || !conR.IsRunning() { return } + + // sleep random amount to give reactor a chance to receive HasProposalBlockPart messages + // so we can reduce the amount of redundant block parts we send + if conR.conS.config.PeerGossipIntraloopSleepDuration > 0 { + // the config sets an upper bound for how long we sleep. + randDuration := cmtrand.Int63n(int64(conR.conS.config.PeerGossipIntraloopSleepDuration)) + time.Sleep(time.Duration(randDuration)) + } + rs := conR.getRoundState() prs := ps.GetRoundState() @@ -572,7 +613,7 @@ OUTER_LOOP: if blockStoreBase > 0 && 0 < prs.Height && prs.Height < rs.Height && prs.Height >= blockStoreBase { heightLogger := logger.With("height", prs.Height) - // if we never received the commit message from the peer, the block parts wont be initialized + // if we never received the commit message from the peer, the block parts won't be initialized if prs.ProposalBlockParts == nil { blockMeta := conR.conS.blockStore.LoadBlockMeta(prs.Height) if blockMeta == nil { @@ -640,8 +681,8 @@ OUTER_LOOP: } func (conR *Reactor) gossipDataForCatchup(logger log.Logger, rs *cstypes.RoundState, - prs *cstypes.PeerRoundState, ps *PeerState, peer p2p.Peer) { - + prs *cstypes.PeerRoundState, ps *PeerState, peer p2p.Peer, +) { if index, ok := prs.ProposalBlockParts.Not().PickRandom(); ok { // Ensure that the peer's PartSetHeader is correct blockMeta := conR.conS.blockStore.LoadBlockMeta(prs.Height) @@ -691,11 +732,66 @@ func (conR *Reactor) gossipDataForCatchup(logger log.Logger, rs *cstypes.RoundSt time.Sleep(conR.conS.config.PeerGossipSleepDuration) } +func pickVoteToSend( + logger log.Logger, + conS *State, + rs *cstypes.RoundState, + ps *PeerState, + prs *cstypes.PeerRoundState, +) *types.Vote { + // If height matches, then send LastCommit, Prevotes, Precommits. + if rs.Height == prs.Height { + heightLogger := logger.With("height", prs.Height) + return pickVoteCurrentHeight(heightLogger, rs, prs, ps) + } + + // Special catchup logic. + // If peer is lagging by height 1, send LastCommit. + if prs.Height != 0 && rs.Height == prs.Height+1 { + if vote := ps.PickVoteToSend(rs.LastCommit); vote != nil { + logger.Debug("Picked rs.LastCommit to send", "height", prs.Height) + return vote + } + } + + // Catchup logic + // If peer is lagging by more than 1, send Commit. + blockStoreBase := conS.blockStore.Base() + if blockStoreBase > 0 && prs.Height != 0 && rs.Height >= prs.Height+2 && prs.Height >= blockStoreBase { + // Load the block's extended commit for prs.Height, + // which contains precommit signatures for prs.Height. + var ec *types.ExtendedCommit + var veEnabled bool + func() { + conS.mtx.RLock() + defer conS.mtx.RUnlock() + veEnabled = conS.state.ConsensusParams.Feature.VoteExtensionsEnabled(prs.Height) + }() + if veEnabled { + ec = conS.blockStore.LoadBlockExtendedCommit(prs.Height) + } else { + c := conS.blockStore.LoadBlockCommit(prs.Height) + if c == nil { + return nil + } + ec = c.WrappedExtendedCommit() + } + if ec == nil { + return nil + } + if vote := ps.PickVoteToSend(ec); vote != nil { + logger.Debug("Picked Catchup commit to send", "height", prs.Height) + return vote + } + } + return nil +} + func (conR *Reactor) gossipVotesRoutine(peer p2p.Peer, ps *PeerState) { logger := conR.Logger.With("peer", peer) // Simple hack to throttle logs upon sleep. - var sleeping = 0 + sleeping := 0 OUTER_LOOP: for { @@ -703,6 +799,15 @@ OUTER_LOOP: if !peer.IsRunning() || !conR.IsRunning() { return } + + // sleep random amount to give reactor a chance to receive HasVote messages + // so we can reduce the amount of redundant votes we send + if conR.conS.config.PeerGossipIntraloopSleepDuration > 0 { + // the config sets an upper bound for how long we sleep. + randDuration := cmtrand.Int63n(int64(conR.conS.config.PeerGossipIntraloopSleepDuration)) + time.Sleep(time.Duration(randDuration)) + } + rs := conR.getRoundState() prs := ps.GetRoundState() @@ -716,42 +821,14 @@ OUTER_LOOP: // logger.Debug("gossipVotesRoutine", "rsHeight", rs.Height, "rsRound", rs.Round, // "prsHeight", prs.Height, "prsRound", prs.Round, "prsStep", prs.Step) - // If height matches, then send LastCommit, Prevotes, Precommits. - if rs.Height == prs.Height { - heightLogger := logger.With("height", prs.Height) - if conR.gossipVotesForHeight(heightLogger, rs, prs, ps) { - continue OUTER_LOOP - } - } - - // Special catchup logic. - // If peer is lagging by height 1, send LastCommit. - if prs.Height != 0 && rs.Height == prs.Height+1 { - if ps.PickSendVote(rs.LastCommit) { - logger.Debug("Picked rs.LastCommit to send", "height", prs.Height) - continue OUTER_LOOP - } - } - - // Catchup logic - // If peer is lagging by more than 1, send Commit. - blockStoreBase := conR.conS.blockStore.Base() - if blockStoreBase > 0 && prs.Height != 0 && rs.Height >= prs.Height+2 && prs.Height >= blockStoreBase { - // Load the block's extended commit for prs.Height, - // which contains precommit signatures for prs.Height. - var ec *types.ExtendedCommit - if conR.conS.state.ConsensusParams.ABCI.VoteExtensionsEnabled(prs.Height) { - ec = conR.conS.blockStore.LoadBlockExtendedCommit(prs.Height) - } else { - ec = conR.conS.blockStore.LoadBlockCommit(prs.Height).WrappedExtendedCommit() - } - if ec == nil { - continue - } - if ps.PickSendVote(ec) { - logger.Debug("Picked Catchup commit to send", "height", prs.Height) + if vote := pickVoteToSend(logger, conR.conS, rs, ps, prs); vote != nil { + if ps.sendVoteSetHasVote(vote) { continue OUTER_LOOP } + logger.Debug("Failed to send vote to peer", + "height", prs.Height, + "vote", vote, + ) } if sleeping == 0 { @@ -766,73 +843,70 @@ OUTER_LOOP: } time.Sleep(conR.conS.config.PeerGossipSleepDuration) - continue OUTER_LOOP } } -func (conR *Reactor) gossipVotesForHeight( +func pickVoteCurrentHeight( logger log.Logger, rs *cstypes.RoundState, prs *cstypes.PeerRoundState, ps *PeerState, -) bool { - +) *types.Vote { // If there are lastCommits to send... if prs.Step == cstypes.RoundStepNewHeight { - if ps.PickSendVote(rs.LastCommit) { + if vote := ps.PickVoteToSend(rs.LastCommit); vote != nil { logger.Debug("Picked rs.LastCommit to send") - return true + return vote } } // If there are POL prevotes to send... if prs.Step <= cstypes.RoundStepPropose && prs.Round != -1 && prs.Round <= rs.Round && prs.ProposalPOLRound != -1 { if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil { - if ps.PickSendVote(polPrevotes) { + if vote := ps.PickVoteToSend(polPrevotes); vote != nil { logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send", "round", prs.ProposalPOLRound) - return true + return vote } } } // If there are prevotes to send... if prs.Step <= cstypes.RoundStepPrevoteWait && prs.Round != -1 && prs.Round <= rs.Round { - if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) { + if vote := ps.PickVoteToSend(rs.Votes.Prevotes(prs.Round)); vote != nil { logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round) - return true + return vote } } // If there are precommits to send... if prs.Step <= cstypes.RoundStepPrecommitWait && prs.Round != -1 && prs.Round <= rs.Round { - if ps.PickSendVote(rs.Votes.Precommits(prs.Round)) { + if vote := ps.PickVoteToSend(rs.Votes.Precommits(prs.Round)); vote != nil { logger.Debug("Picked rs.Precommits(prs.Round) to send", "round", prs.Round) - return true + return vote } } // If there are prevotes to send...Needed because of validBlock mechanism if prs.Round != -1 && prs.Round <= rs.Round { - if ps.PickSendVote(rs.Votes.Prevotes(prs.Round)) { + if vote := ps.PickVoteToSend(rs.Votes.Prevotes(prs.Round)); vote != nil { logger.Debug("Picked rs.Prevotes(prs.Round) to send", "round", prs.Round) - return true + return vote } } // If there are POLPrevotes to send... if prs.ProposalPOLRound != -1 { if polPrevotes := rs.Votes.Prevotes(prs.ProposalPOLRound); polPrevotes != nil { - if ps.PickSendVote(polPrevotes) { + if vote := ps.PickVoteToSend(polPrevotes); vote != nil { logger.Debug("Picked rs.Prevotes(prs.ProposalPOLRound) to send", "round", prs.ProposalPOLRound) - return true + return vote } } } - return false + return nil } // NOTE: `queryMaj23Routine` has a simple crude design since it only comes // into play for liveness when there's a signature DDoS attack happening. func (conR *Reactor) queryMaj23Routine(peer p2p.Peer, ps *PeerState) { - OUTER_LOOP: for { // Manage disconnects from self or peer. @@ -846,13 +920,12 @@ OUTER_LOOP: prs := ps.GetRoundState() if rs.Height == prs.Height { if maj23, ok := rs.Votes.Prevotes(prs.Round).TwoThirdsMajority(); ok { - peer.TrySend(p2p.Envelope{ ChannelID: StateChannel, Message: &cmtcons.VoteSetMaj23{ Height: prs.Height, Round: prs.Round, - Type: cmtproto.PrevoteType, + Type: types.PrevoteType, BlockID: maj23.ToProto(), }, }) @@ -872,7 +945,7 @@ OUTER_LOOP: Message: &cmtcons.VoteSetMaj23{ Height: prs.Height, Round: prs.Round, - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, BlockID: maj23.ToProto(), }, }) @@ -887,13 +960,12 @@ OUTER_LOOP: prs := ps.GetRoundState() if rs.Height == prs.Height && prs.ProposalPOLRound >= 0 { if maj23, ok := rs.Votes.Prevotes(prs.ProposalPOLRound).TwoThirdsMajority(); ok { - peer.TrySend(p2p.Envelope{ ChannelID: StateChannel, Message: &cmtcons.VoteSetMaj23{ Height: prs.Height, Round: prs.ProposalPOLRound, - Type: cmtproto.PrevoteType, + Type: types.PrevoteType, BlockID: maj23.ToProto(), }, }) @@ -916,7 +988,7 @@ OUTER_LOOP: Message: &cmtcons.VoteSetMaj23{ Height: prs.Height, Round: commit.Round, - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, BlockID: commit.BlockID.ToProto(), }, }) @@ -974,37 +1046,32 @@ func (conR *Reactor) peerStatsRoutine() { // String returns a string representation of the Reactor. // NOTE: For now, it is just a hard-coded string to avoid accessing unprotected shared variables. // TODO: improve! -func (conR *Reactor) String() string { +func (*Reactor) String() string { // better not to access shared variables return "ConsensusReactor" // conR.StringIndented("") } -// StringIndented returns an indented string representation of the Reactor +// StringIndented returns an indented string representation of the Reactor. func (conR *Reactor) StringIndented(indent string) string { s := "ConsensusReactor{\n" s += indent + " " + conR.conS.StringIndented(indent+" ") + "\n" - for _, peer := range conR.Switch.Peers().List() { + conR.Switch.Peers().ForEach(func(peer p2p.Peer) { ps, ok := peer.Get(types.PeerStateKey).(*PeerState) if !ok { panic(fmt.Sprintf("Peer %v has no state", peer)) } s += indent + " " + ps.StringIndented(indent+" ") + "\n" - } + }) s += indent + "}" return s } -// ReactorMetrics sets the metrics +// ReactorMetrics sets the metrics. func ReactorMetrics(metrics *Metrics) ReactorOption { return func(conR *Reactor) { conR.Metrics = metrics } } -//----------------------------------------------------------------------------- - -var ( - ErrPeerStateHeightRegression = errors.New("error peer state height regression") - ErrPeerStateInvalidStartTime = errors.New("error peer state invalid startTime") -) +// ----------------------------------------------------------------------------- // PeerState contains the known state of a peer, including its connection and // threadsafe access to its PeerRoundState. @@ -1030,7 +1097,7 @@ func (pss peerStateStats) String() string { pss.Votes, pss.BlockParts) } -// NewPeerState returns a new PeerState for the given Peer +// NewPeerState returns a new PeerState for the given Peer. func NewPeerState(peer p2p.Peer) *PeerState { return &PeerState{ peer: peer, @@ -1067,11 +1134,12 @@ func (ps *PeerState) MarshalJSON() ([]byte, error) { ps.mtx.Lock() defer ps.mtx.Unlock() - return cmtjson.Marshal(ps) + type jsonPeerState PeerState + return cmtjson.Marshal((*jsonPeerState)(ps)) } // GetHeight returns an atomic snapshot of the PeerRoundState's height -// used by the mempool to ensure peers are caught up before broadcasting new txs +// used by the mempool to ensure peers are caught up before broadcasting new txs. func (ps *PeerState) GetHeight() int64 { ps.mtx.Lock() defer ps.mtx.Unlock() @@ -1122,6 +1190,17 @@ func (ps *PeerState) SetHasProposalBlockPart(height int64, round int32, index in ps.mtx.Lock() defer ps.mtx.Unlock() + ps.setHasProposalBlockPart(height, round, index) +} + +func (ps *PeerState) setHasProposalBlockPart(height int64, round int32, index int) { + ps.logger.Debug("setHasProposalBlockPart", + "peerH/R", + log.NewLazySprintf("%d/%d", ps.PRS.Height, ps.PRS.Round), + "H/R", + log.NewLazySprintf("%d/%d", height, round), + "index", index) + if ps.PRS.Height != height || ps.PRS.Round != round { return } @@ -1129,21 +1208,18 @@ func (ps *PeerState) SetHasProposalBlockPart(height int64, round int32, index in ps.PRS.ProposalBlockParts.SetIndex(index, true) } -// PickSendVote picks a vote and sends it to the peer. -// Returns true if vote was sent. -func (ps *PeerState) PickSendVote(votes types.VoteSetReader) bool { - if vote, ok := ps.PickVoteToSend(votes); ok { - ps.logger.Debug("Sending vote message", "ps", ps, "vote", vote) - if ps.peer.Send(p2p.Envelope{ - ChannelID: VoteChannel, - Message: &cmtcons.Vote{ - Vote: vote.ToProto(), - }, - }) { - ps.SetHasVote(vote) - return true - } - return false +// sendVoteSetHasVote sends the vote to the peer. +// Returns true and marks the peer as having the vote if the vote was sent. +func (ps *PeerState) sendVoteSetHasVote(vote *types.Vote) bool { + ps.logger.Debug("Sending vote message", "ps", ps, "vote", vote) + if ps.peer.Send(p2p.Envelope{ + ChannelID: VoteChannel, + Message: &cmtcons.Vote{ + Vote: vote.ToProto(), + }, + }) { + ps.SetHasVote(vote) + return true } return false } @@ -1151,16 +1227,15 @@ func (ps *PeerState) PickSendVote(votes types.VoteSetReader) bool { // PickVoteToSend picks a vote to send to the peer. // Returns true if a vote was picked. // NOTE: `votes` must be the correct Size() for the Height(). -func (ps *PeerState) PickVoteToSend(votes types.VoteSetReader) (vote *types.Vote, ok bool) { +func (ps *PeerState) PickVoteToSend(votes types.VoteSetReader) *types.Vote { ps.mtx.Lock() defer ps.mtx.Unlock() if votes.Size() == 0 { - return nil, false + return nil } - height, round, votesType, size := - votes.GetHeight(), votes.GetRound(), cmtproto.SignedMsgType(votes.Type()), votes.Size() + height, round, votesType, size := votes.GetHeight(), votes.GetRound(), types.SignedMsgType(votes.Type()), votes.Size() // Lazily set data using 'votes'. if votes.IsCommit() { @@ -1170,15 +1245,19 @@ func (ps *PeerState) PickVoteToSend(votes types.VoteSetReader) (vote *types.Vote psVotes := ps.getVoteBitArray(height, round, votesType) if psVotes == nil { - return nil, false // Not something worth sending + return nil // Not something worth sending } if index, ok := votes.BitArray().Sub(psVotes).PickRandom(); ok { - return votes.GetByIndex(int32(index)), true + vote := votes.GetByIndex(int32(index)) + if vote == nil { + ps.logger.Error("votes.GetByIndex returned nil", "votes", votes, "index", index) + } + return vote } - return nil, false + return nil } -func (ps *PeerState) getVoteBitArray(height int64, round int32, votesType cmtproto.SignedMsgType) *bits.BitArray { +func (ps *PeerState) getVoteBitArray(height int64, round int32, votesType types.SignedMsgType) *bits.BitArray { if !types.IsVoteTypeValid(votesType) { return nil } @@ -1186,25 +1265,25 @@ func (ps *PeerState) getVoteBitArray(height int64, round int32, votesType cmtpro if ps.PRS.Height == height { if ps.PRS.Round == round { switch votesType { - case cmtproto.PrevoteType: + case types.PrevoteType: return ps.PRS.Prevotes - case cmtproto.PrecommitType: + case types.PrecommitType: return ps.PRS.Precommits } } if ps.PRS.CatchupCommitRound == round { switch votesType { - case cmtproto.PrevoteType: + case types.PrevoteType: return nil - case cmtproto.PrecommitType: + case types.PrecommitType: return ps.PRS.CatchupCommit } } if ps.PRS.ProposalPOLRound == round { switch votesType { - case cmtproto.PrevoteType: + case types.PrevoteType: return ps.PRS.ProposalPOL - case cmtproto.PrecommitType: + case types.PrecommitType: return nil } } @@ -1213,9 +1292,9 @@ func (ps *PeerState) getVoteBitArray(height int64, round int32, votesType cmtpro if ps.PRS.Height == height+1 { if ps.PRS.LastCommitRound == round { switch votesType { - case cmtproto.PrevoteType: + case types.PrevoteType: return nil - case cmtproto.PrecommitType: + case types.PrecommitType: return ps.PRS.LastCommit } } @@ -1322,7 +1401,7 @@ func (ps *PeerState) BlockPartsSent() int { return ps.Stats.BlockParts } -// SetHasVote sets the given vote as known by the peer +// SetHasVote sets the given vote as known by the peer. func (ps *PeerState) SetHasVote(vote *types.Vote) { ps.mtx.Lock() defer ps.mtx.Unlock() @@ -1330,7 +1409,7 @@ func (ps *PeerState) SetHasVote(vote *types.Vote) { ps.setHasVote(vote.Height, vote.Round, vote.Type, vote.ValidatorIndex) } -func (ps *PeerState) setHasVote(height int64, round int32, voteType cmtproto.SignedMsgType, index int32) { +func (ps *PeerState) setHasVote(height int64, round int32, voteType types.SignedMsgType, index int32) { ps.logger.Debug("setHasVote", "peerH/R", log.NewLazySprintf("%d/%d", ps.PRS.Height, ps.PRS.Round), @@ -1445,6 +1524,18 @@ func (ps *PeerState) ApplyHasVoteMessage(msg *HasVoteMessage) { ps.setHasVote(msg.Height, msg.Round, msg.Type, msg.Index) } +// ApplyHasProposalBlockPartMessage updates the peer state for the new block part. +func (ps *PeerState) ApplyHasProposalBlockPartMessage(msg *HasProposalBlockPartMessage) { + ps.mtx.Lock() + defer ps.mtx.Unlock() + + if ps.PRS.Height != msg.Height { + return + } + + ps.setHasProposalBlockPart(msg.Height, msg.Round, int(msg.Index)) +} + // ApplyVoteSetBitsMessage updates the peer state for the bit-array of votes // it claims to have for the corresponding BlockID. // `ourVotes` is a BitArray of votes we have for msg.BlockID @@ -1466,12 +1557,12 @@ func (ps *PeerState) ApplyVoteSetBitsMessage(msg *VoteSetBitsMessage, ourVotes * } } -// String returns a string representation of the PeerState +// String returns a string representation of the PeerState. func (ps *PeerState) String() string { return ps.StringIndented("") } -// StringIndented returns a string representation of the PeerState +// StringIndented returns a string representation of the PeerState. func (ps *PeerState) StringIndented(indent string) string { ps.mtx.Lock() defer ps.mtx.Unlock() @@ -1486,10 +1577,10 @@ func (ps *PeerState) StringIndented(indent string) string { indent) } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Messages -// Message is a message that can be sent and received on the Reactor +// Message is a message that can be sent and received on the Reactor. type Message interface { ValidateBasic() error } @@ -1502,14 +1593,15 @@ func init() { cmtjson.RegisterType(&BlockPartMessage{}, "tendermint/BlockPart") cmtjson.RegisterType(&VoteMessage{}, "tendermint/Vote") cmtjson.RegisterType(&HasVoteMessage{}, "tendermint/HasVote") + cmtjson.RegisterType(&HasProposalBlockPartMessage{}, "tendermint/HasProposalBlockPart") cmtjson.RegisterType(&VoteSetMaj23Message{}, "tendermint/VoteSetMaj23") cmtjson.RegisterType(&VoteSetBitsMessage{}, "tendermint/VoteSetBits") } -//------------------------------------- +// ------------------------------------- // NewRoundStepMessage is sent for every step taken in the ConsensusState. -// For every height/round/step transition +// For every height/round/step transition. type NewRoundStepMessage struct { Height int64 Round int32 @@ -1521,13 +1613,13 @@ type NewRoundStepMessage struct { // ValidateBasic performs basic validation. func (m *NewRoundStepMessage) ValidateBasic() error { if m.Height < 0 { - return errors.New("negative Height") + return cmterrors.ErrNegativeField{Field: "Height"} } if m.Round < 0 { - return errors.New("negative Round") + return cmterrors.ErrNegativeField{Field: "Round"} } if !m.Step.IsValid() { - return errors.New("invalid Step") + return cmterrors.ErrInvalidField{Field: "Step"} } // NOTE: SecondsSinceStartTime may be negative @@ -1536,7 +1628,7 @@ func (m *NewRoundStepMessage) ValidateBasic() error { // since it can be specified in genesis. The reactor will have to validate this via // ValidateHeight(). if m.LastCommitRound < -1 { - return errors.New("invalid LastCommitRound (cannot be < -1)") + return cmterrors.ErrInvalidField{Field: "LastCommitRound", Reason: "cannot be < -1"} } return nil @@ -1545,16 +1637,24 @@ func (m *NewRoundStepMessage) ValidateBasic() error { // ValidateHeight validates the height given the chain's initial height. func (m *NewRoundStepMessage) ValidateHeight(initialHeight int64) error { if m.Height < initialHeight { - return fmt.Errorf("invalid Height %v (lower than initial height %v)", - m.Height, initialHeight) + return cmterrors.ErrInvalidField{ + Field: "Height", + Reason: fmt.Sprintf("%v should be lower than initial height %v", m.Height, initialHeight), + } } + if m.Height == initialHeight && m.LastCommitRound != -1 { - return fmt.Errorf("invalid LastCommitRound %v (must be -1 for initial height %v)", - m.LastCommitRound, initialHeight) + return cmterrors.ErrInvalidField{ + Field: "LastCommitRound", + Reason: fmt.Sprintf("%v must be -1 for initial height %v", m.LastCommitRound, initialHeight), + } } + if m.Height > initialHeight && m.LastCommitRound < 0 { - return fmt.Errorf("LastCommitRound can only be negative for initial height %v", - initialHeight) + return cmterrors.ErrInvalidField{ + Field: "LastCommitRound", + Reason: fmt.Sprintf("can only be negative for initial height %v", initialHeight), + } } return nil } @@ -1565,7 +1665,7 @@ func (m *NewRoundStepMessage) String() string { m.Height, m.Round, m.Step, m.LastCommitRound) } -//------------------------------------- +// ------------------------------------- // NewValidBlockMessage is sent when a validator observes a valid block B in some round r, // i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. @@ -1581,16 +1681,16 @@ type NewValidBlockMessage struct { // ValidateBasic performs basic validation. func (m *NewValidBlockMessage) ValidateBasic() error { if m.Height < 0 { - return errors.New("negative Height") + return cmterrors.ErrNegativeField{Field: "Height"} } if m.Round < 0 { - return errors.New("negative Round") + return cmterrors.ErrNegativeField{Field: "Round"} } if err := m.BlockPartSetHeader.ValidateBasic(); err != nil { - return fmt.Errorf("wrong BlockPartSetHeader: %v", err) + return cmterrors.ErrWrongField{Field: "BlockPartSetHeader", Err: err} } if m.BlockParts.Size() == 0 { - return errors.New("empty blockParts") + return cmterrors.ErrRequiredField{Field: "blockParts"} } if m.BlockParts.Size() != int(m.BlockPartSetHeader.Total) { return fmt.Errorf("blockParts bit array size %d not equal to BlockPartSetHeader.Total %d", @@ -1609,7 +1709,7 @@ func (m *NewValidBlockMessage) String() string { m.Height, m.Round, m.BlockPartSetHeader, m.BlockParts, m.IsCommit) } -//------------------------------------- +// ------------------------------------- // ProposalMessage is sent when a new block is proposed. type ProposalMessage struct { @@ -1626,7 +1726,7 @@ func (m *ProposalMessage) String() string { return fmt.Sprintf("[Proposal %v]", m.Proposal) } -//------------------------------------- +// ------------------------------------- // ProposalPOLMessage is sent when a previous proposal is re-proposed. type ProposalPOLMessage struct { @@ -1638,13 +1738,13 @@ type ProposalPOLMessage struct { // ValidateBasic performs basic validation. func (m *ProposalPOLMessage) ValidateBasic() error { if m.Height < 0 { - return errors.New("negative Height") + return cmterrors.ErrNegativeField{Field: "Height"} } if m.ProposalPOLRound < 0 { - return errors.New("negative ProposalPOLRound") + return cmterrors.ErrNegativeField{Field: "ProposalPOLRound"} } if m.ProposalPOL.Size() == 0 { - return errors.New("empty ProposalPOL bit array") + return cmterrors.ErrRequiredField{Field: "ProposalPOL"} } if m.ProposalPOL.Size() > types.MaxVotesCount { return fmt.Errorf("proposalPOL bit array is too big: %d, max: %d", m.ProposalPOL.Size(), types.MaxVotesCount) @@ -1657,7 +1757,7 @@ func (m *ProposalPOLMessage) String() string { return fmt.Sprintf("[ProposalPOL H:%v POLR:%v POL:%v]", m.Height, m.ProposalPOLRound, m.ProposalPOL) } -//------------------------------------- +// ------------------------------------- // BlockPartMessage is sent when gossipping a piece of the proposed block. type BlockPartMessage struct { @@ -1669,13 +1769,13 @@ type BlockPartMessage struct { // ValidateBasic performs basic validation. func (m *BlockPartMessage) ValidateBasic() error { if m.Height < 0 { - return errors.New("negative Height") + return cmterrors.ErrNegativeField{Field: "Height"} } if m.Round < 0 { - return errors.New("negative Round") + return cmterrors.ErrNegativeField{Field: "Round"} } if err := m.Part.ValidateBasic(); err != nil { - return fmt.Errorf("wrong Part: %v", err) + return cmterrors.ErrWrongField{Field: "Part", Err: err} } return nil } @@ -1685,7 +1785,7 @@ func (m *BlockPartMessage) String() string { return fmt.Sprintf("[BlockPart H:%v R:%v P:%v]", m.Height, m.Round, m.Part) } -//------------------------------------- +// ------------------------------------- // VoteMessage is sent when voting for a proposal (or lack thereof). type VoteMessage struct { @@ -1702,29 +1802,29 @@ func (m *VoteMessage) String() string { return fmt.Sprintf("[Vote %v]", m.Vote) } -//------------------------------------- +// ------------------------------------- // HasVoteMessage is sent to indicate that a particular vote has been received. type HasVoteMessage struct { Height int64 Round int32 - Type cmtproto.SignedMsgType + Type types.SignedMsgType Index int32 } // ValidateBasic performs basic validation. func (m *HasVoteMessage) ValidateBasic() error { if m.Height < 0 { - return errors.New("negative Height") + return cmterrors.ErrNegativeField{Field: "Height"} } if m.Round < 0 { - return errors.New("negative Round") + return cmterrors.ErrNegativeField{Field: "Round"} } if !types.IsVoteTypeValid(m.Type) { - return errors.New("invalid Type") + return cmterrors.ErrInvalidField{Field: "Type"} } if m.Index < 0 { - return errors.New("negative Index") + return cmterrors.ErrNegativeField{Field: "Index"} } return nil } @@ -1734,29 +1834,29 @@ func (m *HasVoteMessage) String() string { return fmt.Sprintf("[HasVote VI:%v V:{%v/%02d/%v}]", m.Index, m.Height, m.Round, m.Type) } -//------------------------------------- +// ------------------------------------- // VoteSetMaj23Message is sent to indicate that a given BlockID has seen +2/3 votes. type VoteSetMaj23Message struct { Height int64 Round int32 - Type cmtproto.SignedMsgType + Type types.SignedMsgType BlockID types.BlockID } // ValidateBasic performs basic validation. func (m *VoteSetMaj23Message) ValidateBasic() error { if m.Height < 0 { - return errors.New("negative Height") + return cmterrors.ErrNegativeField{Field: "Height"} } if m.Round < 0 { - return errors.New("negative Round") + return cmterrors.ErrNegativeField{Field: "Round"} } if !types.IsVoteTypeValid(m.Type) { - return errors.New("invalid Type") + return cmterrors.ErrInvalidField{Field: "Type"} } if err := m.BlockID.ValidateBasic(); err != nil { - return fmt.Errorf("wrong BlockID: %v", err) + return cmterrors.ErrWrongField{Field: "BlockID", Err: err} } return nil } @@ -1766,13 +1866,13 @@ func (m *VoteSetMaj23Message) String() string { return fmt.Sprintf("[VSM23 %v/%02d/%v %v]", m.Height, m.Round, m.Type, m.BlockID) } -//------------------------------------- +// ------------------------------------- // VoteSetBitsMessage is sent to communicate the bit-array of votes seen for the BlockID. type VoteSetBitsMessage struct { Height int64 Round int32 - Type cmtproto.SignedMsgType + Type types.SignedMsgType BlockID types.BlockID Votes *bits.BitArray } @@ -1780,13 +1880,13 @@ type VoteSetBitsMessage struct { // ValidateBasic performs basic validation. func (m *VoteSetBitsMessage) ValidateBasic() error { if m.Height < 0 { - return errors.New("negative Height") + return cmterrors.ErrNegativeField{Field: "Height"} } if !types.IsVoteTypeValid(m.Type) { - return errors.New("invalid Type") + return cmterrors.ErrInvalidField{Field: "Type"} } if err := m.BlockID.ValidateBasic(); err != nil { - return fmt.Errorf("wrong BlockID: %v", err) + return cmterrors.ErrWrongField{Field: "BlockID", Err: err} } // NOTE: Votes.Size() can be zero if the node does not have any if m.Votes.Size() > types.MaxVotesCount { @@ -1800,4 +1900,42 @@ func (m *VoteSetBitsMessage) String() string { return fmt.Sprintf("[VSB %v/%02d/%v %v %v]", m.Height, m.Round, m.Type, m.BlockID, m.Votes) } -//------------------------------------- +// ------------------------------------- + +// HasProposalBlockPartMessage is sent to indicate that a particular block part has been received. +type HasProposalBlockPartMessage struct { + Height int64 + Round int32 + Index int32 +} + +// ValidateBasic performs basic validation. +func (m *HasProposalBlockPartMessage) ValidateBasic() error { + if m.Height < 1 { + return cmterrors.ErrInvalidField{Field: "Height", Reason: "( < 1 )"} + } + if m.Round < 0 { + return cmterrors.ErrNegativeField{Field: "Round"} + } + if m.Index < 0 { + return cmterrors.ErrNegativeField{Field: "Index"} + } + return nil +} + +// String returns a string representation. +func (m *HasProposalBlockPartMessage) String() string { + return fmt.Sprintf("[HasProposalBlockPart PI:%v HR:{%v/%02d}]", m.Index, m.Height, m.Round) +} + +var ( + _ types.Wrapper = &cmtcons.BlockPart{} + _ types.Wrapper = &cmtcons.HasVote{} + _ types.Wrapper = &cmtcons.HasProposalBlockPart{} + _ types.Wrapper = &cmtcons.NewRoundStep{} + _ types.Wrapper = &cmtcons.NewValidBlock{} + _ types.Wrapper = &cmtcons.Proposal{} + _ types.Wrapper = &cmtcons.ProposalPOL{} + _ types.Wrapper = &cmtcons.VoteSetBits{} + _ types.Wrapper = &cmtcons.VoteSetMaj23{} +) diff --git a/consensus/reactor_test.go b/internal/consensus/reactor_test.go similarity index 82% rename from consensus/reactor_test.go rename to internal/consensus/reactor_test.go index bd68f4a6b5e..3a20bdd09f8 100644 --- a/consensus/reactor_test.go +++ b/internal/consensus/reactor_test.go @@ -14,31 +14,32 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abcicli "github.com/cometbft/cometbft/abci/client" "github.com/cometbft/cometbft/abci/example/kvstore" abci "github.com/cometbft/cometbft/abci/types" + cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1" cfg "github.com/cometbft/cometbft/config" - cstypes "github.com/cometbft/cometbft/consensus/types" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" "github.com/cometbft/cometbft/crypto/tmhash" - "github.com/cometbft/cometbft/libs/bits" + "github.com/cometbft/cometbft/internal/bits" + cstypes "github.com/cometbft/cometbft/internal/consensus/types" + sm "github.com/cometbft/cometbft/internal/state" + statemocks "github.com/cometbft/cometbft/internal/state/mocks" + "github.com/cometbft/cometbft/internal/store" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/bytes" + "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" - cmtsync "github.com/cometbft/cometbft/libs/sync" mempl "github.com/cometbft/cometbft/mempool" "github.com/cometbft/cometbft/p2p" p2pmock "github.com/cometbft/cometbft/p2p/mock" - cmtcons "github.com/cometbft/cometbft/proto/tendermint/consensus" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - statemocks "github.com/cometbft/cometbft/state/mocks" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" + cmttime "github.com/cometbft/cometbft/types/time" ) -//---------------------------------------------- +// ---------------------------------------------- // in-process testnets var defaultTestTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) @@ -48,12 +49,13 @@ func startConsensusNet(t *testing.T, css []*State, n int) ( []types.Subscription, []*types.EventBus, ) { + t.Helper() reactors := make([]*Reactor, n) blocksSubs := make([]types.Subscription, 0) eventBuses := make([]*types.EventBus, n) for i := 0; i < n; i++ { - /*logger, err := cmtflags.ParseLogLevel("consensus:info,*:error", logger, "info") - if err != nil { t.Fatal(err)}*/ + // logger, err := cmtflags.ParseLogLevel("consensus:info,*:error", logger, "info") + // if err != nil { t.Fatal(err)} reactors[i] = NewReactor(css[i], true) // so we dont start the consensus states reactors[i].SetLogger(css[i].Logger) @@ -106,20 +108,20 @@ func stopConsensusNet(logger log.Logger, reactors []*Reactor, eventBuses []*type logger.Info("stopConsensusNet: DONE", "n", len(reactors)) } -// Ensure a testnet makes blocks +// Ensure a testnet makes blocks. func TestReactorBasic(t *testing.T) { - N := 4 - css, cleanup := randConsensusNet(t, N, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) + n := 4 + css, cleanup := randConsensusNet(t, n, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) defer cleanup() - reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N) + reactors, blocksSubs, eventBuses := startConsensusNet(t, css, n) defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses) // wait till everyone makes the first new block - timeoutWaitGroup(t, N, func(j int) { + timeoutWaitGroup(n, func(j int) { <-blocksSubs[j].Out() - }, css) + }) } -// Ensure we can process blocks with evidence +// Ensure we can process blocks with evidence. func TestReactorWithEvidence(t *testing.T) { nValidators := 4 testName := "consensus_reactor_test" @@ -130,7 +132,7 @@ func TestReactorWithEvidence(t *testing.T) { // to unroll unwieldy abstractions. Here we duplicate the code from: // css := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) - genDoc, privVals := randGenesisDoc(nValidators, false, 30, nil) + genDoc, privVals := randGenesisDoc(nValidators, 30, nil, cmttime.Now()) css := make([]*State, nValidators) logger := consensusLogger() for i := 0; i < nValidators; i++ { @@ -141,10 +143,10 @@ func TestReactorWithEvidence(t *testing.T) { state, _ := stateStore.LoadFromDBOrGenesisDoc(genDoc) thisConfig := ResetConfig(fmt.Sprintf("%s_%d", testName, i)) defer os.RemoveAll(thisConfig.RootDir) - ensureDir(path.Dir(thisConfig.Consensus.WalFile()), 0o700) // dir for wal + ensureDir(path.Dir(thisConfig.Consensus.WalFile())) // dir for wal app := appFunc() vals := types.TM2PB.ValidatorUpdates(state.Validators) - _, err := app.InitChain(context.Background(), &abci.RequestInitChain{Validators: vals}) + _, err := app.InitChain(context.Background(), &abci.InitChainRequest{Validators: vals}) require.NoError(t, err) pv := privVals[i] @@ -209,45 +211,45 @@ func TestReactorWithEvidence(t *testing.T) { // we expect for each validator that is the proposer to propose one piece of evidence. for i := 0; i < nValidators; i++ { - timeoutWaitGroup(t, nValidators, func(j int) { + timeoutWaitGroup(nValidators, func(j int) { msg := <-blocksSubs[j].Out() block := msg.Data().(types.EventDataNewBlock).Block assert.Len(t, block.Evidence.Evidence, 1) - }, css) + }) } } -//------------------------------------ +// ------------------------------------ -// Ensure a testnet makes blocks when there are txs +// Ensure a testnet makes blocks when there are txs. func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) { - N := 4 - css, cleanup := randConsensusNet(t, N, "consensus_reactor_test", newMockTickerFunc(true), newKVStore, + n := 4 + css, cleanup := randConsensusNet(t, n, "consensus_reactor_test", newMockTickerFunc(true), newKVStore, func(c *cfg.Config) { c.Consensus.CreateEmptyBlocks = false }) defer cleanup() - reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N) + reactors, blocksSubs, eventBuses := startConsensusNet(t, css, n) defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses) // send a tx - if err := assertMempool(css[3].txNotifier).CheckTx(kvstore.NewTxFromID(1), func(resp *abci.ResponseCheckTx) { - require.False(t, resp.IsErr()) - }, mempl.TxInfo{}); err != nil { + reqRes, err := assertMempool(css[3].txNotifier).CheckTx(kvstore.NewTxFromID(1)) + if err != nil { t.Error(err) } + require.False(t, reqRes.Response.GetCheckTx().IsErr()) // wait till everyone makes the first new block - timeoutWaitGroup(t, N, func(j int) { + timeoutWaitGroup(n, func(j int) { <-blocksSubs[j].Out() - }, css) + }) } func TestReactorReceiveDoesNotPanicIfAddPeerHasntBeenCalledYet(t *testing.T) { - N := 1 - css, cleanup := randConsensusNet(t, N, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) + n := 1 + css, cleanup := randConsensusNet(t, n, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) defer cleanup() - reactors, _, eventBuses := startConsensusNet(t, css, N) + reactors, _, eventBuses := startConsensusNet(t, css, n) defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses) var ( @@ -266,7 +268,7 @@ func TestReactorReceiveDoesNotPanicIfAddPeerHasntBeenCalledYet(t *testing.T) { Height: 1, Round: 1, Index: 1, - Type: cmtproto.PrevoteType, + Type: types.PrevoteType, }, }) reactor.AddPeer(peer) @@ -274,10 +276,10 @@ func TestReactorReceiveDoesNotPanicIfAddPeerHasntBeenCalledYet(t *testing.T) { } func TestReactorReceivePanicsIfInitPeerHasntBeenCalledYet(t *testing.T) { - N := 1 - css, cleanup := randConsensusNet(t, N, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) + n := 1 + css, cleanup := randConsensusNet(t, n, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) defer cleanup() - reactors, _, eventBuses := startConsensusNet(t, css, N) + reactors, _, eventBuses := startConsensusNet(t, css, n) defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses) var ( @@ -296,7 +298,7 @@ func TestReactorReceivePanicsIfInitPeerHasntBeenCalledYet(t *testing.T) { Height: 1, Round: 1, Index: 1, - Type: cmtproto.PrevoteType, + Type: types.PrevoteType, }, }) }) @@ -358,7 +360,7 @@ func TestSwitchToConsensusVoteExtensions(t *testing.T) { cs.state.LastBlockHeight = testCase.storedHeight cs.state.LastValidators = cs.state.Validators.Copy() - cs.state.ConsensusParams.ABCI.VoteExtensionsEnableHeight = testCase.initialRequiredHeight + cs.state.ConsensusParams.Feature.VoteExtensionsEnableHeight = testCase.initialRequiredHeight propBlock, err := cs.createProposalBlock(ctx) require.NoError(t, err) @@ -371,11 +373,14 @@ func TestSwitchToConsensusVoteExtensions(t *testing.T) { var voteSet *types.VoteSet if testCase.includeExtensions { - voteSet = types.NewExtendedVoteSet(cs.state.ChainID, testCase.storedHeight, 0, cmtproto.PrecommitType, cs.state.Validators) + voteSet = types.NewExtendedVoteSet(cs.state.ChainID, testCase.storedHeight, 0, types.PrecommitType, cs.state.Validators) } else { - voteSet = types.NewVoteSet(cs.state.ChainID, testCase.storedHeight, 0, cmtproto.PrecommitType, cs.state.Validators) + voteSet = types.NewVoteSet(cs.state.ChainID, testCase.storedHeight, 0, types.PrecommitType, cs.state.Validators) } - signedVote := signVote(validator, cmtproto.PrecommitType, propBlock.Hash(), blockParts.Header(), testCase.includeExtensions) + signedVote := signVote(validator, types.PrecommitType, cs.state.ChainID, types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: blockParts.Header(), + }, testCase.includeExtensions) var veHeight int64 if testCase.includeExtensions { @@ -390,7 +395,8 @@ func TestSwitchToConsensusVoteExtensions(t *testing.T) { require.NoError(t, err) require.True(t, added) - veHeightParam := types.ABCIParams{VoteExtensionsEnableHeight: veHeight} + veHeightParam := types.DefaultFeatureParams() + veHeightParam.VoteExtensionsEnableHeight = veHeight if testCase.includeExtensions { cs.blockStore.SaveBlockWithExtendedCommit(propBlock, blockParts, voteSet.MakeExtendedCommit(veHeightParam)) } else { @@ -414,27 +420,27 @@ func TestSwitchToConsensusVoteExtensions(t *testing.T) { // Test we record stats about votes and block parts from other peers. func TestReactorRecordsVotesAndBlockParts(t *testing.T) { - N := 4 - css, cleanup := randConsensusNet(t, N, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) + n := 4 + css, cleanup := randConsensusNet(t, n, "consensus_reactor_test", newMockTickerFunc(true), newKVStore) defer cleanup() - reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N) + reactors, blocksSubs, eventBuses := startConsensusNet(t, css, n) defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses) // wait till everyone makes the first new block - timeoutWaitGroup(t, N, func(j int) { + timeoutWaitGroup(n, func(j int) { <-blocksSubs[j].Out() - }, css) + }) // Get peer - peer := reactors[1].Switch.Peers().List()[0] + peer := reactors[1].Switch.Peers().Copy()[0] // Get peer state ps := peer.Get(types.PeerStateKey).(*PeerState) - assert.Equal(t, true, ps.VotesSent() > 0, "number of votes sent should have increased") - assert.Equal(t, true, ps.BlockPartsSent() > 0, "number of votes sent should have increased") + assert.Greater(t, ps.VotesSent(), 0, "number of votes sent should have increased") + assert.Greater(t, ps.BlockPartsSent(), 0, "number of votes sent should have increased") } -//------------------------------------------------------------- +// ------------------------------------------------------------- // ensure we can make blocks despite cycling a validator set func TestReactorVotingPowerChange(t *testing.T) { @@ -460,11 +466,11 @@ func TestReactorVotingPowerChange(t *testing.T) { } // wait till everyone makes block 1 - timeoutWaitGroup(t, nVals, func(j int) { + timeoutWaitGroup(nVals, func(j int) { <-blocksSubs[j].Out() - }, css) + }) - //--------------------------------------------------------------------------- + // --------------------------------------------------------------------------- logger.Debug("---------------------------- Testing changing the voting power of one validator a few times") val1PubKey, err := css[0].privValidator.GetPubKey() @@ -544,15 +550,15 @@ func TestReactorValidatorSetChanges(t *testing.T) { } // wait till everyone makes block 1 - timeoutWaitGroup(t, nPeers, func(j int) { + timeoutWaitGroup(nPeers, func(j int) { <-blocksSubs[j].Out() - }, css) + }) t.Run("Testing adding one validator", func(t *testing.T) { newValidatorPubKey1, err := css[nVals].privValidator.GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) valPubKey1ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey1) - assert.NoError(t, err) + require.NoError(t, err) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) // wait till everyone makes block 2 @@ -610,7 +616,6 @@ func TestReactorValidatorSetChanges(t *testing.T) { newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) t.Run("Testing adding two validators at once", func(t *testing.T) { - waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css, newValidatorTx2, newValidatorTx3) waitForAndValidateBlockWithTx(t, nPeers, activeVals, blocksSubs, css, newValidatorTx2, newValidatorTx3) waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css) @@ -630,26 +635,25 @@ func TestReactorValidatorSetChanges(t *testing.T) { delete(activeVals, string(newValidatorPubKey3.Address())) waitForBlockWithUpdatedValsAndValidateIt(t, nPeers, activeVals, blocksSubs, css) }) - } -// Check we can make blocks with skip_timeout_commit=false +// Check we can make blocks with skip_timeout_commit=false. func TestReactorWithTimeoutCommit(t *testing.T) { - N := 4 - css, cleanup := randConsensusNet(t, N, "consensus_reactor_with_timeout_commit_test", newMockTickerFunc(false), newKVStore) + n := 4 + css, cleanup := randConsensusNet(t, n, "consensus_reactor_with_timeout_commit_test", newMockTickerFunc(false), newKVStore) defer cleanup() // override default SkipTimeoutCommit == true for tests - for i := 0; i < N; i++ { + for i := 0; i < n; i++ { css[i].config.SkipTimeoutCommit = false } - reactors, blocksSubs, eventBuses := startConsensusNet(t, css, N-1) + reactors, blocksSubs, eventBuses := startConsensusNet(t, css, n-1) defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses) // wait till everyone makes the first new block - timeoutWaitGroup(t, N-1, func(j int) { + timeoutWaitGroup(n-1, func(j int) { <-blocksSubs[j].Out() - }, css) + }) } func waitForAndValidateBlock( @@ -660,7 +664,8 @@ func waitForAndValidateBlock( css []*State, txs ...[]byte, ) { - timeoutWaitGroup(t, n, func(j int) { + t.Helper() + timeoutWaitGroup(n, func(j int) { css[j].Logger.Debug("waitForAndValidateBlock") msg := <-blocksSubs[j].Out() newBlock := msg.Data().(types.EventDataNewBlock).Block @@ -670,13 +675,11 @@ func waitForAndValidateBlock( // optionally add transactions for the next block for _, tx := range txs { - err := assertMempool(css[j].txNotifier).CheckTx(tx, func(resp *abci.ResponseCheckTx) { - require.False(t, resp.IsErr()) - fmt.Println(resp) - }, mempl.TxInfo{}) + reqRes, err := assertMempool(css[j].txNotifier).CheckTx(tx) require.NoError(t, err) + require.False(t, reqRes.Response.GetCheckTx().IsErr()) } - }, css) + }) } func waitForAndValidateBlockWithTx( @@ -687,7 +690,8 @@ func waitForAndValidateBlockWithTx( css []*State, txs ...[]byte, ) { - timeoutWaitGroup(t, n, func(j int) { + t.Helper() + timeoutWaitGroup(n, func(j int) { ntxs := 0 BLOCK_TX_LOOP: for { @@ -710,7 +714,7 @@ func waitForAndValidateBlockWithTx( break BLOCK_TX_LOOP } } - }, css) + }) } func waitForBlockWithUpdatedValsAndValidateIt( @@ -720,7 +724,8 @@ func waitForBlockWithUpdatedValsAndValidateIt( blocksSubs []types.Subscription, css []*State, ) { - timeoutWaitGroup(t, n, func(j int) { + t.Helper() + timeoutWaitGroup(n, func(j int) { var newBlock *types.Block LOOP: for { @@ -730,17 +735,16 @@ func waitForBlockWithUpdatedValsAndValidateIt( if newBlock.LastCommit.Size() == len(updatedVals) { css[j].Logger.Debug("waitForBlockWithUpdatedValsAndValidateIt: Got block", "height", newBlock.Height) break LOOP - } else { - css[j].Logger.Debug( - "waitForBlockWithUpdatedValsAndValidateIt: Got block with no new validators. Skipping", - "height", newBlock.Height, "last_commit", newBlock.LastCommit.Size(), "updated_vals", len(updatedVals), - ) } + css[j].Logger.Debug( + "waitForBlockWithUpdatedValsAndValidateIt: Got block with no new validators. Skipping", + "height", newBlock.Height, "last_commit", newBlock.LastCommit.Size(), "updated_vals", len(updatedVals), + ) } err := validateBlock(newBlock, updatedVals) - assert.Nil(t, err) - }, css) + require.NoError(t, err) + }) } // expects high synchrony! @@ -760,7 +764,7 @@ func validateBlock(block *types.Block, activeVals map[string]struct{}) error { return nil } -func timeoutWaitGroup(t *testing.T, n int, f func(int), css []*State) { +func timeoutWaitGroup(n int, f func(int)) { wg := new(sync.WaitGroup) wg.Add(n) for i := 0; i < n; i++ { @@ -776,7 +780,7 @@ func timeoutWaitGroup(t *testing.T, n int, f func(int), css []*State) { close(done) }() - // we're running many nodes in-process, possibly in in a virtual machine, + // we're running many nodes in-process, possibly in a virtual machine, // and spewing debug messages - making a block could take a while, timeout := time.Second * 20 @@ -787,7 +791,7 @@ func timeoutWaitGroup(t *testing.T, n int, f func(int), css []*State) { } } -//------------------------------------------------------------- +// ------------------------------------------------------------- // Ensure basic validation of structs is functioning func TestNewRoundStepMessageValidateBasic(t *testing.T) { @@ -868,9 +872,9 @@ func TestNewValidBlockMessageValidateBasic(t *testing.T) { malleateFn func(*NewValidBlockMessage) expErr string }{ - {func(msg *NewValidBlockMessage) {}, ""}, - {func(msg *NewValidBlockMessage) { msg.Height = -1 }, "negative Height"}, - {func(msg *NewValidBlockMessage) { msg.Round = -1 }, "negative Round"}, + {func(_ *NewValidBlockMessage) {}, ""}, + {func(msg *NewValidBlockMessage) { msg.Height = -1 }, cmterrors.ErrNegativeField{Field: "Height"}.Error()}, + {func(msg *NewValidBlockMessage) { msg.Round = -1 }, cmterrors.ErrNegativeField{Field: "Round"}.Error()}, { func(msg *NewValidBlockMessage) { msg.BlockPartSetHeader.Total = 2 }, "blockParts bit array size 1 not equal to BlockPartSetHeader.Total 2", @@ -880,7 +884,7 @@ func TestNewValidBlockMessageValidateBasic(t *testing.T) { msg.BlockPartSetHeader.Total = 0 msg.BlockParts = bits.NewBitArray(0) }, - "empty blockParts", + cmterrors.ErrRequiredField{Field: "blockParts"}.Error(), }, { func(msg *NewValidBlockMessage) { msg.BlockParts = bits.NewBitArray(int(types.MaxBlockPartsCount) + 1) }, @@ -902,7 +906,7 @@ func TestNewValidBlockMessageValidateBasic(t *testing.T) { tc.malleateFn(msg) err := msg.ValidateBasic() - if tc.expErr != "" && assert.Error(t, err) { + if tc.expErr != "" && assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Contains(t, err.Error(), tc.expErr) } }) @@ -914,10 +918,10 @@ func TestProposalPOLMessageValidateBasic(t *testing.T) { malleateFn func(*ProposalPOLMessage) expErr string }{ - {func(msg *ProposalPOLMessage) {}, ""}, - {func(msg *ProposalPOLMessage) { msg.Height = -1 }, "negative Height"}, - {func(msg *ProposalPOLMessage) { msg.ProposalPOLRound = -1 }, "negative ProposalPOLRound"}, - {func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(0) }, "empty ProposalPOL bit array"}, + {func(_ *ProposalPOLMessage) {}, ""}, + {func(msg *ProposalPOLMessage) { msg.Height = -1 }, cmterrors.ErrNegativeField{Field: "Height"}.Error()}, + {func(msg *ProposalPOLMessage) { msg.ProposalPOLRound = -1 }, cmterrors.ErrNegativeField{Field: "ProposalPOLRound"}.Error()}, + {func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(0) }, cmterrors.ErrRequiredField{Field: "ProposalPOL"}.Error()}, { func(msg *ProposalPOLMessage) { msg.ProposalPOL = bits.NewBitArray(types.MaxVotesCount + 1) }, "proposalPOL bit array is too big: 10001, max: 10000", @@ -935,7 +939,7 @@ func TestProposalPOLMessageValidateBasic(t *testing.T) { tc.malleateFn(msg) err := msg.ValidateBasic() - if tc.expErr != "" && assert.Error(t, err) { + if tc.expErr != "" && assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Contains(t, err.Error(), tc.expErr) } }) @@ -973,13 +977,13 @@ func TestBlockPartMessageValidateBasic(t *testing.T) { message := BlockPartMessage{Height: 0, Round: 0, Part: new(types.Part)} message.Part.Index = 1 - assert.Equal(t, true, message.ValidateBasic() != nil, "Validate Basic had an unexpected result") + require.Error(t, message.ValidateBasic()) } func TestHasVoteMessageValidateBasic(t *testing.T) { const ( - validSignedMsgType cmtproto.SignedMsgType = 0x01 - invalidSignedMsgType cmtproto.SignedMsgType = 0x03 + validSignedMsgType types.SignedMsgType = 0x01 + invalidSignedMsgType types.SignedMsgType = 0x03 ) testCases := []struct { //nolint: maligned @@ -988,7 +992,7 @@ func TestHasVoteMessageValidateBasic(t *testing.T) { messageIndex int32 messageHeight int64 testName string - messageType cmtproto.SignedMsgType + messageType types.SignedMsgType }{ {false, 0, 0, 0, "Valid Message", validSignedMsgType}, {true, -1, 0, 0, "Invalid Message", validSignedMsgType}, @@ -1014,8 +1018,8 @@ func TestHasVoteMessageValidateBasic(t *testing.T) { func TestVoteSetMaj23MessageValidateBasic(t *testing.T) { const ( - validSignedMsgType cmtproto.SignedMsgType = 0x01 - invalidSignedMsgType cmtproto.SignedMsgType = 0x03 + validSignedMsgType types.SignedMsgType = 0x01 + invalidSignedMsgType types.SignedMsgType = 0x03 ) validBlockID := types.BlockID{} @@ -1032,7 +1036,7 @@ func TestVoteSetMaj23MessageValidateBasic(t *testing.T) { messageRound int32 messageHeight int64 testName string - messageType cmtproto.SignedMsgType + messageType types.SignedMsgType messageBlockID types.BlockID }{ {false, 0, 0, "Valid Message", validSignedMsgType, validBlockID}, @@ -1062,9 +1066,9 @@ func TestVoteSetBitsMessageValidateBasic(t *testing.T) { malleateFn func(*VoteSetBitsMessage) expErr string }{ - {func(msg *VoteSetBitsMessage) {}, ""}, - {func(msg *VoteSetBitsMessage) { msg.Height = -1 }, "negative Height"}, - {func(msg *VoteSetBitsMessage) { msg.Type = 0x03 }, "invalid Type"}, + {func(_ *VoteSetBitsMessage) {}, ""}, + {func(msg *VoteSetBitsMessage) { msg.Height = -1 }, cmterrors.ErrNegativeField{Field: "Height"}.Error()}, + {func(msg *VoteSetBitsMessage) { msg.Type = 0x03 }, cmterrors.ErrInvalidField{Field: "Type"}.Error()}, {func(msg *VoteSetBitsMessage) { msg.BlockID = types.BlockID{ Hash: bytes.HexBytes{}, @@ -1093,9 +1097,38 @@ func TestVoteSetBitsMessageValidateBasic(t *testing.T) { tc.malleateFn(msg) err := msg.ValidateBasic() - if tc.expErr != "" && assert.Error(t, err) { + if tc.expErr != "" && assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Contains(t, err.Error(), tc.expErr) } }) } } + +func TestMarshalJSONPeerState(t *testing.T) { + ps := NewPeerState(nil) + data, err := json.Marshal(ps) + require.NoError(t, err) + require.JSONEq(t, `{ + "round_state":{ + "height": "0", + "round": -1, + "step": 0, + "start_time": "0001-01-01T00:00:00Z", + "proposal": false, + "proposal_block_part_set_header": + {"total":0, "hash":""}, + "proposal_block_parts": null, + "proposal_pol_round": -1, + "proposal_pol": null, + "prevotes": null, + "precommits": null, + "last_commit_round": -1, + "last_commit": null, + "catchup_commit_round": -1, + "catchup_commit": null + }, + "stats":{ + "votes":"0", + "block_parts":"0"} + }`, string(data)) +} diff --git a/consensus/replay.go b/internal/consensus/replay.go similarity index 92% rename from consensus/replay.go rename to internal/consensus/replay.go index 6496693950c..a93c1650504 100644 --- a/consensus/replay.go +++ b/internal/consensus/replay.go @@ -3,6 +3,7 @@ package consensus import ( "bytes" "context" + "errors" "fmt" "hash/crc32" "io" @@ -11,9 +12,9 @@ import ( abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/crypto/merkle" + sm "github.com/cometbft/cometbft/internal/state" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" ) @@ -28,10 +29,10 @@ var crc32c = crc32.MakeTable(crc32.Castagnoli) // The former is handled by the WAL, the latter by the proxyApp Handshake on // restart, which ultimately hands off the work to the WAL. -//----------------------------------------- +// ----------------------------------------- // 1. Recover from failure during consensus // (by replaying messages from the WAL) -//----------------------------------------- +// ----------------------------------------- // Unmarshal and apply a single message to the consensus state as if it were // received in receiveRoutine. Lines that start with "#" are ignored. @@ -56,9 +57,9 @@ func (cs *State) readReplayMessage(msg *TimedWALMessage, newStepSub types.Subscr return fmt.Errorf("roundState mismatch. Got %v; Expected %v", m2, m) } case <-newStepSub.Canceled(): - return fmt.Errorf("failed to read off newStepSub.Out(). newStepSub was canceled") + return errors.New("failed to read off newStepSub.Out(). newStepSub was canceled") case <-ticker: - return fmt.Errorf("failed to read off newStepSub.Out()") + return errors.New("failed to read off newStepSub.Out()") } } case msgInfo: @@ -70,7 +71,7 @@ func (cs *State) readReplayMessage(msg *TimedWALMessage, newStepSub types.Subscr case *ProposalMessage: p := msg.Proposal cs.Logger.Info("Replay: Proposal", "height", p.Height, "round", p.Round, "header", - p.BlockID.PartSetHeader, "pol", p.POLRound, "peer", peerID) + p.BlockID.PartSetHeader, "pol", p.POLRound, "peer", peerID, "receive_time", m.ReceiveTime) case *BlockPartMessage: cs.Logger.Info("Replay: BlockPart", "height", msg.Height, "round", msg.Round, "peer", peerID) case *VoteMessage: @@ -92,7 +93,6 @@ func (cs *State) readReplayMessage(msg *TimedWALMessage, newStepSub types.Subscr // Replay only those messages since the last block. `timeoutRoutine` should // run concurrently to read off tickChan. func (cs *State) catchupReplay(csHeight int64) error { - // Set replayMode to true so we don't log signing errors. cs.replayMode = true defer func() { cs.replayMode = false }() @@ -166,7 +166,7 @@ LOOP: return nil } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- // Parses marker lines of the form: // #ENDHEIGHT: 12345 @@ -192,11 +192,11 @@ func makeHeightSearchFunc(height int64) auto.SearchFunc { } }*/ -//--------------------------------------------------- +// --------------------------------------------------- // 2. Recover from failure while applying the block. // (by handshaking with the app to figure out where // we were last, and using the WAL to recover there.) -//--------------------------------------------------- +// --------------------------------------------------- type Handshaker struct { stateStore sm.Store @@ -210,8 +210,8 @@ type Handshaker struct { } func NewHandshaker(stateStore sm.Store, state sm.State, - store sm.BlockStore, genDoc *types.GenesisDoc) *Handshaker { - + store sm.BlockStore, genDoc *types.GenesisDoc, +) *Handshaker { return &Handshaker{ stateStore: stateStore, initialState: state, @@ -239,10 +239,9 @@ func (h *Handshaker) NBlocks() int { } // TODO: retry the handshake/replay if it fails ? -func (h *Handshaker) Handshake(proxyApp proxy.AppConns) error { - +func (h *Handshaker) Handshake(ctx context.Context, proxyApp proxy.AppConns) error { // Handshake is done via ABCI Info on the query conn. - res, err := proxyApp.Query().Info(context.TODO(), proxy.RequestInfo) + res, err := proxyApp.Query().Info(ctx, proxy.InfoRequest) if err != nil { return fmt.Errorf("error calling Info: %v", err) } @@ -266,7 +265,7 @@ func (h *Handshaker) Handshake(proxyApp proxy.AppConns) error { } // Replay blocks up to the latest in the blockstore. - appHash, err = h.ReplayBlocks(h.initialState, appHash, blockHeight, proxyApp) + appHash, err = h.ReplayBlocks(ctx, h.initialState, appHash, blockHeight, proxyApp) if err != nil { return fmt.Errorf("error on replay: %v", err) } @@ -283,6 +282,7 @@ func (h *Handshaker) Handshake(proxyApp proxy.AppConns) error { // matches the current state. // Returns the final AppHash or an error. func (h *Handshaker) ReplayBlocks( + ctx context.Context, state sm.State, appHash []byte, appBlockHeight int64, @@ -309,7 +309,7 @@ func (h *Handshaker) ReplayBlocks( validatorSet := types.NewValidatorSet(validators) nextVals := types.TM2PB.ValidatorUpdates(validatorSet) pbparams := h.genDoc.ConsensusParams.ToProto() - req := &abci.RequestInitChain{ + req := &abci.InitChainRequest{ Time: h.genDoc.GenesisTime, ChainId: h.genDoc.ChainID, InitialHeight: h.genDoc.InitialHeight, @@ -341,7 +341,7 @@ func (h *Handshaker) ReplayBlocks( state.NextValidators = types.NewValidatorSet(vals).CopyIncrementProposerPriority(1) } else if len(h.genDoc.Validators) == 0 { // If validator set is not set in genesis and still empty after InitChain, exit. - return nil, fmt.Errorf("validator set is nil in genesis and still empty after InitChain") + return nil, errors.New("validator set is nil in genesis and still empty after InitChain") } if res.ConsensusParams != nil { @@ -391,14 +391,12 @@ func (h *Handshaker) ReplayBlocks( // Either the app is asking for replay, or we're all synced up. if appBlockHeight < storeBlockHeight { // the app is behind, so replay blocks, but no need to go through WAL (state is already synced to store) - return h.replayBlocks(state, proxyApp, appBlockHeight, storeBlockHeight, false) - + return h.replayBlocks(ctx, state, proxyApp, appBlockHeight, storeBlockHeight, false) } else if appBlockHeight == storeBlockHeight { // We're good! assertAppHashEqualsOneFromState(appHash, state) return appHash, nil } - } else if storeBlockHeight == stateBlockHeight+1 { // We saved the block in the store but haven't updated the state, // so we'll need to replay a block using the WAL. @@ -406,7 +404,7 @@ func (h *Handshaker) ReplayBlocks( case appBlockHeight < stateBlockHeight: // the app is further behind than it should be, so replay blocks // but leave the last block to go through the WAL - return h.replayBlocks(state, proxyApp, appBlockHeight, storeBlockHeight, true) + return h.replayBlocks(ctx, state, proxyApp, appBlockHeight, storeBlockHeight, true) case appBlockHeight == stateBlockHeight: // We haven't run Commit (both the state and app are one block behind), @@ -435,7 +433,6 @@ func (h *Handshaker) ReplayBlocks( state, err = h.replayBlock(state, storeBlockHeight, mockApp) return state.AppHash, err } - } panic(fmt.Sprintf("uncovered case! appHeight: %d, storeHeight: %d, stateHeight: %d", @@ -443,11 +440,13 @@ func (h *Handshaker) ReplayBlocks( } func (h *Handshaker) replayBlocks( + ctx context.Context, state sm.State, proxyApp proxy.AppConns, appBlockHeight, storeBlockHeight int64, - mutateState bool) ([]byte, error) { + mutateState bool, +) ([]byte, error) { // App is further behind than it should be, so we need to replay blocks. // We replay all blocks from appBlockHeight+1. // @@ -469,8 +468,14 @@ func (h *Handshaker) replayBlocks( firstBlock = state.InitialHeight } for i := firstBlock; i <= finalBlock; i++ { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + h.logger.Info("Applying block", "height", i) - block := h.store.LoadBlock(i) + block, _ := h.store.LoadBlock(i) // Extra check to ensure the app was not changed in a way it shouldn't have. if len(appHash) > 0 { assertAppHashEqualsOneFromBlock(appHash, block) @@ -499,8 +504,7 @@ func (h *Handshaker) replayBlocks( // ApplyBlock on the proxyApp with the last block. func (h *Handshaker) replayBlock(state sm.State, height int64, proxyApp proxy.AppConnConsensus) (sm.State, error) { - block := h.store.LoadBlock(height) - meta := h.store.LoadBlockMeta(height) + block, meta := h.store.LoadBlock(height) // Use stubs for both mempool and evidence pool since no transactions nor // evidence are needed here - block already exists. diff --git a/internal/consensus/replay_stubs.go b/internal/consensus/replay_stubs.go new file mode 100644 index 00000000000..485fcdbe098 --- /dev/null +++ b/internal/consensus/replay_stubs.go @@ -0,0 +1,82 @@ +package consensus + +import ( + "context" + + abcicli "github.com/cometbft/cometbft/abci/client" + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/clist" + mempl "github.com/cometbft/cometbft/mempool" + "github.com/cometbft/cometbft/proxy" + "github.com/cometbft/cometbft/types" +) + +// ----------------------------------------------------------------------------- + +type emptyMempool struct{} + +var _ mempl.Mempool = emptyMempool{} + +func (emptyMempool) Lock() {} +func (emptyMempool) Unlock() {} +func (emptyMempool) Size() int { return 0 } +func (emptyMempool) SizeBytes() int64 { return 0 } +func (emptyMempool) CheckTx(types.Tx) (*abcicli.ReqRes, error) { + return nil, nil +} + +func (emptyMempool) RemoveTxByKey(types.TxKey) error { + return nil +} + +func (emptyMempool) ReapMaxBytesMaxGas(int64, int64) types.Txs { return types.Txs{} } +func (emptyMempool) ReapMaxTxs(int) types.Txs { return types.Txs{} } +func (emptyMempool) Update( + int64, + types.Txs, + []*abci.ExecTxResult, + mempl.PreCheckFunc, + mempl.PostCheckFunc, +) error { + return nil +} +func (emptyMempool) Flush() {} +func (emptyMempool) FlushAppConn() error { return nil } +func (emptyMempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } +func (emptyMempool) EnableTxsAvailable() {} +func (emptyMempool) SetTxRemovedCallback(func(types.TxKey)) {} +func (emptyMempool) TxsBytes() int64 { return 0 } +func (emptyMempool) InMempool(types.TxKey) bool { return false } + +func (emptyMempool) TxsFront() *clist.CElement { return nil } +func (emptyMempool) TxsWaitChan() <-chan struct{} { return nil } + +func (emptyMempool) InitWAL() error { return nil } +func (emptyMempool) CloseWAL() {} + +// ----------------------------------------------------------------------------- +// mockProxyApp uses ABCIResponses to give the right results. +// +// Useful because we don't want to call Commit() twice for the same block on +// the real app. + +func newMockProxyApp(finalizeBlockResponse *abci.FinalizeBlockResponse) proxy.AppConnConsensus { + clientCreator := proxy.NewLocalClientCreator(&mockProxyApp{ + finalizeBlockResponse: finalizeBlockResponse, + }) + cli, _ := clientCreator.NewABCIConsensusClient() + err := cli.Start() + if err != nil { + panic(err) + } + return proxy.NewAppConnConsensus(cli, proxy.NopMetrics()) +} + +type mockProxyApp struct { + abci.BaseApplication + finalizeBlockResponse *abci.FinalizeBlockResponse +} + +func (mock *mockProxyApp) FinalizeBlock(context.Context, *abci.FinalizeBlockRequest) (*abci.FinalizeBlockResponse, error) { + return mock.finalizeBlockResponse, nil +} diff --git a/consensus/replay_test.go b/internal/consensus/replay_test.go similarity index 79% rename from consensus/replay_test.go rename to internal/consensus/replay_test.go index 0d0c9f0dcc1..35019f8ce84 100644 --- a/consensus/replay_test.go +++ b/internal/consensus/replay_test.go @@ -18,22 +18,20 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/abci/example/kvstore" abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/abci/types/mocks" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" cfg "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/crypto" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" + cmtrand "github.com/cometbft/cometbft/internal/rand" + sm "github.com/cometbft/cometbft/internal/state" + smmocks "github.com/cometbft/cometbft/internal/state/mocks" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" - cmtrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/mempool" "github.com/cometbft/cometbft/privval" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - smmocks "github.com/cometbft/cometbft/state/mocks" "github.com/cometbft/cometbft/types" ) @@ -55,21 +53,25 @@ func TestMain(m *testing.M) { // These tests ensure we can always recover from failure at any part of the consensus process. // There are two general failure scenarios: failure during consensus, and failure while applying the block. // Only the latter interacts with the app and store, -// but the former has to deal with restrictions on re-use of priv_validator keys. +// but the former has to deal with restrictions on reuse of priv_validator keys. // The `WAL Tests` are for failures during the consensus; // the `Handshake Tests` are for failures in applying the block. // With the help of the WAL, we can recover from it all! -//------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------ // WAL Tests // TODO: It would be better to verify explicitly which states we can recover from without the wal // and which ones we need the wal for - then we'd also be able to only flush the // wal writer when we need to, instead of with every message. -func startNewStateAndWaitForBlock(t *testing.T, consensusReplayConfig *cfg.Config, - lastBlockHeight int64, blockDB dbm.DB, stateStore sm.Store, +func startNewStateAndWaitForBlock( + t *testing.T, + consensusReplayConfig *cfg.Config, + blockDB dbm.DB, + stateStore sm.Store, ) { + t.Helper() logger := log.TestingLogger() state, _ := stateStore.LoadFromDBOrGenesisFile(consensusReplayConfig.GenesisFile()) privValidator := loadPrivValidator(consensusReplayConfig) @@ -115,13 +117,14 @@ func sendTxs(ctx context.Context, cs *State) { return default: tx := kvstore.NewTxFromID(i) - if err := assertMempool(cs.txNotifier).CheckTx(tx, func(resp *abci.ResponseCheckTx) { - if resp.Code != 0 { - panic(fmt.Sprintf("Unexpected code: %d, log: %s", resp.Code, resp.Log)) - } - }, mempool.TxInfo{}); err != nil { + reqRes, err := assertMempool(cs.txNotifier).CheckTx(tx) + if err != nil { panic(err) } + resp := reqRes.Response.GetCheckTx() + if resp.Code != 0 { + panic(fmt.Sprintf("Unexpected code: %d, log: %s", resp.Code, resp.Log)) + } i++ } } @@ -136,12 +139,12 @@ func TestWALCrash(t *testing.T) { }{ { "empty block", - func(stateDB dbm.DB, cs *State, ctx context.Context) {}, + func(_ dbm.DB, _ *State, _ context.Context) {}, 1, }, { "many non-empty blocks", - func(stateDB dbm.DB, cs *State, ctx context.Context) { + func(_ dbm.DB, cs *State, ctx context.Context) { go sendTxs(ctx, cs) }, 3, @@ -160,6 +163,7 @@ func TestWALCrash(t *testing.T) { func crashWALandCheckLiveness(t *testing.T, consensusReplayConfig *cfg.Config, initFn func(dbm.DB, *State, context.Context), heightToStop int64, ) { + t.Helper() walPanicked := make(chan error) crashingWal := &crashingWAL{panicCh: walPanicked, heightToStop: heightToStop} @@ -215,7 +219,7 @@ LOOP: t.Logf("WAL panicked: %v", err) // make sure we can make blocks after a crash - startNewStateAndWaitForBlock(t, consensusReplayConfig, cs.Height, blockDB, stateStore) + startNewStateAndWaitForBlock(t, consensusReplayConfig, blockDB, stateStore) // stop consensus state and transactions sender (initFn) cs.Stop() //nolint:errcheck // Logging this error causes failure @@ -310,19 +314,18 @@ func (w *crashingWAL) Wait() { w.next.Wait() } const numBlocks = 6 -//--------------------------------------- +// --------------------------------------- // Test handshake/replay // 0 - all synced up // 1 - saved block but app and state are behind by one height // 2 - save block and committed (i.e. app got `Commit`) but state is behind -// 3 - same as 2 but with a truncated block store +// 3 - same as 2 but with a truncated block store. var modes = []uint{0, 1, 2, 3} -// This is actually not a test, it's for storing validator change tx data for testHandshakeReplay +// This is actually not a test, it's for storing validator change tx data for testHandshakeReplay. func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (*cfg.Config, []*types.Block, []*types.ExtendedCommit, sm.State) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + t.Helper() nPeers := 7 nVals := 4 @@ -335,12 +338,11 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* func(_ string) abci.Application { return newKVStore() }) + chainID := genDoc.ChainID genesisState, err := sm.MakeGenesisState(genDoc) require.NoError(t, err) t.Cleanup(cleanup) - partSize := types.BlockPartSizeBytes - newRoundCh := subscribe(css[0].eventBus, types.EventQueryNewRound) proposalCh := subscribe(css[0].eventBus, types.EventQueryCompleteProposal) @@ -356,7 +358,7 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* ensureNewRound(newRoundCh, height, 0) ensureNewProposal(proposalCh, height, round) rs := css[0].GetRoundState() - signAddVotes(css[0], cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), true, vss[1:nVals]...) + signAddVotes(css[0], types.PrecommitType, chainID, types.BlockID{Hash: rs.ProposalBlock.Hash(), PartSetHeader: rs.ProposalBlockParts.Header()}, true, vss[1:nVals]...) ensureNewRound(newRoundCh, height+1, 0) // HEIGHT 2 @@ -367,28 +369,20 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* valPubKey1ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey1) require.NoError(t, err) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) - err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx1, nil, mempool.TxInfo{}) - assert.NoError(t, err) - propBlock, err := css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + _, err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx1) require.NoError(t, err) - propBlockParts, err := propBlock.MakePartSet(partSize) - require.NoError(t, err) - blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} - proposal := types.NewProposal(vss[1].Height, round, -1, blockID) - p := proposal.ToProto() - if err := vss[1].SignProposal(test.DefaultTestChainID, p); err != nil { - t.Fatal("failed to sign bad proposal", err) - } - proposal.Signature = p.Signature + propBlock, propBlockParts, blockID := createProposalBlock(t, css[0]) // changeProposer(t, cs1, v2) + proposal := types.NewProposal(vss[1].Height, round, -1, blockID, propBlock.Header.Time) + signProposal(t, proposal, chainID, vss[1]) // set the proposal block - if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { + if err := css[0].SetProposalAndBlock(proposal, propBlockParts, "some peer"); err != nil { t.Fatal(err) } ensureNewProposal(proposalCh, height, round) rs = css[0].GetRoundState() - signAddVotes(css[0], cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), true, vss[1:nVals]...) + signAddVotes(css[0], types.PrecommitType, chainID, types.BlockID{Hash: rs.ProposalBlock.Hash(), PartSetHeader: rs.ProposalBlockParts.Header()}, true, vss[1:nVals]...) ensureNewRound(newRoundCh, height+1, 0) // HEIGHT 3 @@ -399,28 +393,20 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* updatePubKey1ABCI, err := cryptoenc.PubKeyToProto(updateValidatorPubKey1) require.NoError(t, err) updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) - err = assertMempool(css[0].txNotifier).CheckTx(updateValidatorTx1, nil, mempool.TxInfo{}) - assert.NoError(t, err) - propBlock, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + _, err = assertMempool(css[0].txNotifier).CheckTx(updateValidatorTx1) require.NoError(t, err) - propBlockParts, err = propBlock.MakePartSet(partSize) - require.NoError(t, err) - blockID = types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} - proposal = types.NewProposal(vss[2].Height, round, -1, blockID) - p = proposal.ToProto() - if err := vss[2].SignProposal(test.DefaultTestChainID, p); err != nil { - t.Fatal("failed to sign bad proposal", err) - } - proposal.Signature = p.Signature + propBlock, propBlockParts, blockID = createProposalBlock(t, css[0]) // changeProposer(t, cs1, v2) + proposal = types.NewProposal(vss[2].Height, round, -1, blockID, propBlock.Header.Time) + signProposal(t, proposal, chainID, vss[2]) // set the proposal block - if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { + if err := css[0].SetProposalAndBlock(proposal, propBlockParts, "some peer"); err != nil { t.Fatal(err) } ensureNewProposal(proposalCh, height, round) rs = css[0].GetRoundState() - signAddVotes(css[0], cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), true, vss[1:nVals]...) + signAddVotes(css[0], types.PrecommitType, chainID, types.BlockID{Hash: rs.ProposalBlock.Hash(), PartSetHeader: rs.ProposalBlockParts.Header()}, true, vss[1:nVals]...) ensureNewRound(newRoundCh, height+1, 0) // HEIGHT 4 @@ -431,20 +417,18 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* newVal2ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey2) require.NoError(t, err) newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower) - err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx2, nil, mempool.TxInfo{}) + _, err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx2) require.NoError(t, err) newValidatorPubKey3, err := css[nVals+2].privValidator.GetPubKey() require.NoError(t, err) newVal3ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey3) require.NoError(t, err) newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) - err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx3, nil, mempool.TxInfo{}) - assert.NoError(t, err) - propBlock, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + _, err = assertMempool(css[0].txNotifier).CheckTx(newValidatorTx3) require.NoError(t, err) - propBlockParts, err = propBlock.MakePartSet(partSize) - require.NoError(t, err) - blockID = types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} + + propBlock, propBlockParts, blockID = createProposalBlock(t, css[0]) // changeProposer(t, cs1, v2) + newVss := make([]*validatorStub, nVals+1) copy(newVss, vss[:nVals+1]) sort.Sort(ValidatorStubsByPower(newVss)) @@ -466,29 +450,26 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* selfIndex := valIndexFn(0) - proposal = types.NewProposal(vss[3].Height, round, -1, blockID) - p = proposal.ToProto() - if err := vss[3].SignProposal(test.DefaultTestChainID, p); err != nil { - t.Fatal("failed to sign bad proposal", err) - } - proposal.Signature = p.Signature + proposal = types.NewProposal(vss[3].Height, round, -1, blockID, propBlock.Header.Time) + signProposal(t, proposal, chainID, vss[3]) // set the proposal block - if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { + if err := css[0].SetProposalAndBlock(proposal, propBlockParts, "some peer"); err != nil { t.Fatal(err) } ensureNewProposal(proposalCh, height, round) removeValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, 0) - err = assertMempool(css[0].txNotifier).CheckTx(removeValidatorTx2, nil, mempool.TxInfo{}) - assert.Nil(t, err) + _, err = assertMempool(css[0].txNotifier).CheckTx(removeValidatorTx2) + require.NoError(t, err) rs = css[0].GetRoundState() for i := 0; i < nVals+1; i++ { if i == selfIndex { continue } - signAddVotes(css[0], cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), true, newVss[i]) + signAddVotes(css[0], types.PrecommitType, chainID, + types.BlockID{Hash: rs.ProposalBlock.Hash(), PartSetHeader: rs.ProposalBlockParts.Header()}, true, newVss[i]) } ensureNewRound(newRoundCh, height+1, 0) @@ -507,7 +488,7 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* if i == selfIndex { continue } - signAddVotes(css[0], cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), true, newVss[i]) + signAddVotes(css[0], types.PrecommitType, chainID, types.BlockID{Hash: rs.ProposalBlock.Hash(), PartSetHeader: rs.ProposalBlockParts.Header()}, true, newVss[i]) } ensureNewRound(newRoundCh, height+1, 0) @@ -515,27 +496,21 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* height++ incrementHeight(vss...) removeValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, 0) - err = assertMempool(css[0].txNotifier).CheckTx(removeValidatorTx3, nil, mempool.TxInfo{}) - assert.NoError(t, err) - propBlock, err = css[0].createProposalBlock(ctx) // changeProposer(t, cs1, vs2) - require.NoError(t, err) - propBlockParts, err = propBlock.MakePartSet(partSize) + _, err = assertMempool(css[0].txNotifier).CheckTx(removeValidatorTx3) require.NoError(t, err) - blockID = types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} + + propBlock, propBlockParts, blockID = createProposalBlock(t, css[0]) // changeProposer(t, cs1, v2) + newVss = make([]*validatorStub, nVals+3) copy(newVss, vss[:nVals+3]) sort.Sort(ValidatorStubsByPower(newVss)) selfIndex = valIndexFn(0) - proposal = types.NewProposal(vss[1].Height, round, -1, blockID) - p = proposal.ToProto() - if err := vss[1].SignProposal(test.DefaultTestChainID, p); err != nil { - t.Fatal("failed to sign bad proposal", err) - } - proposal.Signature = p.Signature + proposal = types.NewProposal(vss[1].Height, round, -1, blockID, propBlock.Header.Time) + signProposal(t, proposal, chainID, vss[1]) // set the proposal block - if err := css[0].SetProposalAndBlock(proposal, propBlock, propBlockParts, "some peer"); err != nil { + if err := css[0].SetProposalAndBlock(proposal, propBlockParts, "some peer"); err != nil { t.Fatal(err) } ensureNewProposal(proposalCh, height, round) @@ -544,20 +519,21 @@ func setupChainWithChangingValidators(t *testing.T, name string, nBlocks int) (* if i == selfIndex { continue } - signAddVotes(css[0], cmtproto.PrecommitType, rs.ProposalBlock.Hash(), rs.ProposalBlockParts.Header(), true, newVss[i]) + signAddVotes(css[0], types.PrecommitType, chainID, types.BlockID{Hash: rs.ProposalBlock.Hash(), PartSetHeader: rs.ProposalBlockParts.Header()}, true, newVss[i]) } ensureNewRound(newRoundCh, height+1, 0) chain := []*types.Block{} extCommits := []*types.ExtendedCommit{} for i := 1; i <= nBlocks; i++ { - chain = append(chain, css[0].blockStore.LoadBlock(int64(i))) + block, _ := css[0].blockStore.LoadBlock(int64(i)) + chain = append(chain, block) extCommits = append(extCommits, css[0].blockStore.LoadBlockExtendedCommit(int64(i))) } return config, chain, extCommits, genesisState } -// Sync from scratch +// Sync from scratch. func TestHandshakeReplayAll(t *testing.T) { for _, m := range modes { t.Run(fmt.Sprintf("mode_%d_single", m), func(t *testing.T) { @@ -569,7 +545,7 @@ func TestHandshakeReplayAll(t *testing.T) { } } -// Sync many, not from scratch +// Sync many, not from scratch. func TestHandshakeReplaySome(t *testing.T) { for _, m := range modes { t.Run(fmt.Sprintf("mode_%d_single", m), func(t *testing.T) { @@ -581,7 +557,7 @@ func TestHandshakeReplaySome(t *testing.T) { } } -// Sync from lagging by one +// Sync from lagging by one. func TestHandshakeReplayOne(t *testing.T) { for _, m := range modes { t.Run(fmt.Sprintf("mode_%d_single", m), func(t *testing.T) { @@ -593,7 +569,7 @@ func TestHandshakeReplayOne(t *testing.T) { } } -// Sync from caught up +// Sync from caught up. func TestHandshakeReplayNone(t *testing.T) { for _, m := range modes { t.Run(fmt.Sprintf("mode_%d_single", m), func(t *testing.T) { @@ -621,8 +597,9 @@ func tempWALWithData(data []byte) string { } // Make some blocks. Start a fresh app and apply nBlocks blocks. -// Then restart the app and sync it up with the remaining blocks +// Then restart the app and sync it up with the remaining blocks. func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uint, testValidatorsChange bool) { + t.Helper() var ( testConfig *cfg.Config chain []*types.Block @@ -648,8 +625,6 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin walFile := tempWALWithData(walBody) testConfig.Consensus.SetWalFile(walFile) - privVal := privval.LoadFilePV(testConfig.PrivValidatorKeyFile(), testConfig.PrivValidatorStateFile()) - wal, err := NewWAL(walFile) require.NoError(t, err) wal.SetLogger(log.TestingLogger()) @@ -662,9 +637,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin }) chain, extCommits, err = makeBlockchainFromWAL(wal) require.NoError(t, err) - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - stateDB, genesisState, store = stateAndStore(t, testConfig, pubKey, kvstore.AppVersion) + stateDB, genesisState, store = stateAndStore(t, testConfig, kvstore.AppVersion) } stateStore := sm.NewStore(stateDB, sm.StoreOptions{ @@ -726,7 +699,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin }) // perform the replay protocol to sync Tendermint and the application - err = handshaker.Handshake(proxyApp) + err = handshaker.Handshake(context.Background(), proxyApp) if expectError { require.Error(t, err) // finish the test early @@ -735,7 +708,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin require.NoError(t, err) // get the latest app hash from the app - res, err := proxyApp.Query().Info(context.Background(), proxy.RequestInfo) + res, err := proxyApp.Query().Info(context.Background(), proxy.InfoRequest) require.NoError(t, err) // block store and app height should be in sync @@ -768,6 +741,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin } func applyBlock(t *testing.T, stateStore sm.Store, mempool mempool.Mempool, evpool sm.EvidencePool, st sm.State, blk *types.Block, proxyApp proxy.AppConns, bs sm.BlockStore) sm.State { + t.Helper() testPartSize := types.BlockPartSizeBytes blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(), mempool, evpool, bs) @@ -782,6 +756,7 @@ func applyBlock(t *testing.T, stateStore sm.Store, mempool mempool.Mempool, evpo func buildAppStateFromChain(t *testing.T, proxyApp proxy.AppConns, stateStore sm.Store, mempool mempool.Mempool, evpool sm.EvidencePool, state sm.State, chain []*types.Block, nBlocks int, mode uint, bs sm.BlockStore, ) { + t.Helper() // start a new app without handshake, play nBlocks blocks if err := proxyApp.Start(); err != nil { panic(err) @@ -790,7 +765,7 @@ func buildAppStateFromChain(t *testing.T, proxyApp proxy.AppConns, stateStore sm state.Version.Consensus.App = kvstore.AppVersion // simulate handshake, receive app version validators := types.TM2PB.ValidatorUpdates(state.Validators) - if _, err := proxyApp.Consensus().InitChain(context.Background(), &abci.RequestInitChain{ + if _, err := proxyApp.Consensus().InitChain(context.Background(), &abci.InitChainRequest{ Validators: validators, }); err != nil { panic(err) @@ -816,7 +791,7 @@ func buildAppStateFromChain(t *testing.T, proxyApp proxy.AppConns, stateStore sm // update the kvstore height and apphash // as if we ran commit but not // here we expect a dummy state store to be used - state = applyBlock(t, stateStore, mempool, evpool, state, chain[nBlocks-1], proxyApp, bs) + _ = applyBlock(t, stateStore, mempool, evpool, state, chain[nBlocks-1], proxyApp, bs) } default: panic(fmt.Sprintf("unknown mode %v", mode)) @@ -835,6 +810,7 @@ func buildTMStateFromChain( mode uint, bs sm.BlockStore, ) (sm.State, []byte) { + t.Helper() // run the whole chain against this client to build up the CometBFT state clientCreator := proxy.NewLocalClientCreator( kvstore.NewPersistentApplication( @@ -847,7 +823,7 @@ func buildTMStateFromChain( state.Version.Consensus.App = kvstore.AppVersion // simulate handshake, receive app version validators := types.TM2PB.ValidatorUpdates(state.Validators) - if _, err := proxyApp.Consensus().InitChain(context.Background(), &abci.RequestInitChain{ + if _, err := proxyApp.Consensus().InitChain(context.Background(), &abci.InitChainRequest{ Validators: validators, }); err != nil { panic(err) @@ -876,10 +852,13 @@ func buildTMStateFromChain( vals, _ := stateStore.LoadValidators(penultimateHeight) dummyStateStore.On("LoadValidators", penultimateHeight).Return(vals, nil) dummyStateStore.On("Save", mock.Anything).Return(nil) - dummyStateStore.On("SaveFinalizeBlockResponse", lastHeight, mock.MatchedBy(func(response *abci.ResponseFinalizeBlock) bool { + dummyStateStore.On("SaveFinalizeBlockResponse", lastHeight, mock.MatchedBy(func(response *abci.FinalizeBlockResponse) bool { require.NoError(t, stateStore.SaveFinalizeBlockResponse(lastHeight, response)) return true })).Return(nil) + dummyStateStore.On("GetApplicationRetainHeight", mock.Anything).Return(int64(0), nil) + dummyStateStore.On("GetCompanionBlockRetainHeight", mock.Anything).Return(int64(0), nil) + dummyStateStore.On("GetABCIResRetainHeight", mock.Anything).Return(int64(0), nil) // apply the final block to a state copy so we can // get the right next appHash but keep the state back @@ -925,13 +904,12 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) { defer os.RemoveAll(config.RootDir) privVal := privval.LoadFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) const appVersion = 0x0 - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - stateDB, state, store := stateAndStore(t, config, pubKey, appVersion) + stateDB, state, store := stateAndStore(t, config, appVersion) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) - genDoc, _ := sm.MakeGenesisDocFromFile(config.GenesisFile()) + genDoc, err := sm.MakeGenesisDocFromFile(config.GenesisFile()) + require.NoError(t, err) state.LastValidators = state.Validators.Copy() // mode = 0 for committing all the blocks blocks, err := makeBlocks(3, state, []types.PrivValidator{privVal}) @@ -957,7 +935,7 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) { assert.Panics(t, func() { h := NewHandshaker(stateStore, state, store, genDoc) - if err = h.Handshake(proxyApp); err != nil { + if err = h.Handshake(context.Background(), proxyApp); err != nil { t.Log(err) } }) @@ -981,7 +959,7 @@ func TestHandshakePanicsIfAppReturnsWrongAppHash(t *testing.T) { assert.Panics(t, func() { h := NewHandshaker(stateStore, state, store, genDoc) - if err = h.Handshake(proxyApp); err != nil { + if err = h.Handshake(context.Background(), proxyApp); err != nil { t.Log(err) } }) @@ -996,21 +974,21 @@ type badApp struct { onlyLastHashIsWrong bool } -func (app *badApp) FinalizeBlock(_ context.Context, req *abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) { +func (app *badApp) FinalizeBlock(context.Context, *abci.FinalizeBlockRequest) (*abci.FinalizeBlockResponse, error) { app.height++ if app.onlyLastHashIsWrong { if app.height == app.numBlocks { - return &abci.ResponseFinalizeBlock{AppHash: cmtrand.Bytes(8)}, nil + return &abci.FinalizeBlockResponse{AppHash: cmtrand.Bytes(8)}, nil } - return &abci.ResponseFinalizeBlock{AppHash: []byte{app.height}}, nil + return &abci.FinalizeBlockResponse{AppHash: []byte{app.height}}, nil } else if app.allHashesAreWrong { - return &abci.ResponseFinalizeBlock{AppHash: cmtrand.Bytes(8)}, nil + return &abci.FinalizeBlockResponse{AppHash: cmtrand.Bytes(8)}, nil } panic("either allHashesAreWrong or onlyLastHashIsWrong must be set") } -//-------------------------- +// -------------------------- // utils for making blocks func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.ExtendedCommit, error) { @@ -1072,7 +1050,7 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.ExtendedCommit, er } commitHeight := thisBlockExtCommit.Height if commitHeight != height+1 { - panic(fmt.Sprintf("commit doesnt match. got height %d, expected %d", commitHeight, height+1)) + panic(fmt.Sprintf("commit doesn't match. got height %d, expected %d", commitHeight, height+1)) } blocks = append(blocks, block) extCommits = append(extCommits, thisBlockExtCommit) @@ -1086,7 +1064,7 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.ExtendedCommit, er return nil, nil, err } case *types.Vote: - if p.Type == cmtproto.PrecommitType { + if p.Type == types.PrecommitType { thisBlockExtCommit = &types.ExtendedCommit{ Height: p.Height, Round: p.Round, @@ -1115,14 +1093,14 @@ func makeBlockchainFromWAL(wal WAL) ([]*types.Block, []*types.ExtendedCommit, er } commitHeight := thisBlockExtCommit.Height if commitHeight != height+1 { - panic(fmt.Sprintf("commit doesnt match. got height %d, expected %d", commitHeight, height+1)) + panic(fmt.Sprintf("commit doesn't match. got height %d, expected %d", commitHeight, height+1)) } blocks = append(blocks, block) extCommits = append(extCommits, thisBlockExtCommit) return blocks, extCommits, nil } -func readPieceFromWAL(msg *TimedWALMessage) interface{} { +func readPieceFromWAL(msg *TimedWALMessage) any { // for logging switch m := msg.Msg.(type) { case msgInfo: @@ -1141,13 +1119,13 @@ func readPieceFromWAL(msg *TimedWALMessage) interface{} { return nil } -// fresh state and mock store +// fresh state and mock store. func stateAndStore( t *testing.T, config *cfg.Config, - pubKey crypto.PubKey, appVersion uint64, ) (dbm.DB, sm.State, *mockBlockStore) { + t.Helper() stateDB := dbm.NewMemDB() stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, @@ -1161,7 +1139,7 @@ func stateAndStore( return stateDB, state, store } -//---------------------------------- +// ---------------------------------- // mock block store type mockBlockStore struct { @@ -1177,6 +1155,7 @@ var _ sm.BlockStore = &mockBlockStore{} // TODO: NewBlockStore(db.NewMemDB) ... func newMockBlockStore(t *testing.T, config *cfg.Config, params types.ConsensusParams) *mockBlockStore { + t.Helper() return &mockBlockStore{ config: config, params: params, @@ -1184,15 +1163,19 @@ func newMockBlockStore(t *testing.T, config *cfg.Config, params types.ConsensusP } } -func (bs *mockBlockStore) Height() int64 { return int64(len(bs.chain)) } -func (bs *mockBlockStore) Base() int64 { return bs.base } -func (bs *mockBlockStore) Size() int64 { return bs.Height() - bs.Base() + 1 } -func (bs *mockBlockStore) LoadBaseMeta() *types.BlockMeta { return bs.LoadBlockMeta(bs.base) } -func (bs *mockBlockStore) LoadBlock(height int64) *types.Block { return bs.chain[height-1] } -func (bs *mockBlockStore) LoadBlockByHash(hash []byte) *types.Block { - return bs.chain[int64(len(bs.chain))-1] +func (bs *mockBlockStore) Height() int64 { return int64(len(bs.chain)) } +func (bs *mockBlockStore) Base() int64 { return bs.base } +func (bs *mockBlockStore) Size() int64 { return bs.Height() - bs.Base() + 1 } +func (bs *mockBlockStore) LoadBaseMeta() *types.BlockMeta { return bs.LoadBlockMeta(bs.base) } +func (bs *mockBlockStore) LoadBlock(height int64) (*types.Block, *types.BlockMeta) { + return bs.chain[height-1], bs.LoadBlockMeta(height) +} + +func (bs *mockBlockStore) LoadBlockByHash([]byte) (*types.Block, *types.BlockMeta) { + height := int64(len(bs.chain)) + return bs.chain[height-1], bs.LoadBlockMeta(height) } -func (bs *mockBlockStore) LoadBlockMetaByHash(hash []byte) *types.BlockMeta { return nil } +func (*mockBlockStore) LoadBlockMetaByHash([]byte) *types.BlockMeta { return nil } func (bs *mockBlockStore) LoadBlockMeta(height int64) *types.BlockMeta { block := bs.chain[height-1] bps, err := block.MakePartSet(types.BlockPartSizeBytes) @@ -1202,10 +1185,11 @@ func (bs *mockBlockStore) LoadBlockMeta(height int64) *types.BlockMeta { Header: block.Header, } } -func (bs *mockBlockStore) LoadBlockPart(height int64, index int) *types.Part { return nil } -func (bs *mockBlockStore) SaveBlockWithExtendedCommit(block *types.Block, blockParts *types.PartSet, seenCommit *types.ExtendedCommit) { +func (*mockBlockStore) LoadBlockPart(int64, int) *types.Part { return nil } +func (*mockBlockStore) SaveBlockWithExtendedCommit(*types.Block, *types.PartSet, *types.ExtendedCommit) { } -func (bs *mockBlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenCommit *types.Commit) { + +func (*mockBlockStore) SaveBlock(*types.Block, *types.PartSet, *types.Commit) { } func (bs *mockBlockStore) LoadBlockCommit(height int64) *types.Commit { @@ -1215,11 +1199,12 @@ func (bs *mockBlockStore) LoadBlockCommit(height int64) *types.Commit { func (bs *mockBlockStore) LoadSeenCommit(height int64) *types.Commit { return bs.extCommits[height-1].ToCommit() } + func (bs *mockBlockStore) LoadBlockExtendedCommit(height int64) *types.ExtendedCommit { return bs.extCommits[height-1] } -func (bs *mockBlockStore) PruneBlocks(height int64, state sm.State) (uint64, int64, error) { +func (bs *mockBlockStore) PruneBlocks(height int64, _ sm.State) (uint64, int64, error) { evidencePoint := height pruned := uint64(0) for i := int64(0); i < height-1; i++ { @@ -1231,30 +1216,27 @@ func (bs *mockBlockStore) PruneBlocks(height int64, state sm.State) (uint64, int return pruned, evidencePoint, nil } -func (bs *mockBlockStore) DeleteLatestBlock() error { return nil } -func (bs *mockBlockStore) Close() error { return nil } +func (*mockBlockStore) DeleteLatestBlock() error { return nil } +func (*mockBlockStore) Close() error { return nil } -//--------------------------------------- +// --------------------------------------- // Test handshake/init chain func TestHandshakeUpdatesValidators(t *testing.T) { val, _ := types.RandValidator(true, 10) vals := types.NewValidatorSet([]*types.Validator{val}) app := &mocks.Application{} - app.On("Info", mock.Anything, mock.Anything).Return(&abci.ResponseInfo{ + app.On("Info", mock.Anything, mock.Anything).Return(&abci.InfoResponse{ LastBlockHeight: 0, }, nil) - app.On("InitChain", mock.Anything, mock.Anything).Return(&abci.ResponseInitChain{ + app.On("InitChain", mock.Anything, mock.Anything).Return(&abci.InitChainResponse{ Validators: types.TM2PB.ValidatorUpdates(vals), }, nil) clientCreator := proxy.NewLocalClientCreator(app) config := ResetConfig("handshake_test_") defer os.RemoveAll(config.RootDir) - privVal := privval.LoadFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - stateDB, state, store := stateAndStore(t, config, pubKey, 0x0) + stateDB, state, store := stateAndStore(t, config, 0x0) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -1273,9 +1255,10 @@ func TestHandshakeUpdatesValidators(t *testing.T) { t.Error(err) } }) - if err := handshaker.Handshake(proxyApp); err != nil { + if err := handshaker.Handshake(context.Background(), proxyApp); err != nil { t.Fatalf("Error on abci handshake: %v", err) } + var err error // reload the state, check the validator set was updated state, err = stateStore.Load() require.NoError(t, err) diff --git a/consensus/state.go b/internal/consensus/state.go similarity index 76% rename from consensus/state.go rename to internal/consensus/state.go index 47a4c733fcb..868e43e3396 100644 --- a/consensus/state.go +++ b/internal/consensus/state.go @@ -9,47 +9,40 @@ import ( "os" "runtime/debug" "sort" + "strconv" "time" "github.com/cosmos/gogoproto/proto" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" cfg "github.com/cometbft/cometbft/config" - cstypes "github.com/cometbft/cometbft/consensus/types" "github.com/cometbft/cometbft/crypto" - cmtevents "github.com/cometbft/cometbft/libs/events" - "github.com/cometbft/cometbft/libs/fail" + cstypes "github.com/cometbft/cometbft/internal/consensus/types" + cmtevents "github.com/cometbft/cometbft/internal/events" + "github.com/cometbft/cometbft/internal/fail" + cmtos "github.com/cometbft/cometbft/internal/os" + "github.com/cometbft/cometbft/internal/service" + sm "github.com/cometbft/cometbft/internal/state" + cmtsync "github.com/cometbft/cometbft/internal/sync" cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtos "github.com/cometbft/cometbft/libs/os" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/p2p" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" cmttime "github.com/cometbft/cometbft/types/time" ) -// Consensus sentinel errors -var ( - ErrInvalidProposalSignature = errors.New("error invalid proposal signature") - ErrInvalidProposalPOLRound = errors.New("error invalid proposal POL round") - ErrAddingVote = errors.New("error adding vote") - ErrSignatureFoundInPastBlocks = errors.New("found signature from the same key") - - errPubKeyIsNotSet = errors.New("pubkey is not set. Look for \"Can't get private validator pubkey\" errors") -) - var msgQueueSize = 1000 -// msgs from the reactor which may update the state +// msgs from the reactor which may update the state. type msgInfo struct { - Msg Message `json:"msg"` - PeerID p2p.ID `json:"peer_key"` + Msg Message `json:"msg"` + PeerID p2p.ID `json:"peer_key"` + ReceiveTime time.Time `json:"receive_time"` } -// internally generated messages which may update the state +// internally generated messages which may update the state. type timeoutInfo struct { Duration time.Duration `json:"duration"` Height int64 `json:"height"` @@ -61,12 +54,12 @@ func (ti *timeoutInfo) String() string { return fmt.Sprintf("%v ; %d/%d %v", ti.Duration, ti.Height, ti.Round, ti.Step) } -// interface to the mempool +// interface to the mempool. type txNotifier interface { TxsAvailable() <-chan struct{} } -// interface to the evidence pool +// interface to the evidence pool. type evidencePool interface { // reports conflicting votes to the evidence pool to be processed into evidence ReportConflictingVotes(voteA, voteB *types.Vote) @@ -130,7 +123,7 @@ type State struct { // some functions can be overwritten for testing decideProposal func(height int64, round int32) doPrevote func(height int64, round int32) - setProposal func(proposal *types.Proposal) error + setProposal func(proposal *types.Proposal, t time.Time) error // closed when we finish shutting down done chan struct{} @@ -141,6 +134,9 @@ type State struct { // for reporting metrics metrics *Metrics + + // offline state sync height indicating to which height the node synced offline + offlineStateSyncHeight int64 } // StateOption sets an optional parameter on the State. @@ -172,7 +168,9 @@ func NewState( evsw: cmtevents.NewEventSwitch(), metrics: NopMetrics(), } - + for _, option := range options { + option(cs) + } // set function defaults (may be overwritten before calling Start) cs.decideProposal = cs.defaultDecideProposal cs.doPrevote = cs.defaultDoPrevote @@ -180,7 +178,16 @@ func NewState( // We have no votes, so reconstruct LastCommit from SeenCommit. if state.LastBlockHeight > 0 { - cs.reconstructLastCommit(state) + // In case of out of band performed statesync, the state store + // will have a state but no extended commit (as no block has been downloaded). + // If the height at which the vote extensions are enabled is lower + // than the height at which we statesync, consensus will panic because + // it will try to reconstruct the extended commit here. + if cs.offlineStateSyncHeight != 0 { + cs.reconstructSeenCommit(state) + } else { + cs.reconstructLastCommit(state) + } } cs.updateToState(state) @@ -188,9 +195,6 @@ func NewState( // NOTE: we do not call scheduleRound0 yet, we do that upon Start() cs.BaseService = *service.NewBaseService(nil, "State", cs) - for _, option := range options { - option(cs) - } return cs } @@ -212,8 +216,14 @@ func StateMetrics(metrics *Metrics) StateOption { return func(cs *State) { cs.metrics = metrics } } +// OfflineStateSyncHeight indicates the height at which the node +// statesync offline - before booting sets the metrics. +func OfflineStateSyncHeight(height int64) StateOption { + return func(cs *State) { cs.offlineStateSyncHeight = height } +} + // String returns a string. -func (cs *State) String() string { +func (*State) String() string { // better not to access shared variables return "ConsensusState" } @@ -248,7 +258,7 @@ func (cs *State) GetRoundStateJSON() ([]byte, error) { return cmtjson.Marshal(cs.RoundState) } -// GetRoundStateSimpleJSON returns a json of RoundStateSimple +// GetRoundStateSimpleJSON returns a json of RoundStateSimple. func (cs *State) GetRoundStateSimpleJSON() ([]byte, error) { cs.mtx.RLock() defer cs.mtx.RUnlock() @@ -345,7 +355,7 @@ func (cs *State) OnStart() error { repairAttempted = true // 2) backup original WAL file - corruptedFile := fmt.Sprintf("%s.CORRUPTED", cs.config.WalFile()) + corruptedFile := cs.config.WalFile() + ".CORRUPTED" if err := cmtos.CopyFile(cs.config.WalFile(), corruptedFile); err != nil { return err } @@ -387,7 +397,9 @@ func (cs *State) OnStart() error { } // timeoutRoutine: receive requests for timeouts on tickChan and fire timeouts on tockChan -// receiveRoutine: serializes processing of proposoals, block parts, votes; coordinates state transitions +// receiveRoutine: serializes processing of proposoals, block parts, votes; coordinates state transitions. +// + func (cs *State) startRoutines(maxSteps int) { err := cs.timeoutTicker.Start() if err != nil { @@ -422,9 +434,9 @@ func (cs *State) OnStop() { // WAL is stopped in receiveRoutine. } -// Wait waits for the the main routine to return. +// Wait waits for the main routine to return. // NOTE: be sure to Stop() the event switch and drain -// any event channels or this may deadlock +// any event channels or this may deadlock. func (cs *State) Wait() { <-cs.done } @@ -448,7 +460,7 @@ func (cs *State) OpenWAL(walFile string) (WAL, error) { return wal, nil } -//------------------------------------------------------------ +// ------------------------------------------------------------ // Public interface for passing messages into the consensus state, possibly causing a state transition. // If peerID == "", the msg is considered internal. // Messages are added to the appropriate queue (peer or internal). @@ -458,9 +470,9 @@ func (cs *State) OpenWAL(walFile string) (WAL, error) { // AddVote inputs a vote. func (cs *State) AddVote(vote *types.Vote, peerID p2p.ID) (added bool, err error) { if peerID == "" { - cs.internalMsgQueue <- msgInfo{&VoteMessage{vote}, ""} + cs.internalMsgQueue <- msgInfo{&VoteMessage{vote}, "", time.Time{}} } else { - cs.peerMsgQueue <- msgInfo{&VoteMessage{vote}, peerID} + cs.peerMsgQueue <- msgInfo{&VoteMessage{vote}, peerID, time.Time{}} } // TODO: wait for event?! @@ -469,11 +481,10 @@ func (cs *State) AddVote(vote *types.Vote, peerID p2p.ID) (added bool, err error // SetProposal inputs a proposal. func (cs *State) SetProposal(proposal *types.Proposal, peerID p2p.ID) error { - if peerID == "" { - cs.internalMsgQueue <- msgInfo{&ProposalMessage{proposal}, ""} + cs.internalMsgQueue <- msgInfo{&ProposalMessage{proposal}, "", cmttime.Now()} } else { - cs.peerMsgQueue <- msgInfo{&ProposalMessage{proposal}, peerID} + cs.peerMsgQueue <- msgInfo{&ProposalMessage{proposal}, peerID, cmttime.Now()} } // TODO: wait for event?! @@ -482,11 +493,10 @@ func (cs *State) SetProposal(proposal *types.Proposal, peerID p2p.ID) error { // AddProposalBlockPart inputs a part of the proposal block. func (cs *State) AddProposalBlockPart(height int64, round int32, part *types.Part, peerID p2p.ID) error { - if peerID == "" { - cs.internalMsgQueue <- msgInfo{&BlockPartMessage{height, round, part}, ""} + cs.internalMsgQueue <- msgInfo{&BlockPartMessage{height, round, part}, "", time.Time{}} } else { - cs.peerMsgQueue <- msgInfo{&BlockPartMessage{height, round, part}, peerID} + cs.peerMsgQueue <- msgInfo{&BlockPartMessage{height, round, part}, peerID, time.Time{}} } // TODO: wait for event?! @@ -496,11 +506,10 @@ func (cs *State) AddProposalBlockPart(height int64, round int32, part *types.Par // SetProposalAndBlock inputs the proposal and all block parts. func (cs *State) SetProposalAndBlock( proposal *types.Proposal, - block *types.Block, parts *types.PartSet, peerID p2p.ID, ) error { - + // TODO: Since the block parameter is not used, we should instead expose just a SetProposal method. if err := cs.SetProposal(proposal, peerID); err != nil { return err } @@ -515,7 +524,7 @@ func (cs *State) SetProposalAndBlock( return nil } -//------------------------------------------------------------ +// ------------------------------------------------------------ // internal functions for managing the state func (cs *State) updateHeight(height int64) { @@ -543,12 +552,12 @@ func (cs *State) scheduleRound0(rs *cstypes.RoundState) { cs.scheduleTimeout(sleepDuration, rs.Height, 0, cstypes.RoundStepNewHeight) } -// Attempt to schedule a timeout (by sending timeoutInfo on the tickChan) +// Attempt to schedule a timeout (by sending timeoutInfo on the tickChan). func (cs *State) scheduleTimeout(duration time.Duration, height int64, round int32, step cstypes.RoundStepType) { cs.timeoutTicker.ScheduleTimeout(timeoutInfo{duration, height, round, step}) } -// send a msg into the receiveRoutine regarding our own proposal, block part, or vote +// send a msg into the receiveRoutine regarding our own proposal, block part, or vote. func (cs *State) sendInternalMessage(mi msgInfo) { select { case cs.internalMsgQueue <- mi: @@ -562,21 +571,28 @@ func (cs *State) sendInternalMessage(mi msgInfo) { } } +// ReconstructSeenCommit reconstructs the seen commit +// This function is meant to be called after statesync +// that was performed offline as to avoid interfering with vote +// extensions. +func (cs *State) reconstructSeenCommit(state sm.State) { + votes, err := cs.votesFromSeenCommit(state) + if err != nil { + panic(fmt.Sprintf("failed to reconstruct last commit; %s", err)) + } + cs.LastCommit = votes +} + // Reconstruct the LastCommit from either SeenCommit or the ExtendedCommit. SeenCommit // and ExtendedCommit are saved along with the block. If VoteExtensions are required // the method will panic on an absent ExtendedCommit or an ExtendedCommit without // extension data. func (cs *State) reconstructLastCommit(state sm.State) { - extensionsEnabled := state.ConsensusParams.ABCI.VoteExtensionsEnabled(state.LastBlockHeight) + extensionsEnabled := state.ConsensusParams.Feature.VoteExtensionsEnabled(state.LastBlockHeight) if !extensionsEnabled { - votes, err := cs.votesFromSeenCommit(state) - if err != nil { - panic(fmt.Sprintf("failed to reconstruct last commit; %s", err)) - } - cs.LastCommit = votes + cs.reconstructSeenCommit(state) return } - votes, err := cs.votesFromExtendedCommit(state) if err != nil { panic(fmt.Sprintf("failed to reconstruct last extended commit; %s", err)) @@ -595,7 +611,7 @@ func (cs *State) votesFromExtendedCommit(state sm.State) (*types.VoteSet, error) } vs := ec.ToExtendedVoteSet(state.ChainID, state.LastValidators) if !vs.HasTwoThirdsMajority() { - return nil, errors.New("extended commit does not have +2/3 majority") + return nil, ErrCommitQuorumNotMet } return vs, nil } @@ -614,7 +630,7 @@ func (cs *State) votesFromSeenCommit(state sm.State) (*types.VoteSet, error) { } vs := commit.ToVoteSet(state.ChainID, state.LastValidators) if !vs.HasTwoThirdsMajority() { - return nil, errors.New("commit does not have +2/3 majority") + return nil, ErrCommitQuorumNotMet } return vs, nil } @@ -709,6 +725,7 @@ func (cs *State) updateToState(state sm.State) { cs.Validators = validators cs.Proposal = nil + cs.ProposalReceiveTime = time.Time{} cs.ProposalBlock = nil cs.ProposalBlockParts = nil cs.LockedRound = -1 @@ -717,7 +734,7 @@ func (cs *State) updateToState(state sm.State) { cs.ValidRound = -1 cs.ValidBlock = nil cs.ValidBlockParts = nil - if state.ConsensusParams.ABCI.VoteExtensionsEnabled(height) { + if state.ConsensusParams.Feature.VoteExtensionsEnabled(height) { cs.Votes = cstypes.NewExtendedHeightVoteSet(state.ChainID, height, validators) } else { cs.Votes = cstypes.NewHeightVoteSet(state.ChainID, height, validators) @@ -750,7 +767,7 @@ func (cs *State) newStep() { } } -//----------------------------------------- +// ----------------------------------------- // the main go routines // receiveRoutine handles messages which may cause state transitions. @@ -848,7 +865,7 @@ func (cs *State) receiveRoutine(maxSteps int) { } } -// state transitions on complete-proposal, 2/3-any, 2/3-one +// state transitions on complete-proposal, 2/3-any, 2/3-one. func (cs *State) handleMsg(mi msgInfo) { cs.mtx.Lock() defer cs.mtx.Unlock() @@ -863,13 +880,13 @@ func (cs *State) handleMsg(mi msgInfo) { case *ProposalMessage: // will not cause transition. // once proposal is set, we can receive block parts - err = cs.setProposal(msg.Proposal) + err = cs.setProposal(msg.Proposal, mi.ReceiveTime) case *BlockPartMessage: // if the proposal is complete, we'll enterPrevote or tryFinalizeCommit added, err = cs.addProposalBlockPart(msg, peerID) - // We unlock here to yield to any routines that need to read the the RoundState. + // We unlock here to yield to any routines that need to read the RoundState. // Previously, this code held the lock from the point at which the final block // part was received until the block executed against the application. // This prevented the reactor from being able to retrieve the most updated @@ -985,9 +1002,8 @@ func (cs *State) handleTimeout(ti timeoutInfo, rs cstypes.RoundState) { cs.enterNewRound(ti.Height, ti.Round+1) default: - panic(fmt.Sprintf("invalid timeout step: %v", ti.Step)) + panic(cmterrors.ErrInvalidField{Field: "timeout_step"}) } - } func (cs *State) handleTxsAvailable() { @@ -1015,7 +1031,7 @@ func (cs *State) handleTxsAvailable() { } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // State functions // Used internally by handleTimeout and handleMsg to make state transitions @@ -1042,7 +1058,7 @@ func (cs *State) enterNewRound(height int64, round int32) { logger.Debug("need to set a buffer and log message here for sanity", "start_time", cs.StartTime, "now", now) } - logger.Debug("entering new round", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) + prevHeight, prevRound, prevStep := cs.Height, cs.Round, cs.Step // increment validators if necessary validators := cs.Validators @@ -1056,17 +1072,22 @@ func (cs *State) enterNewRound(height int64, round int32) { // but we fire an event, so update the round step first cs.updateRoundStep(round, cstypes.RoundStepNewRound) cs.Validators = validators - if round == 0 { - // We've already reset these upon new height, - // and meanwhile we might have received a proposal - // for round 0. - } else { - logger.Debug("resetting proposal info") + // If round == 0, we've already reset these upon new height, and meanwhile + // we might have received a proposal for round 0. + propAddress := validators.GetProposer().PubKey.Address() + if round != 0 { + logger.Info("resetting proposal info", "proposer", propAddress) cs.Proposal = nil + cs.ProposalReceiveTime = time.Time{} cs.ProposalBlock = nil cs.ProposalBlockParts = nil } + logger.Debug("entering new round", + "previous", log.NewLazySprintf("%v/%v/%v", prevHeight, prevRound, prevStep), + "proposer", propAddress, + ) + cs.Votes.SetRound(cmtmath.SafeAddInt32(round, 1)) // also track next round (round+1) to allow round-skipping cs.TriggeredTimeoutPrecommit = false @@ -1082,13 +1103,14 @@ func (cs *State) enterNewRound(height int64, round int32) { cs.scheduleTimeout(cs.config.CreateEmptyBlocksInterval, height, round, cstypes.RoundStepNewRound) } - } else { - cs.enterPropose(height, round) + return } + + cs.enterPropose(height, round) } // needProofBlock returns true on the first height (so the genesis app hash is signed right away) -// and where the last block (height-1) caused the app hash to change +// and where the last block (height-1) caused the app hash to change. func (cs *State) needProofBlock(height int64) bool { if height == cs.state.InitialHeight { return true @@ -1109,7 +1131,7 @@ func (cs *State) needProofBlock(height int64) bool { // // after enterNewRound(height,round), after timeout of CreateEmptyBlocksInterval // -// Enter (!CreateEmptyBlocks) : after enterNewRound(height,round), once txs are in the mempool +// Enter (!CreateEmptyBlocks) : after enterNewRound(height,round), once txs are in the mempool. func (cs *State) enterPropose(height int64, round int32) { logger := cs.Logger.With("height", height, "round", round) @@ -1121,6 +1143,16 @@ func (cs *State) enterPropose(height int64, round int32) { return } + // If this validator is the proposer of this round, and the previous block time is later than + // our local clock time, wait to propose until our local clock time has passed the block time. + if cs.isPBTSEnabled(height) && cs.privValidatorPubKey != nil && cs.isProposer(cs.privValidatorPubKey.Address()) { + proposerWaitTime := proposerWaitTime(cmttime.DefaultSource{}, cs.state.LastBlockTime) + if proposerWaitTime > 0 { + cs.scheduleTimeout(proposerWaitTime, height, round, cstypes.RoundStepNewRound) + return + } + } + logger.Debug("entering propose step", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) defer func() { @@ -1141,29 +1173,29 @@ func (cs *State) enterPropose(height int64, round int32) { // Nothing more to do if we're not a validator if cs.privValidator == nil { - logger.Debug("node is not a validator") + logger.Debug("propose step; not proposing since node is not a validator") return } - logger.Debug("node is a validator") - if cs.privValidatorPubKey == nil { // If this node is a validator & proposer in the current round, it will // miss the opportunity to create a block. - logger.Error("propose step; empty priv validator public key", "err", errPubKeyIsNotSet) + logger.Error("propose step; empty priv validator public key", "err", ErrPubKeyIsNotSet) return } - address := cs.privValidatorPubKey.Address() + addr := cs.privValidatorPubKey.Address() // if not a validator, we're done - if !cs.Validators.HasAddress(address) { - logger.Debug("node is not a validator", "addr", address, "vals", cs.Validators) + if !cs.Validators.HasAddress(addr) { + logger.Debug("propose step; not proposing since node is not in the validator set", + "addr", addr, + "vals", cs.Validators) return } - if cs.isProposer(address) { - logger.Debug("propose step; our turn to propose", "proposer", address) + if cs.isProposer(addr) { + logger.Debug("propose step; our turn to propose", "proposer", addr) cs.decideProposal(height, round) } else { logger.Debug("propose step; not our turn to propose", "proposer", cs.Validators.GetProposer().Address) @@ -1208,17 +1240,17 @@ func (cs *State) defaultDecideProposal(height int64, round int32) { // Make proposal propBlockID := types.BlockID{Hash: block.Hash(), PartSetHeader: blockParts.Header()} - proposal := types.NewProposal(height, round, cs.ValidRound, propBlockID) + proposal := types.NewProposal(height, round, cs.ValidRound, propBlockID, block.Header.Time) p := proposal.ToProto() if err := cs.privValidator.SignProposal(cs.state.ChainID, p); err == nil { proposal.Signature = p.Signature // send proposal and block parts on internal msg queue - cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""}) + cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, "", cmttime.Now()}) for i := 0; i < int(blockParts.Total()); i++ { part := blockParts.GetPart(i) - cs.sendInternalMessage(msgInfo{&BlockPartMessage{cs.Height, cs.Round, part}, ""}) + cs.sendInternalMessage(msgInfo{&BlockPartMessage{cs.Height, cs.Round, part}, "", time.Time{}}) } cs.Logger.Debug("signed proposal", "height", height, "round", round, "proposal", proposal) @@ -1240,7 +1272,6 @@ func (cs *State) isProposalComplete() bool { } // if this is false the proposer is lying or we haven't received the POL yet return cs.Votes.Prevotes(cs.Proposal.POLRound).HasTwoThirdsMajority() - } // Create the next block to propose and return it. Returns nil block upon error. @@ -1252,7 +1283,7 @@ func (cs *State) isProposalComplete() bool { // CONTRACT: cs.privValidator is not nil. func (cs *State) createProposalBlock(ctx context.Context) (*types.Block, error) { if cs.privValidator == nil { - return nil, errors.New("entered createProposalBlock with privValidator being nil") + return nil, ErrNilPrivValidator } // TODO(sergio): wouldn't it be easier if CreateProposalBlock accepted cs.LastCommit directly? @@ -1265,16 +1296,16 @@ func (cs *State) createProposalBlock(ctx context.Context) (*types.Block, error) case cs.LastCommit.HasTwoThirdsMajority(): // Make the commit from LastCommit - lastExtCommit = cs.LastCommit.MakeExtendedCommit(cs.state.ConsensusParams.ABCI) + lastExtCommit = cs.LastCommit.MakeExtendedCommit(cs.state.ConsensusParams.Feature) default: // This shouldn't happen. - return nil, errors.New("propose step; cannot propose anything without commit for the previous block") + return nil, ErrProposalWithoutPreviousCommit } if cs.privValidatorPubKey == nil { // If this node is a validator & proposer in the current round, it will // miss the opportunity to create a block. - return nil, fmt.Errorf("propose step; empty priv validator public key, error: %w", errPubKeyIsNotSet) + return nil, fmt.Errorf("propose step; empty priv validator public key, error: %w", ErrPubKeyIsNotSet) } proposerAddr := cs.privValidatorPubKey.Address() @@ -1286,10 +1317,14 @@ func (cs *State) createProposalBlock(ctx context.Context) (*types.Block, error) return ret, nil } -// Enter: `timeoutPropose` after entering Propose. -// Enter: proposal block and POL is ready. -// Prevote for LockedBlock if we're locked, or ProposalBlock if valid. -// Otherwise vote nil. +// Enter: isProposalComplete() and Step <= RoundStepPropose. +// Enter: `timeout_propose` (timeout of RoundStepPropose type) expires. +// +// If we received a valid proposal and the associated proposed block within +// this round and: (i) we are not locked on a block, or we are locked on the +// proposed block, or (ii) the proposed block received a POL in a round greater +// or equal than our locked round, we will prevote for the poroposed block ID. +// Otherwise, we prevote nil. func (cs *State) enterPrevote(height int64, round int32) { logger := cs.Logger.With("height", height, "round", round) @@ -1316,64 +1351,208 @@ func (cs *State) enterPrevote(height int64, round int32) { // (so we have more time to try and collect +2/3 prevotes for a single block) } +func (cs *State) timelyProposalMargins() (time.Duration, time.Duration) { + sp := cs.state.ConsensusParams.Synchrony.InRound(cs.Round) + + // cs.ProposalReceiveTime - cs.Proposal.Timestamp >= -1 * Precision + // cs.ProposalReceiveTime - cs.Proposal.Timestamp <= MessageDelay + Precision + return -sp.Precision, sp.MessageDelay + sp.Precision +} + +func (cs *State) proposalIsTimely() bool { + sp := cs.state.ConsensusParams.Synchrony.InRound(cs.Proposal.Round) + + return cs.Proposal.IsTimely(cs.ProposalReceiveTime, sp) +} + +// Implements doPrevote. Called by enterPrevote(height, round) provided that +// round == cs.Round, height == cs.Height, and cs.Step <= // RoundStepPropose. func (cs *State) defaultDoPrevote(height int64, round int32) { logger := cs.Logger.With("height", height, "round", round) - // If a block is locked, prevote that. - if cs.LockedBlock != nil { - logger.Debug("prevote step; already locked on a block; prevoting locked block") - cs.signAddVote(cmtproto.PrevoteType, cs.LockedBlock.Hash(), cs.LockedBlockParts.Header()) + // We did not receive a valid proposal for this round (and thus executing this from a timeout). + if cs.Proposal == nil { + logger.Debug("prevote step: did not receive a valid Proposal; prevoting nil") + cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) return } - // If ProposalBlock is nil, prevote nil. + // We did not (fully) receive the proposed block (and thus executing this from a timeout). if cs.ProposalBlock == nil { - logger.Debug("prevote step: ProposalBlock is nil") - cs.signAddVote(cmtproto.PrevoteType, nil, types.PartSetHeader{}) + logger.Debug("prevote step: did not receive the ProposalBlock; prevoting nil") + cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) return } + // Timestamp validation using Proposed-Based TimeStamp (PBTS) algorithm. + // See: https://github.com/cometbft/cometbft/blob/main/spec/consensus/proposer-based-timestamp/ + if cs.isPBTSEnabled(height) { + if !cs.Proposal.Timestamp.Equal(cs.ProposalBlock.Header.Time) { + logger.Debug("prevote step: proposal timestamp not equal; prevoting nil") + cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) + return + } + + if cs.Proposal.POLRound == -1 && !cs.proposalIsTimely() { + lowerBound, upperBound := cs.timelyProposalMargins() + // TODO: use Warn level once available. + logger.Info("prevote step: Proposal is not timely; prevoting nil", + "timestamp", cs.Proposal.Timestamp.Format(time.RFC3339Nano), + "receive_time", cs.ProposalReceiveTime.Format(time.RFC3339Nano), + "timestamp_difference", cs.ProposalReceiveTime.Sub(cs.Proposal.Timestamp), + "lower_bound", lowerBound, + "upper_bound", upperBound) + cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) + return + } + + if cs.Proposal.POLRound == -1 { + logger.Debug("prevote step: Proposal is timely", + "timestamp", cs.Proposal.Timestamp.Format(time.RFC3339Nano), + "receive_time", cs.ProposalReceiveTime.Format(time.RFC3339Nano), + "timestamp_difference", cs.ProposalReceiveTime.Sub(cs.Proposal.Timestamp)) + } + } + // Validate proposal block, from consensus' perspective err := cs.blockExec.ValidateBlock(cs.state, cs.ProposalBlock) if err != nil { // ProposalBlock is invalid, prevote nil. logger.Error("prevote step: consensus deems this block invalid; prevoting nil", "err", err) - cs.signAddVote(cmtproto.PrevoteType, nil, types.PartSetHeader{}) + cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) return } /* - Before prevoting on the block received from the proposer for the current round and height, - we request the Application, via `ProcessProposal` ABCI call, to confirm that the block is - valid. If the Application does not accept the block, consensus prevotes `nil`. - - WARNING: misuse of block rejection by the Application can seriously compromise - the liveness properties of consensus. - Please see `PrepareProosal`-`ProcessProposal` coherence and determinism properties - in the ABCI++ specification. + 22: upon from proposer(h_p, round_p) while step_p = propose do + 23: if valid(v) && (lockedRound_p = −1 || lockedValue_p = v) then + 24: broadcast + 25: else + 26: broadcast + + Here, cs.Proposal.POLRound corresponds to the -1 in the rule of the pseude-code (line 22). + This means that the proposer is producing a new proposal that has not previously + seen a 2/3 majority by the network. + + If the application deems the proposal as valid AND we're not locked on a + block OR the proposal matches our locked block (line 23), we prevote the + proposal (line 24). + + Otherwise, we have already locked on a value that is different from the + proposed value, so we prevote nil (line 26). + + Note that there are two cases on which we know that the proposal is + application-valid, that is, it was validated by the application at least + by one correct node in a previous step: + - when the proposal matches our non-nil valid block AND we're not locked on a block, and + - when the proposal matches our non-nil locked block. + In these cases we do not need to query the application to validate the + proposal. */ - isAppValid, err := cs.blockExec.ProcessProposal(cs.ProposalBlock, cs.state) - if err != nil { - panic(fmt.Sprintf( - "state machine returned an error (%v) when calling ProcessProposal", err, - )) - } - cs.metrics.MarkProposalProcessed(isAppValid) + if cs.Proposal.POLRound == -1 { + if cs.LockedRound == -1 { + if cs.ValidRound != -1 && cs.ProposalBlock.HashesTo(cs.ValidBlock.Hash()) { + logger.Debug("prevote step: ProposalBlock matches our valid block; prevoting the proposal") + cs.signAddVote(types.PrevoteType, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header(), nil) + return + } - // Vote nil if the Application rejected the block - if !isAppValid { - logger.Error("prevote step: state machine rejected a proposed block; this should not happen:"+ - "the proposer may be misbehaving; prevoting nil", "err", err) - cs.signAddVote(cmtproto.PrevoteType, nil, types.PartSetHeader{}) + // We request the Application, via a `ProcessProposal` ABCI call, to + // confirm that the block is valid. If the application does not + // accept the block, consensus prevotes nil. + // + // WARNING: misuse of block rejection by the Application can seriously compromise + // the liveness properties of consensus. + // Please see `PrepareProosal`-`ProcessProposal` coherence and determinism properties + // in the ABCI++ specification. + isAppValid, err := cs.blockExec.ProcessProposal(cs.ProposalBlock, cs.state) + if err != nil { + panic(fmt.Sprintf( + "state machine returned an error (%v) when calling ProcessProposal", err, + )) + } + cs.metrics.MarkProposalProcessed(isAppValid) + + if !isAppValid { + logger.Error("prevote step: state machine rejected a proposed block; this should not happen:"+ + "the proposer may be misbehaving; prevoting nil", "err", err) + cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) + return + } + + logger.Debug("prevote step: ProposalBlock is valid and there is no locked block; prevoting the proposal") + cs.signAddVote(types.PrevoteType, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header(), nil) + return + } + + if cs.ProposalBlock.HashesTo(cs.LockedBlock.Hash()) { + logger.Debug("prevote step: ProposalBlock is valid (POLRound is -1) and matches our locked block; prevoting the proposal") + cs.signAddVote(types.PrevoteType, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header(), nil) + return + } + + logger.Debug("prevote step: ProposalBlock is valid (POLRound is -1), but doesn't match our locked block; prevoting nil") + cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) return } - // Prevote cs.ProposalBlock - // NOTE: the proposal signature is validated when it is received, - // and the proposal block parts are validated as they are received (against the merkle hash in the proposal) - logger.Debug("prevote step: ProposalBlock is valid") - cs.signAddVote(cmtproto.PrevoteType, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header()) + /* + 28: upon from proposer(h_p, round_p) AND 2f + 1 while + step_p = propose && (v_r ≥ 0 && v_r < round_p) do + 29: if valid(v) && (lockedRound_p ≤ v_r || lockedValue_p = v) then + 30: broadcast + 31: else + 32: broadcast + + This rule is a bit confusing but breaks down as follows: + + First note that 'valid(v)' in line 29 states that we should request the + application to validate the proposal. We know that the proposal was + prevoted by a +2/3 majority, so it must have been prevoted and validated + at least by one correct node. Therefore it must be valid and in the + following cases we don't need to query the application again. + + If we see a proposal in the current round for value 'v' that lists its valid round as 'v_r' + AND this validator saw a 2/3 majority of the voting power prevote for 'v' in round 'v_r' (line 28), + then we will issue a prevote for 'v' in this round (line 30) if 'v' either matches our locked value OR + 'v_r' is a round greater than or equal to our current locked round (line 29). + Otherwise we prevote nil (line 32). + + Note that 'v_r' can be a round greater than to our current locked round if a 2/3 majority of + the network prevoted a value in round 'v_r' but we did not lock on it, possibly because we + missed the proposal in round 'v_r'. + */ + blockID, ok := cs.Votes.Prevotes(cs.Proposal.POLRound).TwoThirdsMajority() + ok = ok && !blockID.IsNil() + if ok && cs.ProposalBlock.HashesTo(blockID.Hash) && cs.Proposal.POLRound < cs.Round { + if cs.LockedRound < cs.Proposal.POLRound { + logger.Debug("prevote step: ProposalBlock is valid and received a 2/3" + + "majority in a round later than the locked round; prevoting the proposal") + cs.signAddVote(types.PrevoteType, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header(), nil) + return + } + if cs.ProposalBlock.HashesTo(cs.LockedBlock.Hash()) { + logger.Debug("prevote step: ProposalBlock is valid and matches our locked block; prevoting the proposal") + cs.signAddVote(types.PrevoteType, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header(), nil) + return + } + // If v_r = lockedRound_p we expect v to match lockedValue_p. If it is not the case, + // we have two 2/3+ majorities for different values at round v_r, meaning that the + // assumption of a 2/3+ majority of honest processes was violated. We should at + // least log this scenario, see: https://github.com/cometbft/cometbft/issues/1309. + if cs.LockedRound == cs.Proposal.POLRound { + logger.Info("prevote step: ProposalBlock is valid and received a 2/3" + + "majority at our locked round, while not matching our locked value;" + + "this can only happen when 1/3 or more validators are double signing; prevoting the proposal") + cs.signAddVote(types.PrevoteType, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header(), nil) + return + } + } + + logger.Debug("prevote step: ProposalBlock is valid but was not our locked block or " + + "did not receive a more recent majority; prevoting nil") + cs.signAddVote(types.PrevoteType, nil, types.PartSetHeader{}, nil) } // Enter: any +2/3 prevotes at next round. @@ -1411,7 +1590,6 @@ func (cs *State) enterPrevoteWait(height int64, round int32) { // Enter: `timeoutPrecommit` after any +2/3 precommits. // Enter: +2/3 precomits for block or nil. // Lock & precommit the ProposalBlock if we have enough prevotes for it (a POL in this round) -// else, unlock an existing lock and precommit nil if +2/3 of prevotes were nil, // else, precommit nil otherwise. func (cs *State) enterPrecommit(height int64, round int32) { logger := cs.Logger.With("height", height, "round", round) @@ -1443,7 +1621,7 @@ func (cs *State) enterPrecommit(height int64, round int32) { logger.Debug("precommit step; no +2/3 prevotes during enterPrecommit; precommitting nil") } - cs.signAddVote(cmtproto.PrecommitType, nil, types.PartSetHeader{}) + cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}, nil) return } @@ -1458,25 +1636,12 @@ func (cs *State) enterPrecommit(height int64, round int32) { panic(fmt.Sprintf("this POLRound should be %v but got %v", round, polRound)) } - // +2/3 prevoted nil. Unlock and precommit nil. - if len(blockID.Hash) == 0 { - if cs.LockedBlock == nil { - logger.Debug("precommit step; +2/3 prevoted for nil") - } else { - logger.Debug("precommit step; +2/3 prevoted for nil; unlocking") - cs.LockedRound = -1 - cs.LockedBlock = nil - cs.LockedBlockParts = nil - - if err := cs.eventBus.PublishEventUnlock(cs.RoundStateEvent()); err != nil { - logger.Error("failed publishing event unlock", "err", err) - } - } - - cs.signAddVote(cmtproto.PrecommitType, nil, types.PartSetHeader{}) + // +2/3 prevoted nil. Precommit nil. + if blockID.IsNil() { + logger.Debug("precommit step; +2/3 prevoted for nil; precommitting nil") + cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}, nil) return } - // At this point, +2/3 prevoted for a particular block. // If we're already locked on that block, precommit it, and update the LockedRound @@ -1485,20 +1650,22 @@ func (cs *State) enterPrecommit(height int64, round int32) { cs.LockedRound = round if err := cs.eventBus.PublishEventRelock(cs.RoundStateEvent()); err != nil { - logger.Error("failed publishing event relock", "err", err) + logger.Error("precommit step; failed publishing event relock", "err", err) } - cs.signAddVote(cmtproto.PrecommitType, blockID.Hash, blockID.PartSetHeader) + cs.signAddVote(types.PrecommitType, blockID.Hash, blockID.PartSetHeader, cs.LockedBlock) return } - // If +2/3 prevoted for proposal block, stage and precommit it + // If greater than 2/3 of the voting power on the network prevoted for + // the proposed block, update our locked block to this block and issue a + // precommit vote for it. if cs.ProposalBlock.HashesTo(blockID.Hash) { - logger.Debug("precommit step; +2/3 prevoted proposal block; locking", "hash", blockID.Hash) + logger.Debug("precommit step: +2/3 prevoted proposal block; locking", "hash", blockID.Hash) // Validate the block. if err := cs.blockExec.ValidateBlock(cs.state, cs.ProposalBlock); err != nil { - panic(fmt.Sprintf("precommit step; +2/3 prevoted for an invalid block: %v", err)) + panic(fmt.Sprintf("precommit step; +2/3 prevoted for an invalid block: %v; relocking", err)) } cs.LockedRound = round @@ -1506,32 +1673,23 @@ func (cs *State) enterPrecommit(height int64, round int32) { cs.LockedBlockParts = cs.ProposalBlockParts if err := cs.eventBus.PublishEventLock(cs.RoundStateEvent()); err != nil { - logger.Error("failed publishing event lock", "err", err) + logger.Error("precommit step; failed publishing event lock", "err", err) } - cs.signAddVote(cmtproto.PrecommitType, blockID.Hash, blockID.PartSetHeader) + cs.signAddVote(types.PrecommitType, blockID.Hash, blockID.PartSetHeader, cs.ProposalBlock) return } // There was a polka in this round for a block we don't have. - // Fetch that block, unlock, and precommit nil. - // The +2/3 prevotes for this round is the POL for our unlock. + // Fetch that block, and precommit nil. logger.Debug("precommit step; +2/3 prevotes for a block we do not have; voting nil", "block_id", blockID) - cs.LockedRound = -1 - cs.LockedBlock = nil - cs.LockedBlockParts = nil - if !cs.ProposalBlockParts.HasHeader(blockID.PartSetHeader) { cs.ProposalBlock = nil cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartSetHeader) } - if err := cs.eventBus.PublishEventUnlock(cs.RoundStateEvent()); err != nil { - logger.Error("failed publishing event unlock", "err", err) - } - - cs.signAddVote(cmtproto.PrecommitType, nil, types.PartSetHeader{}) + cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}, nil) } // Enter: any +2/3 precommits for next round. @@ -1566,7 +1724,7 @@ func (cs *State) enterPrecommitWait(height int64, round int32) { cs.scheduleTimeout(cs.config.Precommit(round), height, round, cstypes.RoundStepPrecommitWait) } -// Enter: +2/3 precommits for block +// Enter: +2/3 precommits for block. func (cs *State) enterCommit(height int64, commitRound int32) { logger := cs.Logger.With("height", height, "commit_round", commitRound) @@ -1593,7 +1751,7 @@ func (cs *State) enterCommit(height int64, commitRound int32) { }() blockID, ok := cs.Votes.Precommits(commitRound).TwoThirdsMajority() - if !ok { + if !ok || blockID.IsNil() { panic("RunActionCommit() expects +2/3 precommits") } @@ -1638,7 +1796,7 @@ func (cs *State) tryFinalizeCommit(height int64) { } blockID, ok := cs.Votes.Precommits(cs.CommitRound).TwoThirdsMajority() - if !ok || len(blockID.Hash) == 0 { + if !ok || blockID.IsNil() { logger.Error("failed attempt to finalize commit; there was no +2/3 majority or +2/3 was for nil") return } @@ -1657,7 +1815,7 @@ func (cs *State) tryFinalizeCommit(height int64) { cs.finalizeCommit(height) } -// Increment height and goto cstypes.RoundStepNewHeight +// Increment height and goto cstypes.RoundStepNewHeight. func (cs *State) finalizeCommit(height int64) { logger := cs.Logger.With("height", height) @@ -1702,8 +1860,8 @@ func (cs *State) finalizeCommit(height int64) { if cs.blockStore.Height() < block.Height { // NOTE: the seenCommit is local justification to commit this block, // but may differ from the LastCommit included in the next block - seenExtendedCommit := cs.Votes.Precommits(cs.CommitRound).MakeExtendedCommit(cs.state.ConsensusParams.ABCI) - if cs.state.ConsensusParams.ABCI.VoteExtensionsEnabled(block.Height) { + seenExtendedCommit := cs.Votes.Precommits(cs.CommitRound).MakeExtendedCommit(cs.state.ConsensusParams.Feature) + if cs.state.ConsensusParams.Feature.VoteExtensionsEnabled(block.Height) { cs.blockStore.SaveBlockWithExtendedCommit(block, blockParts, seenExtendedCommit) } else { cs.blockStore.SaveBlock(block, blockParts, seenExtendedCommit.ToCommit()) @@ -1742,7 +1900,7 @@ func (cs *State) finalizeCommit(height int64) { stateCopy := cs.state.Copy() // Execute and commit the block, update and save the state, and update the mempool. - // NOTE The block.AppHash wont reflect these txs until the next block. + // NOTE The block.AppHash won't reflect these txs until the next block. stateCopy, err := cs.blockExec.ApplyBlock( stateCopy, types.BlockID{ @@ -1807,7 +1965,7 @@ func (cs *State) recordMetrics(height int64, block *types.Block) { if cs.privValidator != nil { if cs.privValidatorPubKey == nil { // Metrics won't be updated, but it's not critical. - cs.Logger.Error(fmt.Sprintf("recordMetrics: %v", errPubKeyIsNotSet)) + cs.Logger.Error(fmt.Sprintf("recordMetrics: %v", ErrPubKeyIsNotSet)) } else { address = cs.privValidatorPubKey.Address() } @@ -1831,7 +1989,6 @@ func (cs *State) recordMetrics(height int64, block *types.Block) { cs.metrics.ValidatorMissedBlocks.With(label...).Add(float64(1)) } } - } } cs.metrics.MissingValidators.Set(float64(missingValidators)) @@ -1865,15 +2022,16 @@ func (cs *State) recordMetrics(height int64, block *types.Block) { cs.metrics.NumTxs.Set(float64(len(block.Data.Txs))) cs.metrics.TotalTxs.Add(float64(len(block.Data.Txs))) cs.metrics.BlockSizeBytes.Set(float64(block.Size())) + cs.metrics.ChainSizeBytes.Add(float64(block.Size())) cs.metrics.CommittedHeight.Set(float64(block.Height)) } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- -func (cs *State) defaultSetProposal(proposal *types.Proposal) error { +func (cs *State) defaultSetProposal(proposal *types.Proposal, recvTime time.Time) error { // Already have one // TODO: possibly catch double proposals - if cs.Proposal != nil { + if cs.Proposal != nil || proposal == nil { return nil } @@ -1890,14 +2048,26 @@ func (cs *State) defaultSetProposal(proposal *types.Proposal) error { p := proposal.ToProto() // Verify signature - if !cs.Validators.GetProposer().PubKey.VerifySignature( + pubKey := cs.Validators.GetProposer().PubKey + if !pubKey.VerifySignature( types.ProposalSignBytes(cs.state.ChainID, p), proposal.Signature, ) { return ErrInvalidProposalSignature } + // Validate the proposed block size, derived from its PartSetHeader + maxBytes := cs.state.ConsensusParams.Block.MaxBytes + if maxBytes == -1 { + maxBytes = int64(types.MaxBlockSizeBytes) + } + if int64(proposal.BlockID.PartSetHeader.Total) > (maxBytes-1)/int64(types.BlockPartSizeBytes)+1 { + return ErrProposalTooManyParts + } + proposal.Signature = p.Signature cs.Proposal = proposal + cs.ProposalReceiveTime = recvTime + cs.calculateProposalTimestampDifferenceMetric() // We don't update cs.ProposalBlockParts if it is already set. // This happens if we're already in cstypes.RoundStepCommit or if there is a valid block in the current round. // TODO: We can check if Proposal is for a different block as this is a sign of misbehavior! @@ -1905,7 +2075,7 @@ func (cs *State) defaultSetProposal(proposal *types.Proposal) error { cs.ProposalBlockParts = types.NewPartSetFromHeader(proposal.BlockID.PartSetHeader) } - cs.Logger.Info("received proposal", "proposal", proposal) + cs.Logger.Info("received proposal", "proposal", proposal, "proposer", pubKey.Address()) return nil } @@ -1946,10 +2116,25 @@ func (cs *State) addProposalBlockPart(msg *BlockPartMessage, peerID p2p.ID) (add } cs.metrics.BlockGossipPartsReceived.With("matches_current", "true").Add(1) + if !added { + // NOTE: we are disregarding possible duplicates above where heights dont match or we're not expecting block parts yet + // but between the matches_current = true and false, we have all the info. + cs.metrics.DuplicateBlockPart.Add(1) + } else { + cs.evsw.FireEvent(types.EventProposalBlockPart, msg) + } + + count, total := cs.ProposalBlockParts.Count(), cs.ProposalBlockParts.Total() + cs.Logger.Debug("receive block part", "height", height, "round", round, + "index", part.Index, "count", count, "total", total, "from", peerID) - if cs.ProposalBlockParts.ByteSize() > cs.state.ConsensusParams.Block.MaxBytes { + maxBytes := cs.state.ConsensusParams.Block.MaxBytes + if maxBytes == -1 { + maxBytes = int64(types.MaxBlockSizeBytes) + } + if cs.ProposalBlockParts.ByteSize() > maxBytes { return added, fmt.Errorf("total size of proposal block parts exceeds maximum block bytes (%d > %d)", - cs.ProposalBlockParts.ByteSize(), cs.state.ConsensusParams.Block.MaxBytes, + cs.ProposalBlockParts.ByteSize(), maxBytes, ) } if added && cs.ProposalBlockParts.IsComplete() { @@ -1958,7 +2143,7 @@ func (cs *State) addProposalBlockPart(msg *BlockPartMessage, peerID p2p.ID) (add return added, err } - var pbb = new(cmtproto.Block) + pbb := new(cmtproto.Block) err = proto.Unmarshal(bz, pbb) if err != nil { return added, err @@ -1985,7 +2170,7 @@ func (cs *State) handleCompleteProposal(blockHeight int64) { // Update Valid* if we can. prevotes := cs.Votes.Prevotes(cs.Round) blockID, hasTwoThirds := prevotes.TwoThirdsMajority() - if hasTwoThirds && !blockID.IsZero() && (cs.ValidRound < cs.Round) { + if hasTwoThirds && !blockID.IsNil() && (cs.ValidRound < cs.Round) { if cs.ProposalBlock.HashesTo(blockID.Hash) { cs.Logger.Debug( "updating valid block to new proposal block", @@ -2016,10 +2201,10 @@ func (cs *State) handleCompleteProposal(blockHeight int64) { } } -// Attempt to add the vote. if its a duplicate signature, dupeout the validator +// Attempt to add the vote. if its a duplicate signature, dupeout the validator. func (cs *State) tryAddVote(vote *types.Vote, peerID p2p.ID) (bool, error) { added, err := cs.addVote(vote, peerID) - + // NOTE: some of these errors are swallowed here if err != nil { // If the vote height is off, we'll just ignore it, // But if it's a conflicting sig, add it to the cs.evpool. @@ -2027,7 +2212,7 @@ func (cs *State) tryAddVote(vote *types.Vote, peerID p2p.ID) (bool, error) { //nolint: gocritic if voteErr, ok := err.(*types.ErrVoteConflictingVotes); ok { if cs.privValidatorPubKey == nil { - return false, errPubKeyIsNotSet + return false, ErrPubKeyIsNotSet } if bytes.Equal(vote.ValidatorAddress, cs.privValidatorPubKey.Address()) { @@ -2051,9 +2236,9 @@ func (cs *State) tryAddVote(vote *types.Vote, peerID p2p.ID) (bool, error) { return added, err } else if errors.Is(err, types.ErrVoteNonDeterministicSignature) { - cs.Logger.Debug("vote has non-deterministic signature", "err", err) + cs.Logger.Info("vote has non-deterministic signature", "err", err) } else if errors.Is(err, types.ErrInvalidVoteExtension) { - cs.Logger.Debug("vote has invalid extension") + cs.Logger.Info("vote has invalid extension") } else { // Either // 1) bad peer OR @@ -2085,16 +2270,20 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error // A precommit for the previous height? // These come in while we wait timeoutCommit - if vote.Height+1 == cs.Height && vote.Type == cmtproto.PrecommitType { + if vote.Height+1 == cs.Height && vote.Type == types.PrecommitType { if cs.Step != cstypes.RoundStepNewHeight { // Late precommit at prior height is ignored cs.Logger.Debug("precommit vote came in after commit timeout and has been ignored", "vote", vote) - return + return added, err } added, err = cs.LastCommit.AddVote(vote) if !added { - return + // If the vote wasn't added but there's no error, its a duplicate vote + if err == nil { + cs.metrics.DuplicateVote.Add(1) + } + return added, err } cs.Logger.Debug("added vote to last precommits", "last_commit", cs.LastCommit.StringShort()) @@ -2111,18 +2300,18 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error cs.enterNewRound(cs.Height, 0) } - return + return added, err } // Height mismatch is ignored. // Not necessarily a bad peer, but not favorable behavior. if vote.Height != cs.Height { cs.Logger.Debug("vote ignored and not added", "vote_height", vote.Height, "cs_height", cs.Height, "peer", peerID) - return + return added, err } // Check to see if the chain is configured to extend votes. - extEnabled := cs.state.ConsensusParams.ABCI.VoteExtensionsEnabled(vote.Height) + extEnabled := cs.state.ConsensusParams.Feature.VoteExtensionsEnabled(vote.Height) if extEnabled { // The chain is configured to extend votes, check that the vote is // not for a nil block and verify the extensions signature against the @@ -2134,9 +2323,8 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error } // Verify VoteExtension if precommit and not nil // https://github.com/tendermint/tendermint/issues/8487 - if vote.Type == cmtproto.PrecommitType && !vote.BlockID.IsZero() && + if vote.Type == types.PrecommitType && !vote.BlockID.IsNil() && !bytes.Equal(vote.ValidatorAddress, myAddr) { // Skip the VerifyVoteExtension call if the vote was issued by this validator. - // The core fields of the vote message were already validated in the // consensus reactor when the vote was received. // Here, we verify the signature of the vote extension included in the vote @@ -2152,23 +2340,26 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error return false, err } } - } else { + } else if len(vote.Extension) > 0 || len(vote.ExtensionSignature) > 0 { // Vote extensions are not enabled on the network. // Reject the vote, as it is malformed // // TODO punish a peer if it sent a vote with an extension when the feature // is disabled on the network. // https://github.com/tendermint/tendermint/issues/8565 - if len(vote.Extension) > 0 || len(vote.ExtensionSignature) > 0 { - return false, fmt.Errorf("received vote with vote extension for height %v (extensions disabled) from peer ID %s", vote.Height, peerID) - } + return false, fmt.Errorf("received vote with vote extension for height %v (extensions disabled) from peer ID %s", vote.Height, peerID) } height := cs.Height added, err = cs.Votes.AddVote(vote, peerID, extEnabled) if !added { // Either duplicate, or error upon cs.Votes.AddByIndex() - return + + // If the vote wasn't added but there's no error, its a duplicate vote + if err == nil { + cs.metrics.DuplicateVote.Add(1) + } + return added, err } if vote.Round == cs.Round { vals := cs.state.Validators @@ -2182,37 +2373,17 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error cs.evsw.FireEvent(types.EventVote, vote) switch vote.Type { - case cmtproto.PrevoteType: + case types.PrevoteType: prevotes := cs.Votes.Prevotes(vote.Round) cs.Logger.Debug("added vote to prevote", "vote", vote, "prevotes", prevotes.StringShort()) - // If +2/3 prevotes for a block or nil for *any* round: - if blockID, ok := prevotes.TwoThirdsMajority(); ok { - // There was a polka! - // If we're locked but this is a recent polka, unlock. - // If it matches our ProposalBlock, update the ValidBlock - - // Unlock if `cs.LockedRound < vote.Round <= cs.Round` - // NOTE: If vote.Round > cs.Round, we'll deal with it when we get to vote.Round - if (cs.LockedBlock != nil) && - (cs.LockedRound < vote.Round) && - (vote.Round <= cs.Round) && - !cs.LockedBlock.HashesTo(blockID.Hash) { - - cs.Logger.Debug("unlocking because of POL", "locked_round", cs.LockedRound, "pol_round", vote.Round) - - cs.LockedRound = -1 - cs.LockedBlock = nil - cs.LockedBlockParts = nil - - if err := cs.eventBus.PublishEventUnlock(cs.RoundStateEvent()); err != nil { - return added, err - } - } + // Check to see if >2/3 of the voting power on the network voted for any non-nil block. + if blockID, ok := prevotes.TwoThirdsMajority(); ok && !blockID.IsNil() { + // Greater than 2/3 of the voting power on the network voted for some + // non-nil block // Update Valid* if we can. - // NOTE: our proposal block may be nil or not what received a polka.. - if len(blockID.Hash) != 0 && (cs.ValidRound < vote.Round) && (vote.Round == cs.Round) { + if cs.ValidRound < vote.Round && vote.Round == cs.Round { if cs.ProposalBlock.HashesTo(blockID.Hash) { cs.Logger.Debug("updating valid block because of POL", "valid_round", cs.ValidRound, "pol_round", vote.Round) cs.ValidRound = vote.Round @@ -2248,7 +2419,7 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error case cs.Round == vote.Round && cstypes.RoundStepPrevote <= cs.Step: // current round blockID, ok := prevotes.TwoThirdsMajority() - if ok && (cs.isProposalComplete() || len(blockID.Hash) == 0) { + if ok && (cs.isProposalComplete() || blockID.IsNil()) { cs.enterPrecommit(height, vote.Round) } else if prevotes.HasTwoThirdsAny() { cs.enterPrevoteWait(height, vote.Round) @@ -2261,7 +2432,7 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error } } - case cmtproto.PrecommitType: + case types.PrecommitType: precommits := cs.Votes.Precommits(vote.Round) cs.Logger.Debug("added vote to precommit", "height", vote.Height, @@ -2276,7 +2447,7 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error cs.enterNewRound(height, vote.Round) cs.enterPrecommit(height, vote.Round) - if len(blockID.Hash) != 0 { + if !blockID.IsNil() { cs.enterCommit(height, vote.Round) if cs.config.SkipTimeoutCommit && precommits.HasAll() { cs.enterNewRound(cs.Height, 0) @@ -2298,9 +2469,10 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error // CONTRACT: cs.privValidator is not nil. func (cs *State) signVote( - msgType cmtproto.SignedMsgType, + msgType types.SignedMsgType, hash []byte, header types.PartSetHeader, + block *types.Block, ) (*types.Vote, error) { // Flush the WAL. Otherwise, we may not recompute the same vote to sign, // and the privValidator will refuse to sign anything. @@ -2309,28 +2481,29 @@ func (cs *State) signVote( } if cs.privValidatorPubKey == nil { - return nil, errPubKeyIsNotSet + return nil, ErrPubKeyIsNotSet } addr := cs.privValidatorPubKey.Address() valIdx, _ := cs.Validators.GetByAddress(addr) + timestamp := cs.voteTime(cs.Height) vote := &types.Vote{ ValidatorAddress: addr, ValidatorIndex: valIdx, Height: cs.Height, Round: cs.Round, - Timestamp: cs.voteTime(), + Timestamp: timestamp, Type: msgType, BlockID: types.BlockID{Hash: hash, PartSetHeader: header}, } - extEnabled := cs.state.ConsensusParams.ABCI.VoteExtensionsEnabled(vote.Height) - if msgType == cmtproto.PrecommitType && !vote.BlockID.IsZero() { + extEnabled := cs.state.ConsensusParams.Feature.VoteExtensionsEnabled(vote.Height) + if msgType == types.PrecommitType && !vote.BlockID.IsNil() { // if the signedMessage type is for a non-nil precommit, add // VoteExtension if extEnabled { - ext, err := cs.blockExec.ExtendVote(context.TODO(), vote) + ext, err := cs.blockExec.ExtendVote(context.TODO(), vote, block, cs.state) if err != nil { return nil, err } @@ -2338,17 +2511,21 @@ func (cs *State) signVote( } } - recoverable, err := types.SignAndCheckVote(vote, cs.privValidator, cs.state.ChainID, extEnabled && (msgType == cmtproto.PrecommitType)) + recoverable, err := types.SignAndCheckVote(vote, cs.privValidator, cs.state.ChainID, extEnabled && (msgType == types.PrecommitType)) if err != nil && !recoverable { - panic(fmt.Sprintf("non-recoverable error when signing vote (%d/%d)", vote.Height, vote.Round)) + panic(fmt.Sprintf("non-recoverable error when signing vote %v: %v", vote, err)) } return vote, err } -func (cs *State) voteTime() time.Time { +func (cs *State) voteTime(height int64) time.Time { + if cs.isPBTSEnabled(height) { + return cmttime.Now() + } now := cmttime.Now() minVoteTime := now + // Minimum time increment between blocks const timeIota = time.Millisecond // TODO: We should remove next line in case we don't vote for v in case cs.ProposalBlock == nil, @@ -2368,10 +2545,12 @@ func (cs *State) voteTime() time.Time { } // sign the vote and publish on internalMsgQueue +// block information is only used to extend votes (precommit only); should be nil in all other cases. func (cs *State) signAddVote( - msgType cmtproto.SignedMsgType, + msgType types.SignedMsgType, hash []byte, header types.PartSetHeader, + block *types.Block, ) { if cs.privValidator == nil { // the node does not have a key return @@ -2379,7 +2558,7 @@ func (cs *State) signAddVote( if cs.privValidatorPubKey == nil { // Vote won't be signed, but it's not critical. - cs.Logger.Error(fmt.Sprintf("signAddVote: %v", errPubKeyIsNotSet)) + cs.Logger.Error(fmt.Sprintf("signAddVote: %v", ErrPubKeyIsNotSet)) return } @@ -2389,22 +2568,22 @@ func (cs *State) signAddVote( } // TODO: pass pubKey to signVote - vote, err := cs.signVote(msgType, hash, header) + vote, err := cs.signVote(msgType, hash, header, block) if err != nil { cs.Logger.Error("failed signing vote", "height", cs.Height, "round", cs.Round, "vote", vote, "err", err) return } hasExt := len(vote.ExtensionSignature) > 0 - extEnabled := cs.state.ConsensusParams.ABCI.VoteExtensionsEnabled(vote.Height) - if vote.Type == cmtproto.PrecommitType && !vote.BlockID.IsZero() && hasExt != extEnabled { + extEnabled := cs.state.ConsensusParams.Feature.VoteExtensionsEnabled(vote.Height) + if vote.Type == types.PrecommitType && !vote.BlockID.IsNil() && hasExt != extEnabled { panic(fmt.Errorf("vote extension absence/presence does not match extensions enabled %t!=%t, height %d, type %v", hasExt, extEnabled, vote.Height, vote.Type)) } - cs.sendInternalMessage(msgInfo{&VoteMessage{vote}, ""}) + cs.sendInternalMessage(msgInfo{&VoteMessage{vote}, "", time.Time{}}) cs.Logger.Debug("signed and pushed vote", "height", cs.Height, "round", cs.Round, "vote", vote) } -// updatePrivValidatorPubKey get's the private validator public key and +// updatePrivValidatorPubKey gets the private validator public key and // memoizes it. This func returns an error if the private validator is not // responding or responds with an error. func (cs *State) updatePrivValidatorPubKey() error { @@ -2420,7 +2599,7 @@ func (cs *State) updatePrivValidatorPubKey() error { return nil } -// look back to check existence of the node's consensus votes before joining consensus +// look back to check existence of the node's consensus votes before joining consensus. func (cs *State) checkDoubleSigningRisk(height int64) error { if cs.privValidator != nil && cs.privValidatorPubKey != nil && cs.config.DoubleSignCheckHeight > 0 && height > 0 { valAddr := cs.privValidatorPubKey.Address() @@ -2471,7 +2650,7 @@ func (cs *State) calculatePrevoteMessageDelayMetrics() { } } -//--------------------------------------------------------- +// --------------------------------------------------------- func CompareHRS(h1 int64, r1 int32, s1 cstypes.RoundStepType, h2 int64, r2 int32, s2 cstypes.RoundStepType) int { if h1 < h2 { @@ -2525,5 +2704,36 @@ func repairWalFile(src, dst string) error { } } + //nolint:nilerr return nil } + +func (cs *State) calculateProposalTimestampDifferenceMetric() { + if cs.Proposal != nil && cs.Proposal.POLRound == -1 { + sp := cs.state.ConsensusParams.Synchrony.InRound(cs.Proposal.Round) + + isTimely := cs.Proposal.IsTimely(cs.ProposalReceiveTime, sp) + cs.metrics.ProposalTimestampDifference. + With("is_timely", strconv.FormatBool(isTimely)). + Observe(cs.ProposalReceiveTime.Sub(cs.Proposal.Timestamp).Seconds()) + } +} + +// proposerWaitTime determines how long the proposer should wait to propose its next block. +// If the result is zero, a block can be proposed immediately. +// +// Block times must be monotonically increasing, so if the block time of the previous +// block is larger than the proposer's current time, then the proposer will sleep +// until its local clock exceeds the previous block time. +func proposerWaitTime(lt cmttime.Source, bt time.Time) time.Duration { + t := lt.Now() + if bt.After(t) { + return bt.Sub(t) + } + return 0 +} + +// isPBTSEnabled returns true if PBTS is enabled at the current height. +func (cs *State) isPBTSEnabled(height int64) bool { + return cs.state.ConsensusParams.Feature.PbtsEnabled(height) +} diff --git a/internal/consensus/state_test.go b/internal/consensus/state_test.go new file mode 100644 index 00000000000..c9aa1b89e7b --- /dev/null +++ b/internal/consensus/state_test.go @@ -0,0 +1,3254 @@ +package consensus + +import ( + "bytes" + "context" + "fmt" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/cometbft/cometbft/abci/example/kvstore" + abci "github.com/cometbft/cometbft/abci/types" + abcimocks "github.com/cometbft/cometbft/abci/types/mocks" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/crypto/tmhash" + cstypes "github.com/cometbft/cometbft/internal/consensus/types" + "github.com/cometbft/cometbft/internal/protoio" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + cmtrand "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/internal/test" + cmtbytes "github.com/cometbft/cometbft/libs/bytes" + "github.com/cometbft/cometbft/libs/log" + p2pmock "github.com/cometbft/cometbft/p2p/mock" + "github.com/cometbft/cometbft/types" +) + +/* + +ProposeSuite +x * TestProposerSelection0 - round robin ordering, round 0 +x * TestProposerSelection2 - round robin ordering, round 2++ +x * TestEnterProposeNoValidator - timeout into prevote round +x * TestEnterPropose - finish propose without timing out (we have the proposal) +x * TestBadProposal - 2 vals, bad proposal (bad block state hash), should prevote and precommit nil +x * TestOversizedBlock - block with too many txs should be rejected +FullRoundSuite +x * TestFullRound1 - 1 val, full successful round +x * TestFullRoundNil - 1 val, full round of nil +x * TestFullRound2 - 2 vals, both required for full round +LockSuite +x * TestStateLock_NoPOL - 2 vals, 4 rounds. one val locked, precommits nil every round except first. +x * TestStateLock_POLUpdateLock - 4 vals, one precommits, +other 3 polka at next round, so we unlock and precomit the polka +x * TestStateLock_POLRelock - 4 vals, polka in round 1 and polka in round 2. +Ensure validator updates locked round. +x * TestStateLock_POLDoesNotUnlock 4 vals, one precommits, other 3 polka nil at +next round, so we precommit nil but maintain lock +x * TestStateLock_MissingProposalWhenPOLSeenDoesNotUpdateLock - 4 vals, 1 misses proposal but sees POL. +x * TestStateLock_MissingProposalWhenPOLSeenDoesNotUnlock - 4 vals, 1 misses proposal but sees POL. + * TestStateLock_MissingProposalWhenPOLForLockedBlock - 4 vals, 1 misses proposal but sees POL for locked block. +x * TestState_MissingProposalValidBlockReceivedTimeout - 4 vals, 1 misses proposal but receives full block. +x * TestState_MissingProposalValidBlockReceivedPrecommit - 4 vals, 1 misses proposal but receives full block. +x * TestStateLock_POLSafety1 - 4 vals. We shouldn't change lock based on polka at earlier round +x * TestStateLock_POLSafety2 - 4 vals. We shouldn't accept a proposal with POLRound smaller than our locked round. +x * TestState_PrevotePOLFromPreviousRound 4 vals, prevote a proposal if a POL was seen for it in a previous round. + * TestNetworkLock - once +1/3 precommits, network should be locked + * TestNetworkLockPOL - once +1/3 precommits, the block with more recent polka is committed +SlashingSuite +x * TestStateSlashing_Prevotes - a validator prevoting twice in a round gets slashed +x * TestStateSlashing_Precommits - a validator precomitting twice in a round gets slashed +CatchupSuite + * TestCatchup - if we might be behind and we've seen any 2/3 prevotes, round skip to new round, precommit, or prevote +HaltSuite +x * TestHalt1 - if we see +2/3 precommits after timing out into new round, we should still commit + +*/ + +// ---------------------------------------------------------------------------------------------------- +// ProposeSuite + +func TestStateProposerSelection0(t *testing.T) { + cs1, vss := randState(4) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + pv, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + + startTestRound(cs1, height, round) + + // Wait for new round so proposer is set. + ensureNewRound(newRoundCh, height, round) + + // Commit a block and ensure proposer for the next height is correct. + prop := cs1.GetRoundState().Validators.GetProposer() + address := pv.Address() + require.Truef(t, bytes.Equal(prop.Address, address), "expected proposer to be validator 0 (%X). Got %X", address, prop.Address) + + // Wait for complete proposal. + ensureNewProposal(proposalCh, height, round) + + rs := cs1.GetRoundState() + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + }, true, vss[1:]...) + + // Wait for new round so next validator is set. + ensureNewRound(newRoundCh, height+1, 0) + + prop = cs1.GetRoundState().Validators.GetProposer() + pv1, err := vss[1].GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + require.Truef(t, bytes.Equal(prop.Address, addr), "expected proposer to be validator 1 (%X). Got %X", addr, prop.Address) +} + +// Now let's do it all again, but starting from round 2 instead of 0. +func TestStateProposerSelection2(t *testing.T) { + cs1, vss := randState(4) // test needs more work for more than 3 validators + height, chainID := cs1.Height, cs1.state.ChainID + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + // this time we jump in at round 2 + incrementRound(vss[1:]...) + incrementRound(vss[1:]...) + + var round int32 = 2 + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) // wait for the new round + + // everyone just votes nil. we get a new proposer each round + for i := int32(0); int(i) < len(vss); i++ { + prop := cs1.GetRoundState().Validators.GetProposer() + pvk, err := vss[int(i+round)%len(vss)].GetPubKey() + require.NoError(t, err) + addr := pvk.Address() + correctProposer := addr + require.Truef(t, bytes.Equal(prop.Address, correctProposer), + "expected RoundState.Validators.GetProposer() to be validator %d (%X). Got %X", + int(i+2)%len(vss), correctProposer, prop.Address, + ) + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vss[1:]...) + ensureNewRound(newRoundCh, height, i+round+1) // wait for the new round event each round + incrementRound(vss[1:]...) + } +} + +// a non-validator should timeout into the prevote round. +func TestStateEnterProposeNoPrivValidator(t *testing.T) { + cs, _ := randState(1) + cs.SetPrivValidator(nil) + height, round := cs.Height, cs.Round + + // Listen for propose timeout event + timeoutCh := subscribe(cs.eventBus, types.EventQueryTimeoutPropose) + + startTestRound(cs, height, round) + + // if we're not a validator, EnterPropose should timeout + ensureNewTimeout(timeoutCh, height, round, cs.config.TimeoutPropose.Nanoseconds()) + + if cs.GetRoundState().Proposal != nil { + t.Error("Expected to make no proposal, since no privValidator") + } +} + +// a validator should not timeout of the prevote round (TODO: unless the block is really big!) +func TestStateEnterProposeYesPrivValidator(t *testing.T) { + cs, _ := randState(1) + height, round := cs.Height, cs.Round + + // Listen for propose timeout event + + timeoutCh := subscribe(cs.eventBus, types.EventQueryTimeoutPropose) + proposalCh := subscribe(cs.eventBus, types.EventQueryCompleteProposal) + + cs.enterNewRound(height, round) + cs.startRoutines(3) + + ensureNewProposal(proposalCh, height, round) + + // Check that Proposal, ProposalBlock, ProposalBlockParts are set. + rs := cs.GetRoundState() + if rs.Proposal == nil { + t.Error("rs.Proposal should be set") + } + if rs.ProposalBlock == nil { + t.Error("rs.ProposalBlock should be set") + } + if rs.ProposalBlockParts.Total() == 0 { + t.Error("rs.ProposalBlockParts should be set") + } + + // if we're a validator, enterPropose should not timeout + ensureNoNewTimeout(timeoutCh, cs.config.TimeoutPropose.Nanoseconds()) +} + +func TestStateBadProposal(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(2) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + vs2 := vss[1] + + partSize := types.BlockPartSizeBytes + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + voteCh := subscribe(cs1.eventBus, types.EventQueryVote) + + propBlock, err := cs1.createProposalBlock(ctx) // changeProposer(t, cs1, vs2) + require.NoError(t, err) + + // make the second validator the proposer by incrementing round + round++ + incrementRound(vss[1:]...) + + // make the block bad by tampering with statehash + stateHash := propBlock.AppHash + if len(stateHash) == 0 { + stateHash = make([]byte, 32) + } + stateHash[0] = (stateHash[0] + 1) % 255 + propBlock.AppHash = stateHash + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} + proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time) + signProposal(t, proposal, chainID, vs2) + + // set the proposal block + err = cs1.SetProposalAndBlock(proposal, propBlockParts, "some peer") + require.NoError(t, err) + + // start the machine + startTestRound(cs1, height, round) + + // wait for proposal + ensureProposal(proposalCh, height, round, blockID) + + // wait for prevote + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // add bad prevote from vs2 and wait for it + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2) + ensurePrevote(voteCh, height, round) + + // wait for precommit + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs2) +} + +func TestStateOversizedBlock(t *testing.T) { + const maxBytes = int64(types.BlockPartSizeBytes) + + for _, testCase := range []struct { + name string + oversized bool + }{ + { + name: "max size, correct block", + oversized: false, + }, + { + name: "off-by-1 max size, incorrect block", + oversized: true, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + cs1, vss := randState(2) + cs1.state.ConsensusParams.Block.MaxBytes = maxBytes + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + vs2 := vss[1] + + partSize := types.BlockPartSizeBytes + + propBlock, propBlockParts := findBlockSizeLimit(t, height, maxBytes, cs1, partSize, testCase.oversized) + + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + voteCh := subscribe(cs1.eventBus, types.EventQueryVote) + + // make the second validator the proposer by incrementing round + round++ + incrementRound(vss[1:]...) + + blockID := types.BlockID{Hash: propBlock.Hash(), PartSetHeader: propBlockParts.Header()} + proposal := types.NewProposal(height, round, -1, blockID, propBlock.Header.Time) + signProposal(t, proposal, chainID, vs2) + + totalBytes := 0 + for i := 0; i < int(propBlockParts.Total()); i++ { + part := propBlockParts.GetPart(i) + totalBytes += len(part.Bytes) + } + + maxBlockParts := maxBytes / int64(types.BlockPartSizeBytes) + if maxBytes > maxBlockParts*int64(types.BlockPartSizeBytes) { + maxBlockParts++ + } + numBlockParts := int64(propBlockParts.Total()) + + err := cs1.SetProposalAndBlock(proposal, propBlockParts, "some peer") + require.NoError(t, err) + + // start the machine + startTestRound(cs1, height, round) + + t.Log("Block Sizes;", "Limit", maxBytes, "Current", totalBytes) + t.Log("Proposal Parts;", "Maximum", maxBlockParts, "Current", numBlockParts) + + validateHash := propBlock.Hash() + lockedRound := int32(1) + if testCase.oversized { + validateHash = nil + lockedRound = -1 + // if the block is oversized cs1 should log an error with the block part message as it exceeds + // the consensus params. The block is not added to cs.ProposalBlock so the node timeouts. + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) + // and then should send nil prevote and precommit regardless of whether other validators prevote and + // precommit on it + } + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], validateHash) + + // Should not accept a Proposal with too many block parts + if numBlockParts > maxBlockParts { + require.Nil(t, cs1.Proposal) + } + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2) + ensurePrevote(voteCh, height, round) + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, lockedRound, vss[0], validateHash, validateHash) + + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs2) + }) + } +} + +// ---------------------------------------------------------------------------------------------------- +// FullRoundSuite + +// propose, prevote, and precommit a block. +func TestStateFullRound1(t *testing.T) { + cs, vss := randState(1) + height, round := cs.Height, cs.Round + + // NOTE: buffer capacity of 0 ensures we can validate prevote and last commit + // before consensus can move to the next height (and cause a race condition) + if err := cs.eventBus.Stop(); err != nil { + t.Error(err) + } + eventBus := types.NewEventBusWithBufferCapacity(0) + eventBus.SetLogger(log.TestingLogger().With("module", "events")) + cs.SetEventBus(eventBus) + if err := eventBus.Start(); err != nil { + t.Error(err) + } + + voteCh := subscribeUnBuffered(cs.eventBus, types.EventQueryVote) + propCh := subscribe(cs.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs.eventBus, types.EventQueryNewRound) + + // Maybe it would be better to call explicitly startRoutines(4) + startTestRound(cs, height, round) + + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(propCh, height, round) + propBlockHash := cs.GetRoundState().ProposalBlock.Hash() + + ensurePrevote(voteCh, height, round) // wait for prevote + validatePrevote(t, cs, round, vss[0], propBlockHash) + + ensurePrecommit(voteCh, height, round) // wait for precommit + + // we're going to roll right into new height + ensureNewRound(newRoundCh, height+1, 0) + + validateLastPrecommit(t, cs, vss[0], propBlockHash) +} + +// nil is proposed, so prevote and precommit nil. +func TestStateFullRoundNil(t *testing.T) { + cs, _ := randState(1) + height, round := cs.Height, cs.Round + + voteCh := subscribeUnBuffered(cs.eventBus, types.EventQueryVote) + + cs.enterPrevote(height, round) + cs.startRoutines(4) + + ensurePrevoteMatch(t, voteCh, height, round, nil) // prevote + ensurePrecommitMatch(t, voteCh, height, round, nil) // precommit +} + +// run through propose, prevote, precommit commit with two validators +// where the first validator has to wait for votes from the second. +func TestStateFullRound2(t *testing.T) { + cs1, vss := randState(2) + vs2 := vss[1] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + voteCh := subscribeUnBuffered(cs1.eventBus, types.EventQueryVote) + newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlock) + + // start round and wait for propose and prevote + startTestRound(cs1, height, round) + + ensurePrevote(voteCh, height, round) // prevote + + // we should be stuck in limbo waiting for more prevotes + rs := cs1.GetRoundState() + blockID := types.BlockID{Hash: rs.ProposalBlock.Hash(), PartSetHeader: rs.ProposalBlockParts.Header()} + + // prevote arrives from vs2: + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2) + ensurePrevote(voteCh, height, round) // prevote + + ensurePrecommit(voteCh, height, round) // precommit + // the proposed block should now be locked and our precommit added + validatePrecommit(t, cs1, 0, 0, vss[0], blockID.Hash, blockID.Hash) + + // we should be stuck in limbo waiting for more precommits + + // precommit arrives from vs2: + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs2) + ensurePrecommit(voteCh, height, round) + + // wait to finish commit, propose in next height + ensureNewBlock(newBlockCh, height) +} + +// ------------------------------------------------------------------------------------------ +// LockSuite + +// two validators, 4 rounds. +// two vals take turns proposing. val1 locks on first one, precommits nil on everything else. +func TestStateLock_NoPOL(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(2) + vs2 := vss[1] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + voteCh := subscribeUnBuffered(cs1.eventBus, types.EventQueryVote) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + /* + Round1 (cs1, B) // B B // B B2 + */ + + // start round and wait for prevote + cs1.enterNewRound(height, round) + cs1.startRoutines(0) + + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + roundState := cs1.GetRoundState() + initialBlockID := types.BlockID{ + Hash: roundState.ProposalBlock.Hash(), + PartSetHeader: roundState.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) // prevote + + // we should now be stuck in limbo forever, waiting for more prevotes + // prevote arrives from vs2: + signAddVotes(cs1, types.PrevoteType, chainID, initialBlockID, false, vs2) + ensurePrevote(voteCh, height, round) // prevote + validatePrevote(t, cs1, round, vss[0], initialBlockID.Hash) + + // the proposed block should now be locked and our precommit added + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], initialBlockID.Hash, initialBlockID.Hash) + + // we should now be stuck in limbo forever, waiting for more precommits + // lets add one for a different block + hash := make([]byte, len(initialBlockID.Hash)) + copy(hash, initialBlockID.Hash) + hash[0] = (hash[0] + 1) % 255 + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{ + Hash: hash, + PartSetHeader: initialBlockID.PartSetHeader, + }, true, vs2) + ensurePrecommit(voteCh, height, round) // precommit + + // (note we're entering precommit for a second time this round) + // but with invalid args. then we enterPrecommitWait, and the timeout to new round + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + // + + round++ // moving to the next round + ensureNewRound(newRoundCh, height, round) + t.Log("#### ONTO ROUND 1") + /* + Round2 (cs1, B) // B B2 + */ + + incrementRound(vs2) + + // now we're on a new round and not the proposer, so wait for timeout + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) + + rs := cs1.GetRoundState() + + require.Nil(t, rs.ProposalBlock, "Expected proposal block to be nil") + + // we should have prevoted nil since we did not see a proposal in the round. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // add a conflicting prevote from the other validator + partSet, err := rs.LockedBlock.MakePartSet(partSize) + require.NoError(t, err) + conflictingBlockID := types.BlockID{Hash: hash, PartSetHeader: partSet.Header()} + signAddVotes(cs1, types.PrevoteType, chainID, conflictingBlockID, false, vs2) + ensurePrevote(voteCh, height, round) + + // now we're going to enter prevote again, but with invalid args + // and then prevote wait, which should timeout. then wait for precommit + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) + // the proposed block should still be locked block. + // we should precommit nil and be locked on the proposal. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, 0, vss[0], nil, initialBlockID.Hash) + + // add conflicting precommit from vs2 + signAddVotes(cs1, types.PrecommitType, chainID, conflictingBlockID, true, vs2) + ensurePrecommit(voteCh, height, round) + + // (note we're entering precommit for a second time this round, but with invalid args + // then we enterPrecommitWait and timeout into NewRound + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + round++ // entering new round + ensureNewRound(newRoundCh, height, round) + t.Log("#### ONTO ROUND 2") + /* + Round3 (vs2, _) // B, B2 + */ + + incrementRound(vs2) + + ensureNewProposal(proposalCh, height, round) + rs = cs1.GetRoundState() + + // now we're on a new round and are the proposer + require.Truef(t, bytes.Equal(rs.ProposalBlock.Hash(), rs.LockedBlock.Hash()), + "expected proposal block to be locked block. Got %v, Expected %v", + rs.ProposalBlock, rs.LockedBlock, + ) + + ensurePrevote(voteCh, height, round) // prevote + validatePrevote(t, cs1, round, vss[0], rs.LockedBlock.Hash()) + partSet, err = rs.ProposalBlock.MakePartSet(partSize) + require.NoError(t, err) + newBlockID := types.BlockID{Hash: hash, PartSetHeader: partSet.Header()} + signAddVotes(cs1, types.PrevoteType, chainID, newBlockID, false, vs2) + ensurePrevote(voteCh, height, round) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) + ensurePrecommit(voteCh, height, round) // precommit + + validatePrecommit(t, cs1, round, 0, vss[0], nil, initialBlockID.Hash) // precommit nil but be locked on proposal + + signAddVotes( + cs1, + types.PrecommitType, + chainID, + newBlockID, + true, + vs2) // NOTE: conflicting precommits at same height + ensurePrecommit(voteCh, height, round) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + cs2, _ := randState(2) // needed so generated block is different than locked block + // before we time out into new round, set next proposal block + prop, propBlock := decideProposal(ctx, t, cs2, vs2, vs2.Height, vs2.Round+1) + require.NotNil(t, propBlock, "Failed to create proposal block with vs2") + require.NotNil(t, prop, "Failed to create proposal block with vs2") + propBlockID := types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: partSet.Header(), + } + + incrementRound(vs2) + + round++ // entering new round + ensureNewRound(newRoundCh, height, round) + t.Log("#### ONTO ROUND 3") + /* + Round4 (vs2, C) // B C // B C + */ + + // now we're on a new round and not the proposer + // so set the proposal block + bps3, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + err = cs1.SetProposalAndBlock(prop, bps3, "") + require.NoError(t, err) + + ensureNewProposal(proposalCh, height, round) + + // prevote for nil since we did not see a proposal for our locked block in the round. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, 3, vss[0], nil) + + // prevote for proposed block + signAddVotes(cs1, types.PrevoteType, chainID, propBlockID, false, vs2) + ensurePrevote(voteCh, height, round) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, 0, vss[0], nil, initialBlockID.Hash) // precommit nil but locked on proposal + + signAddVotes( + cs1, + types.PrecommitType, + chainID, + propBlockID, + true, + vs2) // NOTE: conflicting precommits at same height + ensurePrecommit(voteCh, height, round) +} + +// TestStateLock_POLUpdateLock tests that a validator updates its locked +// block if the following conditions are met within a round: +// 1. The validator received a valid proposal for the block +// 2. The validator received prevotes representing greater than 2/3 of the voting +// power on the network for the block. +func TestStateLock_POLUpdateLock(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + lockCh := subscribe(cs1.eventBus, types.EventQueryLock) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + /* + Round 0: + cs1 creates a proposal for block B. + Send a prevote for B from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + This ensures that cs1 will lock on B in this round but not precommit it. + */ + t.Log("### Starting Round 0") + + // start round and wait for propose and prevote + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + initialBlockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + + signAddVotes(cs1, types.PrevoteType, chainID, initialBlockID, false, vs2, vs3, vs4) + + // check that the validator generates a Lock event. + ensureLock(lockCh, height, round) + + // the proposed block should now be locked and our precommit added. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], initialBlockID.Hash, initialBlockID.Hash) + + // add precommits from the rest of the validators. + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + // timeout to new round. + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + Create a block, D and send a proposal for it to cs1 + Send a prevote for D from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + Check that cs1 is now locked on the new block, D and no longer on the old block. + */ + t.Log("### Starting Round 1") + incrementRound(vs2, vs3, vs4) + round++ + + // Generate a new proposal block. + cs2 := newState(cs1.state, vs2, kvstore.NewInMemoryApplication()) + propR1, propBlockR1 := decideProposal(ctx, t, cs2, vs2, vs2.Height, vs2.Round) + propBlockR1Parts, err := propBlockR1.MakePartSet(partSize) + require.NoError(t, err) + propBlockR1Hash := propBlockR1.Hash() + r1BlockID := types.BlockID{ + Hash: propBlockR1Hash, + PartSetHeader: propBlockR1Parts.Header(), + } + require.NotEqual(t, propBlockR1Hash, initialBlockID.Hash) + err = cs1.SetProposalAndBlock(propR1, propBlockR1Parts, "some peer") + require.NoError(t, err) + + ensureNewRound(newRoundCh, height, round) + + // ensure that the validator receives the proposal. + ensureNewProposal(proposalCh, height, round) + + // Prevote our nil since the proposal does not match our locked block. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // Add prevotes from the remainder of the validators for the new locked block. + signAddVotes(cs1, types.PrevoteType, chainID, r1BlockID, false, vs2, vs3, vs4) + + // Check that we lock on a new block. + ensureLock(lockCh, height, round) + + ensurePrecommit(voteCh, height, round) + + // We should now be locked on the new block and prevote it since we saw a sufficient amount + // prevote for the block. + validatePrecommit(t, cs1, round, round, vss[0], propBlockR1Hash, propBlockR1Hash) +} + +// TestStateLock_POLRelock tests that a validator updates its locked round if +// it receives votes representing over 2/3 of the voting power on the network +// for a block that it is already locked in. +func TestStateLock_POLRelock(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + lockCh := subscribe(cs1.eventBus, types.EventQueryLock) + relockCh := subscribe(cs1.eventBus, types.EventQueryRelock) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + /* + Round 0: + cs1 creates a proposal for block B. + Send a prevote for B from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + This ensures that cs1 will lock on B in this round but not precommit it. + */ + t.Log("### Starting Round 0") + + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + theBlock := rs.ProposalBlock + theBlockParts := rs.ProposalBlockParts + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + // check that the validator generates a Lock event. + ensureLock(lockCh, height, round) + + // the proposed block should now be locked and our precommit added. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) + + // add precommits from the rest of the validators. + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + // timeout to new round. + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + Create a proposal for block B, the same block from round 1. + Send a prevote for B from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + Check that cs1 updates its 'locked round' value to the current round. + */ + t.Log("### Starting Round 1") + incrementRound(vs2, vs3, vs4) + round++ + propR1 := types.NewProposal(height, round, cs1.ValidRound, blockID, theBlock.Header.Time) + signProposal(t, propR1, chainID, vs2) + err = cs1.SetProposalAndBlock(propR1, theBlockParts, "") + require.NoError(t, err) + + ensureNewRound(newRoundCh, height, round) + + // ensure that the validator receives the proposal. + ensureNewProposal(proposalCh, height, round) + + // Prevote our locked block since it matches the propsal seen in this round. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID.Hash) + + // Add prevotes from the remainder of the validators for the locked block. + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + // Check that we relock. + ensureRelock(relockCh, height, round) + + ensurePrecommit(voteCh, height, round) + + // We should now be locked on the same block but with an updated locked round. + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) +} + +// TestStateLock_PrevoteNilWhenLockedAndMissProposal tests that a validator prevotes nil +// if it is locked on a block and misses the proposal in a round. +func TestStateLock_PrevoteNilWhenLockedAndMissProposal(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + lockCh := subscribe(cs1.eventBus, types.EventQueryLock) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + /* + Round 0: + cs1 creates a proposal for block B. + Send a prevote for B from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + This ensures that cs1 will lock on B in this round but not precommit it. + */ + t.Log("### Starting Round 0") + + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + // check that the validator generates a Lock event. + ensureLock(lockCh, height, round) + + // the proposed block should now be locked and our precommit added. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) + + // add precommits from the rest of the validators. + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + // timeout to new round. + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + Send a prevote for nil from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + Check that cs1 prevotes nil instead of its locked block, but ensure + that it maintains its locked block. + */ + t.Log("### Starting Round 1") + incrementRound(vs2, vs3, vs4) + round++ + + ensureNewRound(newRoundCh, height, round) + + // Prevote our nil. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // Add prevotes from the remainder of the validators nil. + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs2, vs3, vs4) + ensurePrecommit(voteCh, height, round) + // We should now be locked on the same block but with an updated locked round. + validatePrecommit(t, cs1, round, 0, vss[0], nil, blockID.Hash) +} + +// TestStateLock_PrevoteNilWhenLockedAndDifferentProposal tests that a validator prevotes nil +// if it is locked on a block and gets a different proposal in a round. +func TestStateLock_PrevoteNilWhenLockedAndDifferentProposal(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + /* + All of the assertions in this test occur on the `cs1` validator. + The test sends signed votes from the other validators to cs1 and + cs1's state is then examined to verify that it now matches the expected + state. + */ + + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + lockCh := subscribe(cs1.eventBus, types.EventQueryLock) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + /* + Round 0: + cs1 creates a proposal for block B. + Send a prevote for B from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + This ensures that cs1 will lock on B in this round but not precommit it. + */ + t.Log("### Starting Round 0") + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + // check that the validator generates a Lock event. + ensureLock(lockCh, height, round) + + // the proposed block should now be locked and our precommit added. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) + + // add precommits from the rest of the validators. + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + // timeout to new round. + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + Create a proposal for a new block. + Send a prevote for nil from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + Check that cs1 prevotes nil instead of its locked block, but ensure + that it maintains its locked block. + */ + t.Log("### Starting Round 1") + incrementRound(vs2, vs3, vs4) + round++ + cs2 := newState(cs1.state, vs2, kvstore.NewInMemoryApplication()) + propR1, propBlockR1 := decideProposal(ctx, t, cs2, vs2, vs2.Height, vs2.Round) + propBlockR1Parts, err := propBlockR1.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) + propBlockR1Hash := propBlockR1.Hash() + require.NotEqual(t, propBlockR1Hash, blockID.Hash) + err = cs1.SetProposalAndBlock(propR1, propBlockR1Parts, "some peer") + require.NoError(t, err) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + + // Prevote our nil. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // Add prevotes from the remainder of the validators for nil. + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs2, vs3, vs4) + + // We should now be locked on the same block but prevote nil. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, 0, vss[0], nil, blockID.Hash) +} + +// TestStateLock_POLDoesNotUnlock tests that a validator maintains its locked block +// despite receiving +2/3 nil prevotes and nil precommits from other validators. +// Tendermint used to 'unlock' its locked block when greater than 2/3 prevotes +// for a nil block were seen. This behavior has been removed and this test ensures +// that it has been completely removed. +func TestStateLock_POLDoesNotUnlock(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + /* + All of the assertions in this test occur on the `cs1` validator. + The test sends signed votes from the other validators to cs1 and + cs1's state is then examined to verify that it now matches the expected + state. + */ + + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + lockCh := subscribe(cs1.eventBus, types.EventQueryLock) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + /* + Round 0: + Create a block, B + Send a prevote for B from each of the validators to `cs1`. + Send a precommit for B from one of the validators to `cs1`. + + This ensures that cs1 will lock on B in this round. + */ + t.Log("#### ONTO ROUND 0") + + // start round and wait for propose and prevote + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID.Hash) + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + // the validator should have locked a block in this round. + ensureLock(lockCh, height, round) + + ensurePrecommit(voteCh, height, round) + // the proposed block should now be locked and our should be for this locked block. + + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) + + // Add precommits from the other validators. + // We only issue 1/2 Precommits for the block in this round. + // This ensures that the validator being tested does not commit the block. + // We do not want the validator to commit the block because we want the test + // test to proceeds to the next consensus round. + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs4) + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs3) + + // timeout to new round + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + Send a prevote for nil from >2/3 of the validators to `cs1`. + Check that cs1 maintains its lock on B but precommits nil. + Send a precommit for nil from >2/3 of the validators to `cs1`. + */ + t.Log("#### ONTO ROUND 1") + round++ + incrementRound(vs2, vs3, vs4) + cs2 := newState(cs1.state, vs2, kvstore.NewInMemoryApplication()) + prop, propBlock := decideProposal(ctx, t, cs2, vs2, vs2.Height, vs2.Round) + propBlockParts, err := propBlock.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) + require.NotEqual(t, propBlock.Hash(), blockID.Hash) + err = cs1.SetProposalAndBlock(prop, propBlockParts, "") + require.NoError(t, err) + + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + + // Prevote for nil since the proposed block does not match our locked block. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // add >2/3 prevotes for nil from all other validators + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + + // verify that we haven't update our locked block since the first round + validatePrecommit(t, cs1, round, 0, vss[0], nil, blockID.Hash) + + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 2: + The validator cs1 saw >2/3 precommits for nil in the previous round. + Send the validator >2/3 prevotes for nil and ensure that it did not + unlock its block at the end of the previous round. + */ + t.Log("#### ONTO ROUND 2") + round++ + incrementRound(vs2, vs3, vs4) + cs3 := newState(cs1.state, vs2, kvstore.NewInMemoryApplication()) + prop, propBlock = decideProposal(ctx, t, cs3, vs3, vs3.Height, vs3.Round) + propBlockParts, err = propBlock.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) + err = cs1.SetProposalAndBlock(prop, propBlockParts, "") + require.NoError(t, err) + + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + + // Prevote for nil since the proposal does not match our locked block. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + + // verify that we haven't update our locked block since the first round + validatePrecommit(t, cs1, round, 0, vss[0], nil, blockID.Hash) +} + +// TestStateLock_MissingProposalWhenPOLSeenDoesNotUpdateLock tests that observing +// a two thirds majority for a block does not cause a validator to update its lock on the +// new block if a proposal was not seen for that block. +func TestStateLock_MissingProposalWhenPOLSeenDoesNotUpdateLock(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + /* + Round 0: + cs1 creates a proposal for block B. + Send a prevote for B from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + This ensures that cs1 will lock on B in this round but not precommit it. + */ + t.Log("### Starting Round 0") + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + firstBlockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) // prevote + + signAddVotes(cs1, types.PrevoteType, chainID, firstBlockID, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) // our precommit + // the proposed block should now be locked and our precommit added + validatePrecommit(t, cs1, round, round, vss[0], firstBlockID.Hash, firstBlockID.Hash) + + // add precommits from the rest + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + // timeout to new round + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + Create a new block, D but do not send it to cs1. + Send a prevote for D from each of the validators to cs1. + + Check that cs1 does not update its locked block to this missed block D. + */ + t.Log("### Starting Round 1") + incrementRound(vs2, vs3, vs4) + round++ + cs2 := newState(cs1.state, vs2, kvstore.NewInMemoryApplication()) + prop, propBlock := decideProposal(ctx, t, cs2, vs2, vs2.Height, vs2.Round) + require.NotNil(t, propBlock, "Failed to create proposal block with vs2") + require.NotNil(t, prop, "Failed to create proposal block with vs2") + partSet, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + secondBlockID := types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: partSet.Header(), + } + require.NotEqual(t, secondBlockID.Hash, firstBlockID.Hash) + + ensureNewRound(newRoundCh, height, round) + + // prevote for nil since the proposal was not seen. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // now lets add prevotes from everyone else for the new block + signAddVotes(cs1, types.PrevoteType, chainID, secondBlockID, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, 0, vss[0], nil, firstBlockID.Hash) +} + +// TestStateLock_MissingProposalWhenPOLForLockedBlock tests that observing +// a two thirds majority for a block that matches the validator's locked block +// causes a validator to update its lock round and Precommit the locked block. +func TestStateLock_MissingProposalWhenPOLForLockedBlock(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + /* + Round 0: + cs1 creates a proposal for block B. + Send a prevote for B from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + This ensures that cs1 will lock on B in this round but not commit it. + */ + t.Log("### Starting Round 0") + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) // prevote + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) // our precommit + // the proposed block should now be locked and our precommit added + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) + + // add precommits from the rest + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + // timeout to new round + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + The same block B is re-proposed, but it is not sent to cs1. + Send a prevote for B from each of the validators to cs1. + + Check that cs1 precommits B, since B matches its locked value. + Check that cs1 maintains its lock on block B but updates its locked round. + */ + t.Log("### Starting Round 1") + incrementRound(vs2, vs3, vs4) + round++ + + ensureNewRound(newRoundCh, height, round) + + // prevote for nil since the proposal was not seen (although it matches the locked block) + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // now lets add prevotes from everyone else for the locked block + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + // the validator precommits the valid block (as it received 2/3+ + // prevotes) which matches its locked block (which also received 2/3+ + // prevotes in the previous round). + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) +} + +// TestState_MissingProposalValidBlockReceivedTimeout tests if a node that +// misses the round's Proposal but receives a Polka for a block and the full +// block will not prevote for the valid block because the Proposal was missing. +func TestState_MissingProposalValidBlockReceivedTimeout(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(4) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + voteCh := subscribe(cs1.eventBus, types.EventQueryVote) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + + // Produce a block + block, err := cs1.createProposalBlock(ctx) + require.NoError(t, err) + blockParts, err := block.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) + blockID := types.BlockID{ + Hash: block.Hash(), + PartSetHeader: blockParts.Header(), + } + + // Skip round 0 and start consensus threads + round++ + incrementRound(vss[1:]...) + startTestRound(cs1, height, round) + + // Receive prevotes(height, round=1, blockID) from all other validators. + for i := 1; i < len(vss); i++ { + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vss[i]) + ensurePrevote(voteCh, height, round) + } + + // We have polka for blockID so we can accept the associated full block. + for i := 0; i < int(blockParts.Total()); i++ { + err := cs1.AddProposalBlockPart(height, round, blockParts.GetPart(i), "peer") + require.NoError(t, err) + } + ensureNewValidBlock(validBlockCh, height, round) + + // We don't prevote right now because we didn't receive the round's + // Proposal. Wait for the propose timeout. + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) + + rs := cs1.GetRoundState() + assert.Equal(t, rs.ValidRound, round) + assert.Equal(t, rs.ValidBlock.Hash(), blockID.Hash) + + // Since we didn't see the round's Proposal, we should prevote nil. + // NOTE: introduced by https://github.com/cometbft/cometbft/pull/1203. + // In branches v0.{34,37,38}.x, the node prevotes for the valid block. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) +} + +// TestState_MissingProposalValidBlockReceivedPrecommit tests if a node that +// misses the round's Proposal, but receives a Polka for a block and the full +// block, precommits the valid block even though the Proposal is missing. +func TestState_MissingProposalValidBlockReceivedPrecommit(t *testing.T) { + cs1, vss := randState(4) + height, round := cs1.Height, cs1.Round + chainID := cs1.state.ChainID + + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + voteCh := subscribe(cs1.eventBus, types.EventQueryVote) + + // Produce a block + _, blockParts, blockID := createProposalBlock(t, cs1) + + // Skip round 0 and start consensus + round++ + incrementRound(vss[1:]...) + startTestRound(cs1, height, round) + + // We are late, so we already receive prevotes for the block + for i := 1; i < len(vss); i++ { + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vss[i]) + ensurePrevote(voteCh, height, round) + } + // We received a Polka for blockID, which is now valid + ensureNewValidBlock(validBlockCh, height, round) + + // We don't have the Proposal, so we wait for timeout propose + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // We accept the full block associated with the valid blockID + for i := 0; i < int(blockParts.Total()); i++ { + err := cs1.AddProposalBlockPart(height, round, blockParts.GetPart(i), "peer") + require.NoError(t, err) + } + + // we don't have the Proposal for blockID, but we have the full block + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) +} + +// TestStateLock_DoesNotLockOnOldProposal tests that observing +// a two thirds majority for a block does not cause a validator to lock on the +// block if a proposal was not seen for that block in the current round, but +// was seen in a previous round. +func TestStateLock_DoesNotLockOnOldProposal(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + /* + Round 0: + cs1 creates a proposal for block B. + Send a prevote for nil from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + This ensures that cs1 will not lock on B. + */ + t.Log("### Starting Round 0") + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + firstBlockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs2, vs3, vs4) + + // The proposed block should not have been locked. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + incrementRound(vs2, vs3, vs4) + + // timeout to new round + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + No proposal new proposal is created. + Send a prevote for B, the block from round 0, from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + cs1 saw a POL for the block it saw in round 0. We ensure that it does not + lock on this block, since it did not see a proposal for it in this round. + */ + t.Log("### Starting Round 1") + round++ + ensureNewRound(newRoundCh, height, round) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // All validators prevote for the old block. + signAddVotes(cs1, types.PrevoteType, chainID, firstBlockID, false, vs2, vs3, vs4) + + // Make sure that cs1 did not lock on the block since it did not receive a proposal for it. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) +} + +// TestStateLock_POLSafety1 tests that a node should not change a lock based on +// polka in a round earlier than the locked round. The nodes proposes a block +// in round 0, this value receive a polka, not seen by anyone. A second block +// is proposed in round 1, we see the polka and lock it. Then we receive the +// polka from round 0. We don't do anything and remaining locked on round 1. +func TestStateLock_POLSafety1(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // block for round 1, from vs2, empty + // we build it now, to prevent timeouts + block1, blockParts1, blockID1 := createProposalBlock(t, cs1) + prop1 := types.NewProposal(vs2.Height, vs2.Round+1, -1, blockID1, block1.Time) + signProposal(t, prop1, chainID, vs2) + + // add a tx to the mempool + tx := kvstore.NewRandomTx(22) + reqRes, err := assertMempool(cs1.txNotifier).CheckTx(tx) + require.NoError(t, err) + require.False(t, reqRes.Response.GetCheckTx().IsErr()) + + // start the machine + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + // our proposal, it includes tx + ensureNewProposal(proposalCh, height, round) + blockID := cs1.GetRoundState().Proposal.BlockID + require.NotEqual(t, blockID, blockID1) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID.Hash) + + // the others sign a polka in round 0, but no one sees it + prevotes := signVotes(types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + // the others precommit nil + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + // precommit nil, locked value remains unset + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + t.Log("### ONTO ROUND 1") + incrementRound(vs2, vs3, vs4) + round++ + + ensureNewRound(newRoundCh, height, round) + err = cs1.SetProposalAndBlock(prop1, blockParts1, "some peer") + require.NoError(t, err) + + // prevote for proposal for block1 + ensureNewProposal(proposalCh, height, round) + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID1.Hash) + + // we see prevotes for it, so we should lock on and precommit it + signAddVotes(cs1, types.PrevoteType, chainID, blockID1, false, vs2, vs3, vs4) + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID1.Hash, blockID1.Hash) + + // the other don't see the polka, so precommit nil + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + t.Log("### ONTO ROUND 2") + incrementRound(vs2, vs3, vs4) + round++ + + // new round, no proposal, prevote nil + ensureNewRound(newRoundCh, height, round) + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // prevotes from the round-2 are added, nothing should change, no new round step + newStepCh := subscribe(cs1.eventBus, types.EventQueryNewRoundStep) + addVotes(cs1, prevotes...) + ensureNoNewRoundStep(newStepCh) + + // receive prevotes for nil, precommit nil, locked round is the same + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round-1, vss[0], nil, blockID1.Hash) +} + +// TestStateLock_POLSafety2 tests that a node should not accept a proposal with +// POLRound lower that its locked round. The nodes proposes a block in round 0, +// this value receives a polka, only seen by v3. A second block is proposed in +// round 1, we see the polka and lock it. Then we receive the polka from round +// 0 and the proposal from v3 re-proposing the block originally from round 0. +// We must reject this proposal, since we are locked on round 1. +func TestStateLock_POLSafety2(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // block for round 1, from vs2, empty + // we build it now, to prevent timeouts + block1, blockParts1, blockID1 := createProposalBlock(t, cs1) + prop1 := types.NewProposal(vs2.Height, vs2.Round+1, -1, blockID1, block1.Time) + signProposal(t, prop1, chainID, vs2) + + // add a tx to the mempool + tx := kvstore.NewRandomTx(22) + reqRes, err := assertMempool(cs1.txNotifier).CheckTx(tx) + require.NoError(t, err) + require.False(t, reqRes.Response.GetCheckTx().IsErr()) + + // start the machine + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + // our proposal, it includes tx + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + block0, blockParts0 := rs.ProposalBlock, rs.ProposalBlockParts + blockID0 := rs.Proposal.BlockID + require.NotEqual(t, blockID0, blockID1) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID0.Hash) + + // the others sign a polka in round 0 + prevotes := signVotes(types.PrevoteType, chainID, blockID0, false, vs2, vs3, vs4) + + // v2, v4 precommit nil, as they don't see the polka + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs4) + // v3 precommits the block, it has seen the polka + signAddVotes(cs1, types.PrecommitType, chainID, blockID0, true, vs3) + + // conflicting prevots, precommit nil, locked value remains unset + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + t.Log("### ONTO ROUND 1") + incrementRound(vs2, vs3, vs4) + round++ + + ensureNewRound(newRoundCh, height, round) + err = cs1.SetProposalAndBlock(prop1, blockParts1, "some peer") + require.NoError(t, err) + + // prevote for proposal for block1 + ensureNewProposal(proposalCh, height, round) + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID1.Hash) + + // we see prevotes for it, so we should lock on and precommit it + signAddVotes(cs1, types.PrevoteType, chainID, blockID1, false, vs2, vs3, vs4) + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID1.Hash, blockID1.Hash) + + // prevotes from round 0 are late received + newStepCh := subscribe(cs1.eventBus, types.EventQueryNewRoundStep) + addVotes(cs1, prevotes...) + ensureNoNewRoundStep(newStepCh) + + // the other don't see the polka, so precommit nil + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + t.Log("### ONTO ROUND 2") + incrementRound(vs2, vs3, vs4) + round++ + + // v3 has seen a polka for our block in round 0 + // it re-proposes block 0 with POLRound == 0 + prop2 := types.NewProposal(vs3.Height, vs3.Round, 0, blockID0, block0.Time) + signProposal(t, prop2, chainID, vs3) + + ensureNewRound(newRoundCh, height, round) + err = cs1.SetProposalAndBlock(prop2, blockParts0, "some peer") + require.NoError(t, err) + ensureNewProposal(proposalCh, height, round) + + // our locked round is 1, so we reject the proposal from v3 + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // receive prevotes for nil, precommit nil, locked round is the same + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round-1, vss[0], nil, blockID1.Hash) +} + +// TestState_PrevotePOLFromPreviousRound tests that a validator will prevote +// for a block if it is locked on a different block but saw a POL for the block +// it is not locked on in a previous round. +func TestState_PrevotePOLFromPreviousRound(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + lockCh := subscribe(cs1.eventBus, types.EventQueryLock) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + /* + Round 0: + cs1 creates a proposal for block B. + Send a prevote for B from each of the validators to cs1. + Send a precommit for nil from all of the validators to cs1. + + This ensures that cs1 will lock on B in this round but not precommit it. + */ + t.Log("### Starting Round 0") + + startTestRound(cs1, height, round) + + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + r0BlockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + + signAddVotes(cs1, types.PrevoteType, chainID, r0BlockID, false, vs2, vs3, vs4) + + // check that the validator generates a Lock event. + ensureLock(lockCh, height, round) + + // the proposed block should now be locked and our precommit added. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], r0BlockID.Hash, r0BlockID.Hash) + + // add precommits from the rest of the validators. + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + // timeout to new round. + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 1: + Create a block, D but do not send a proposal for it to cs1. + Send a prevote for D from each of the validators to cs1 so that cs1 sees a POL. + Send a precommit for nil from all of the validators to cs1. + + cs1 has now seen greater than 2/3 of the voting power prevote D in this round + but cs1 did not see the proposal for D in this round so it will not prevote or precommit it. + */ + t.Log("### Starting Round 1") + incrementRound(vs2, vs3, vs4) + round++ + // Generate a new proposal block. + cs2 := newState(cs1.state, vs2, kvstore.NewInMemoryApplication()) + cs2.ValidRound = 1 + propR1, propBlockR1 := decideProposal(ctx, t, cs2, vs2, vs2.Height, round) + t.Log(propR1.POLRound) + propBlockR1Parts, err := propBlockR1.MakePartSet(partSize) + require.NoError(t, err) + r1BlockID := types.BlockID{ + Hash: propBlockR1.Hash(), + PartSetHeader: propBlockR1Parts.Header(), + } + require.NotEqual(t, r1BlockID.Hash, r0BlockID.Hash) + + ensureNewRound(newRoundCh, height, round) + + signAddVotes(cs1, types.PrevoteType, chainID, r1BlockID, false, vs2, vs3, vs4) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + + // timeout to new round. + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + /* + Round 2: + Create a new proposal for D, the same block from Round 1. + cs1 already saw greater than 2/3 of the voting power on the network vote for + D in a previous round, so it should prevote D once it receives a proposal for it. + + cs1 does not need to receive prevotes from other validators before the proposal + in this round. It will still prevote the block. + + Send cs1 prevotes for nil and check that it still prevotes its locked block + and not the block that it prevoted. + */ + t.Log("### Starting Round 2") + incrementRound(vs2, vs3, vs4) + round++ + propR2 := types.NewProposal(height, round, 1, r1BlockID, propBlockR1.Header.Time) + signProposal(t, propR2, chainID, vs3) + + // cs1 receives a proposal for D, the block that received a POL in round 1. + err = cs1.SetProposalAndBlock(propR2, propBlockR1Parts, "") + require.NoError(t, err) + + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + + // We should now prevote this block, despite being locked on the block from + // round 0. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], r1BlockID.Hash) + + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs2, vs3, vs4) + + // cs1 did not receive a POL within this round, so it should remain locked + // on the block from round 0. + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, 0, vss[0], nil, r0BlockID.Hash) +} + +// 4 vals. +// polka P0 at R0 for B0. We lock B0 on P0 at R0. + +// What we want: +// P0 proposes B0 at R3. +func TestProposeValidBlock(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // start round and wait for propose and prevote + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + propBlock := rs.ProposalBlock + partSet, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + blockID := types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: partSet.Header(), + } + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID.Hash) + + // the others sign a polka + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + // we should have precommitted the proposed block in this round. + + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) + + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + incrementRound(vs2, vs3, vs4) + round++ // moving to the next round + + ensureNewRound(newRoundCh, height, round) + t.Log("### ONTO ROUND 1") + + // timeout of propose + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) + + // We did not see a valid proposal within this round, so prevote nil. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + // we should have precommitted nil during this round because we received + // >2/3 precommits for nil from the other validators. + validatePrecommit(t, cs1, round, 0, vss[0], nil, blockID.Hash) + + incrementRound(vs2, vs3, vs4) + incrementRound(vs2, vs3, vs4) + + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + round += 2 // increment by multiple rounds + + ensureNewRound(newRoundCh, height, round) + t.Log("### ONTO ROUND 3") + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + round++ // moving to the next round + + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + + rs = cs1.GetRoundState() + assert.True(t, bytes.Equal(rs.ProposalBlock.Hash(), blockID.Hash)) + assert.True(t, bytes.Equal(rs.ProposalBlock.Hash(), rs.ValidBlock.Hash())) + assert.Equal(t, rs.Proposal.POLRound, rs.ValidRound) + assert.True(t, bytes.Equal(rs.Proposal.BlockID.Hash, rs.ValidBlock.Hash())) +} + +// What we want: +// P0 miss to lock B but set valid block to B after receiving delayed prevote. +func TestSetValidBlockOnDelayedPrevote(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // start round and wait for propose and prevote + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + propBlock := rs.ProposalBlock + partSet, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + blockID := types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: partSet.Header(), + } + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID.Hash) + + // vs2 send prevote for propBlock + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2) + + // vs3 send prevote nil + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs3) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) + + ensurePrecommit(voteCh, height, round) + // we should have precommitted + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + + rs = cs1.GetRoundState() + + assert.Nil(t, rs.ValidBlock) + assert.Nil(t, rs.ValidBlockParts) + assert.Equal(t, int32(-1), rs.ValidRound) + + // vs2 send (delayed) prevote for propBlock + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs4) + + ensureNewValidBlock(validBlockCh, height, round) + + rs = cs1.GetRoundState() + + assert.True(t, bytes.Equal(rs.ValidBlock.Hash(), blockID.Hash)) + assert.True(t, rs.ValidBlockParts.Header().Equals(blockID.PartSetHeader)) + assert.Equal(t, rs.ValidRound, round) +} + +// What we want: +// P0 miss to lock B as Proposal Block is missing, but set valid block to B after +// receiving delayed Block Proposal. +func TestSetValidBlockOnDelayedProposal(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + + round++ // move to round in which P0 is not proposer + incrementRound(vs2, vs3, vs4) + + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + prop, propBlock := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round+1) + partSet, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + blockID := types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: partSet.Header(), + } + + // vs2, vs3 and vs4 send prevote for propBlock + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + ensureNewValidBlock(validBlockCh, height, round) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Prevote(round).Nanoseconds()) + + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + + partSet, err = propBlock.MakePartSet(partSize) + require.NoError(t, err) + err = cs1.SetProposalAndBlock(prop, partSet, "some peer") + require.NoError(t, err) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + + assert.True(t, bytes.Equal(rs.ValidBlock.Hash(), blockID.Hash)) + assert.True(t, rs.ValidBlockParts.Header().Equals(blockID.PartSetHeader)) + assert.Equal(t, rs.ValidRound, round) +} + +func TestProcessProposalAccept(t *testing.T) { + for _, testCase := range []struct { + name string + accept bool + expectedNilPrevote bool + }{ + { + name: "accepted block is prevoted", + accept: true, + expectedNilPrevote: false, + }, + { + name: "rejected block is not prevoted", + accept: false, + expectedNilPrevote: true, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + m := abcimocks.NewApplication(t) + status := abci.PROCESS_PROPOSAL_STATUS_REJECT + if testCase.accept { + status = abci.PROCESS_PROPOSAL_STATUS_ACCEPT + } + m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ProcessProposalResponse{Status: status}, nil) + m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{}, nil).Maybe() + cs1, _ := randStateWithApp(4, m) + height, round := cs1.Height, cs1.Round + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + var prevoteHash cmtbytes.HexBytes + if !testCase.expectedNilPrevote { + prevoteHash = rs.ProposalBlock.Hash() + } + ensurePrevoteMatch(t, voteCh, height, round, prevoteHash) + }) + } +} + +// TestExtendVoteCalledWhenEnabled tests that the vote extension methods are called at the +// correct point in the consensus algorithm when vote extensions are enabled. +func TestExtendVoteCalledWhenEnabled(t *testing.T) { + for _, testCase := range []struct { + name string + enabled bool + }{ + { + name: "enabled", + enabled: true, + }, + { + name: "disabled", + enabled: false, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + m := abcimocks.NewApplication(t) + m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{}, nil) + m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil) + if testCase.enabled { + m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ExtendVoteResponse{ + VoteExtension: []byte("extension"), + }, nil) + m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.VerifyVoteExtensionResponse{ + Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT, + }, nil) + } + m.On("Commit", mock.Anything, mock.Anything).Return(&abci.CommitResponse{}, nil).Maybe() + m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.FinalizeBlockResponse{}, nil).Maybe() + height := int64(1) + if !testCase.enabled { + height = 0 + } + cs1, vss := randStateWithAppWithHeight(4, m, height) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + + m.AssertNotCalled(t, "ExtendVote", mock.Anything, mock.Anything) + + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vss[1:]...) + ensurePrevoteMatch(t, voteCh, height, round, blockID.Hash) + + ensurePrecommit(voteCh, height, round) + + if testCase.enabled { + m.AssertCalled(t, "ExtendVote", context.TODO(), &abci.ExtendVoteRequest{ + Height: height, + Hash: blockID.Hash, + Time: rs.ProposalBlock.Time, + Txs: rs.ProposalBlock.Txs.ToSliceOfBytes(), + ProposedLastCommit: abci.CommitInfo{}, + Misbehavior: rs.ProposalBlock.Evidence.Evidence.ToABCI(), + NextValidatorsHash: rs.ProposalBlock.NextValidatorsHash, + ProposerAddress: rs.ProposalBlock.ProposerAddress, + }) + } else { + m.AssertNotCalled(t, "ExtendVote", mock.Anything, mock.Anything) + } + + signAddVotes(cs1, types.PrecommitType, chainID, blockID, testCase.enabled, vss[1:]...) + ensureNewRound(newRoundCh, height+1, 0) + m.AssertExpectations(t) + + // Only 3 of the vote extensions are seen, as consensus proceeds as soon as the +2/3 threshold + // is observed by the consensus engine. + for _, pv := range vss[1:3] { + pv, err := pv.GetPubKey() + require.NoError(t, err) + addr := pv.Address() + if testCase.enabled { + m.AssertCalled(t, "VerifyVoteExtension", context.TODO(), &abci.VerifyVoteExtensionRequest{ + Hash: blockID.Hash, + ValidatorAddress: addr, + Height: height, + VoteExtension: []byte("extension"), + }) + } else { + m.AssertNotCalled(t, "VerifyVoteExtension", mock.Anything, mock.Anything) + } + } + }) + } +} + +// TestVerifyVoteExtensionNotCalledOnAbsentPrecommit tests that the VerifyVoteExtension +// method is not called for a validator's vote that is never delivered. +func TestVerifyVoteExtensionNotCalledOnAbsentPrecommit(t *testing.T) { + m := abcimocks.NewApplication(t) + m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{}, nil) + m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil) + m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ExtendVoteResponse{ + VoteExtension: []byte("extension"), + }, nil) + m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.VerifyVoteExtensionResponse{ + Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT, + }, nil) + m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.FinalizeBlockResponse{}, nil).Maybe() + m.On("Commit", mock.Anything, mock.Anything).Return(&abci.CommitResponse{}, nil).Maybe() + cs1, vss := randStateWithApp(4, m) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + cs1.state.ConsensusParams.Feature.VoteExtensionsEnableHeight = cs1.Height + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vss...) + ensurePrevoteMatch(t, voteCh, height, round, blockID.Hash) + + ensurePrecommit(voteCh, height, round) + + m.AssertCalled(t, "ExtendVote", context.TODO(), &abci.ExtendVoteRequest{ + Height: height, + Hash: blockID.Hash, + Time: rs.ProposalBlock.Time, + Txs: rs.ProposalBlock.Txs.ToSliceOfBytes(), + ProposedLastCommit: abci.CommitInfo{}, + Misbehavior: rs.ProposalBlock.Evidence.Evidence.ToABCI(), + NextValidatorsHash: rs.ProposalBlock.NextValidatorsHash, + ProposerAddress: rs.ProposalBlock.ProposerAddress, + }) + + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vss[2:]...) + ensureNewRound(newRoundCh, height+1, 0) + m.AssertExpectations(t) + + // vss[1] did not issue a precommit for the block, ensure that a vote extension + // for its address was not sent to the application. + pv, err := vss[1].GetPubKey() + require.NoError(t, err) + addr = pv.Address() + + m.AssertNotCalled(t, "VerifyVoteExtension", context.TODO(), &abci.VerifyVoteExtensionRequest{ + Hash: blockID.Hash, + ValidatorAddress: addr, + Height: height, + VoteExtension: []byte("extension"), + }) +} + +// TestPrepareProposalReceivesVoteExtensions tests that the PrepareProposal method +// is called with the vote extensions from the previous height. The test functions +// by completing a consensus height with a mock application as the proposer. The +// test then proceeds to fail several rounds of consensus until the mock application +// is the proposer again and ensures that the mock application receives the set of +// vote extensions from the previous consensus instance. +func TestPrepareProposalReceivesVoteExtensions(t *testing.T) { + // create a list of vote extensions, one for each validator. + voteExtensions := [][]byte{ + []byte("extension 0"), + []byte("extension 1"), + []byte("extension 2"), + []byte("extension 3"), + } + + m := abcimocks.NewApplication(t) + m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ExtendVoteResponse{ + VoteExtension: voteExtensions[0], + }, nil) + m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil) + + // capture the prepare proposal request. + rpp := &abci.PrepareProposalRequest{} + m.On("PrepareProposal", mock.Anything, mock.MatchedBy(func(r *abci.PrepareProposalRequest) bool { + rpp = r + return true + })).Return(&abci.PrepareProposalResponse{}, nil) + + m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.VerifyVoteExtensionResponse{Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT}, nil) + m.On("Commit", mock.Anything, mock.Anything).Return(&abci.CommitResponse{}, nil).Maybe() + m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.FinalizeBlockResponse{}, nil) + + cs1, vss := randStateWithApp(4, m) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vss[1:]...) + + // create a precommit for each validator with the associated vote extension. + for i, vs := range vss[1:] { + signAddPrecommitWithExtension(t, cs1, chainID, blockID, voteExtensions[i+1], vs) + } + + ensurePrevote(voteCh, height, round) + + // ensure that the height is committed. + ensurePrecommitMatch(t, voteCh, height, round, blockID.Hash) + incrementHeight(vss[1:]...) + + height++ + round = 0 + ensureNewRound(newRoundCh, height, round) + incrementRound(vss[1:]...) + incrementRound(vss[1:]...) + incrementRound(vss[1:]...) + round = 3 + + blockID2 := types.BlockID{} + signAddVotes(cs1, types.PrecommitType, chainID, blockID2, true, vss[1:]...) + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + + // ensure that the proposer received the list of vote extensions from the + // previous height. + require.Len(t, rpp.LocalLastCommit.Votes, len(vss)) + for i := range vss { + vote := &rpp.LocalLastCommit.Votes[i] + require.Equal(t, vote.VoteExtension, voteExtensions[i]) + + require.NotZero(t, len(vote.ExtensionSignature)) + cve := cmtproto.CanonicalVoteExtension{ + Extension: vote.VoteExtension, + Height: height - 1, // the vote extension was signed in the previous height + Round: int64(rpp.LocalLastCommit.Round), + ChainId: test.DefaultTestChainID, + } + extSignBytes, err := protoio.MarshalDelimited(&cve) + require.NoError(t, err) + pubKey, err := vss[i].PrivValidator.GetPubKey() + require.NoError(t, err) + require.True(t, pubKey.VerifySignature(extSignBytes, vote.ExtensionSignature)) + } +} + +func TestFinalizeBlockCalled(t *testing.T) { + for _, testCase := range []struct { + name string + voteNil bool + expectCalled bool + }{ + { + name: "finalize block called when block committed", + voteNil: false, + expectCalled: true, + }, + { + name: "not called when block not committed", + voteNil: true, + expectCalled: false, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + m := abcimocks.NewApplication(t) + m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ProcessProposalResponse{ + Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT, + }, nil) + m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{}, nil) + // We only expect VerifyVoteExtension to be called on non-nil precommits. + // https://github.com/tendermint/tendermint/issues/8487 + if !testCase.voteNil { + m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ExtendVoteResponse{}, nil) + m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.VerifyVoteExtensionResponse{ + Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT, + }, nil) + } + r := &abci.FinalizeBlockResponse{AppHash: []byte("the_hash")} + m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(r, nil).Maybe() + m.On("Commit", mock.Anything, mock.Anything).Return(&abci.CommitResponse{}, nil).Maybe() + + cs1, vss := randStateWithApp(4, m) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + + blockID := types.BlockID{} + nextRound := round + 1 + nextHeight := height + if !testCase.voteNil { + nextRound = 0 + nextHeight = height + 1 + blockID = types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + } + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vss[1:]...) + ensurePrevoteMatch(t, voteCh, height, round, rs.ProposalBlock.Hash()) + + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vss[1:]...) + ensurePrecommit(voteCh, height, round) + + ensureNewRound(newRoundCh, nextHeight, nextRound) + m.AssertExpectations(t) + + if !testCase.expectCalled { + m.AssertNotCalled(t, "FinalizeBlock", context.TODO(), mock.Anything) + } else { + m.AssertCalled(t, "FinalizeBlock", context.TODO(), mock.Anything) + } + }) + } +} + +// TestVoteExtensionEnableHeight tests that 'ExtensionRequireHeight' correctly +// enforces that vote extensions be present in consensus for heights greater than +// or equal to the configured value. +func TestVoteExtensionEnableHeight(t *testing.T) { + for _, testCase := range []struct { + name string + enableHeight int64 + hasExtension bool + expectExtendCalled bool + expectVerifyCalled bool + expectSuccessfulRound bool + }{ + { + name: "extension present but not enabled", + hasExtension: true, + enableHeight: 0, + expectExtendCalled: false, + expectVerifyCalled: false, + expectSuccessfulRound: false, + }, + { + name: "extension absent but not required", + hasExtension: false, + enableHeight: 0, + expectExtendCalled: false, + expectVerifyCalled: false, + expectSuccessfulRound: true, + }, + { + name: "extension present and required", + hasExtension: true, + enableHeight: 1, + expectExtendCalled: true, + expectVerifyCalled: true, + expectSuccessfulRound: true, + }, + { + name: "extension absent but required", + hasExtension: false, + enableHeight: 1, + expectExtendCalled: true, + expectVerifyCalled: false, + expectSuccessfulRound: false, + }, + { + name: "extension absent but required in future height", + hasExtension: false, + enableHeight: 2, + expectExtendCalled: false, + expectVerifyCalled: false, + expectSuccessfulRound: true, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + numValidators := 3 + m := abcimocks.NewApplication(t) + m.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ProcessProposalResponse{ + Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT, + }, nil) + m.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{}, nil) + if testCase.expectExtendCalled { + m.On("ExtendVote", mock.Anything, mock.Anything).Return(&abci.ExtendVoteResponse{}, nil) + } + if testCase.expectVerifyCalled { + m.On("VerifyVoteExtension", mock.Anything, mock.Anything).Return(&abci.VerifyVoteExtensionResponse{ + Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT, + }, nil).Times(numValidators - 1) + } + m.On("FinalizeBlock", mock.Anything, mock.Anything).Return(&abci.FinalizeBlockResponse{}, nil).Maybe() + m.On("Commit", mock.Anything, mock.Anything).Return(&abci.CommitResponse{}, nil).Maybe() + cs1, vss := randStateWithAppWithHeight(numValidators, m, testCase.enableHeight) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + cs1.state.ConsensusParams.Feature.VoteExtensionsEnableHeight = testCase.enableHeight + + timeoutCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + startTestRound(cs1, cs1.Height, round) + ensureNewRound(newRoundCh, height, round) + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + // sign all of the votes + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vss[1:]...) + ensurePrevoteMatch(t, voteCh, height, round, rs.ProposalBlock.Hash()) + + var ext []byte + if testCase.hasExtension { + ext = []byte("extension") + } + + for _, vs := range vss[1:] { + vote, err := vs.signVote(types.PrecommitType, chainID, blockID, ext, testCase.hasExtension, vs.clock.Now()) + require.NoError(t, err) + addVotes(cs1, vote) + } + if testCase.expectSuccessfulRound { + ensurePrecommit(voteCh, height, round) + height++ + ensureNewRound(newRoundCh, height, round) + } else { + ensureNoNewTimeout(timeoutCh, cs1.config.Precommit(round).Nanoseconds()) + } + + m.AssertExpectations(t) + }) + } +} + +// 4 vals, 3 Nil Precommits at P0 +// What we want: +// P0 waits for timeoutPrecommit before starting next round. +func TestWaitingTimeoutOnNilPolka(*testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + + // start round + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + ensureNewRound(newRoundCh, height, round+1) +} + +// 4 vals, 3 Prevotes for nil from the higher round. +// What we want: +// P0 waits for timeoutPropose in the next round before entering prevote. +func TestWaitingTimeoutProposeOnNewRound(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // start round + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + ensurePrevote(voteCh, height, round) + + incrementRound(vss[1:]...) + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs2, vs3, vs4) + + round++ // moving to the next round + ensureNewRound(newRoundCh, height, round) + + rs := cs1.GetRoundState() + assert.Equal(t, cstypes.RoundStepPropose, rs.Step) // P0 does not prevote before timeoutPropose expires + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Propose(round).Nanoseconds()) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) +} + +// 4 vals, 3 Precommits for nil from the higher round. +// What we want: +// P0 jump to higher round, precommit and start precommit wait. +func TestRoundSkipOnNilPolkaFromHigherRound(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // start round + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + ensurePrevote(voteCh, height, round) + + incrementRound(vss[1:]...) + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2, vs3, vs4) + + round++ // moving to the next round + ensureNewRound(newRoundCh, height, round) + + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, -1, vss[0], nil, nil) + + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + round++ // moving to the next round + ensureNewRound(newRoundCh, height, round) +} + +// 4 vals, 3 Prevotes for nil in the current round. +// What we want: +// P0 wait for timeoutPropose to expire before sending prevote. +func TestWaitTimeoutProposeOnNilPolkaForTheCurrentRound(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, int32(1), cs1.state.ChainID + + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // start round in which PO is not proposer + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + incrementRound(vss[1:]...) + signAddVotes(cs1, types.PrevoteType, chainID, types.BlockID{}, false, vs2, vs3, vs4) + + ensureNewTimeout(timeoutProposeCh, height, round, cs1.config.Propose(round).Nanoseconds()) + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) +} + +// What we want: +// P0 emit NewValidBlock event upon receiving 2/3+ Precommit for B but hasn't received block B yet. +func TestEmitNewValidBlockEventOnCommitWithoutBlock(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, int32(1), cs1.state.ChainID + + incrementRound(vs2, vs3, vs4) + + partSize := types.BlockPartSizeBytes + + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + + _, propBlock := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round) + partSet, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + blockID := types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: partSet.Header(), + } + + // start round in which PO is not proposer + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + // vs2, vs3 and vs4 send precommit for propBlock + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs2, vs3, vs4) + ensureNewValidBlock(validBlockCh, height, round) + + rs := cs1.GetRoundState() + assert.Equal(t, rs.Step, cstypes.RoundStepCommit) //nolint:testifylint // this will tell us to reverse the items being compared no matter what + assert.Nil(t, rs.ProposalBlock) + assert.True(t, rs.ProposalBlockParts.Header().Equals(blockID.PartSetHeader)) +} + +// What we want: +// P0 receives 2/3+ Precommit for B for round 0, while being in round 1. It emits NewValidBlock event. +// After receiving block, it executes block and moves to the next height. +func TestCommitFromPreviousRound(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, int32(1), cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + validBlockCh := subscribe(cs1.eventBus, types.EventQueryValidBlock) + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + + prop, propBlock := decideProposal(ctx, t, cs1, vs2, vs2.Height, vs2.Round) + partSet, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + blockID := types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: partSet.Header(), + } + + // start round in which PO is not proposer + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + // vs2, vs3 and vs4 send precommit for propBlock for the previous round + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs2, vs3, vs4) + + ensureNewValidBlock(validBlockCh, height, round) + + rs := cs1.GetRoundState() + assert.Equal(t, cstypes.RoundStepCommit, rs.Step) + assert.Equal(t, vs2.Round, rs.CommitRound) + assert.Nil(t, rs.ProposalBlock, nil) + assert.True(t, rs.ProposalBlockParts.Header().Equals(blockID.PartSetHeader)) + partSet, err = propBlock.MakePartSet(partSize) + require.NoError(t, err) + err = cs1.SetProposalAndBlock(prop, partSet, "some peer") + require.NoError(t, err) + + ensureNewProposal(proposalCh, height, round) + ensureNewRound(newRoundCh, height+1, 0) +} + +type fakeTxNotifier struct { + ch chan struct{} +} + +func (n *fakeTxNotifier) TxsAvailable() <-chan struct{} { + return n.ch +} + +func (n *fakeTxNotifier) Notify() { + n.ch <- struct{}{} +} + +// 2 vals precommit votes for a block but node times out waiting for the third. Move to next round +// and third precommit arrives which leads to the commit of that header and the correct +// start of the next round. +func TestStartNextHeightCorrectlyAfterTimeout(t *testing.T) { + config.Consensus.SkipTimeoutCommit = false + cs1, vss := randState(4) + cs1.txNotifier = &fakeTxNotifier{ch: make(chan struct{})} + + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + timeoutProposeCh := subscribe(cs1.eventBus, types.EventQueryTimeoutPropose) + precommitTimeoutCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // start round and wait for propose and prevote + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID.Hash) + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + // the proposed block should now be locked and our precommit added + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) + + // add precommits + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2) + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs3) + + // wait till timeout occurs + ensureNewTimeout(precommitTimeoutCh, height, round, cs1.config.TimeoutPrecommit.Nanoseconds()) + + ensureNewRound(newRoundCh, height, round+1) + + // majority is now reached + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs4) + + ensureNewBlockHeader(newBlockHeader, height, blockID.Hash) + + cs1.txNotifier.(*fakeTxNotifier).Notify() + + ensureNewTimeout(timeoutProposeCh, height+1, round, cs1.config.Propose(round).Nanoseconds()) + rs = cs1.GetRoundState() + assert.False( + t, + rs.TriggeredTimeoutPrecommit, + "triggeredTimeoutPrecommit should be false at the beginning of each round") +} + +func TestResetTimeoutPrecommitUponNewHeight(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + config.Consensus.SkipTimeoutCommit = false + cs1, vss := randState(4) + + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + + partSize := types.BlockPartSizeBytes + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + newBlockHeader := subscribe(cs1.eventBus, types.EventQueryNewBlockHeader) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // start round and wait for propose and prevote + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + blockID := types.BlockID{ + Hash: rs.ProposalBlock.Hash(), + PartSetHeader: rs.ProposalBlockParts.Header(), + } + + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], blockID.Hash) + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) + + // add precommits + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2) + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs3) + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs4) + + ensureNewBlockHeader(newBlockHeader, height, blockID.Hash) + + prop, propBlock := decideProposal(ctx, t, cs1, vs2, height+1, 0) + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + + err = cs1.SetProposalAndBlock(prop, propBlockParts, "some peer") + require.NoError(t, err) + ensureNewProposal(proposalCh, height+1, 0) + + rs = cs1.GetRoundState() + assert.False( + t, + rs.TriggeredTimeoutPrecommit, + "triggeredTimeoutPrecommit should be false at the beginning of each height") +} + +// ------------------------------------------------------------------------------------------ +// CatchupSuite + +// ------------------------------------------------------------------------------------------ +// HaltSuite + +// 4 vals. +// we receive a final precommit after going into next round, but others might have gone to commit already! +func TestStateHalt1(t *testing.T) { + cs1, vss := randState(4) + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + partSize := types.BlockPartSizeBytes + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + timeoutWaitCh := subscribe(cs1.eventBus, types.EventQueryTimeoutWait) + newRoundCh := subscribe(cs1.eventBus, types.EventQueryNewRound) + newBlockCh := subscribe(cs1.eventBus, types.EventQueryNewBlock) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + // start round and wait for propose and prevote + startTestRound(cs1, height, round) + ensureNewRound(newRoundCh, height, round) + + ensureNewProposal(proposalCh, height, round) + rs := cs1.GetRoundState() + propBlock := rs.ProposalBlock + partSet, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + blockID := types.BlockID{ + Hash: propBlock.Hash(), + PartSetHeader: partSet.Header(), + } + + ensurePrevote(voteCh, height, round) + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + ensurePrecommit(voteCh, height, round) + // the proposed block should now be locked and our precommit added + validatePrecommit(t, cs1, round, round, vss[0], propBlock.Hash(), propBlock.Hash()) + + // add precommits from the rest + signAddVotes(cs1, types.PrecommitType, chainID, types.BlockID{}, true, vs2) // didn't receive proposal + signAddVotes(cs1, types.PrecommitType, chainID, blockID, true, vs3) + // we receive this later, but vs3 might receive it earlier and with ours will go to commit! + precommit4 := signVote(vs4, types.PrecommitType, chainID, blockID, true) + + incrementRound(vs2, vs3, vs4) + + // timeout to new round + ensureNewTimeout(timeoutWaitCh, height, round, cs1.config.Precommit(round).Nanoseconds()) + + round++ // moving to the next round + + ensureNewRound(newRoundCh, height, round) + + t.Log("### ONTO ROUND 1") + /* Round2 + // we timeout and prevote + // a polka happened but we didn't see it! + */ + + // prevote for nil since we did not receive a proposal in this round. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // now we receive the precommit from the previous round + addVotes(cs1, precommit4) + + // receiving that precommit should take us straight to commit + ensureNewBlock(newBlockCh, height) + + ensureNewRound(newRoundCh, height+1, 0) +} + +func TestStateOutputsBlockPartsStats(t *testing.T) { + // create dummy peer + cs, _ := randState(1) + peer := p2pmock.NewPeer(nil) + + // 1) new block part + parts := types.NewPartSetFromData(cmtrand.Bytes(100), 10) + msg := &BlockPartMessage{ + Height: 1, + Round: 0, + Part: parts.GetPart(0), + } + + cs.ProposalBlockParts = types.NewPartSetFromHeader(parts.Header()) + cs.handleMsg(msgInfo{msg, peer.ID(), time.Time{}}) + + statsMessage := <-cs.statsMsgQueue + require.Equal(t, msg, statsMessage.Msg, "") + require.Equal(t, peer.ID(), statsMessage.PeerID, "") + + // sending the same part from different peer + cs.handleMsg(msgInfo{msg, "peer2", time.Time{}}) + + // sending the part with the same height, but different round + msg.Round = 1 + cs.handleMsg(msgInfo{msg, peer.ID(), time.Time{}}) + + // sending the part from the smaller height + msg.Height = 0 + cs.handleMsg(msgInfo{msg, peer.ID(), time.Time{}}) + + // sending the part from the bigger height + msg.Height = 3 + cs.handleMsg(msgInfo{msg, peer.ID(), time.Time{}}) + + select { + case <-cs.statsMsgQueue: + t.Errorf("should not output stats message after receiving the known block part!") + case <-time.After(50 * time.Millisecond): + } +} + +func TestStateOutputVoteStats(t *testing.T) { + cs, vss := randState(2) + chainID := cs.state.ChainID + // create dummy peer + peer := p2pmock.NewPeer(nil) + + randBytes := cmtrand.Bytes(tmhash.Size) + blockID := types.BlockID{ + Hash: randBytes, + } + + vote := signVote(vss[1], types.PrecommitType, chainID, blockID, true) + + voteMessage := &VoteMessage{vote} + cs.handleMsg(msgInfo{voteMessage, peer.ID(), time.Time{}}) + + statsMessage := <-cs.statsMsgQueue + require.Equal(t, voteMessage, statsMessage.Msg, "") + require.Equal(t, peer.ID(), statsMessage.PeerID, "") + + // sending the same part from different peer + cs.handleMsg(msgInfo{&VoteMessage{vote}, "peer2", time.Time{}}) + + // sending the vote for the bigger height + incrementHeight(vss[1]) + vote = signVote(vss[1], types.PrecommitType, chainID, blockID, true) + + cs.handleMsg(msgInfo{&VoteMessage{vote}, peer.ID(), time.Time{}}) + + select { + case <-cs.statsMsgQueue: + t.Errorf("should not output stats message after receiving the known vote or vote from bigger height") + case <-time.After(50 * time.Millisecond): + } +} + +func TestSignSameVoteTwice(t *testing.T) { + cs, vss := randState(2) + chainID := cs.state.ChainID + + randBytes := cmtrand.Bytes(tmhash.Size) + + vote := signVote(vss[1], + types.PrecommitType, + chainID, + types.BlockID{ + Hash: randBytes, + PartSetHeader: types.PartSetHeader{Total: 10, Hash: randBytes}, + }, + true, + ) + + vote2 := signVote(vss[1], + types.PrecommitType, + chainID, + types.BlockID{ + Hash: randBytes, + PartSetHeader: types.PartSetHeader{Total: 10, Hash: randBytes}, + }, + true, + ) + + require.Equal(t, vote, vote2) +} + +// TestStateTimestamp_ProposalNotMatch tests that a validator does not prevote a +// proposed block if the timestamp in the block does not match the timestamp in the +// corresponding proposal message. +func TestStateTimestamp_ProposalNotMatch(t *testing.T) { + cs1, vss := randState(4) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + propBlock, propBlockParts, blockID := createProposalBlock(t, cs1) + + round++ + incrementRound(vss[1:]...) + + // Create a proposal with a timestamp that does not match the timestamp of the block. + proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time.Add(time.Millisecond)) + signProposal(t, proposal, chainID, vs2) + require.NoError(t, cs1.SetProposalAndBlock(proposal, propBlockParts, "some peer")) + + startTestRound(cs1, height, round) + ensureProposal(proposalCh, height, round, blockID) + + // ensure that the validator prevotes nil. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], nil) + + // This does not refer to the main concern of this test unit. Since + // 2/3+ validators have seen the proposal, validated and prevoted for + // it, it is a valid proposal. We should lock and precommit for it. + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, round, vss[0], blockID.Hash, blockID.Hash) +} + +// TestStateTimestamp_ProposalMatch tests that a validator prevotes a +// proposed block if the timestamp in the block matches the timestamp in the +// corresponding proposal message. +func TestStateTimestamp_ProposalMatch(t *testing.T) { + cs1, vss := randState(4) + height, round, chainID := cs1.Height, cs1.Round, cs1.state.ChainID + vs2, vs3, vs4 := vss[1], vss[2], vss[3] + + proposalCh := subscribe(cs1.eventBus, types.EventQueryCompleteProposal) + pv1, err := cs1.privValidator.GetPubKey() + require.NoError(t, err) + addr := pv1.Address() + voteCh := subscribeToVoter(cs1, addr) + + propBlock, propBlockParts, blockID := createProposalBlock(t, cs1) + + round++ + incrementRound(vss[1:]...) + + // Create a proposal with a timestamp that matches the timestamp of the block. + proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time) + signProposal(t, proposal, chainID, vs2) + require.NoError(t, cs1.SetProposalAndBlock(proposal, propBlockParts, "some peer")) + + startTestRound(cs1, height, round) + ensureProposal(proposalCh, height, round, blockID) + + signAddVotes(cs1, types.PrevoteType, chainID, blockID, false, vs2, vs3, vs4) + + // ensure that the validator prevotes the block. + ensurePrevote(voteCh, height, round) + validatePrevote(t, cs1, round, vss[0], propBlock.Hash()) + + ensurePrecommit(voteCh, height, round) + validatePrecommit(t, cs1, round, 1, vss[0], propBlock.Hash(), propBlock.Hash()) +} + +// subscribe subscribes test client to the given query and returns a channel with cap = 1. +func subscribe(eventBus *types.EventBus, q cmtpubsub.Query) <-chan cmtpubsub.Message { + sub, err := eventBus.Subscribe(context.Background(), testSubscriber, q) + if err != nil { + panic(fmt.Sprintf("failed to subscribe %s to %v; err %v", testSubscriber, q, err)) + } + return sub.Out() +} + +// subscribe subscribes test client to the given query and returns a channel with cap = 1. +func unsubscribe(eventBus *types.EventBus, q cmtpubsub.Query) { //nolint: unused + err := eventBus.Unsubscribe(context.Background(), testSubscriber, q) + if err != nil { + panic(fmt.Sprintf("failed to subscribe %s to %v; err %v", testSubscriber, q, err)) + } +} + +// subscribe subscribes test client to the given query and returns a channel with cap = 0. +func subscribeUnBuffered(eventBus *types.EventBus, q cmtpubsub.Query) <-chan cmtpubsub.Message { + sub, err := eventBus.SubscribeUnbuffered(context.Background(), testSubscriber, q) + if err != nil { + panic(fmt.Sprintf("failed to subscribe %s to %v; err %v", testSubscriber, q, err)) + } + return sub.Out() +} + +func signAddPrecommitWithExtension( + t *testing.T, + cs *State, + chainID string, + blockID types.BlockID, + extension []byte, + stub *validatorStub, +) { + t.Helper() + v, err := stub.signVote(types.PrecommitType, chainID, blockID, extension, true, stub.clock.Now()) + require.NoError(t, err, "failed to sign vote") + addVotes(cs, v) +} + +func findBlockSizeLimit(t *testing.T, height, maxBytes int64, cs *State, partSize uint32, oversized bool) (*types.Block, *types.PartSet) { + t.Helper() + var offset int64 + if !oversized { + offset = -2 + } + softMaxDataBytes := int(types.MaxDataBytes(maxBytes, 0, 0)) + for i := softMaxDataBytes; i < softMaxDataBytes*2; i++ { + propBlock := cs.state.MakeBlock( + height, + []types.Tx{[]byte("a=" + strings.Repeat("o", i-2))}, + &types.Commit{}, + nil, + cs.privValidatorPubKey.Address(), + ) + + propBlockParts, err := propBlock.MakePartSet(partSize) + require.NoError(t, err) + if propBlockParts.ByteSize() > maxBytes+offset { + s := "real max" + if oversized { + s = "off-by-1" + } + t.Log("Detected "+s+" data size for block;", "size", i, "softMaxDataBytes", softMaxDataBytes) + return propBlock, propBlockParts + } + } + require.Fail(t, "We shouldn't hit the end of the loop") + return nil, nil +} diff --git a/consensus/ticker.go b/internal/consensus/ticker.go similarity index 83% rename from consensus/ticker.go rename to internal/consensus/ticker.go index ae5fab794ab..2b79d02481f 100644 --- a/consensus/ticker.go +++ b/internal/consensus/ticker.go @@ -3,13 +3,11 @@ package consensus import ( "time" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" ) -var ( - tickTockBufferSize = 10 -) +var tickTockBufferSize = 10 // TimeoutTicker is a timer that schedules timeouts // conditional on the height/round/step in the timeoutInfo. @@ -20,7 +18,7 @@ type TimeoutTicker interface { Chan() <-chan timeoutInfo // on which to receive a timeout ScheduleTimeout(ti timeoutInfo) // reset the timer - SetLogger(log.Logger) + SetLogger(l log.Logger) } // timeoutTicker wraps time.Timer, @@ -50,7 +48,6 @@ func NewTimeoutTicker() TimeoutTicker { // OnStart implements service.Service. It starts the timeout routine. func (t *timeoutTicker) OnStart() error { - go t.timeoutRoutine() return nil @@ -74,9 +71,9 @@ func (t *timeoutTicker) ScheduleTimeout(ti timeoutInfo) { t.tickChan <- ti } -//------------------------------------------------------------- +// ------------------------------------------------------------- -// stop the timer and drain if necessary +// stop the timer and drain if necessary. func (t *timeoutTicker) stopTimer() { // Stop() returns false if it was already fired or was stopped if !t.timer.Stop() { @@ -89,8 +86,8 @@ func (t *timeoutTicker) stopTimer() { } // send on tickChan to start a new timer. -// timers are interupted and replaced by new ticks from later steps -// timeouts of 0 on the tickChan will be immediately relayed to the tockChan +// timers are interrupted and replaced by new ticks from later steps +// timeouts of 0 on the tickChan will be immediately relayed to the tockChan. func (t *timeoutTicker) timeoutRoutine() { t.Logger.Debug("Starting timeout routine") var ti timeoutInfo @@ -99,24 +96,14 @@ func (t *timeoutTicker) timeoutRoutine() { case newti := <-t.tickChan: t.Logger.Debug("Received tick", "old_ti", ti, "new_ti", newti) - // ignore tickers for old height/round/step - if newti.Height < ti.Height { + if shouldSkipTick(newti, ti) { continue - } else if newti.Height == ti.Height { - if newti.Round < ti.Round { - continue - } else if newti.Round == ti.Round { - if ti.Step > 0 && newti.Step <= ti.Step { - continue - } - } } // stop the last timer t.stopTimer() // update timeoutInfo and reset timer - // NOTE time.Timer allows duration to be non-positive ti = newti t.timer.Reset(ti.Duration) t.Logger.Debug("Scheduled timeout", "dur", ti.Duration, "height", ti.Height, "round", ti.Round, "step", ti.Step) @@ -132,3 +119,14 @@ func (t *timeoutTicker) timeoutRoutine() { } } } + +// shouldSkipTick returns true if the new timeoutInfo should be skipped. +func shouldSkipTick(newti, ti timeoutInfo) bool { + if newti.Height < ti.Height { + return true + } + if newti.Height == ti.Height && ((newti.Round < ti.Round) || (newti.Round == ti.Round && ti.Step > 0 && newti.Step <= ti.Step)) { + return true + } + return false +} diff --git a/consensus/types/height_vote_set.go b/internal/consensus/types/height_vote_set.go similarity index 87% rename from consensus/types/height_vote_set.go rename to internal/consensus/types/height_vote_set.go index 2c45a29aa63..47a1fae075a 100644 --- a/consensus/types/height_vote_set.go +++ b/internal/consensus/types/height_vote_set.go @@ -9,7 +9,6 @@ import ( cmtjson "github.com/cometbft/cometbft/libs/json" cmtmath "github.com/cometbft/cometbft/libs/math" "github.com/cometbft/cometbft/p2p" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" ) @@ -18,10 +17,8 @@ type RoundVoteSet struct { Precommits *types.VoteSet } -var ( - ErrGotVoteFromUnwantedRound = errors.New( - "peer has sent a vote that does not match our round for more than one round", - ) +var ErrGotVoteFromUnwantedRound = errors.New( + "peer has sent a vote that does not match our round for more than one round", ) /* @@ -115,12 +112,12 @@ func (hvs *HeightVoteSet) addRound(round int32) { panic("addRound() for an existing round") } // log.Debug("addRound(round)", "round", round) - prevotes := types.NewVoteSet(hvs.chainID, hvs.height, round, cmtproto.PrevoteType, hvs.valSet) + prevotes := types.NewVoteSet(hvs.chainID, hvs.height, round, types.PrevoteType, hvs.valSet) var precommits *types.VoteSet if hvs.extensionsEnabled { - precommits = types.NewExtendedVoteSet(hvs.chainID, hvs.height, round, cmtproto.PrecommitType, hvs.valSet) + precommits = types.NewExtendedVoteSet(hvs.chainID, hvs.height, round, types.PrecommitType, hvs.valSet) } else { - precommits = types.NewVoteSet(hvs.chainID, hvs.height, round, cmtproto.PrecommitType, hvs.valSet) + precommits = types.NewVoteSet(hvs.chainID, hvs.height, round, types.PrecommitType, hvs.valSet) } hvs.roundVoteSets[round] = RoundVoteSet{ Prevotes: prevotes, @@ -137,34 +134,34 @@ func (hvs *HeightVoteSet) AddVote(vote *types.Vote, peerID p2p.ID, extEnabled bo panic(fmt.Errorf("extensions enabled general param does not match the one in HeightVoteSet %t!=%t", hvs.extensionsEnabled, extEnabled)) } if !types.IsVoteTypeValid(vote.Type) { - return + return false, fmt.Errorf("invalid vote type %T", vote.Type) } voteSet := hvs.getVoteSet(vote.Round, vote.Type) if voteSet == nil { - if rndz := hvs.peerCatchupRounds[peerID]; len(rndz) < 2 { - hvs.addRound(vote.Round) - voteSet = hvs.getVoteSet(vote.Round, vote.Type) - hvs.peerCatchupRounds[peerID] = append(rndz, vote.Round) - } else { + rndz := hvs.peerCatchupRounds[peerID] + if len(rndz) >= 2 { // punish peer err = ErrGotVoteFromUnwantedRound - return + return false, err } + hvs.addRound(vote.Round) + voteSet = hvs.getVoteSet(vote.Round, vote.Type) + hvs.peerCatchupRounds[peerID] = append(rndz, vote.Round) } added, err = voteSet.AddVote(vote) - return + return added, err } func (hvs *HeightVoteSet) Prevotes(round int32) *types.VoteSet { hvs.mtx.Lock() defer hvs.mtx.Unlock() - return hvs.getVoteSet(round, cmtproto.PrevoteType) + return hvs.getVoteSet(round, types.PrevoteType) } func (hvs *HeightVoteSet) Precommits(round int32) *types.VoteSet { hvs.mtx.Lock() defer hvs.mtx.Unlock() - return hvs.getVoteSet(round, cmtproto.PrecommitType) + return hvs.getVoteSet(round, types.PrecommitType) } // Last round and blockID that has +2/3 prevotes for a particular block or nil. @@ -173,7 +170,7 @@ func (hvs *HeightVoteSet) POLInfo() (polRound int32, polBlockID types.BlockID) { hvs.mtx.Lock() defer hvs.mtx.Unlock() for r := hvs.round; r >= 0; r-- { - rvs := hvs.getVoteSet(r, cmtproto.PrevoteType) + rvs := hvs.getVoteSet(r, types.PrevoteType) polBlockID, ok := rvs.TwoThirdsMajority() if ok { return r, polBlockID @@ -182,15 +179,15 @@ func (hvs *HeightVoteSet) POLInfo() (polRound int32, polBlockID types.BlockID) { return -1, types.BlockID{} } -func (hvs *HeightVoteSet) getVoteSet(round int32, voteType cmtproto.SignedMsgType) *types.VoteSet { +func (hvs *HeightVoteSet) getVoteSet(round int32, voteType types.SignedMsgType) *types.VoteSet { rvs, ok := hvs.roundVoteSets[round] if !ok { return nil } switch voteType { - case cmtproto.PrevoteType: + case types.PrevoteType: return rvs.Prevotes - case cmtproto.PrecommitType: + case types.PrecommitType: return rvs.Precommits default: panic(fmt.Sprintf("Unexpected vote type %X", voteType)) @@ -200,12 +197,13 @@ func (hvs *HeightVoteSet) getVoteSet(round int32, voteType cmtproto.SignedMsgTyp // If a peer claims that it has 2/3 majority for given blockKey, call this. // NOTE: if there are too many peers, or too much peer churn, // this can cause memory issues. -// TODO: implement ability to remove peers too +// TODO: implement ability to remove peers too. func (hvs *HeightVoteSet) SetPeerMaj23( round int32, - voteType cmtproto.SignedMsgType, + voteType types.SignedMsgType, peerID p2p.ID, - blockID types.BlockID) error { + blockID types.BlockID, +) error { hvs.mtx.Lock() defer hvs.mtx.Unlock() if !types.IsVoteTypeValid(voteType) { @@ -218,7 +216,7 @@ func (hvs *HeightVoteSet) SetPeerMaj23( return voteSet.SetPeerMaj23(types.P2PID(peerID), blockID) } -//--------------------------------------------------------- +// --------------------------------------------------------- // string and json func (hvs *HeightVoteSet) String() string { diff --git a/consensus/types/height_vote_set_test.go b/internal/consensus/types/height_vote_set_test.go similarity index 83% rename from consensus/types/height_vote_set_test.go rename to internal/consensus/types/height_vote_set_test.go index 5cac9e5d827..f81f39d4e16 100644 --- a/consensus/types/height_vote_set_test.go +++ b/internal/consensus/types/height_vote_set_test.go @@ -4,14 +4,14 @@ import ( "os" "testing" + "github.com/stretchr/testify/require" + cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto/tmhash" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/internal/test" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" - "github.com/stretchr/testify/require" ) var config *cfg.Config // NOTE: must be reset for each _test.go file @@ -28,19 +28,19 @@ func TestPeerCatchupRounds(t *testing.T) { hvs := NewExtendedHeightVoteSet(test.DefaultTestChainID, 1, valSet) - vote999_0 := makeVoteHR(t, 1, 0, 999, privVals) + vote999_0 := makeVoteHR(999, privVals) added, err := hvs.AddVote(vote999_0, "peer1", true) if !added || err != nil { t.Error("Expected to successfully add vote from peer", added, err) } - vote1000_0 := makeVoteHR(t, 1, 0, 1000, privVals) + vote1000_0 := makeVoteHR(1000, privVals) added, err = hvs.AddVote(vote1000_0, "peer1", true) if !added || err != nil { t.Error("Expected to successfully add vote from peer", added, err) } - vote1001_0 := makeVoteHR(t, 1, 0, 1001, privVals) + vote1001_0 := makeVoteHR(1001, privVals) added, err = hvs.AddVote(vote1001_0, "peer1", true) if err != ErrGotVoteFromUnwantedRound { t.Errorf("expected GotVoteFromUnwantedRoundError, but got %v", err) @@ -54,41 +54,40 @@ func TestPeerCatchupRounds(t *testing.T) { t.Error("Expected to successfully add vote from another peer") } } + func TestInconsistentExtensionData(t *testing.T) { valSet, privVals := types.RandValidatorSet(10, 1) hvsE := NewExtendedHeightVoteSet(test.DefaultTestChainID, 1, valSet) - voteNoExt := makeVoteHR(t, 1, 0, 20, privVals) + voteNoExt := makeVoteHR(20, privVals) voteNoExt.Extension, voteNoExt.ExtensionSignature = nil, nil require.Panics(t, func() { _, _ = hvsE.AddVote(voteNoExt, "peer1", false) }) hvsNoE := NewHeightVoteSet(test.DefaultTestChainID, 1, valSet) - voteExt := makeVoteHR(t, 1, 0, 20, privVals) + voteExt := makeVoteHR(20, privVals) require.Panics(t, func() { _, _ = hvsNoE.AddVote(voteExt, "peer1", true) }) - } func makeVoteHR( - t *testing.T, - height int64, - valIndex, round int32, privVals []types.PrivValidator, ) *types.Vote { + height := int64(1) + valIndex := 0 privVal := privVals[valIndex] randBytes := cmtrand.Bytes(tmhash.Size) vote, err := types.MakeVote( privVal, test.DefaultTestChainID, - valIndex, + 0, height, round, - cmtproto.PrecommitType, + types.PrecommitType, types.BlockID{Hash: randBytes, PartSetHeader: types.PartSetHeader{}}, cmttime.Now(), ) diff --git a/consensus/types/peer_round_state.go b/internal/consensus/types/peer_round_state.go similarity index 86% rename from consensus/types/peer_round_state.go rename to internal/consensus/types/peer_round_state.go index 4e8b440c015..89a8a726af7 100644 --- a/consensus/types/peer_round_state.go +++ b/internal/consensus/types/peer_round_state.go @@ -4,11 +4,11 @@ import ( "fmt" "time" - "github.com/cometbft/cometbft/libs/bits" + "github.com/cometbft/cometbft/internal/bits" "github.com/cometbft/cometbft/types" ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // PeerRoundState contains the known state of a peer. // NOTE: Read-only when returned by PeerState.GetRoundState(). @@ -23,11 +23,13 @@ type PeerRoundState struct { // True if peer has proposal for this round Proposal bool `json:"proposal"` ProposalBlockPartSetHeader types.PartSetHeader `json:"proposal_block_part_set_header"` - ProposalBlockParts *bits.BitArray `json:"proposal_block_parts"` + // This bit array is length(# of block parts) + ProposalBlockParts *bits.BitArray `json:"proposal_block_parts"` // Proposal's POL round. -1 if none. ProposalPOLRound int32 `json:"proposal_pol_round"` // nil until ProposalPOLMessage received. + // these bitarrays are length(validator set) ProposalPOL *bits.BitArray `json:"proposal_pol"` Prevotes *bits.BitArray `json:"prevotes"` // All votes peer has for this round Precommits *bits.BitArray `json:"precommits"` // All precommits peer has for this round @@ -41,12 +43,12 @@ type PeerRoundState struct { CatchupCommit *bits.BitArray `json:"catchup_commit"` } -// String returns a string representation of the PeerRoundState +// String returns a string representation of the PeerRoundState. func (prs PeerRoundState) String() string { return prs.StringIndented("") } -// StringIndented returns a string representation of the PeerRoundState +// StringIndented returns a string representation of the PeerRoundState. func (prs PeerRoundState) StringIndented(indent string) string { return fmt.Sprintf(`PeerRoundState{ %s %v/%v/%v @%v diff --git a/consensus/types/round_state.go b/internal/consensus/types/round_state.go similarity index 87% rename from consensus/types/round_state.go rename to internal/consensus/types/round_state.go index 6749d4265a0..4e3b24022c9 100644 --- a/consensus/types/round_state.go +++ b/internal/consensus/types/round_state.go @@ -9,13 +9,13 @@ import ( "github.com/cometbft/cometbft/types" ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // RoundStepType enum type -// RoundStepType enumerates the state of the consensus state machine +// RoundStepType enumerates the state of the consensus state machine. type RoundStepType uint8 // These must be numeric, ordered. -// RoundStepType +// RoundStepType. const ( RoundStepNewHeight = RoundStepType(0x01) // Wait til CommitTime + timeoutCommit RoundStepNewRound = RoundStepType(0x02) // Setup new round and go to RoundStepPropose @@ -35,7 +35,7 @@ func (rs RoundStepType) IsValid() bool { return uint8(rs) >= 0x01 && uint8(rs) <= 0x08 } -// String returns a string +// String returns a string. func (rs RoundStepType) String() string { switch rs { case RoundStepNewHeight: @@ -59,11 +59,11 @@ func (rs RoundStepType) String() string { } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // RoundState defines the internal consensus state. // NOTE: Not thread safe. Should only be manipulated by functions downstream -// of the cs.receiveRoutine +// of the cs.receiveRoutine. type RoundState struct { Height int64 `json:"height"` // Height we are working on Round int32 `json:"round"` @@ -71,14 +71,15 @@ type RoundState struct { StartTime time.Time `json:"start_time"` // Subjective time when +2/3 precommits for Block at Round were found - CommitTime time.Time `json:"commit_time"` - Validators *types.ValidatorSet `json:"validators"` - Proposal *types.Proposal `json:"proposal"` - ProposalBlock *types.Block `json:"proposal_block"` - ProposalBlockParts *types.PartSet `json:"proposal_block_parts"` - LockedRound int32 `json:"locked_round"` - LockedBlock *types.Block `json:"locked_block"` - LockedBlockParts *types.PartSet `json:"locked_block_parts"` + CommitTime time.Time `json:"commit_time"` + Validators *types.ValidatorSet `json:"validators"` + Proposal *types.Proposal `json:"proposal"` + ProposalReceiveTime time.Time `json:"proposal_receive_time"` + ProposalBlock *types.Block `json:"proposal_block"` + ProposalBlockParts *types.PartSet `json:"proposal_block_parts"` + LockedRound int32 `json:"locked_round"` + LockedBlock *types.Block `json:"locked_block"` + LockedBlockParts *types.PartSet `json:"locked_block_parts"` // The variables below starting with "Valid..." derive their name from // the algorithm presented in this paper: @@ -102,7 +103,7 @@ type RoundState struct { TriggeredTimeoutPrecommit bool `json:"triggered_timeout_precommit"` } -// Compressed version of the RoundState for use in RPC +// Compressed version of the RoundState for use in RPC. type RoundStateSimple struct { HeightRoundStep string `json:"height/round/step"` StartTime time.Time `json:"start_time"` @@ -113,7 +114,7 @@ type RoundStateSimple struct { Proposer types.ValidatorInfo `json:"proposer"` } -// Compress the RoundState to RoundStateSimple +// Compress the RoundState to RoundStateSimple. func (rs *RoundState) RoundStateSimple() RoundStateSimple { votesJSON, err := rs.Votes.MarshalJSON() if err != nil { @@ -179,12 +180,12 @@ func (rs *RoundState) RoundStateEvent() types.EventDataRoundState { } } -// String returns a string +// String returns a string. func (rs *RoundState) String() string { return rs.StringIndented("") } -// StringIndented returns a string +// StringIndented returns a string. func (rs *RoundState) StringIndented(indent string) string { return fmt.Sprintf(`RoundState{ %s H:%v R:%v S:%v @@ -217,7 +218,7 @@ func (rs *RoundState) StringIndented(indent string) string { indent) } -// StringShort returns a string +// StringShort returns a string. func (rs *RoundState) StringShort() string { return fmt.Sprintf(`RoundState{H:%v R:%v S:%v ST:%v}`, rs.Height, rs.Round, rs.Step, rs.StartTime) diff --git a/consensus/wal.go b/internal/consensus/wal.go similarity index 89% rename from consensus/wal.go rename to internal/consensus/wal.go index 82ab330d8b1..4af07afd3af 100644 --- a/consensus/wal.go +++ b/internal/consensus/wal.go @@ -11,24 +11,25 @@ import ( "github.com/cosmos/gogoproto/proto" - auto "github.com/cometbft/cometbft/libs/autofile" + cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1" + auto "github.com/cometbft/cometbft/internal/autofile" + cmtos "github.com/cometbft/cometbft/internal/os" + "github.com/cometbft/cometbft/internal/service" cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" - cmtos "github.com/cometbft/cometbft/libs/os" - "github.com/cometbft/cometbft/libs/service" - cmtcons "github.com/cometbft/cometbft/proto/tendermint/consensus" + cmterrors "github.com/cometbft/cometbft/types/errors" cmttime "github.com/cometbft/cometbft/types/time" ) const ( - // time.Time + max consensus msg size + // time.Time + max consensus msg size. maxMsgSizeBytes = maxMsgSize + 24 - // how often the WAL should be sync'd during period sync'ing + // how often the WAL should be sync'd during period sync'ing. walDefaultFlushInterval = 2 * time.Second ) -//-------------------------------------------------------- +// -------------------------------------------------------- // types and functions for savings consensus messages // TimedWALMessage wraps WALMessage and adds Time for debugging purposes. @@ -43,7 +44,7 @@ type EndHeightMessage struct { Height int64 `json:"height"` } -type WALMessage interface{} +type WALMessage any func init() { cmtjson.RegisterType(msgInfo{}, "tendermint/wal/MsgInfo") @@ -51,13 +52,13 @@ func init() { cmtjson.RegisterType(EndHeightMessage{}, "tendermint/wal/EndHeightMessage") } -//-------------------------------------------------------- +// -------------------------------------------------------- // Simple write-ahead logger // WAL is an interface for any write-ahead logger. type WAL interface { - Write(WALMessage) error - WriteSync(WALMessage) error + Write(msg WALMessage) error + WriteSync(msg WALMessage) error FlushAndSync() error SearchForEndHeight(height int64, options *WALSearchOptions) (rd io.ReadCloser, found bool, err error) @@ -89,7 +90,7 @@ var _ WAL = &BaseWAL{} // NewWAL returns a new write-ahead logger based on `baseWAL`, which implements // WAL. It's flushed and synced to disk every 2s and once when stopped. func NewWAL(walFile string, groupOptions ...func(*auto.Group)) (*BaseWAL, error) { - err := cmtos.EnsureDir(filepath.Dir(walFile), 0700) + err := cmtos.EnsureDir(filepath.Dir(walFile), 0o700) if err != nil { return nil, fmt.Errorf("failed to ensure WAL directory is in place: %w", err) } @@ -153,7 +154,7 @@ func (wal *BaseWAL) processFlushTicks() { } // FlushAndSync flushes and fsync's the underlying group's data to disk. -// See auto#FlushAndSync +// See auto#FlushAndSync. func (wal *BaseWAL) FlushAndSync() error { return wal.group.FlushAndSync() } @@ -180,7 +181,7 @@ func (wal *BaseWAL) Wait() { // Write is called in newStep and for each receive on the // peerMsgQueue and the timeoutTicker. -// NOTE: does not call fsync() +// NOTE: does not call fsync(). func (wal *BaseWAL) Write(msg WALMessage) error { if wal == nil { return nil @@ -197,7 +198,7 @@ func (wal *BaseWAL) Write(msg WALMessage) error { // WriteSync is called when we receive a msg from ourselves // so that we write to disk before sending signed messages. -// NOTE: calls fsync() +// NOTE: calls fsync(). func (wal *BaseWAL) WriteSync(msg WALMessage) error { if wal == nil { return nil @@ -230,7 +231,8 @@ type WALSearchOptions struct { // CONTRACT: caller must close group reader. func (wal *BaseWAL) SearchForEndHeight( height int64, - options *WALSearchOptions) (rd io.ReadCloser, found bool, err error) { + options *WALSearchOptions, +) (rd io.ReadCloser, found bool, err error) { var ( msg *TimedWALMessage gr *auto.GroupReader @@ -284,7 +286,7 @@ func (wal *BaseWAL) SearchForEndHeight( // A WALEncoder writes custom-encoded WAL messages to an output stream. // -// Format: 4 bytes CRC sum + 4 bytes length + arbitrary-length value +// Format: 4 bytes CRC sum + 4 bytes length + arbitrary-length value. type WALEncoder struct { wr io.Writer } @@ -334,7 +336,7 @@ func IsDataCorruptionError(err error) bool { return ok } -// DataCorruptionError is an error that occures if data on disk was corrupted. +// DataCorruptionError is an error that occurs if data on disk was corrupted. type DataCorruptionError struct { cause error } @@ -400,7 +402,7 @@ func (dec *WALDecoder) Decode() (*TimedWALMessage, error) { return nil, DataCorruptionError{fmt.Errorf("checksums do not match: read: %v, actual: %v", crc, actualCRC)} } - var res = new(cmtcons.TimedWALMessage) + res := new(cmtcons.TimedWALMessage) err = proto.Unmarshal(data, res) if err != nil { return nil, DataCorruptionError{fmt.Errorf("failed to decode data: %v", err)} @@ -408,7 +410,7 @@ func (dec *WALDecoder) Decode() (*TimedWALMessage, error) { walMsg, err := WALFromProto(res.Msg) if err != nil { - return nil, DataCorruptionError{fmt.Errorf("failed to convert from proto: %w", err)} + return nil, DataCorruptionError{cmterrors.ErrMsgFromProto{MessageName: "WALMessage", Err: err}} } tMsgWal := &TimedWALMessage{ Time: res.Time, @@ -422,10 +424,10 @@ type nilWAL struct{} var _ WAL = nilWAL{} -func (nilWAL) Write(m WALMessage) error { return nil } -func (nilWAL) WriteSync(m WALMessage) error { return nil } -func (nilWAL) FlushAndSync() error { return nil } -func (nilWAL) SearchForEndHeight(height int64, options *WALSearchOptions) (rd io.ReadCloser, found bool, err error) { +func (nilWAL) Write(WALMessage) error { return nil } +func (nilWAL) WriteSync(WALMessage) error { return nil } +func (nilWAL) FlushAndSync() error { return nil } +func (nilWAL) SearchForEndHeight(int64, *WALSearchOptions) (rd io.ReadCloser, found bool, err error) { return nil, false, nil } func (nilWAL) Start() error { return nil } diff --git a/consensus/wal_fuzz.go b/internal/consensus/wal_fuzz.go similarity index 100% rename from consensus/wal_fuzz.go rename to internal/consensus/wal_fuzz.go diff --git a/consensus/wal_generator.go b/internal/consensus/wal_generator.go similarity index 86% rename from consensus/wal_generator.go rename to internal/consensus/wal_generator.go index 56abdfb359b..6f7f9a96175 100644 --- a/consensus/wal_generator.go +++ b/internal/consensus/wal_generator.go @@ -10,16 +10,14 @@ import ( "time" db "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/abci/example/kvstore" cfg "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/internal/test" + cmtrand "github.com/cometbft/cometbft/internal/rand" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/libs/log" - cmtrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/privval" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" ) @@ -29,6 +27,8 @@ import ( // (byteBufferWAL) and waits until numBlocks are created. // If the node fails to produce given numBlocks, it returns an error. func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int, config *cfg.Config) (err error) { + t.Helper() + app := kvstore.NewPersistentApplication(filepath.Join(config.DBDir(), "wal_generator")) logger := log.TestingLogger().With("wal_generator", "wal_generator") @@ -122,6 +122,8 @@ func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int, config *cfg.C // WALWithNBlocks returns a WAL content with numBlocks. func WALWithNBlocks(t *testing.T, numBlocks int, config *cfg.Config) (data []byte, err error) { + t.Helper() + var b bytes.Buffer wr := bufio.NewWriter(&b) @@ -139,23 +141,10 @@ func randPort() int { return base + cmtrand.Intn(spread) } -func makeAddrs() (string, string, string) { +func makeAddrs() (address, port string) { start := randPort() return fmt.Sprintf("tcp://127.0.0.1:%d", start), - fmt.Sprintf("tcp://127.0.0.1:%d", start+1), - fmt.Sprintf("tcp://127.0.0.1:%d", start+2) -} - -// getConfig returns a config for test cases -func getConfig(t *testing.T) *cfg.Config { - c := test.ResetTestRoot(t.Name()) - - // and we use random ports to run in parallel - cmt, rpc, grpc := makeAddrs() - c.P2P.ListenAddress = cmt - c.RPC.ListenAddress = rpc - c.RPC.GRPCListenAddress = grpc - return c + fmt.Sprintf("tcp://127.0.0.1:%d", start+1) } // byteBufferWAL is a WAL which writes all msgs to a byte buffer. Writing stops @@ -170,7 +159,7 @@ type byteBufferWAL struct { logger log.Logger } -// needed for determinism +// needed for determinism. var fixedTime, _ = time.Parse(time.RFC3339, "2017-01-02T15:04:05Z") func newByteBufferWAL(logger log.Logger, enc *WALEncoder, nBlocks int64, signalStop chan<- struct{}) *byteBufferWAL { @@ -214,15 +203,15 @@ func (w *byteBufferWAL) WriteSync(m WALMessage) error { return w.Write(m) } -func (w *byteBufferWAL) FlushAndSync() error { return nil } +func (*byteBufferWAL) FlushAndSync() error { return nil } -func (w *byteBufferWAL) SearchForEndHeight( - height int64, - options *WALSearchOptions, +func (*byteBufferWAL) SearchForEndHeight( + int64, + *WALSearchOptions, ) (rd io.ReadCloser, found bool, err error) { return nil, false, nil } -func (w *byteBufferWAL) Start() error { return nil } -func (w *byteBufferWAL) Stop() error { return nil } -func (w *byteBufferWAL) Wait() {} +func (*byteBufferWAL) Start() error { return nil } +func (*byteBufferWAL) Stop() error { return nil } +func (*byteBufferWAL) Wait() {} diff --git a/consensus/wal_test.go b/internal/consensus/wal_test.go similarity index 50% rename from consensus/wal_test.go rename to internal/consensus/wal_test.go index 32d8a7b8596..6a4975d22bb 100644 --- a/consensus/wal_test.go +++ b/internal/consensus/wal_test.go @@ -3,19 +3,26 @@ package consensus import ( "bytes" "crypto/rand" + "encoding/hex" + "fmt" + "io" "os" "path/filepath" - - // "sync" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/cometbft/cometbft/consensus/types" + dbm "github.com/cometbft/cometbft-db" + cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto/merkle" - "github.com/cometbft/cometbft/libs/autofile" + "github.com/cometbft/cometbft/crypto/tmhash" + "github.com/cometbft/cometbft/internal/autofile" + "github.com/cometbft/cometbft/internal/consensus/types" + cmtrand "github.com/cometbft/cometbft/internal/rand" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" cmttypes "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" @@ -67,14 +74,14 @@ func TestWALTruncate(t *testing.T) { h := int64(50) gr, found, err := wal.SearchForEndHeight(h, &WALSearchOptions{}) - assert.NoError(t, err, "expected not to err on height %d", h) + require.NoError(t, err, "expected not to err on height %d", h) assert.True(t, found, "expected to find end height for %d", h) assert.NotNil(t, gr) defer gr.Close() dec := NewWALDecoder(gr) msg, err := dec.Decode() - assert.NoError(t, err, "expected to decode a message") + require.NoError(t, err, "expected to decode a message") rs, ok := msg.Msg.(cmttypes.EventDataRoundState) assert.True(t, ok, "expected message of type EventDataRoundState") assert.Equal(t, rs.Height, h+1, "wrong height") @@ -82,10 +89,37 @@ func TestWALTruncate(t *testing.T) { func TestWALEncoderDecoder(t *testing.T) { now := cmttime.Now() + + randbytes := cmtrand.Bytes(tmhash.Size) + cs1, vss := randState(1) + + block1 := cmttypes.BlockID{ + Hash: randbytes, + PartSetHeader: cmttypes.PartSetHeader{Total: 5, Hash: randbytes}, + } + + p := cmttypes.Proposal{ + Type: cmttypes.ProposalType, + Height: 42, + Round: 13, + BlockID: block1, + POLRound: 12, + Timestamp: cmttime.Canonical(now), + } + + pp := p.ToProto() + err := vss[0].SignProposal(cs1.state.ChainID, pp) + require.NoError(t, err) + + p.Signature = pp.Signature + msgs := []TimedWALMessage{ {Time: now, Msg: EndHeightMessage{0}}, {Time: now, Msg: timeoutInfo{Duration: time.Second, Height: 1, Round: 1, Step: types.RoundStepPropose}}, {Time: now, Msg: cmttypes.EventDataRoundState{Height: 1, Round: 1, Step: ""}}, + {Time: now, Msg: msgInfo{Msg: &ProposalMessage{Proposal: &p}, PeerID: "Nobody", ReceiveTime: now}}, + {Time: now, Msg: msgInfo{Msg: &ProposalMessage{Proposal: &p}, PeerID: "Nobody", ReceiveTime: time.Time{}}}, + {Time: now, Msg: msgInfo{Msg: &ProposalMessage{Proposal: &p}, PeerID: "Nobody"}}, } b := new(bytes.Buffer) @@ -107,6 +141,117 @@ func TestWALEncoderDecoder(t *testing.T) { } } +func TestWALEncoderDecoderMultiVersion(t *testing.T) { + now := time.Time{}.AddDate(100, 10, 20) + v038Data, _ := hex.DecodeString("a570586b000000c50a0b0880e2c3b1a4feffffff0112b50112b2010aa7011aa4010aa1010820102a180d200c2a480a2001c073624aaf3978514ef8443bb2a859c75fc3cc6af26d5aaa20926f046baa6612240805122001c073624aaf3978514ef8443bb2a859c75fc3cc6af26d5aaa20926f046baa66320b0880e2c3b1a4feffffff013a404942b2803552651e1c7e7b72557cdade0a4c5a638dcda9822ec402d42c5f75c767f62c0f3fb0d58aef7842a4e18964faaff3d17559989cf1f11dd006e31a9d0f12064e6f626f6479") + + ss, privVals := makeState(1, "execution_chain") + var pVal cmttypes.PrivValidator + for mk := range privVals { + pVal = privVals[mk] + } + vs := newValidatorStub(pVal, 1) + + cmtrand.Seed(0) + randbytes := cmtrand.Bytes(tmhash.Size) + block1 := cmttypes.BlockID{ + Hash: randbytes, + PartSetHeader: cmttypes.PartSetHeader{Total: 5, Hash: randbytes}, + } + + p := cmttypes.Proposal{ + Type: cmttypes.ProposalType, + Height: 42, + Round: 13, + BlockID: block1, + POLRound: 12, + Timestamp: cmttime.Canonical(now), + } + + pp := p.ToProto() + err := vs.SignProposal(ss.ChainID, pp) + require.NoError(t, err) + p.Signature = pp.Signature + + cases := []struct { + twm TimedWALMessage + expectFailure bool + }{ + {twm: TimedWALMessage{Time: now, Msg: msgInfo{Msg: &ProposalMessage{Proposal: &p}, PeerID: "Nobody", ReceiveTime: now}}, expectFailure: true}, + {twm: TimedWALMessage{Time: now, Msg: msgInfo{Msg: &ProposalMessage{Proposal: &p}, PeerID: "Nobody", ReceiveTime: time.Time{}}}, expectFailure: false}, + {twm: TimedWALMessage{Time: now, Msg: msgInfo{Msg: &ProposalMessage{Proposal: &p}, PeerID: "Nobody"}}, expectFailure: false}, + } + + b := new(bytes.Buffer) + b.Reset() + + _, err = b.Write(v038Data) + require.NoError(t, err) + + dec := NewWALDecoder(b) + v038decoded, err := dec.Decode() + require.NoError(t, err) + twmV038 := v038decoded.Msg + msgInfoV038 := twmV038.(msgInfo) + + for _, tc := range cases { + if tc.expectFailure { + assert.NotEqual(t, tc.twm.Msg, msgInfoV038) + } else { + assert.Equal(t, tc.twm.Msg, msgInfoV038) + } + } +} + +func TestWALEncoder(t *testing.T) { + now := time.Time{}.AddDate(100, 10, 20) + + ss, privVals := makeState(1, "execution_chain") + var pVal cmttypes.PrivValidator + for mk := range privVals { + pVal = privVals[mk] + } + vs := newValidatorStub(pVal, 1) + + cmtrand.Seed(0) + randbytes := cmtrand.Bytes(tmhash.Size) + block1 := cmttypes.BlockID{ + Hash: randbytes, + PartSetHeader: cmttypes.PartSetHeader{Total: 5, Hash: randbytes}, + } + + p := cmttypes.Proposal{ + Type: cmttypes.ProposalType, + Height: 42, + Round: 13, + BlockID: block1, + POLRound: 12, + Timestamp: cmttime.Canonical(now), + } + + pp := p.ToProto() + err := vs.SignProposal(ss.ChainID, pp) + require.NoError(t, err) + p.Signature = pp.Signature + + b := new(bytes.Buffer) + enc := NewWALEncoder(b) + twm := TimedWALMessage{Time: now, Msg: msgInfo{Msg: &ProposalMessage{Proposal: &p}, PeerID: "Nobody"}} + err = enc.Encode(&twm) + require.NoError(t, err) + + var b1 bytes.Buffer + tee := io.TeeReader(b, &b1) + b2, err := io.ReadAll(tee) + require.NoError(t, err) + fmt.Printf("%s\n", hex.EncodeToString(b1.Bytes())) + + // Encoded string generated with v0.38 (before PBTS) + data, err := hex.DecodeString("a570586b000000c50a0b0880e2c3b1a4feffffff0112b50112b2010aa7011aa4010aa1010820102a180d200c2a480a2001c073624aaf3978514ef8443bb2a859c75fc3cc6af26d5aaa20926f046baa6612240805122001c073624aaf3978514ef8443bb2a859c75fc3cc6af26d5aaa20926f046baa66320b0880e2c3b1a4feffffff013a404942b2803552651e1c7e7b72557cdade0a4c5a638dcda9822ec402d42c5f75c767f62c0f3fb0d58aef7842a4e18964faaff3d17559989cf1f11dd006e31a9d0f12064e6f626f6479") + require.NoError(t, err) + require.Equal(t, data, b2) +} + func TestWALWrite(t *testing.T) { walDir, err := os.MkdirTemp("", "wal") require.NoError(t, err) @@ -144,7 +289,7 @@ func TestWALWrite(t *testing.T) { err = wal.Write(msgInfo{ Msg: msg, }) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Contains(t, err.Error(), "msg is too big") } } @@ -162,14 +307,14 @@ func TestWALSearchForEndHeight(t *testing.T) { h := int64(3) gr, found, err := wal.SearchForEndHeight(h, &WALSearchOptions{}) - assert.NoError(t, err, "expected not to err on height %d", h) + require.NoError(t, err, "expected not to err on height %d", h) assert.True(t, found, "expected to find end height for %d", h) assert.NotNil(t, gr) defer gr.Close() dec := NewWALDecoder(gr) msg, err := dec.Decode() - assert.NoError(t, err, "expected to decode a message") + require.NoError(t, err, "expected to decode a message") rs, ok := msg.Msg.(cmttypes.EventDataRoundState) assert.True(t, ok, "expected message of type EventDataRoundState") assert.Equal(t, rs.Height, h+1, "wrong height") @@ -209,7 +354,7 @@ func TestWALPeriodicSync(t *testing.T) { h := int64(4) gr, found, err := wal.SearchForEndHeight(h, &WALSearchOptions{}) - assert.NoError(t, err, "expected not to err on height %d", h) + require.NoError(t, err, "expected not to err on height %d", h) assert.True(t, found, "expected to find end height for %d", h) assert.NotNil(t, gr) if gr != nil { @@ -217,6 +362,28 @@ func TestWALPeriodicSync(t *testing.T) { } } +// FIXME: this helper is very similar to the one in internal/state/helpers_test.go. +func makeState(nVals int, chainID string) (sm.State, map[string]cmttypes.PrivValidator) { + vals, privVals := test.GenesisValidatorSet(nVals) + + s, _ := sm.MakeGenesisState(&cmttypes.GenesisDoc{ + ChainID: chainID, + Validators: vals, + AppHash: nil, + ConsensusParams: test.ConsensusParams(), + }) + + stateDB := dbm.NewMemDB() + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + if err := stateStore.Save(s); err != nil { + panic(err) + } + + return s, privVals +} + /* var initOnce sync.Once @@ -237,13 +404,14 @@ func nBytes(n int) []byte { } func benchmarkWalDecode(b *testing.B, n int) { + b.Helper() // registerInterfacesOnce() buf := new(bytes.Buffer) enc := NewWALEncoder(buf) data := nBytes(n) - if err := enc.Encode(&TimedWALMessage{Msg: data, Time: time.Now().Round(time.Second).UTC()}); err != nil { + if err := enc.Encode(&TimedWALMessage{Msg: data, Time: cmttime.Now().Round(time.Second).UTC()}); err != nil { b.Error(err) } @@ -268,18 +436,35 @@ func BenchmarkWalDecode512B(b *testing.B) { func BenchmarkWalDecode10KB(b *testing.B) { benchmarkWalDecode(b, 10*1024) } + func BenchmarkWalDecode100KB(b *testing.B) { benchmarkWalDecode(b, 100*1024) } + func BenchmarkWalDecode1MB(b *testing.B) { benchmarkWalDecode(b, 1024*1024) } + func BenchmarkWalDecode10MB(b *testing.B) { benchmarkWalDecode(b, 10*1024*1024) } + func BenchmarkWalDecode100MB(b *testing.B) { benchmarkWalDecode(b, 100*1024*1024) } + func BenchmarkWalDecode1GB(b *testing.B) { benchmarkWalDecode(b, 1024*1024*1024) } + +// getConfig returns a config for test cases. +func getConfig(t *testing.T) *cfg.Config { + t.Helper() + c := test.ResetTestRoot(t.Name()) + + // and we use random ports to run in parallel + cmt, rpc := makeAddrs() + c.P2P.ListenAddress = cmt + c.RPC.ListenAddress = rpc + return c +} diff --git a/libs/events/Makefile b/internal/events/Makefile similarity index 100% rename from libs/events/Makefile rename to internal/events/Makefile diff --git a/libs/events/README.md b/internal/events/README.md similarity index 100% rename from libs/events/README.md rename to internal/events/README.md diff --git a/libs/events/event_cache.go b/internal/events/event_cache.go similarity index 84% rename from libs/events/event_cache.go rename to internal/events/event_cache.go index f508e873da0..6a840003737 100644 --- a/libs/events/event_cache.go +++ b/internal/events/event_cache.go @@ -1,20 +1,20 @@ package events // An EventCache buffers events for a Fireable -// All events are cached. Filtering happens on Flush +// All events are cached. Filtering happens on Flush. type EventCache struct { evsw Fireable events []eventInfo } -// Create a new EventCache with an EventSwitch as backend +// Create a new EventCache with an EventSwitch as backend. func NewEventCache(evsw Fireable) *EventCache { return &EventCache{ evsw: evsw, } } -// a cached event +// a cached event. type eventInfo struct { event string data EventData @@ -27,7 +27,7 @@ func (evc *EventCache) FireEvent(event string, data EventData) { } // Fire events by running evsw.FireEvent on all cached events. Blocks. -// Clears cached events +// Clears cached events. func (evc *EventCache) Flush() { for _, ei := range evc.events { evc.evsw.FireEvent(ei.event, ei.data) diff --git a/libs/events/event_cache_test.go b/internal/events/event_cache_test.go similarity index 90% rename from libs/events/event_cache_test.go rename to internal/events/event_cache_test.go index 3f8641f93d8..d48e2e48760 100644 --- a/libs/events/event_cache_test.go +++ b/internal/events/event_cache_test.go @@ -12,7 +12,7 @@ func TestEventCache_Flush(t *testing.T) { err := evsw.Start() require.NoError(t, err) - err = evsw.AddListenerForEvent("nothingness", "", func(data EventData) { + err = evsw.AddListenerForEvent("nothingness", "", func(_ EventData) { // Check we are not initializing an empty buffer full // of zeroed eventInfos in the EventCache require.FailNow(t, "We should never receive a message on this switch since none are fired") @@ -25,7 +25,7 @@ func TestEventCache_Flush(t *testing.T) { evc.Flush() fail := true pass := false - err = evsw.AddListenerForEvent("somethingness", "something", func(data EventData) { + err = evsw.AddListenerForEvent("somethingness", "something", func(_ EventData) { if fail { require.FailNow(t, "Shouldn't see a message until flushed") } diff --git a/libs/events/events.go b/internal/events/events.go similarity index 93% rename from libs/events/events.go rename to internal/events/events.go index 293e6fb8da9..7071897f12b 100644 --- a/libs/events/events.go +++ b/internal/events/events.go @@ -4,8 +4,8 @@ package events import ( "fmt" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) // ErrListenerWasRemoved is returned by AddEvent if the listener was removed. @@ -20,7 +20,7 @@ func (e ErrListenerWasRemoved) Error() string { // EventData is a generic event data can be typed and registered with // tendermint/go-amino via concrete implementation of this interface. -type EventData interface{} +type EventData any // Eventable is the interface reactors and other modules must export to become // eventable. @@ -68,11 +68,11 @@ func NewEventSwitch() EventSwitch { return evsw } -func (evsw *eventSwitch) OnStart() error { +func (*eventSwitch) OnStart() error { return nil } -func (evsw *eventSwitch) OnStop() {} +func (*eventSwitch) OnStop() {} func (evsw *eventSwitch) AddListenerForEvent(listenerID, event string, cb EventCallback) error { // Get/Create eventCell and listener. @@ -158,7 +158,7 @@ func (evsw *eventSwitch) FireEvent(event string, data EventData) { eventCell.FireEvent(data) } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // eventCell handles keeping track of listener callbacks for a given event. type eventCell struct { @@ -199,7 +199,7 @@ func (cell *eventCell) FireEvent(data EventData) { } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- type EventCallback func(data EventData) diff --git a/libs/events/events_test.go b/internal/events/events_test.go similarity index 98% rename from libs/events/events_test.go rename to internal/events/events_test.go index d6bbcd08c35..58bbb9ae9e4 100644 --- a/libs/events/events_test.go +++ b/internal/events/events_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/cometbft/cometbft/libs/rand" + "github.com/cometbft/cometbft/internal/rand" ) // TestAddListenerForEventFireOnce sets up an EventSwitch, subscribes a single @@ -228,7 +228,7 @@ func TestAddAndRemoveListenerConcurrency(t *testing.T) { // we explicitly ignore errors here, since the listener will sometimes be removed // (that's what we're testing) _ = evsw.AddListenerForEvent("listener", fmt.Sprintf("event%d", index), - func(data EventData) { + func(_ EventData) { t.Errorf("should not run callback for %d.\n", index) stopInputEvent = true }) @@ -298,7 +298,7 @@ func TestAddAndRemoveListener(t *testing.T) { } } -// TestRemoveListener does basic tests on adding and removing +// TestRemoveListener does basic tests on adding and removing. func TestRemoveListener(t *testing.T) { evsw := NewEventSwitch() err := evsw.Start() @@ -313,13 +313,13 @@ func TestRemoveListener(t *testing.T) { sum1, sum2 := 0, 0 // add some listeners and make sure they work err = evsw.AddListenerForEvent("listener", "event1", - func(data EventData) { + func(_ EventData) { sum1++ }) require.NoError(t, err) err = evsw.AddListenerForEvent("listener", "event2", - func(data EventData) { + func(_ EventData) { sum2++ }) require.NoError(t, err) @@ -451,7 +451,7 @@ func TestRemoveListenersAsync(t *testing.T) { } } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ // Helper functions // sumReceivedNumbers takes two channels and adds all numbers received @@ -476,7 +476,8 @@ func sumReceivedNumbers(numbers, doneSum chan uint64) { // sent on `doneChan` for assertion that all events have been sent, and enabling // the test to assert all events have also been received. func fireEvents(evsw Fireable, event string, doneChan chan uint64, - offset uint64) { + offset uint64, +) { var sentSum uint64 for i := offset; i <= offset+uint64(999); i++ { sentSum += i diff --git a/evidence/doc.go b/internal/evidence/doc.go similarity index 100% rename from evidence/doc.go rename to internal/evidence/doc.go diff --git a/internal/evidence/errors.go b/internal/evidence/errors.go new file mode 100644 index 00000000000..3ed7e0cbbea --- /dev/null +++ b/internal/evidence/errors.go @@ -0,0 +1,125 @@ +package evidence + +import ( + "errors" + "fmt" + + "github.com/cometbft/cometbft/libs/bytes" + "github.com/cometbft/cometbft/types" +) + +var ( + ErrEvidenceAlreadyCommitted = errors.New("evidence was already committed") + ErrDuplicateEvidence = errors.New("duplicate evidence") +) + +type ( + ErrNoHeaderAtHeight struct { + Height int64 + } + + ErrNoCommitAtHeight struct { + Height int64 + } + + ErrUnrecognizedEvidenceType struct { + Evidence types.Evidence + } + + // ErrVotingPowerDoesNotMatch is returned when voting power from trusted validator set does not match voting power from evidence. + ErrVotingPowerDoesNotMatch struct { + TrustedVotingPower int64 + EvidenceVotingPower int64 + } + + ErrAddressNotValidatorAtHeight struct { + Address bytes.HexBytes + Height int64 + } + + // ErrValidatorAddressesDoNotMatch is returned when provided DuplicateVoteEvidence's votes have different validators as signers. + ErrValidatorAddressesDoNotMatch struct { + ValidatorA bytes.HexBytes + ValidatorB bytes.HexBytes + } + + // ErrSameBlockIDs is returned if a duplicate vote evidence has votes from the same block id (should be different). + ErrSameBlockIDs struct { + BlockID types.BlockID + } + + // ErrInvalidEvidenceValidators is returned when evidence validation spots an error related to validator set. + ErrInvalidEvidenceValidators struct { + ValError error + } + + ErrConflictingBlock struct { + ConflictingBlockError error + } + + ErrInvalidEvidence struct { + EvidenceError error + } + + // ErrDuplicateEvidenceHRTMismatch is returned when double sign evidence's votes are not from the same height, round or type. + ErrDuplicateEvidenceHRTMismatch struct { + VoteA types.Vote + VoteB types.Vote + } +) + +func (e ErrNoHeaderAtHeight) Error() string { + return fmt.Sprintf("don't have header at height #%d", e.Height) +} + +func (e ErrNoCommitAtHeight) Error() string { + return fmt.Sprintf("don't have commit at height #%d", e.Height) +} + +func (e ErrUnrecognizedEvidenceType) Error() string { + return fmt.Sprintf("unrecognized evidence type: %T", e.Evidence) +} + +func (e ErrVotingPowerDoesNotMatch) Error() string { + return fmt.Sprintf("total voting power from the evidence and our validator set does not match (%d != %d)", e.TrustedVotingPower, e.EvidenceVotingPower) +} + +func (e ErrAddressNotValidatorAtHeight) Error() string { + return fmt.Sprintf("address %X was not a validator at height %d", e.Address, e.Height) +} + +func (e ErrValidatorAddressesDoNotMatch) Error() string { + return fmt.Sprintf("validator addresses do not match: %X vs %X", + e.ValidatorA, + e.ValidatorB, + ) +} + +func (e ErrSameBlockIDs) Error() string { + return fmt.Sprintf( + "block IDs are the same (%v) - not a real duplicate vote", + e.BlockID, + ) +} + +func (e ErrInvalidEvidenceValidators) Error() string { + return fmt.Sprintf("invalid evidence validators: %v", e.ValError) +} + +func (e ErrInvalidEvidenceValidators) Unwrap() error { + return e.ValError +} + +func (e ErrConflictingBlock) Error() string { + return fmt.Sprintf("conflicting block error: %v", e.ConflictingBlockError) +} + +func (e ErrInvalidEvidence) Error() string { + return fmt.Sprintf("evidence error: %v", e.EvidenceError) +} + +func (e ErrDuplicateEvidenceHRTMismatch) Error() string { + return fmt.Sprintf("h/r/t does not match: %d/%d/%v vs %d/%d/%v", + e.VoteA.Height, e.VoteA.Round, e.VoteA.Type, + e.VoteB.Height, e.VoteB.Round, e.VoteB.Type) +} diff --git a/evidence/mocks/block_store.go b/internal/evidence/mocks/block_store.go similarity index 81% rename from evidence/mocks/block_store.go rename to internal/evidence/mocks/block_store.go index 566fdcec8c4..45be790b5bf 100644 --- a/evidence/mocks/block_store.go +++ b/internal/evidence/mocks/block_store.go @@ -16,6 +16,10 @@ type BlockStore struct { func (_m *BlockStore) Height() int64 { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Height") + } + var r0 int64 if rf, ok := ret.Get(0).(func() int64); ok { r0 = rf() @@ -30,6 +34,10 @@ func (_m *BlockStore) Height() int64 { func (_m *BlockStore) LoadBlockCommit(height int64) *types.Commit { ret := _m.Called(height) + if len(ret) == 0 { + panic("no return value specified for LoadBlockCommit") + } + var r0 *types.Commit if rf, ok := ret.Get(0).(func(int64) *types.Commit); ok { r0 = rf(height) @@ -46,6 +54,10 @@ func (_m *BlockStore) LoadBlockCommit(height int64) *types.Commit { func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta { ret := _m.Called(height) + if len(ret) == 0 { + panic("no return value specified for LoadBlockMeta") + } + var r0 *types.BlockMeta if rf, ok := ret.Get(0).(func(int64) *types.BlockMeta); ok { r0 = rf(height) @@ -58,13 +70,12 @@ func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta { return r0 } -type mockConstructorTestingTNewBlockStore interface { +// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBlockStore(t interface { mock.TestingT Cleanup(func()) -} - -// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBlockStore(t mockConstructorTestingTNewBlockStore) *BlockStore { +}) *BlockStore { mock := &BlockStore{} mock.Mock.Test(t) diff --git a/evidence/pool.go b/internal/evidence/pool.go similarity index 76% rename from evidence/pool.go rename to internal/evidence/pool.go index e36b66db38e..0158f4fe544 100644 --- a/evidence/pool.go +++ b/internal/evidence/pool.go @@ -2,7 +2,6 @@ package evidence import ( "bytes" - "errors" "fmt" "sync" "sync/atomic" @@ -10,22 +9,18 @@ import ( "github.com/cosmos/gogoproto/proto" gogotypes "github.com/cosmos/gogoproto/types" + "github.com/google/orderedcode" dbm "github.com/cometbft/cometbft-db" - - clist "github.com/cometbft/cometbft/libs/clist" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/internal/clist" + sm "github.com/cometbft/cometbft/internal/state" "github.com/cometbft/cometbft/libs/log" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" ) -const ( - baseKeyCommitted = byte(0x00) - baseKeyPending = byte(0x01) -) - -// Pool maintains a pool of valid evidence to be broadcasted and committed +// Pool maintains a pool of valid evidence to be broadcasted and committed. type Pool struct { logger log.Logger @@ -48,14 +43,66 @@ type Pool struct { pruningHeight int64 pruningTime time.Time + + dbKeyLayout KeyLayout +} + +func isEmpty(evidenceDB dbm.DB) bool { + iter, err := evidenceDB.Iterator(nil, nil) + if err != nil { + panic(err) + } + + defer iter.Close() + for ; iter.Valid(); iter.Next() { + return false + } + return true +} + +func setDBLayout(pool *Pool, dbKeyLayoutVersion string) { + if !isEmpty(pool.evidenceStore) { + var version []byte + var err error + if version, err = pool.evidenceStore.Get([]byte("version")); err != nil { + // WARN: This is because currently cometBFT DB does not return an error if the key does not exist + // If this behavior changes we need to account for that. + panic(err) + } + if len(version) != 0 { + dbKeyLayoutVersion = string(version) + } + } + + switch dbKeyLayoutVersion { + case "v1", "": + pool.dbKeyLayout = &v1LegacyLayout{} + dbKeyLayoutVersion = "v1" + case "v2": + pool.dbKeyLayout = &v2Layout{} + default: + panic("unknown key layout version") + } + if err := pool.evidenceStore.SetSync([]byte("version"), []byte(dbKeyLayoutVersion)); err != nil { + panic(err) + } +} + +type PoolOptions func(*Pool) + +// WithCompaction sets the compaciton parameters. +func WithDBKeyLayout(dbKeyLayoutV string) PoolOptions { + return func(pool *Pool) { + setDBLayout(pool, dbKeyLayoutV) + } } // NewPool creates an evidence pool. If using an existing evidence store, // it will add all pending evidence to the concurrent list. -func NewPool(evidenceDB dbm.DB, stateDB sm.Store, blockStore BlockStore) (*Pool, error) { +func NewPool(evidenceDB dbm.DB, stateDB sm.Store, blockStore BlockStore, options ...PoolOptions) (*Pool, error) { state, err := stateDB.Load() if err != nil { - return nil, fmt.Errorf("cannot load state: %w", err) + return nil, sm.ErrCannotLoadState{Err: err} } pool := &Pool{ @@ -68,10 +115,18 @@ func NewPool(evidenceDB dbm.DB, stateDB sm.Store, blockStore BlockStore) (*Pool, consensusBuffer: make([]duplicateVoteSet, 0), } + for _, option := range options { + option(pool) + } + + if pool.dbKeyLayout == nil { + setDBLayout(pool, "v1") + } + // if pending evidence already in db, in event of prior failure, then check for expiration, // update the size and load it back to the evidenceList pool.pruningHeight, pool.pruningTime = pool.removeExpiredPendingEvidence() - evList, _, err := pool.listEvidence(baseKeyPending, -1) + evList, _, err := pool.listEvidence(pool.dbKeyLayout.PrefixToBytesPending(), -1) if err != nil { return nil, err } @@ -88,9 +143,10 @@ func (evpool *Pool) PendingEvidence(maxBytes int64) ([]types.Evidence, int64) { if evpool.Size() == 0 { return []types.Evidence{}, 0 } - evidence, size, err := evpool.listEvidence(baseKeyPending, maxBytes) + evidence, size, err := evpool.listEvidence(evpool.dbKeyLayout.PrefixToBytesPending(), maxBytes) if err != nil { evpool.logger.Error("Unable to retrieve pending evidence", "err", err) + return []types.Evidence{}, 0 } return evidence, size } @@ -132,11 +188,11 @@ func (evpool *Pool) Update(state sm.State, ev types.EvidenceList) { // AddEvidence checks the evidence is valid and adds it to the pool. func (evpool *Pool) AddEvidence(ev types.Evidence) error { - evpool.logger.Debug("Attempting to add evidence", "ev", ev) + evpool.logger.Info("Attempting to add evidence", "ev", ev) // We have already verified this piece of evidence - no need to do it again if evpool.isPending(ev) { - evpool.logger.Debug("Evidence already pending, ignoring this one", "ev", ev) + evpool.logger.Info("Evidence already pending, ignoring this one", "ev", ev) return nil } @@ -144,7 +200,7 @@ func (evpool *Pool) AddEvidence(ev types.Evidence) error { if evpool.isCommitted(ev) { // this can happen if the peer that sent us the evidence is behind so we shouldn't // punish the peer. - evpool.logger.Debug("Evidence was already committed, ignoring this one", "ev", ev) + evpool.logger.Info("Evidence was already committed, ignoring this one", "ev", ev) return nil } @@ -192,7 +248,6 @@ func (evpool *Pool) ReportConflictingVotes(voteA, voteB *types.Vote) { func (evpool *Pool) CheckEvidence(evList types.EvidenceList) error { hashes := make([][]byte, len(evList)) for idx, ev := range evList { - _, isLightEv := ev.(*types.LightClientAttackEvidence) // We must verify light client attack evidence regardless because there could be a @@ -200,7 +255,7 @@ func (evpool *Pool) CheckEvidence(evList types.EvidenceList) error { if isLightEv || !evpool.isPending(ev) { // check that the evidence isn't already committed if evpool.isCommitted(ev) { - return &types.ErrInvalidEvidence{Evidence: ev, Reason: errors.New("evidence was already committed")} + return &types.ErrInvalidEvidence{Evidence: ev, Reason: ErrEvidenceAlreadyCommitted} } err := evpool.verify(ev) @@ -221,7 +276,7 @@ func (evpool *Pool) CheckEvidence(evList types.EvidenceList) error { hashes[idx] = ev.Hash() for i := idx - 1; i >= 0; i-- { if bytes.Equal(hashes[i], hashes[idx]) { - return &types.ErrInvalidEvidence{Evidence: ev, Reason: errors.New("duplicate evidence")} + return &types.ErrInvalidEvidence{Evidence: ev, Reason: ErrDuplicateEvidence} } } } @@ -229,12 +284,12 @@ func (evpool *Pool) CheckEvidence(evList types.EvidenceList) error { return nil } -// EvidenceFront goes to the first evidence in the clist +// EvidenceFront goes to the first evidence in the clist. func (evpool *Pool) EvidenceFront() *clist.CElement { return evpool.evidenceList.Front() } -// EvidenceWaitChan is a channel that closes once the first evidence in the list is there. i.e Front is not nil +// EvidenceWaitChan is a channel that closes once the first evidence in the list is there. i.e Front is not nil. func (evpool *Pool) EvidenceWaitChan() <-chan struct{} { return evpool.evidenceList.WaitChan() } @@ -261,7 +316,7 @@ func (evpool *Pool) Close() error { } // IsExpired checks whether evidence or a polc is expired by checking whether a height and time is older -// than set by the evidence consensus parameters +// than set by the evidence consensus parameters. func (evpool *Pool) isExpired(height int64, time time.Time) bool { var ( params = evpool.State().ConsensusParams.Evidence @@ -274,7 +329,7 @@ func (evpool *Pool) isExpired(height int64, time time.Time) bool { // IsCommitted returns true if we have already seen this exact evidence and it is already marked as committed. func (evpool *Pool) isCommitted(evidence types.Evidence) bool { - key := keyCommitted(evidence) + key := evpool.dbKeyLayout.CalcKeyCommitted(evidence) ok, err := evpool.evidenceStore.Has(key) if err != nil { evpool.logger.Error("Unable to find committed evidence", "err", err) @@ -284,7 +339,7 @@ func (evpool *Pool) isCommitted(evidence types.Evidence) bool { // IsPending checks whether the evidence is already pending. DB errors are passed to the logger. func (evpool *Pool) isPending(evidence types.Evidence) bool { - key := keyPending(evidence) + key := evpool.dbKeyLayout.CalcKeyPending(evidence) ok, err := evpool.evidenceStore.Has(key) if err != nil { evpool.logger.Error("Unable to find pending evidence", "err", err) @@ -295,7 +350,7 @@ func (evpool *Pool) isPending(evidence types.Evidence) bool { func (evpool *Pool) addPendingEvidence(ev types.Evidence) error { evpb, err := types.EvidenceToProto(ev) if err != nil { - return fmt.Errorf("unable to convert to proto, err: %w", err) + return cmterrors.ErrMsgToProto{MessageName: "Evidence", Err: err} } evBytes, err := evpb.Marshal() @@ -303,7 +358,7 @@ func (evpool *Pool) addPendingEvidence(ev types.Evidence) error { return fmt.Errorf("unable to marshal evidence: %w", err) } - key := keyPending(ev) + key := evpool.dbKeyLayout.CalcKeyPending(ev) err = evpool.evidenceStore.Set(key, evBytes) if err != nil { @@ -314,7 +369,7 @@ func (evpool *Pool) addPendingEvidence(ev types.Evidence) error { } func (evpool *Pool) removePendingEvidence(evidence types.Evidence) { - key := keyPending(evidence) + key := evpool.dbKeyLayout.CalcKeyPending(evidence) if err := evpool.evidenceStore.Delete(key); err != nil { evpool.logger.Error("Unable to delete pending evidence", "err", err) } else { @@ -335,7 +390,7 @@ func (evpool *Pool) markEvidenceAsCommitted(evidence types.EvidenceList) { // Add evidence to the committed list. As the evidence is stored in the block store // we only need to record the height that it was saved at. - key := keyCommitted(ev) + key := evpool.dbKeyLayout.CalcKeyCommitted(ev) h := gogotypes.Int64Value{Value: ev.Height()} evBytes, err := proto.Marshal(&h) @@ -357,7 +412,7 @@ func (evpool *Pool) markEvidenceAsCommitted(evidence types.EvidenceList) { // listEvidence retrieves lists evidence from oldest to newest within maxBytes. // If maxBytes is -1, there's no cap on the size of returned evidence. -func (evpool *Pool) listEvidence(prefixKey byte, maxBytes int64) ([]types.Evidence, int64, error) { +func (evpool *Pool) listEvidence(prefixKey []byte, maxBytes int64) ([]types.Evidence, int64, error) { var ( evSize int64 totalSize int64 @@ -365,7 +420,7 @@ func (evpool *Pool) listEvidence(prefixKey byte, maxBytes int64) ([]types.Eviden evList cmtproto.EvidenceList // used for calculating the bytes size ) - iter, err := dbm.IteratePrefix(evpool.evidenceStore, []byte{prefixKey}) + iter, err := dbm.IteratePrefix(evpool.evidenceStore, prefixKey) if err != nil { return nil, totalSize, fmt.Errorf("database error: %v", err) } @@ -401,7 +456,7 @@ func (evpool *Pool) listEvidence(prefixKey byte, maxBytes int64) ([]types.Eviden } func (evpool *Pool) removeExpiredPendingEvidence() (int64, time.Time) { - iter, err := dbm.IteratePrefix(evpool.evidenceStore, []byte{baseKeyPending}) + iter, err := dbm.IteratePrefix(evpool.evidenceStore, evpool.dbKeyLayout.PrefixToBytesPending()) if err != nil { evpool.logger.Error("Unable to iterate over pending evidence", "err", err) return evpool.State().LastBlockHeight, evpool.State().LastBlockTime @@ -460,7 +515,6 @@ func (evpool *Pool) processConsensusBuffer(state sm.State) { evpool.mtx.Lock() defer evpool.mtx.Unlock() for _, voteSet := range evpool.consensusBuffer { - // Check the height of the conflicting votes and fetch the corresponding time and validator set // to produce the valid evidence var ( @@ -513,13 +567,13 @@ func (evpool *Pool) processConsensusBuffer(state sm.State) { // check if we already have this evidence if evpool.isPending(dve) { - evpool.logger.Debug("evidence already pending; ignoring", "evidence", dve) + evpool.logger.Info("evidence already pending; ignoring", "evidence", dve) continue } // check that the evidence is not already committed on chain if evpool.isCommitted(dve) { - evpool.logger.Debug("evidence already committed; ignoring", "evidence", dve) + evpool.logger.Info("evidence already committed; ignoring", "evidence", dve) continue } @@ -555,19 +609,103 @@ func evMapKey(ev types.Evidence) string { return string(ev.Hash()) } -// big endian padded hex -func bE(h int64) string { - return fmt.Sprintf("%0.16X", h) +// -------------- DB Key layout representation --------------- + +type KeyLayout interface { + CalcKeyCommitted(evidence types.Evidence) []byte + + CalcKeyPending(evidence types.Evidence) []byte + + PrefixToBytesPending() []byte + + PrefixToBytesCommitted() []byte +} + +type v1LegacyLayout struct{} + +// PrefixToBytesCommitted implements EvidenceKeyLayout. +func (v1LegacyLayout) PrefixToBytesCommitted() []byte { + return []byte{baseKeyCommitted} +} + +// PrefixToBytesPending implements EvidenceKeyLayout. +func (v1LegacyLayout) PrefixToBytesPending() []byte { + return []byte{baseKeyPending} } -func keyCommitted(evidence types.Evidence) []byte { +// CalcKeyCommitted implements EvidenceKeyLayout. +func (v1LegacyLayout) CalcKeyCommitted(evidence types.Evidence) []byte { return append([]byte{baseKeyCommitted}, keySuffix(evidence)...) } -func keyPending(evidence types.Evidence) []byte { +// CalcKeyPending implements EvidenceKeyLayout. +func (v1LegacyLayout) CalcKeyPending(evidence types.Evidence) []byte { return append([]byte{baseKeyPending}, keySuffix(evidence)...) } +var _ KeyLayout = (*v1LegacyLayout)(nil) + +type v2Layout struct{} + +// PrefixToBytesCommitted implements EvidenceKeyLayout. +func (v2Layout) PrefixToBytesCommitted() []byte { + key, err := orderedcode.Append(nil, prefixCommitted) + if err != nil { + panic(err) + } + return key +} + +// PrefixToBytesPending implements EvidenceKeyLayout. +func (v2Layout) PrefixToBytesPending() []byte { + key, err := orderedcode.Append(nil, prefixPending) + if err != nil { + panic(err) + } + return key +} + +// CalcKeyCommitted implements EvidenceKeyLayout. +func (v2Layout) CalcKeyCommitted(evidence types.Evidence) []byte { + key, err := orderedcode.Append(nil, prefixCommitted, evidence.Height(), string(evidence.Hash())) + if err != nil { + panic(err) + } + return key +} + +// CalcKeyPending implements EvidenceKeyLayout. +func (v2Layout) CalcKeyPending(evidence types.Evidence) []byte { + key, err := orderedcode.Append(nil, prefixPending, evidence.Height(), string(evidence.Hash())) + if err != nil { + panic(err) + } + return key +} + +var _ KeyLayout = (*v2Layout)(nil) + +// -------- Util --------- +// big endian padded hex. +func bE(h int64) string { + return fmt.Sprintf("%0.16X", h) +} + func keySuffix(evidence types.Evidence) []byte { return []byte(fmt.Sprintf("%s/%X", bE(evidence.Height()), evidence.Hash())) } + +// --------------------- + +// ---- v2 layout ----. +const ( + // prefixes must be unique across all db's. + prefixCommitted = int64(9) + prefixPending = int64(10) +) + +// ---- v1 layout ----. +const ( + baseKeyCommitted = byte(0x00) + baseKeyPending = byte(0x01) +) diff --git a/evidence/pool_test.go b/internal/evidence/pool_test.go similarity index 89% rename from evidence/pool_test.go rename to internal/evidence/pool_test.go index 815e3666134..f3aea5ec19f 100644 --- a/evidence/pool_test.go +++ b/internal/evidence/pool_test.go @@ -10,15 +10,14 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - - "github.com/cometbft/cometbft/evidence" - "github.com/cometbft/cometbft/evidence/mocks" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" + "github.com/cometbft/cometbft/internal/evidence" + "github.com/cometbft/cometbft/internal/evidence/mocks" + sm "github.com/cometbft/cometbft/internal/state" + smmocks "github.com/cometbft/cometbft/internal/state/mocks" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" - sm "github.com/cometbft/cometbft/state" - smmocks "github.com/cometbft/cometbft/state/mocks" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" "github.com/cometbft/cometbft/version" ) @@ -51,14 +50,18 @@ func TestEvidencePoolBasic(t *testing.T) { stateStore.On("LoadValidators", mock.AnythingOfType("int64")).Return(valSet, nil) stateStore.On("Load").Return(createState(height+1, valSet), nil) - pool, err := evidence.NewPool(evidenceDB, stateStore, blockStore) + require.Panics(t, func() { _, _ = evidence.NewPool(evidenceDB, stateStore, blockStore, evidence.WithDBKeyLayout("2")) }, "failed to create tore") + + pool, err := evidence.NewPool(evidenceDB, stateStore, blockStore, evidence.WithDBKeyLayout("v2")) + require.NoError(t, err) + require.NoError(t, err) pool.SetLogger(log.TestingLogger()) // evidence not seen yet: evs, size := pool.PendingEvidence(defaultEvidenceMaxBytes) - assert.Equal(t, 0, len(evs)) - assert.Zero(t, size) + require.Empty(t, evs) + require.Zero(t, size) ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, defaultEvidenceTime, privVals[0], evidenceChainID) require.NoError(t, err) @@ -71,7 +74,7 @@ func TestEvidencePoolBasic(t *testing.T) { }() // evidence seen but not yet committed: - assert.NoError(t, pool.AddEvidence(ev)) + require.NoError(t, pool.AddEvidence(ev)) select { case <-evAdded: @@ -84,16 +87,16 @@ func TestEvidencePoolBasic(t *testing.T) { const evidenceBytes int64 = 372 evs, size = pool.PendingEvidence(evidenceBytes) - assert.Equal(t, 1, len(evs)) + assert.Len(t, evs, 1) assert.Equal(t, evidenceBytes, size) // check that the size of the single evidence in bytes is correct // shouldn't be able to add evidence twice - assert.NoError(t, pool.AddEvidence(ev)) + require.NoError(t, pool.AddEvidence(ev)) evs, _ = pool.PendingEvidence(defaultEvidenceMaxBytes) - assert.Equal(t, 1, len(evs)) + assert.Len(t, evs, 1) } -// Tests inbound evidence for the right time and height +// Tests inbound evidence for the right time and height. func TestAddExpiredEvidence(t *testing.T) { var ( val = types.NewMockPV() @@ -138,9 +141,9 @@ func TestAddExpiredEvidence(t *testing.T) { require.NoError(t, err) err = pool.AddEvidence(ev) if tc.expErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -212,8 +215,8 @@ func TestEvidencePoolUpdate(t *testing.T) { // b) If we try to check this evidence again it should fail because it has already been committed err = pool.CheckEvidence(types.EvidenceList{ev}) - if assert.Error(t, err) { - assert.Equal(t, "evidence was already committed", err.(*types.ErrInvalidEvidence).Reason.Error()) + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here + assert.Equal(t, evidence.ErrEvidenceAlreadyCommitted.Error(), err.(*types.ErrInvalidEvidence).Reason.Error()) } } @@ -227,7 +230,7 @@ func TestVerifyPendingEvidencePasses(t *testing.T) { require.NoError(t, err) err = pool.CheckEvidence(types.EvidenceList{ev}) - assert.NoError(t, err) + require.NoError(t, err) } func TestVerifyDuplicatedEvidenceFails(t *testing.T) { @@ -237,13 +240,13 @@ func TestVerifyDuplicatedEvidenceFails(t *testing.T) { val, evidenceChainID) require.NoError(t, err) err = pool.CheckEvidence(types.EvidenceList{ev, ev}) - if assert.Error(t, err) { - assert.Equal(t, "duplicate evidence", err.(*types.ErrInvalidEvidence).Reason.Error()) + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here + assert.Equal(t, evidence.ErrDuplicateEvidence.Error(), err.(*types.ErrInvalidEvidence).Reason.Error()) } } // check that valid light client evidence is correctly validated and stored in -// evidence pool +// evidence pool. func TestLightClientAttackEvidenceLifecycle(t *testing.T) { var ( height int64 = 100 @@ -251,7 +254,7 @@ func TestLightClientAttackEvidenceLifecycle(t *testing.T) { ) ev, trusted, common := makeLunaticEvidence(t, height, commonHeight, - 10, 5, 5, defaultEvidenceTime, defaultEvidenceTime.Add(1*time.Hour)) + 5, 5, defaultEvidenceTime, defaultEvidenceTime.Add(1*time.Hour)) state := sm.State{ LastBlockTime: defaultEvidenceTime.Add(2 * time.Hour), @@ -273,7 +276,7 @@ func TestLightClientAttackEvidenceLifecycle(t *testing.T) { pool.SetLogger(log.TestingLogger()) err = pool.AddEvidence(ev) - assert.NoError(t, err) + require.NoError(t, err) hash := ev.Hash() @@ -281,7 +284,7 @@ func TestLightClientAttackEvidenceLifecycle(t *testing.T) { require.NoError(t, pool.AddEvidence(ev)) pendingEv, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) - require.Equal(t, 1, len(pendingEv)) + require.Len(t, pendingEv, 1) require.Equal(t, ev, pendingEv[0]) require.NoError(t, pool.CheckEvidence(pendingEv)) @@ -304,7 +307,7 @@ func TestLightClientAttackEvidenceLifecycle(t *testing.T) { } // Tests that restarting the evidence pool after a potential failure will recover the -// pending evidence and continue to gossip it +// pending evidence and continue to gossip it. func TestRecoverPendingEvidence(t *testing.T) { height := int64(10) val := types.NewMockPV() @@ -348,11 +351,11 @@ func TestRecoverPendingEvidence(t *testing.T) { }, }, nil) newPool, err := evidence.NewPool(evidenceDB, newStateStore, blockStore) - assert.NoError(t, err) + require.NoError(t, err) evList, _ := newPool.PendingEvidence(defaultEvidenceMaxBytes) - assert.Equal(t, 1, len(evList)) + require.Len(t, evList, 1) next := newPool.EvidenceFront() - assert.Equal(t, goodEvidence, next.Value.(types.Evidence)) + require.Equal(t, goodEvidence, next.Value.(types.Evidence)) } func initializeStateFromValidatorSet(valSet *types.ValidatorSet, height int64) sm.Store { @@ -416,8 +419,7 @@ func initializeBlockStore(db dbm.DB, state sm.State, valAddr []byte) (*store.Blo block := state.MakeBlock(i, test.MakeNTxs(i, 1), lastCommit.ToCommit(), nil, state.Validators.Proposer.Address) block.Header.Time = defaultEvidenceTime.Add(time.Duration(i) * time.Minute) block.Header.Version = cmtversion.Consensus{Block: version.BlockProtocol, App: 1} - const parts = 1 - partSet, err := block.MakePartSet(parts) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) if err != nil { return nil, err } diff --git a/evidence/reactor.go b/internal/evidence/reactor.go similarity index 95% rename from evidence/reactor.go rename to internal/evidence/reactor.go index 10d3e53111b..4a686780098 100644 --- a/evidence/reactor.go +++ b/internal/evidence/reactor.go @@ -6,10 +6,10 @@ import ( "github.com/cosmos/gogoproto/proto" - clist "github.com/cometbft/cometbft/libs/clist" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/internal/clist" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/p2p" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" ) @@ -23,7 +23,7 @@ const ( // Most evidence should be committed in the very next block that is why we wait // just over the block production rate before sending evidence again. broadcastEvidenceIntervalS = 10 - // If a message fails wait this much before sending it again + // If a message fails wait this much before sending it again. peerRetryMessageIntervalMS = 100 ) @@ -51,7 +51,7 @@ func (evR *Reactor) SetLogger(l log.Logger) { // GetChannels implements Reactor. // It returns the list of channels for this reactor. -func (evR *Reactor) GetChannels() []*p2p.ChannelDescriptor { +func (*Reactor) GetChannels() []*p2p.ChannelDescriptor { return []*p2p.ChannelDescriptor{ { ID: EvidenceChannel, @@ -167,7 +167,6 @@ func (evR Reactor) prepareEvidenceMessage( peer p2p.Peer, ev types.Evidence, ) (evis []types.Evidence) { - // make sure the peer is up to date evHeight := ev.Height() peerState, ok := peer.Get(types.PeerStateKey).(PeerState) @@ -191,7 +190,6 @@ func (evR Reactor) prepareEvidenceMessage( if peerHeight <= evHeight { // peer is behind. sleep while he catches up return nil } else if ageNumBlocks > params.MaxAgeNumBlocks { // evidence is too old relative to the peer, skip - // NOTE: if evidence is too old for an honest peer, then we're behind and // either it already got committed or it never will! evR.Logger.Info("Not sending peer old evidence", @@ -216,7 +214,7 @@ type PeerState interface { } // encodemsg takes a array of evidence -// returns the byte encoding of the List Message +// returns the byte encoding of the List Message. func evidenceListToProto(evis []types.Evidence) (*cmtproto.EvidenceList, error) { evi := make([]cmtproto.Evidence, len(evis)) for i := 0; i < len(evis); i++ { diff --git a/evidence/reactor_test.go b/internal/evidence/reactor_test.go similarity index 90% rename from evidence/reactor_test.go rename to internal/evidence/reactor_test.go index 620c8fa7d5e..2c60e484231 100644 --- a/evidence/reactor_test.go +++ b/internal/evidence/reactor_test.go @@ -14,17 +14,16 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/tmhash" - "github.com/cometbft/cometbft/evidence" - "github.com/cometbft/cometbft/evidence/mocks" + "github.com/cometbft/cometbft/internal/evidence" + "github.com/cometbft/cometbft/internal/evidence/mocks" + sm "github.com/cometbft/cometbft/internal/state" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/p2p" p2pmocks "github.com/cometbft/cometbft/p2p/mocks" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" ) @@ -39,14 +38,14 @@ var ( // evidence pools. func TestReactorBroadcastEvidence(t *testing.T) { config := cfg.TestConfig() - N := 7 + n := 7 // create statedb for everyone - stateDBs := make([]sm.Store, N) + stateDBs := make([]sm.Store, n) val := types.NewMockPV() // we need validators saved for heights at least as high as we have evidence for height := int64(numEvidence) + 10 - for i := 0; i < N; i++ { + for i := 0; i < n; i++ { stateDBs[i] = initializeValidatorState(val, height) } @@ -55,7 +54,7 @@ func TestReactorBroadcastEvidence(t *testing.T) { // set the peer height on each reactor for _, r := range reactors { - for _, peer := range r.Switch.Peers().List() { + for _, peer := range r.Switch.Peers().Copy() { ps := peerState{height} peer.Set(types.PeerStateKey, ps) } @@ -86,14 +85,14 @@ func TestReactorSelectiveBroadcast(t *testing.T) { // set the peer height on each reactor for _, r := range reactors { - for _, peer := range r.Switch.Peers().List() { + for _, peer := range r.Switch.Peers().Copy() { ps := peerState{height1} peer.Set(types.PeerStateKey, ps) } } // update the first reactor peer's height to be very small - peer := reactors[0].Switch.Peers().List()[0] + peer := reactors[0].Switch.Peers().Copy()[0] ps := peerState{height2} peer.Set(types.PeerStateKey, ps) @@ -104,15 +103,15 @@ func TestReactorSelectiveBroadcast(t *testing.T) { waitForEvidence(t, evList[:numEvidence/2-1], []*evidence.Pool{pools[1]}) // peers should still be connected - peers := reactors[1].Switch.Peers().List() - assert.Equal(t, 1, len(peers)) + peers := reactors[1].Switch.Peers().Copy() + assert.Len(t, peers, 1) } // This tests aims to ensure that reactors don't send evidence that they have committed or that ar // not ready for the peer through three scenarios. // First, committed evidence to a newly connected peer // Second, evidence to a peer that is behind -// Third, evidence that was pending and became committed just before the peer caught up +// Third, evidence that was pending and became committed just before the peer caught up. func TestReactorsGossipNoCommittedEvidence(t *testing.T) { config := cfg.TestConfig() @@ -135,11 +134,11 @@ func TestReactorsGossipNoCommittedEvidence(t *testing.T) { time.Sleep(100 * time.Millisecond) - peer := reactors[0].Switch.Peers().List()[0] + peer := reactors[0].Switch.Peers().Copy()[0] ps := peerState{height - 2} peer.Set(types.PeerStateKey, ps) - peer = reactors[1].Switch.Peers().List()[0] + peer = reactors[1].Switch.Peers().Copy()[0] ps = peerState{height} peer.Set(types.PeerStateKey, ps) @@ -177,7 +176,7 @@ func TestReactorsGossipNoCommittedEvidence(t *testing.T) { // now update the state of the second reactor pools[1].Update(state, types.EvidenceList{}) - peer = reactors[0].Switch.Peers().List()[0] + peer = reactors[0].Switch.Peers().Copy()[0] ps = peerState{height} peer.Set(types.PeerStateKey, ps) @@ -208,7 +207,7 @@ func TestReactorBroadcastEvidenceMemoryLeak(t *testing.T) { // i.e. broadcastEvidenceRoutine finishes when peer is stopped defer leaktest.CheckTimeout(t, 10*time.Second)() - p.On("Send", mock.MatchedBy(func(i interface{}) bool { + p.On("Send", mock.MatchedBy(func(i any) bool { e, ok := i.(p2p.Envelope) return ok && e.ChannelID == evidence.EvidenceChannel })).Return(false) @@ -229,7 +228,7 @@ func TestReactorBroadcastEvidenceMemoryLeak(t *testing.T) { // evidenceLogger is a TestingLogger which uses a different // color for each validator ("validator" key must exist). func evidenceLogger() log.Logger { - return log.TestingLoggerWithColorFn(func(keyvals ...interface{}) term.FgBgColor { + return log.TestingLoggerWithColorFn(func(keyvals ...any) term.FgBgColor { for i := 0; i < len(keyvals)-1; i += 2 { if keyvals[i] == "validator" { return term.FgBgColor{Fg: term.Color(uint8(keyvals[i+1].(int) + 1))} @@ -239,18 +238,18 @@ func evidenceLogger() log.Logger { }) } -// connect N evidence reactors through N switches +// connect N evidence reactors through N switches. func makeAndConnectReactorsAndPools(config *cfg.Config, stateStores []sm.Store) ([]*evidence.Reactor, []*evidence.Pool, ) { - N := len(stateStores) + n := len(stateStores) - reactors := make([]*evidence.Reactor, N) - pools := make([]*evidence.Pool, N) + reactors := make([]*evidence.Reactor, n) + pools := make([]*evidence.Pool, n) logger := evidenceLogger() evidenceTime := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) - for i := 0; i < N; i++ { + for i := 0; i < n; i++ { evidenceDB := dbm.NewMemDB() blockStore := &mocks.BlockStore{} blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return( @@ -265,7 +264,7 @@ func makeAndConnectReactorsAndPools(config *cfg.Config, stateStores []sm.Store) reactors[i].SetLogger(logger.With("validator", i)) } - p2p.MakeConnectedSwitches(config.P2P, N, func(i int, s *p2p.Switch) *p2p.Switch { + p2p.MakeConnectedSwitches(config.P2P, n, func(i int, s *p2p.Switch) *p2p.Switch { s.AddReactor("EVIDENCE", reactors[i]) return s }, p2p.Connect2Switches) @@ -273,8 +272,9 @@ func makeAndConnectReactorsAndPools(config *cfg.Config, stateStores []sm.Store) return reactors, pools } -// wait for all evidence on all reactors +// wait for all evidence on all reactors. func waitForEvidence(t *testing.T, evs types.EvidenceList, pools []*evidence.Pool) { + t.Helper() // wait for the evidence in all evpools wg := new(sync.WaitGroup) for i := 0; i < len(pools); i++ { @@ -296,7 +296,7 @@ func waitForEvidence(t *testing.T, evs types.EvidenceList, pools []*evidence.Poo } } -// wait for all evidence on a single evpool +// wait for all evidence on a single evpool. func _waitForEvidence( t *testing.T, wg *sync.WaitGroup, @@ -304,6 +304,7 @@ func _waitForEvidence( poolIdx int, pools []*evidence.Pool, ) { + t.Helper() evpool := pools[poolIdx] var evList []types.Evidence currentPoolSize := 0 @@ -329,6 +330,7 @@ func _waitForEvidence( } func sendEvidence(t *testing.T, evpool *evidence.Pool, val types.PrivValidator, n int) types.EvidenceList { + t.Helper() evList := make([]types.Evidence, n) for i := 0; i < n; i++ { ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(int64(i+1), @@ -356,7 +358,7 @@ func exampleVote(t byte) *types.Vote { } return &types.Vote{ - Type: cmtproto.SignedMsgType(t), + Type: types.SignedMsgType(t), Height: 3, Round: 2, Timestamp: stamp, @@ -415,6 +417,5 @@ func TestEvidenceVectors(t *testing.T) { require.NoError(t, err, tc.testName) require.Equal(t, tc.expBytes, hex.EncodeToString(bz), tc.testName) - } } diff --git a/evidence/services.go b/internal/evidence/services.go similarity index 77% rename from evidence/services.go rename to internal/evidence/services.go index 5ebbc5a5b71..45c330972a9 100644 --- a/evidence/services.go +++ b/internal/evidence/services.go @@ -4,7 +4,7 @@ import ( "github.com/cometbft/cometbft/types" ) -//go:generate ../scripts/mockery_generate.sh BlockStore +//go:generate ../../scripts/mockery_generate.sh BlockStore type BlockStore interface { LoadBlockMeta(height int64) *types.BlockMeta diff --git a/evidence/verify.go b/internal/evidence/verify.go similarity index 73% rename from evidence/verify.go rename to internal/evidence/verify.go index 3ccdd0f4292..8f7523528dc 100644 --- a/evidence/verify.go +++ b/internal/evidence/verify.go @@ -15,7 +15,7 @@ import ( // - it is sufficiently recent (MaxAge) // - it is from a key who was a validator at the given height // - it is internally consistent with state -// - it was properly signed by the alleged equivocator and meets the individual evidence verification requirements +// - it was properly signed by the alleged equivocator and meets the individual evidence verification requirements. func (evpool *Pool) verify(evidence types.Evidence) error { var ( state = evpool.State() @@ -26,23 +26,23 @@ func (evpool *Pool) verify(evidence types.Evidence) error { // verify the time of the evidence blockMeta := evpool.blockStore.LoadBlockMeta(evidence.Height()) if blockMeta == nil { - return fmt.Errorf("don't have header #%d", evidence.Height()) + return ErrNoHeaderAtHeight{Height: height} } evTime := blockMeta.Header.Time if evidence.Time() != evTime { - return fmt.Errorf("evidence has a different time to the block it is associated with (%v != %v)", - evidence.Time(), evTime) + return ErrInvalidEvidence{fmt.Errorf("evidence has a different time to the block it is associated with (%v != %v)", + evidence.Time(), evTime)} } // checking if evidence is expired calculated using the block evidence time and height if IsEvidenceExpired(height, state.LastBlockTime, evidence.Height(), evTime, evidenceParams) { - return fmt.Errorf( + return ErrInvalidEvidence{fmt.Errorf( "evidence from height %d (created at: %v) is too old; min height is %d and evidence can not be older than %v", evidence.Height(), evTime, height-evidenceParams.MaxAgeNumBlocks, state.LastBlockTime.Add(evidenceParams.MaxAgeDuration), - ) + )} } // apply the evidence-specific verification logic @@ -79,23 +79,21 @@ func (evpool *Pool) verify(evidence types.Evidence) error { return err } if trustedHeader.Time.Before(ev.ConflictingBlock.Time) { - return fmt.Errorf("latest block time (%v) is before conflicting block time (%v)", + return ErrConflictingBlock{fmt.Errorf("latest block time (%v) is before conflicting block time (%v)", trustedHeader.Time, ev.ConflictingBlock.Time, - ) + )} } } } - err = VerifyLightClientAttack(ev, commonHeader, trustedHeader, commonVals, state.LastBlockTime, - state.ConsensusParams.Evidence.MaxAgeDuration) + err = VerifyLightClientAttack(ev, commonHeader, trustedHeader, commonVals) if err != nil { return err } return nil default: - return fmt.Errorf("unrecognized evidence type: %T", evidence) + return ErrUnrecognizedEvidenceType{Evidence: evidence} } - } // VerifyLightClientAttack verifies LightClientAttackEvidence against the state of the full node. This involves @@ -104,48 +102,54 @@ func (evpool *Pool) verify(evidence types.Evidence) error { // the conflicting header's commit // - 2/3+ of the conflicting validator set correctly signed the conflicting block // - the nodes trusted header at the same height as the conflicting header has a different hash +// - all signatures must be checked as this will be used as evidence // // CONTRACT: must run ValidateBasic() on the evidence before verifying // // must check that the evidence has not expired (i.e. is outside the maximum age threshold) -func VerifyLightClientAttack(e *types.LightClientAttackEvidence, commonHeader, trustedHeader *types.SignedHeader, - commonVals *types.ValidatorSet, now time.Time, trustPeriod time.Duration) error { +func VerifyLightClientAttack( + e *types.LightClientAttackEvidence, + commonHeader, trustedHeader *types.SignedHeader, + commonVals *types.ValidatorSet, +) error { + // TODO: Should the current time and trust period be used in this method? + // If not, why were the parameters present? + // In the case of lunatic attack there will be a different commonHeader height. Therefore the node perform a single // verification jump between the common header and the conflicting one if commonHeader.Height != e.ConflictingBlock.Height { - err := commonVals.VerifyCommitLightTrusting(trustedHeader.ChainID, e.ConflictingBlock.Commit, light.DefaultTrustLevel) + err := commonVals.VerifyCommitLightTrustingAllSignatures(trustedHeader.ChainID, e.ConflictingBlock.Commit, light.DefaultTrustLevel) if err != nil { - return fmt.Errorf("skipping verification of conflicting block failed: %w", err) + return ErrConflictingBlock{fmt.Errorf("skipping verification of conflicting block failed: %w", err)} } // In the case of equivocation and amnesia we expect all header hashes to be correctly derived } else if e.ConflictingHeaderIsInvalid(trustedHeader.Header) { - return errors.New("common height is the same as conflicting block height so expected the conflicting" + - " block to be correctly derived yet it wasn't") + return ErrConflictingBlock{errors.New("common height is the same as conflicting block height so expected the conflicting" + + " block to be correctly derived yet it wasn't")} } // Verify that the 2/3+ commits from the conflicting validator set were for the conflicting header - if err := e.ConflictingBlock.ValidatorSet.VerifyCommitLight(trustedHeader.ChainID, e.ConflictingBlock.Commit.BlockID, + if err := e.ConflictingBlock.ValidatorSet.VerifyCommitLightAllSignatures(trustedHeader.ChainID, e.ConflictingBlock.Commit.BlockID, e.ConflictingBlock.Height, e.ConflictingBlock.Commit); err != nil { - return fmt.Errorf("invalid commit from conflicting block: %w", err) + return ErrConflictingBlock{fmt.Errorf("invalid commit from conflicting block: %w", err)} } // Assert the correct amount of voting power of the validator set if evTotal, valsTotal := e.TotalVotingPower, commonVals.TotalVotingPower(); evTotal != valsTotal { - return fmt.Errorf("total voting power from the evidence and our validator set does not match (%d != %d)", - evTotal, valsTotal) + return ErrVotingPowerDoesNotMatch{TrustedVotingPower: valsTotal, EvidenceVotingPower: evTotal} } // check in the case of a forward lunatic attack that monotonically increasing time has been violated if e.ConflictingBlock.Height > trustedHeader.Height && e.ConflictingBlock.Time.After(trustedHeader.Time) { - return fmt.Errorf("conflicting block doesn't violate monotonically increasing time (%v is after %v)", + return ErrConflictingBlock{fmt.Errorf("conflicting block doesn't violate monotonically increasing time (%v is after %v)", e.ConflictingBlock.Time, trustedHeader.Time, - ) + )} // In all other cases check that the hashes of the conflicting header and the trusted header are different } else if bytes.Equal(trustedHeader.Hash(), e.ConflictingBlock.Hash()) { - return fmt.Errorf("trusted header hash matches the evidence's conflicting header hash: %X", - trustedHeader.Hash()) + return ErrConflictingBlock{fmt.Errorf("trusted header hash matches the evidence's conflicting header hash: %X", + trustedHeader.Hash())} } return validateABCIEvidence(e, commonVals, trustedHeader) @@ -160,7 +164,7 @@ func VerifyLightClientAttack(e *types.LightClientAttackEvidence, commonHeader, t func VerifyDuplicateVote(e *types.DuplicateVoteEvidence, chainID string, valSet *types.ValidatorSet) error { _, val := valSet.GetByAddress(e.VoteA.ValidatorAddress) if val == nil { - return fmt.Errorf("address %X was not a validator at height %d", e.VoteA.ValidatorAddress, e.Height()) + return ErrAddressNotValidatorAtHeight{Address: e.VoteA.ValidatorAddress, Height: e.Height()} } pubKey := val.PubKey @@ -168,42 +172,32 @@ func VerifyDuplicateVote(e *types.DuplicateVoteEvidence, chainID string, valSet if e.VoteA.Height != e.VoteB.Height || e.VoteA.Round != e.VoteB.Round || e.VoteA.Type != e.VoteB.Type { - return fmt.Errorf("h/r/s does not match: %d/%d/%v vs %d/%d/%v", - e.VoteA.Height, e.VoteA.Round, e.VoteA.Type, - e.VoteB.Height, e.VoteB.Round, e.VoteB.Type) + return ErrDuplicateEvidenceHRTMismatch{*e.VoteA, *e.VoteB} } // Address must be the same if !bytes.Equal(e.VoteA.ValidatorAddress, e.VoteB.ValidatorAddress) { - return fmt.Errorf("validator addresses do not match: %X vs %X", - e.VoteA.ValidatorAddress, - e.VoteB.ValidatorAddress, - ) + return ErrValidatorAddressesDoNotMatch{ValidatorA: e.VoteA.ValidatorAddress, ValidatorB: e.VoteB.ValidatorAddress} } // BlockIDs must be different if e.VoteA.BlockID.Equals(e.VoteB.BlockID) { - return fmt.Errorf( - "block IDs are the same (%v) - not a real duplicate vote", - e.VoteA.BlockID, - ) + return ErrSameBlockIDs{e.VoteA.BlockID} } // pubkey must match address (this should already be true, sanity check) addr := e.VoteA.ValidatorAddress if !bytes.Equal(pubKey.Address(), addr) { - return fmt.Errorf("address (%X) doesn't match pubkey (%v - %X)", - addr, pubKey, pubKey.Address()) + return ErrInvalidEvidenceValidators{fmt.Errorf("address (%X) doesn't match pubkey (%v - %X)", + addr, pubKey, pubKey.Address())} } // validator voting power and total voting power must match if val.VotingPower != e.ValidatorPower { - return fmt.Errorf("validator power from evidence and our validator set does not match (%d != %d)", - e.ValidatorPower, val.VotingPower) + return ErrVotingPowerDoesNotMatch{TrustedVotingPower: val.VotingPower, EvidenceVotingPower: e.ValidatorPower} } if valSet.TotalVotingPower() != e.TotalVotingPower { - return fmt.Errorf("total voting power from the evidence and our validator set does not match (%d != %d)", - e.TotalVotingPower, valSet.TotalVotingPower()) + return ErrVotingPowerDoesNotMatch{TrustedVotingPower: valSet.TotalVotingPower(), EvidenceVotingPower: e.TotalVotingPower} } va := e.VoteA.ToProto() @@ -220,15 +214,14 @@ func VerifyDuplicateVote(e *types.DuplicateVoteEvidence, chainID string, valSet } // validateABCIEvidence validates the ABCI component of the light client attack -// evidence i.e voting power and byzantine validators +// evidence i.e voting power and byzantine validators. func validateABCIEvidence( ev *types.LightClientAttackEvidence, commonVals *types.ValidatorSet, trustedHeader *types.SignedHeader, ) error { if evTotal, valsTotal := ev.TotalVotingPower, commonVals.TotalVotingPower(); evTotal != valsTotal { - return fmt.Errorf("total voting power from the evidence and our validator set does not match (%d != %d)", - evTotal, valsTotal) + return ErrVotingPowerDoesNotMatch{TrustedVotingPower: valsTotal, EvidenceVotingPower: evTotal} } // Find out what type of attack this was and thus extract the malicious @@ -239,29 +232,29 @@ func validateABCIEvidence( // Ensure this matches the validators that are listed in the evidence. They // should be ordered based on power. if validators == nil && ev.ByzantineValidators != nil { - return fmt.Errorf( + return ErrInvalidEvidenceValidators{fmt.Errorf( "expected nil validators from an amnesia light client attack but got %d", len(ev.ByzantineValidators), - ) + )} } if exp, got := len(validators), len(ev.ByzantineValidators); exp != got { - return fmt.Errorf("expected %d byzantine validators from evidence but got %d", exp, got) + return ErrInvalidEvidenceValidators{fmt.Errorf("expected %d byzantine validators from evidence but got %d", exp, got)} } for idx, val := range validators { if !bytes.Equal(ev.ByzantineValidators[idx].Address, val.Address) { - return fmt.Errorf( + return ErrInvalidEvidenceValidators{fmt.Errorf( "evidence contained an unexpected byzantine validator address; expected: %v, got: %v", val.Address, ev.ByzantineValidators[idx].Address, - ) + )} } if ev.ByzantineValidators[idx].VotingPower != val.VotingPower { - return fmt.Errorf( + return ErrInvalidEvidenceValidators{fmt.Errorf( "evidence contained unexpected byzantine validator power; expected %d, got %d", val.VotingPower, ev.ByzantineValidators[idx].VotingPower, - ) + )} } } @@ -271,11 +264,11 @@ func validateABCIEvidence( func getSignedHeader(blockStore BlockStore, height int64) (*types.SignedHeader, error) { blockMeta := blockStore.LoadBlockMeta(height) if blockMeta == nil { - return nil, fmt.Errorf("don't have header at height #%d", height) + return nil, ErrNoHeaderAtHeight{Height: height} } commit := blockStore.LoadBlockCommit(height) if commit == nil { - return nil, fmt.Errorf("don't have commit at height #%d", height) + return nil, ErrNoCommitAtHeight{Height: height} } return &types.SignedHeader{ Header: &blockMeta.Header, @@ -283,7 +276,7 @@ func getSignedHeader(blockStore BlockStore, height int64) (*types.SignedHeader, }, nil } -// check that the evidence hasn't expired +// check that the evidence hasn't expired. func IsEvidenceExpired(heightNow int64, timeNow time.Time, heightEv int64, timeEv time.Time, evidenceParams types.EvidenceParams) bool { ageDuration := timeNow.Sub(timeEv) ageNumBlocks := heightNow - heightEv diff --git a/evidence/verify_test.go b/internal/evidence/verify_test.go similarity index 86% rename from evidence/verify_test.go rename to internal/evidence/verify_test.go index 57c3c4f8b8c..031e85132e6 100644 --- a/evidence/verify_test.go +++ b/internal/evidence/verify_test.go @@ -9,17 +9,15 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/tmhash" - "github.com/cometbft/cometbft/evidence" - "github.com/cometbft/cometbft/evidence/mocks" + "github.com/cometbft/cometbft/internal/evidence" + "github.com/cometbft/cometbft/internal/evidence/mocks" + sm "github.com/cometbft/cometbft/internal/state" + smmocks "github.com/cometbft/cometbft/internal/state/mocks" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" - sm "github.com/cometbft/cometbft/state" - smmocks "github.com/cometbft/cometbft/state/mocks" "github.com/cometbft/cometbft/types" "github.com/cometbft/cometbft/version" ) @@ -38,31 +36,27 @@ func TestVerifyLightClientAttack_Lunatic(t *testing.T) { attackTime := defaultEvidenceTime.Add(1 * time.Hour) // create valid lunatic evidence ev, trusted, common := makeLunaticEvidence( - t, height, commonHeight, totalVals, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime) + t, height, commonHeight, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime) require.NoError(t, ev.ValidateBasic()) // good pass -> no error - err := evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet, - defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour) - assert.NoError(t, err) + err := evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet) + require.NoError(t, err) // trusted and conflicting hashes are the same -> an error should be returned - err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, ev.ConflictingBlock.SignedHeader, common.ValidatorSet, - defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour) - assert.Error(t, err) + err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, ev.ConflictingBlock.SignedHeader, common.ValidatorSet) + require.Error(t, err) // evidence with different total validator power should fail ev.TotalVotingPower = 1 * defaultVotingPower - err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet, - defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour) - assert.Error(t, err) + err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet) + require.Error(t, err) // evidence without enough malicious votes should fail ev, trusted, common = makeLunaticEvidence( - t, height, commonHeight, totalVals, byzVals-1, totalVals-byzVals, defaultEvidenceTime, attackTime) - err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet, - defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour) - assert.Error(t, err) + t, height, commonHeight, byzVals-1, totalVals-byzVals, defaultEvidenceTime, attackTime) + err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet) + require.Error(t, err) } func TestVerify_LunaticAttackAgainstState(t *testing.T) { @@ -75,7 +69,7 @@ func TestVerify_LunaticAttackAgainstState(t *testing.T) { attackTime := defaultEvidenceTime.Add(1 * time.Hour) // create valid lunatic evidence ev, trusted, common := makeLunaticEvidence( - t, height, commonHeight, totalVals, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime) + t, height, commonHeight, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime) // now we try to test verification against state state := sm.State{ @@ -97,18 +91,18 @@ func TestVerify_LunaticAttackAgainstState(t *testing.T) { evList := types.EvidenceList{ev} // check that the evidence pool correctly verifies the evidence - assert.NoError(t, pool.CheckEvidence(evList)) + require.NoError(t, pool.CheckEvidence(evList)) // as it was not originally in the pending bucket, it should now have been added pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) - assert.Equal(t, 1, len(pendingEvs)) + assert.Len(t, pendingEvs, 1) assert.Equal(t, ev, pendingEvs[0]) // if we submit evidence only against a single byzantine validator when we see there are more validators then this // should return an error ev.ByzantineValidators = ev.ByzantineValidators[:1] t.Log(evList) - assert.Error(t, pool.CheckEvidence(evList)) + require.Error(t, pool.CheckEvidence(evList)) // restore original byz vals ev.ByzantineValidators = ev.GetByzantineValidators(common.ValidatorSet, trusted.SignedHeader) @@ -116,20 +110,20 @@ func TestVerify_LunaticAttackAgainstState(t *testing.T) { evList = types.EvidenceList{ev, ev} pool, err = evidence.NewPool(dbm.NewMemDB(), stateStore, blockStore) require.NoError(t, err) - assert.Error(t, pool.CheckEvidence(evList)) + require.Error(t, pool.CheckEvidence(evList)) // If evidence is submitted with an altered timestamp it should return an error ev.Timestamp = defaultEvidenceTime.Add(1 * time.Minute) pool, err = evidence.NewPool(dbm.NewMemDB(), stateStore, blockStore) require.NoError(t, err) - assert.Error(t, pool.AddEvidence(ev)) + require.Error(t, pool.AddEvidence(ev)) ev.Timestamp = defaultEvidenceTime // Evidence submitted with a different validator power should fail ev.TotalVotingPower = 1 pool, err = evidence.NewPool(dbm.NewMemDB(), stateStore, blockStore) require.NoError(t, err) - assert.Error(t, pool.AddEvidence(ev)) + require.Error(t, pool.AddEvidence(ev)) ev.TotalVotingPower = common.ValidatorSet.TotalVotingPower() } @@ -145,7 +139,7 @@ func TestVerify_ForwardLunaticAttack(t *testing.T) { // create a forward lunatic attack ev, trusted, common := makeLunaticEvidence( - t, attackHeight, commonHeight, totalVals, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime) + t, attackHeight, commonHeight, byzVals, totalVals-byzVals, defaultEvidenceTime, attackTime) // now we try to test verification against state state := sm.State{ @@ -172,7 +166,7 @@ func TestVerify_ForwardLunaticAttack(t *testing.T) { require.NoError(t, err) // check that the evidence pool correctly verifies the evidence - assert.NoError(t, pool.CheckEvidence(types.EvidenceList{ev})) + require.NoError(t, pool.CheckEvidence(types.EvidenceList{ev})) // now we use a time which isn't able to contradict the FLA - thus we can't verify the evidence oldBlockStore := &mocks.BlockStore{} @@ -188,7 +182,7 @@ func TestVerify_ForwardLunaticAttack(t *testing.T) { pool, err = evidence.NewPool(dbm.NewMemDB(), stateStore, oldBlockStore) require.NoError(t, err) - assert.Error(t, pool.CheckEvidence(types.EvidenceList{ev})) + require.Error(t, pool.CheckEvidence(types.EvidenceList{ev})) } func TestVerifyLightClientAttack_Equivocation(t *testing.T) { @@ -207,7 +201,7 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) { // we are simulating a duplicate vote attack where all the validators in the conflictingVals set // except the last validator vote twice blockID := makeBlockID(conflictingHeader.Hash(), 1000, []byte("partshash")) - voteSet := types.NewVoteSet(evidenceChainID, 10, 1, cmtproto.SignedMsgType(2), conflictingVals) + voteSet := types.NewVoteSet(evidenceChainID, 10, 1, types.SignedMsgType(2), conflictingVals) commit, err := test.MakeCommitFromVoteSet(blockID, voteSet, conflictingPrivVals[:4], defaultEvidenceTime) require.NoError(t, err) ev := &types.LightClientAttackEvidence{ @@ -225,7 +219,7 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) { } trustedBlockID := makeBlockID(trustedHeader.Hash(), 1000, []byte("partshash")) - trustedVoteSet := types.NewVoteSet(evidenceChainID, 10, 1, cmtproto.SignedMsgType(2), conflictingVals) + trustedVoteSet := types.NewVoteSet(evidenceChainID, 10, 1, types.SignedMsgType(2), conflictingVals) trustedCommit, err := test.MakeCommitFromVoteSet(trustedBlockID, trustedVoteSet, conflictingPrivVals, defaultEvidenceTime) require.NoError(t, err) trustedSignedHeader := &types.SignedHeader{ @@ -234,21 +228,18 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) { } // good pass -> no error - err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals, - defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour) - assert.NoError(t, err) + err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals) + require.NoError(t, err) // trusted and conflicting hashes are the same -> an error should be returned - err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals, - defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour) - assert.Error(t, err) + err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals) + require.Error(t, err) // conflicting header has different next validators hash which should have been correctly derived from // the previous round ev.ConflictingBlock.Header.NextValidatorsHash = crypto.CRandBytes(tmhash.Size) - err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, nil, - defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour) - assert.Error(t, err) + err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, nil) + require.Error(t, err) // revert next validators hash ev.ConflictingBlock.Header.NextValidatorsHash = trustedHeader.NextValidatorsHash @@ -270,10 +261,10 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) { evList := types.EvidenceList{ev} err = pool.CheckEvidence(evList) - assert.NoError(t, err) + require.NoError(t, err) pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) - assert.Equal(t, 1, len(pendingEvs)) + assert.Len(t, pendingEvs, 1) } func TestVerifyLightClientAttack_Amnesia(t *testing.T) { @@ -291,7 +282,7 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) { // we are simulating an amnesia attack where all the validators in the conflictingVals set // except the last validator vote twice. However this time the commits are of different rounds. blockID := makeBlockID(conflictingHeader.Hash(), 1000, []byte("partshash")) - voteSet := types.NewVoteSet(evidenceChainID, 10, 0, cmtproto.SignedMsgType(2), conflictingVals) + voteSet := types.NewVoteSet(evidenceChainID, 10, 0, types.SignedMsgType(2), conflictingVals) commit, err := test.MakeCommitFromVoteSet(blockID, voteSet, conflictingPrivVals, defaultEvidenceTime) require.NoError(t, err) ev := &types.LightClientAttackEvidence{ @@ -309,7 +300,7 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) { } trustedBlockID := makeBlockID(trustedHeader.Hash(), 1000, []byte("partshash")) - trustedVoteSet := types.NewVoteSet(evidenceChainID, 10, 1, cmtproto.SignedMsgType(2), conflictingVals) + trustedVoteSet := types.NewVoteSet(evidenceChainID, 10, 1, types.SignedMsgType(2), conflictingVals) trustedCommit, err := test.MakeCommitFromVoteSet(trustedBlockID, trustedVoteSet, conflictingPrivVals, defaultEvidenceTime) require.NoError(t, err) trustedSignedHeader := &types.SignedHeader{ @@ -318,14 +309,12 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) { } // good pass -> no error - err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals, - defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour) - assert.NoError(t, err) + err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, trustedSignedHeader, conflictingVals) + require.NoError(t, err) // trusted and conflicting hashes are the same -> an error should be returned - err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals, - defaultEvidenceTime.Add(1*time.Minute), 2*time.Hour) - assert.Error(t, err) + err = evidence.VerifyLightClientAttack(ev, trustedSignedHeader, ev.ConflictingBlock.SignedHeader, conflictingVals) + require.Error(t, err) state := sm.State{ LastBlockTime: defaultEvidenceTime.Add(1 * time.Minute), @@ -345,10 +334,10 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) { evList := types.EvidenceList{ev} err = pool.CheckEvidence(evList) - assert.NoError(t, err) + require.NoError(t, err) pendingEvs, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) - assert.Equal(t, 1, len(pendingEvs)) + assert.Len(t, pendingEvs, 1) } type voteData struct { @@ -372,11 +361,11 @@ func TestVerifyDuplicateVoteEvidence(t *testing.T) { vote1 := types.MakeVoteNoError(t, val, chainID, 0, 10, 2, 1, blockID, defaultEvidenceTime) v1 := vote1.ToProto() - err := val.SignVote(chainID, v1) + err := val.SignVote(chainID, v1, false) require.NoError(t, err) badVote := types.MakeVoteNoError(t, val, chainID, 0, 10, 2, 1, blockID, defaultEvidenceTime) bv := badVote.ToProto() - err = val2.SignVote(chainID, bv) + err = val2.SignVote(chainID, bv, false) require.NoError(t, err) vote1.Signature = v1.Signature @@ -407,9 +396,9 @@ func TestVerifyDuplicateVoteEvidence(t *testing.T) { Timestamp: defaultEvidenceTime, } if c.valid { - assert.Nil(t, evidence.VerifyDuplicateVote(ev, chainID, valSet), "evidence should be valid") + require.NoError(t, evidence.VerifyDuplicateVote(ev, chainID, valSet), "evidence should be valid") } else { - assert.NotNil(t, evidence.VerifyDuplicateVote(ev, chainID, valSet), "evidence should be invalid") + require.Error(t, evidence.VerifyDuplicateVote(ev, chainID, valSet), "evidence should be invalid") } } @@ -441,25 +430,27 @@ func TestVerifyDuplicateVoteEvidence(t *testing.T) { evList := types.EvidenceList{goodEv} err = pool.CheckEvidence(evList) - assert.NoError(t, err) + require.NoError(t, err) // evidence with a different validator power should fail evList = types.EvidenceList{badEv} err = pool.CheckEvidence(evList) - assert.Error(t, err) + require.Error(t, err) // evidence with a different timestamp should fail evList = types.EvidenceList{badTimeEv} err = pool.CheckEvidence(evList) - assert.Error(t, err) + require.Error(t, err) } func makeLunaticEvidence( t *testing.T, height, commonHeight int64, - totalVals, byzVals, phantomVals int, + byzVals, phantomVals int, commonTime, attackTime time.Time, ) (ev *types.LightClientAttackEvidence, trusted *types.LightBlock, common *types.LightBlock) { + t.Helper() + totalVals := 10 commonValSet, commonPrivVals := types.RandValidatorSet(totalVals, defaultVotingPower) require.Greater(t, totalVals, byzVals) @@ -484,7 +475,7 @@ func makeLunaticEvidence( conflictingHeader.ValidatorsHash = conflictingVals.Hash() blockID := makeBlockID(conflictingHeader.Hash(), 1000, []byte("partshash")) - voteSet := types.NewVoteSet(evidenceChainID, height, 1, cmtproto.SignedMsgType(2), conflictingVals) + voteSet := types.NewVoteSet(evidenceChainID, height, 1, types.SignedMsgType(2), conflictingVals) commit, err := test.MakeCommitFromVoteSet(blockID, voteSet, conflictingPrivVals, defaultEvidenceTime) require.NoError(t, err) ev = &types.LightClientAttackEvidence{ @@ -511,7 +502,7 @@ func makeLunaticEvidence( } trustedBlockID := makeBlockID(trustedHeader.Hash(), 1000, []byte("partshash")) trustedVals, privVals := types.RandValidatorSet(totalVals, defaultVotingPower) - trustedVoteSet := types.NewVoteSet(evidenceChainID, height, 1, cmtproto.SignedMsgType(2), trustedVals) + trustedVoteSet := types.NewVoteSet(evidenceChainID, height, 1, types.SignedMsgType(2), trustedVals) trustedCommit, err := test.MakeCommitFromVoteSet(trustedBlockID, trustedVoteSet, privVals, defaultEvidenceTime) require.NoError(t, err) trusted = &types.LightBlock{ @@ -570,6 +561,7 @@ func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.Bloc func orderPrivValsByValSet( t *testing.T, vals *types.ValidatorSet, privVals []types.PrivValidator, ) []types.PrivValidator { + t.Helper() output := make([]types.PrivValidator, len(privVals)) for idx, v := range vals.Validators { for _, p := range privVals { diff --git a/libs/fail/fail.go b/internal/fail/fail.go similarity index 94% rename from libs/fail/fail.go rename to internal/fail/fail.go index 38cec9a2969..70b8e169c54 100644 --- a/libs/fail/fail.go +++ b/internal/fail/fail.go @@ -22,7 +22,7 @@ func envSet() int { return callIndexToFail } -// Fail when FAIL_TEST_INDEX == callIndex +// Fail when FAIL_TEST_INDEX == callIndex. var callIndex int // indexes Fail calls func Fail() { diff --git a/libs/flowrate/README.md b/internal/flowrate/README.md similarity index 100% rename from libs/flowrate/README.md rename to internal/flowrate/README.md diff --git a/libs/flowrate/flowrate.go b/internal/flowrate/flowrate.go similarity index 99% rename from libs/flowrate/flowrate.go rename to internal/flowrate/flowrate.go index 23252f4e333..ccb431384a1 100644 --- a/libs/flowrate/flowrate.go +++ b/internal/flowrate/flowrate.go @@ -10,7 +10,7 @@ import ( "math" "time" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) // Monitor monitors and limits the transfer rate of a data stream. @@ -221,7 +221,7 @@ func (m *Monitor) SetTransferSize(bytes int64) { // sample is done. func (m *Monitor) update(n int) (now time.Duration) { if !m.active { - return + return now } if now = clock(); n > 0 { m.tLast = now @@ -243,7 +243,7 @@ func (m *Monitor) update(n int) (now time.Duration) { } m.reset(now) } - return + return now } // reset clears the current sample state in preparation for the next sample. diff --git a/libs/flowrate/io.go b/internal/flowrate/io.go similarity index 96% rename from libs/flowrate/io.go rename to internal/flowrate/io.go index fbe0909725a..fdcb6dad841 100644 --- a/libs/flowrate/io.go +++ b/internal/flowrate/io.go @@ -46,14 +46,14 @@ func (r *Reader) Read(p []byte) (n int, err error) { if len(p) > 0 { n, err = r.IO(r.Reader.Read(p)) } - return + return n, err } // SetLimit changes the transfer rate limit to new bytes per second and returns // the previous setting. func (r *Reader) SetLimit(new int64) (old int64) { old, r.limit = r.limit, new - return + return old } // SetBlocking changes the blocking behavior and returns the previous setting. A @@ -61,7 +61,7 @@ func (r *Reader) SetLimit(new int64) (old int64) { // may be read at this time due to the rate limit. func (r *Reader) SetBlocking(new bool) (old bool) { old, r.block = r.block, new - return + return old } // Close closes the underlying reader if it implements the io.Closer interface. @@ -97,22 +97,21 @@ func (w *Writer) Write(p []byte) (n int, err error) { var c int for len(p) > 0 && err == nil { s := p[:w.Limit(len(p), w.limit, w.block)] - if len(s) > 0 { - c, err = w.IO(w.Writer.Write(s)) - } else { + if len(s) == 0 { return n, ErrLimit } + c, err = w.IO(w.Writer.Write(s)) p = p[c:] n += c } - return + return n, err } // SetLimit changes the transfer rate limit to new bytes per second and returns // the previous setting. func (w *Writer) SetLimit(new int64) (old int64) { old, w.limit = w.limit, new - return + return old } // SetBlocking changes the blocking behavior and returns the previous setting. A @@ -120,7 +119,7 @@ func (w *Writer) SetLimit(new int64) (old int64) { // may be written at this time due to the rate limit. func (w *Writer) SetBlocking(new bool) (old bool) { old, w.block = w.block, new - return + return old } // Close closes the underlying writer if it implements the io.Closer interface. diff --git a/libs/flowrate/io_test.go b/internal/flowrate/io_test.go similarity index 52% rename from libs/flowrate/io_test.go rename to internal/flowrate/io_test.go index 4d7de417e46..e5c2f2a6229 100644 --- a/libs/flowrate/io_test.go +++ b/internal/flowrate/io_test.go @@ -99,93 +99,125 @@ func TestReader(t *testing.T) { } } +// TestWriter tests the behavior of the Writer in the flowrate package. +// It verifies that the Writer correctly implements the Limiter interface, +// and that it correctly reports its status after writing data. func TestWriter(t *testing.T) { - b := make([]byte, 100) + const bufferSize = 100 + const limit = 200 + const writeSize = 20 + const remainingSize = 80 + const transferSize = 100 + + // Initialize a buffer with sequential bytes + b := make([]byte, bufferSize) for i := range b { b[i] = byte(i) } - w := NewWriter(&bytes.Buffer{}, 200) - start := time.Now() - // Make sure w implements Limiter - _ = Limiter(w) - - // Non-blocking 20-byte write for the first sample returns ErrLimit - w.SetBlocking(false) - if n, err := w.Write(b); n != 20 || err != ErrLimit { - t.Fatalf("w.Write(b) expected 20 (ErrLimit); got %v (%v)", n, err) - } else if rt := time.Since(start); rt > _50ms { - t.Fatalf("w.Write(b) took too long (%v)", rt) - } + // Create a new Writer with a limit of 200 bytes per second + w := NewWriter(&bytes.Buffer{}, limit) + start := time.Now() - // Blocking 80-byte write - w.SetBlocking(true) - if n, err := w.Write(b[20:]); n != 80 || err != nil { - t.Fatalf("w.Write(b[20:]) expected 80 (); got %v (%v)", n, err) - } else if rt := time.Since(start); rt < _300ms { - // Explanation for `rt < _300ms` (as opposed to `< _400ms`) + // Subtest to verify that the Writer implements the Limiter interface + t.Run("implements limiter interface", func(t *testing.T) { + _, ok := any(w).(Limiter) + if !ok { + t.Fatalf("Expected Writer to implement Limiter interface") + } + }) + + // Subtest for non-blocking write + t.Run("non-blocking write", func(t *testing.T) { + w.SetBlocking(false) + n, err := w.Write(b) + if n != writeSize || err != ErrLimit { + t.Fatalf("w.Write(b) expected %d (ErrLimit); got %v (%v)", writeSize, n, err) + } + if rt := time.Since(start); rt > _50ms { + t.Fatalf("w.Write(b) took too long (%v)", rt) + } + }) + + // Subtest for blocking write + t.Run("blocking write", func(t *testing.T) { + w.SetBlocking(true) + n, err := w.Write(b[writeSize:]) + if n != remainingSize || err != nil { + t.Fatalf("w.Write(b[%d:]) expected %d (); got %v (%v)", writeSize, remainingSize, n, err) + } + // Explanation for `rt < _300ms` (as opposed to `< _500ms`) // - // |<-- start | | - // epochs: -----0ms|---100ms|---200ms|---300ms|---400ms - // sends: 20|20 |20 |20 |20# + // |<-- start | | | // - // NOTE: The '#' symbol can thus happen before 400ms is up. + // epochs: -----0ms|---100ms|---200ms|---300ms|---400ms|---500ms + // sends: 20|20 |20 |20 |20 |20# + // + // NOTE: The '#' symbol can thus happen before 500ms is up. // Thus, we can only panic if rt < _300ms. - t.Fatalf("w.Write(b[20:]) returned ahead of time (%v)", rt) - } - - w.SetTransferSize(100) - status := []Status{w.Status(), nextStatus(w.Monitor)} - start = status[0].Start + if rt := time.Since(start); rt < _300ms || rt > _500ms { + t.Fatalf("w.Write(b[%d:]) returned at unexpected time (%v)", writeSize, rt) + } + }) + + // Subtest for setting transfer size + t.Run("setting transfer size", func(t *testing.T) { + w.SetTransferSize(transferSize) + status := []Status{w.Status(), nextStatus(w.Monitor)} + start = status[0].Start + + // Define expected statuses + want := []Status{ + {start, remainingSize, 4, limit, limit, limit, limit, writeSize, _400ms, 0, _100ms, 80000, true}, + {start, bufferSize, 5, limit, limit, limit, limit, 0, _500ms, _100ms, 0, 100000, true}, + } - // Active, Bytes, Samples, InstRate, CurRate, AvgRate, PeakRate, BytesRem, Start, Duration, Idle, TimeRem, Progress - want := []Status{ - {start, 80, 4, 200, 200, 200, 200, 20, _400ms, 0, _100ms, 80000, true}, - {start, 100, 5, 200, 200, 200, 200, 0, _500ms, _100ms, 0, 100000, true}, - } + // Compare actual and expected statuses + for i, s := range status { + if !statusesAreEqual(&s, &want[i]) { + t.Errorf("w.Status(%v)\nexpected: %v\ngot : %v\n", i, want[i], s) + } + } + }) - for i, s := range status { - s := s - if !statusesAreEqual(&s, &want[i]) { - t.Errorf("w.Status(%v)\nexpected: %v\ngot : %v\n", i, want[i], s) + // Subtest to verify that the written data matches the input + t.Run("written data matches input", func(t *testing.T) { + if !bytes.Equal(b, w.Writer.(*bytes.Buffer).Bytes()) { + t.Errorf("w.Write() input doesn't match output") } - } - if !bytes.Equal(b, w.Writer.(*bytes.Buffer).Bytes()) { - t.Errorf("w.Write() input doesn't match output") - } + }) } -const maxDeviationForDuration = 50 * time.Millisecond -const maxDeviationForRate int64 = 50 - // statusesAreEqual returns true if s1 is equal to s2. Equality here means // general equality of fields except for the duration and rates, which can // drift due to unpredictable delays (e.g. thread wakes up 25ms after // `time.Sleep` has ended). func statusesAreEqual(s1 *Status, s2 *Status) bool { if s1.Active == s2.Active && - s1.Start == s2.Start && - durationsAreEqual(s1.Duration, s2.Duration, maxDeviationForDuration) && - s1.Idle == s2.Idle && + s1.Start.Equal(s2.Start) && + durationsAreEqual(s1.Duration, s2.Duration) && + durationsAreEqual(s1.Idle, s2.Idle) && s1.Bytes == s2.Bytes && s1.Samples == s2.Samples && - ratesAreEqual(s1.InstRate, s2.InstRate, maxDeviationForRate) && - ratesAreEqual(s1.CurRate, s2.CurRate, maxDeviationForRate) && - ratesAreEqual(s1.AvgRate, s2.AvgRate, maxDeviationForRate) && - ratesAreEqual(s1.PeakRate, s2.PeakRate, maxDeviationForRate) && + ratesAreEqual(s1.InstRate, s2.InstRate) && + ratesAreEqual(s1.CurRate, s2.CurRate) && + ratesAreEqual(s1.AvgRate, s2.AvgRate) && + ratesAreEqual(s1.PeakRate, s2.PeakRate) && s1.BytesRem == s2.BytesRem && - durationsAreEqual(s1.TimeRem, s2.TimeRem, maxDeviationForDuration) && + durationsAreEqual(s1.TimeRem, s2.TimeRem) && s1.Progress == s2.Progress { return true } return false } -func durationsAreEqual(d1 time.Duration, d2 time.Duration, maxDeviation time.Duration) bool { +func durationsAreEqual(d1 time.Duration, d2 time.Duration) bool { + const maxDeviation = 50 * time.Millisecond return d2-d1 <= maxDeviation } -func ratesAreEqual(r1 int64, r2 int64, maxDeviation int64) bool { +func ratesAreEqual(r1 int64, r2 int64) bool { + const maxDeviation = int64(50) sub := r1 - r2 if sub < 0 { sub = -sub diff --git a/libs/flowrate/util.go b/internal/flowrate/util.go similarity index 98% rename from libs/flowrate/util.go rename to internal/flowrate/util.go index b33ddc70138..ab931d970fb 100644 --- a/libs/flowrate/util.go +++ b/internal/flowrate/util.go @@ -29,6 +29,7 @@ func clockToTime(c time.Duration) time.Time { // clockRound returns d rounded to the nearest clockRate increment. func clockRound(d time.Duration) time.Duration { + //nolint:durationcheck return (d + clockRate>>1) / clockRate * clockRate } diff --git a/internal/indexer/indexer_utils.go b/internal/indexer/indexer_utils.go new file mode 100644 index 00000000000..f6a5418d21e --- /dev/null +++ b/internal/indexer/indexer_utils.go @@ -0,0 +1,118 @@ +package indexer + +import ( + "fmt" + "math/big" + + "github.com/cometbft/cometbft/internal/state/indexer" +) + +// If the actual event value is a float, we get the condition and parse it as a float +// to compare against. +func compareFloat(op1 *big.Float, op2 any) (int, bool, error) { + switch opVal := op2.(type) { + case *big.Int: + vF := new(big.Float) + vF.SetInt(opVal) + cmp := op1.Cmp(vF) + return cmp, false, nil + + case *big.Float: + return op1.Cmp(opVal), true, nil + default: + return -1, false, fmt.Errorf("unable to parse arguments, bad type: %T", op2) + } +} + +// If the event value we compare against the condition (op2) is an integer +// we convert the int to float with a precision equal to the number of bits +// needed to represent the integer to avoid rounding issues with floats +// where 100 would equal to 100.2 because 100.2 is rounded to 100, while 100.7 +// would be rounded to 101. +func compareInt(op1 *big.Int, op2 any) (int, bool, error) { + switch opVal := op2.(type) { + case *big.Int: + return op1.Cmp(opVal), false, nil + case *big.Float: + vF := new(big.Float) + vF.SetInt(op1) + return vF.Cmp(opVal), true, nil + default: + return -1, false, fmt.Errorf("unable to parse arguments, unexpected type: %T", op2) + } +} + +func CheckBounds(ranges indexer.QueryRange, v any) (bool, error) { + // These functions fetch the lower and upper bounds of the query + // It is expected that for x > 5, the value of lowerBound is 6. + // This is achieved by adding one to the actual lower bound. + // For a query of x < 5, the value of upper bound is 4. + // This is achieved by subtracting one from the actual upper bound. + + // For integers this behavior will work. However, for floats, we cannot simply add/sub 1. + // Query :x < 5.5 ; x = 5 should match the query. If we subtracted one as for integers, + // the upperBound would be 4.5 and x would not match. Thus we do not subtract anything for + // floating point bounds. + + // We can rewrite these functions to not add/sub 1 but the function handles also time arguments. + // To be sure we are not breaking existing queries that compare time, and as we are planning to replace + // the indexer in the future, we adapt the code here to handle floats as a special case. + lowerBound := ranges.LowerBoundValue() + upperBound := ranges.UpperBoundValue() + + // *Explanation for the isFloat condition below.* + // In LowerBoundValue(), for floating points, we cannot simply add 1 due to the reasons explained in + // the comment at the beginning. The same is true for subtracting one for UpperBoundValue(). + // That means that for integers, if the condition is >=, cmp will be either 0 or 1 + // ( cmp == -1 should always be false). + // But if the lowerBound is a float, we have not subtracted one, so returning a 0 + // is correct only if ranges.IncludeLowerBound is true. + // example int: x < 100; upperBound = 99; if x.Cmp(99) == 0 the condition holds + // example float: x < 100.0; upperBound = 100.0; if x.Cmp(100) ==0 then returning x + // would be wrong. + switch vVal := v.(type) { + case *big.Int: + if lowerBound != nil { + cmp, isFloat, err := compareInt(vVal, lowerBound) + if err != nil { + return false, err + } + if cmp == -1 || (isFloat && cmp == 0 && !ranges.IncludeLowerBound) { + return false, err + } + } + if upperBound != nil { + cmp, isFloat, err := compareInt(vVal, upperBound) + if err != nil { + return false, err + } + if cmp == 1 || (isFloat && cmp == 0 && !ranges.IncludeUpperBound) { + return false, err + } + } + + case *big.Float: + if lowerBound != nil { + cmp, isFloat, err := compareFloat(vVal, lowerBound) + if err != nil { + return false, err + } + if cmp == -1 || (cmp == 0 && isFloat && !ranges.IncludeLowerBound) { + return false, err + } + } + if upperBound != nil { + cmp, isFloat, err := compareFloat(vVal, upperBound) + if err != nil { + return false, err + } + if cmp == 1 || (cmp == 0 && isFloat && !ranges.IncludeUpperBound) { + return false, err + } + } + + default: + return false, fmt.Errorf("invalid argument type in query: %T", v) + } + return true, nil +} diff --git a/inspect/doc.go b/internal/inspect/doc.go similarity index 100% rename from inspect/doc.go rename to internal/inspect/doc.go diff --git a/inspect/inspect.go b/internal/inspect/inspect.go similarity index 83% rename from inspect/inspect.go rename to internal/inspect/inspect.go index b09faa23eed..4d5e8d28c42 100644 --- a/inspect/inspect.go +++ b/internal/inspect/inspect.go @@ -6,24 +6,22 @@ import ( "net" "os" + "golang.org/x/sync/errgroup" + "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/inspect/rpc" + "github.com/cometbft/cometbft/internal/inspect/rpc" + "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/indexer/block" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/internal/store" + cmtstrings "github.com/cometbft/cometbft/internal/strings" "github.com/cometbft/cometbft/libs/log" - cmtstrings "github.com/cometbft/cometbft/libs/strings" rpccore "github.com/cometbft/cometbft/rpc/core" - "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/state/indexer/block" - "github.com/cometbft/cometbft/state/txindex" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" - - "golang.org/x/sync/errgroup" ) -var ( - logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) -) +var logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) // Inspector manages an RPC service that exports methods to debug a failed node. // After a node shuts down due to a consensus failure, it will no longer start @@ -49,8 +47,14 @@ type Inspector struct { // The sinks are used to enable block and transaction querying via the RPC server. // The caller is responsible for starting and stopping the Inspector service. // -//nolint:lll -func New(cfg *config.RPCConfig, bs state.BlockStore, ss state.Store, txidx txindex.TxIndexer, blkidx indexer.BlockIndexer, lg log.Logger) *Inspector { + +func New( + cfg *config.RPCConfig, + bs state.BlockStore, + ss state.Store, + txidx txindex.TxIndexer, + blkidx indexer.BlockIndexer, +) *Inspector { routes := rpc.Routes(*cfg, ss, bs, txidx, blkidx, logger) eb := types.NewEventBus() eb.SetLogger(logger.With("module", "events")) @@ -69,7 +73,7 @@ func NewFromConfig(cfg *config.Config) (*Inspector, error) { if err != nil { return nil, err } - bs := store.NewBlockStore(bsDB) + bs := store.NewBlockStore(bsDB, store.WithDBKeyLayout(cfg.Storage.ExperimentalKeyLayout)) sDB, err := config.DefaultDBProvider(&config.DBContext{ID: "state", Config: cfg}) if err != nil { return nil, err @@ -82,9 +86,8 @@ func NewFromConfig(cfg *config.Config) (*Inspector, error) { if err != nil { return nil, err } - lg := logger.With("module", "inspect") ss := state.NewStore(sDB, state.StoreOptions{}) - return New(cfg.RPC, bs, ss, txidx, blkidx, lg), nil + return New(cfg.RPC, bs, ss, txidx, blkidx), nil } // Run starts the Inspector servers and blocks until the servers shut down. The passed diff --git a/inspect/inspect_test.go b/internal/inspect/inspect_test.go similarity index 85% rename from inspect/inspect_test.go rename to internal/inspect/inspect_test.go index 69aa9f7a082..3cfd6e1ae59 100644 --- a/inspect/inspect_test.go +++ b/internal/inspect/inspect_test.go @@ -10,20 +10,20 @@ import ( "testing" "time" + "github.com/fortytw2/leaktest" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + abcitypes "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/inspect" + "github.com/cometbft/cometbft/internal/inspect" + "github.com/cometbft/cometbft/internal/pubsub/query" + indexermocks "github.com/cometbft/cometbft/internal/state/indexer/mocks" + statemocks "github.com/cometbft/cometbft/internal/state/mocks" + txindexmocks "github.com/cometbft/cometbft/internal/state/txindex/mocks" "github.com/cometbft/cometbft/internal/test" - "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/pubsub/query" httpclient "github.com/cometbft/cometbft/rpc/client/http" - indexermocks "github.com/cometbft/cometbft/state/indexer/mocks" - statemocks "github.com/cometbft/cometbft/state/mocks" - txindexmocks "github.com/cometbft/cometbft/state/txindex/mocks" "github.com/cometbft/cometbft/types" - "github.com/fortytw2/leaktest" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" ) func TestInspectConstructor(t *testing.T) { @@ -35,7 +35,6 @@ func TestInspectConstructor(t *testing.T) { require.NoError(t, err) require.NotNil(t, d) }) - } func TestInspectRun(t *testing.T) { @@ -55,7 +54,6 @@ func TestInspectRun(t *testing.T) { cancel() stoppedWG.Wait() }) - } func TestBlock(t *testing.T) { @@ -69,16 +67,14 @@ func TestBlock(t *testing.T) { blockStoreMock := &statemocks.BlockStore{} blockStoreMock.On("Height").Return(testHeight) blockStoreMock.On("Base").Return(int64(0)) - blockStoreMock.On("LoadBlockMeta", testHeight).Return(&types.BlockMeta{}) - blockStoreMock.On("LoadBlock", testHeight).Return(testBlock) + blockStoreMock.On("LoadBlock", testHeight).Return(testBlock, &types.BlockMeta{}) blockStoreMock.On("Close").Return(nil) txIndexerMock := &txindexmocks.TxIndexer{} blkIdxMock := &indexermocks.BlockIndexer{} rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} wg.Add(1) @@ -93,8 +89,8 @@ func TestBlock(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) resultBlock, err := cli.Block(context.Background(), &testHeight) require.NoError(t, err) @@ -130,8 +126,7 @@ func TestTxSearch(t *testing.T) { Return([]*abcitypes.TxResult{testTxResult}, nil) rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} wg.Add(1) @@ -146,11 +141,11 @@ func TestTxSearch(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) - var page = 1 + page := 1 resultTxSearch, err := cli.TxSearch(context.Background(), testQuery, false, &page, &page, "") require.NoError(t, err) require.Len(t, resultTxSearch.Txs, 1) @@ -163,6 +158,7 @@ func TestTxSearch(t *testing.T) { stateStoreMock.AssertExpectations(t) blockStoreMock.AssertExpectations(t) } + func TestTx(t *testing.T) { testHash := []byte("test") testTx := []byte("tx") @@ -178,8 +174,7 @@ func TestTx(t *testing.T) { }, nil) rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} wg.Add(1) @@ -194,8 +189,8 @@ func TestTx(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) res, err := cli.Tx(context.Background(), testHash, false) @@ -209,6 +204,7 @@ func TestTx(t *testing.T) { stateStoreMock.AssertExpectations(t) blockStoreMock.AssertExpectations(t) } + func TestConsensusParams(t *testing.T) { testHeight := int64(1) testMaxGas := int64(55) @@ -226,8 +222,7 @@ func TestConsensusParams(t *testing.T) { txIndexerMock := &txindexmocks.TxIndexer{} blkIdxMock := &indexermocks.BlockIndexer{} rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} @@ -243,8 +238,8 @@ func TestConsensusParams(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) params, err := cli.ConsensusParams(context.Background(), &testHeight) require.NoError(t, err) @@ -262,8 +257,8 @@ func TestBlockResults(t *testing.T) { testGasUsed := int64(100) stateStoreMock := &statemocks.Store{} stateStoreMock.On("Close").Return(nil) - // cmtstate "github.com/cometbft/cometbft/proto/tendermint/state" - stateStoreMock.On("LoadFinalizeBlockResponse", testHeight).Return(&abcitypes.ResponseFinalizeBlock{ + // cmtstate "github.com/cometbft/cometbft/api/cometbft/state/v1" + stateStoreMock.On("LoadFinalizeBlockResponse", testHeight).Return(&abcitypes.FinalizeBlockResponse{ TxResults: []*abcitypes.ExecTxResult{ { GasUsed: testGasUsed, @@ -277,8 +272,7 @@ func TestBlockResults(t *testing.T) { txIndexerMock := &txindexmocks.TxIndexer{} blkIdxMock := &indexermocks.BlockIndexer{} rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} @@ -294,12 +288,12 @@ func TestBlockResults(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) res, err := cli.BlockResults(context.Background(), &testHeight) require.NoError(t, err) - require.Equal(t, res.TxsResults[0].GasUsed, testGasUsed) + require.Equal(t, res.TxResults[0].GasUsed, testGasUsed) cancel() wg.Wait() @@ -325,8 +319,7 @@ func TestCommit(t *testing.T) { txIndexerMock := &txindexmocks.TxIndexer{} blkIdxMock := &indexermocks.BlockIndexer{} rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} @@ -342,8 +335,8 @@ func TestCommit(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) res, err := cli.Commit(context.Background(), &testHeight) require.NoError(t, err) @@ -367,7 +360,7 @@ func TestBlockByHash(t *testing.T) { stateStoreMock.On("Close").Return(nil) blockStoreMock := &statemocks.BlockStore{} blockStoreMock.On("Close").Return(nil) - blockStoreMock.On("LoadBlockMeta", testHeight).Return(&types.BlockMeta{ + blockStoreMock.On("LoadBlockByHash", testHash).Return(testBlock, &types.BlockMeta{ BlockID: types.BlockID{ Hash: testHash, }, @@ -375,12 +368,10 @@ func TestBlockByHash(t *testing.T) { Height: testHeight, }, }, nil) - blockStoreMock.On("LoadBlockByHash", testHash).Return(testBlock, nil) txIndexerMock := &txindexmocks.TxIndexer{} blkIdxMock := &indexermocks.BlockIndexer{} rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} @@ -396,8 +387,8 @@ func TestBlockByHash(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) res, err := cli.BlockByHash(context.Background(), testHash) require.NoError(t, err) @@ -432,8 +423,7 @@ func TestBlockchain(t *testing.T) { txIndexerMock := &txindexmocks.TxIndexer{} blkIdxMock := &indexermocks.BlockIndexer{} rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} @@ -449,8 +439,8 @@ func TestBlockchain(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) res, err := cli.BlockchainInfo(context.Background(), 0, 100) require.NoError(t, err) @@ -485,8 +475,7 @@ func TestValidators(t *testing.T) { txIndexerMock := &txindexmocks.TxIndexer{} blkIdxMock := &indexermocks.BlockIndexer{} rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} @@ -502,8 +491,8 @@ func TestValidators(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) testPage := 1 @@ -536,18 +525,16 @@ func TestBlockSearch(t *testing.T) { Header: types.Header{ Height: testHeight, }, - }, nil) - blockStoreMock.On("LoadBlockMeta", testHeight).Return(&types.BlockMeta{ + }, &types.BlockMeta{ BlockID: types.BlockID{ Hash: testBlockHash, }, - }) + }, nil) blkIdxMock.On("Search", mock.Anything, mock.MatchedBy(func(q *query.Query) bool { return testQuery == q.String() })). Return([]int64{testHeight}, nil) rpcConfig := config.TestRPCConfig() - l := log.TestingLogger() - d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock, l) + d := inspect.New(rpcConfig, blockStoreMock, stateStoreMock, txIndexerMock, blkIdxMock) ctx, cancel := context.WithCancel(context.Background()) wg := &sync.WaitGroup{} @@ -563,8 +550,8 @@ func TestBlockSearch(t *testing.T) { // FIXME: used to induce context switch. // Determine more deterministic method for prompting a context switch startedWG.Wait() - requireConnect(t, rpcConfig.ListenAddress, 20) - cli, err := httpclient.New(rpcConfig.ListenAddress, "/websocket") + requireConnect(t, rpcConfig.ListenAddress) + cli, err := httpclient.New(rpcConfig.ListenAddress + "/v1") require.NoError(t, err) testPage := 1 @@ -582,10 +569,12 @@ func TestBlockSearch(t *testing.T) { stateStoreMock.AssertExpectations(t) } -func requireConnect(t testing.TB, addr string, retries int) { +func requireConnect(tb testing.TB, addr string) { + tb.Helper() + retries := 20 parts := strings.SplitN(addr, "://", 2) if len(parts) != 2 { - t.Fatalf("malformed address to dial: %s", addr) + tb.Fatalf("malformed address to dial: %s", addr) } var err error for i := 0; i < retries; i++ { @@ -598,5 +587,5 @@ func requireConnect(t testing.TB, addr string, retries int) { // FIXME attempt to yield and let the other goroutine continue execution. time.Sleep(time.Microsecond * 100) } - t.Fatalf("unable to connect to server %s after %d tries: %s", addr, retries, err) + tb.Fatalf("unable to connect to server %s after %d tries: %s", addr, retries, err) } diff --git a/inspect/rpc/rpc.go b/internal/inspect/rpc/rpc.go similarity index 95% rename from inspect/rpc/rpc.go rename to internal/inspect/rpc/rpc.go index 4367ade2d59..331b5251318 100644 --- a/inspect/rpc/rpc.go +++ b/internal/inspect/rpc/rpc.go @@ -8,12 +8,12 @@ import ( "github.com/rs/cors" "github.com/cometbft/cometbft/config" + "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/txindex" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/rpc/core" "github.com/cometbft/cometbft/rpc/jsonrpc/server" - "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/state/txindex" ) // Server defines parameters for running an Inspector rpc server. @@ -61,6 +61,7 @@ func Handler(rpcConfig *config.RPCConfig, routes core.RoutesMap, logger log.Logg server.ReadLimit(rpcConfig.MaxBodyBytes)) wm.SetLogger(wmLogger) mux.HandleFunc("/websocket", wm.WebsocketHandler) + mux.HandleFunc("/v1/websocket", wm.WebsocketHandler) server.RegisterRPCFuncs(mux, routes, logger) var rootHandler http.Handler = mux diff --git a/libs/net/net.go b/internal/net/net.go similarity index 72% rename from libs/net/net.go rename to internal/net/net.go index fa85256fa84..4ab83a4139d 100644 --- a/libs/net/net.go +++ b/internal/net/net.go @@ -1,6 +1,7 @@ package net import ( + "context" "net" "strings" ) @@ -13,11 +14,19 @@ func Connect(protoAddr string) (net.Conn, error) { return conn, err } +// ConnectContext dials the given address and returns a net.Conn, similarly to +// Connect, but honors the given context. +func ConnectContext(ctx context.Context, protoAddr string) (net.Conn, error) { + proto, addr := ProtocolAndAddress(protoAddr) + var d net.Dialer + return d.DialContext(ctx, proto, addr) +} + // ProtocolAndAddress splits an address into the protocol and address components. // For instance, "tcp://127.0.0.1:8080" will be split into "tcp" and "127.0.0.1:8080". // If the address has no protocol prefix, the default is "tcp". -func ProtocolAndAddress(listenAddr string) (string, string) { - protocol, address := "tcp", listenAddr +func ProtocolAndAddress(listenAddr string) (protocol, address string) { + protocol, address = "tcp", listenAddr parts := strings.SplitN(address, "://", 2) if len(parts) == 2 { protocol, address = parts[0], parts[1] diff --git a/libs/net/net_test.go b/internal/net/net_test.go similarity index 99% rename from libs/net/net_test.go rename to internal/net/net_test.go index 38cd58f6a24..975e4f6d0f7 100644 --- a/libs/net/net_test.go +++ b/internal/net/net_test.go @@ -7,7 +7,6 @@ import ( ) func TestProtocolAndAddress(t *testing.T) { - cases := []struct { fullAddr string proto string diff --git a/libs/os/os.go b/internal/os/os.go similarity index 98% rename from libs/os/os.go rename to internal/os/os.go index 334eaf4c896..e3f909a8a5b 100644 --- a/libs/os/os.go +++ b/internal/os/os.go @@ -12,7 +12,7 @@ import ( ) type logger interface { - Info(msg string, keyvals ...interface{}) + Info(msg string, keyvals ...any) } // TrapSignal catches the SIGTERM/SIGINT and executes cb function. After that it exits diff --git a/libs/os/os_test.go b/internal/os/os_test.go similarity index 85% rename from libs/os/os_test.go rename to internal/os/os_test.go index 4de51844423..540a509d0bf 100644 --- a/libs/os/os_test.go +++ b/internal/os/os_test.go @@ -2,7 +2,6 @@ package os import ( "bytes" - "fmt" "os" "path/filepath" "testing" @@ -21,7 +20,7 @@ func TestCopyFile(t *testing.T) { t.Fatal(err) } - copyfile := fmt.Sprintf("%s.copy", tmpfile.Name()) + copyfile := tmpfile.Name() + ".copy" if err := CopyFile(tmpfile.Name(), copyfile); err != nil { t.Fatal(err) } @@ -44,30 +43,30 @@ func TestEnsureDir(t *testing.T) { defer os.RemoveAll(tmp) // Should be possible to create a new directory. - err = EnsureDir(filepath.Join(tmp, "dir"), 0755) + err = EnsureDir(filepath.Join(tmp, "dir"), 0o755) require.NoError(t, err) require.DirExists(t, filepath.Join(tmp, "dir")) // Should succeed on existing directory. - err = EnsureDir(filepath.Join(tmp, "dir"), 0755) + err = EnsureDir(filepath.Join(tmp, "dir"), 0o755) require.NoError(t, err) // Should fail on file. - err = os.WriteFile(filepath.Join(tmp, "file"), []byte{}, 0644) + err = os.WriteFile(filepath.Join(tmp, "file"), []byte{}, 0o644) require.NoError(t, err) - err = EnsureDir(filepath.Join(tmp, "file"), 0755) + err = EnsureDir(filepath.Join(tmp, "file"), 0o755) require.Error(t, err) // Should allow symlink to dir. err = os.Symlink(filepath.Join(tmp, "dir"), filepath.Join(tmp, "linkdir")) require.NoError(t, err) - err = EnsureDir(filepath.Join(tmp, "linkdir"), 0755) + err = EnsureDir(filepath.Join(tmp, "linkdir"), 0o755) require.NoError(t, err) // Should error on symlink to file. err = os.Symlink(filepath.Join(tmp, "file"), filepath.Join(tmp, "linkfile")) require.NoError(t, err) - err = EnsureDir(filepath.Join(tmp, "linkfile"), 0755) + err = EnsureDir(filepath.Join(tmp, "linkfile"), 0o755) require.Error(t, err) } @@ -83,7 +82,7 @@ func TestTrickedTruncation(t *testing.T) { originalWALPath := filepath.Join(tmpDir, "wal") originalWALContent := []byte("I AM BECOME DEATH, DESTROYER OF ALL WORLDS!") - if err := os.WriteFile(originalWALPath, originalWALContent, 0755); err != nil { + if err := os.WriteFile(originalWALPath, originalWALContent, 0o755); err != nil { t.Fatal(err) } diff --git a/libs/progressbar/progressbar.go b/internal/progressbar/progressbar.go similarity index 97% rename from libs/progressbar/progressbar.go rename to internal/progressbar/progressbar.go index 072804c7625..bd3aa09c15c 100644 --- a/libs/progressbar/progressbar.go +++ b/internal/progressbar/progressbar.go @@ -36,6 +36,6 @@ func (bar *Bar) Play(cur int64) { fmt.Printf("\r[%-50s]%3d%% %8d/%d", bar.rate, bar.percent, bar.cur, bar.total) } -func (bar *Bar) Finish() { +func (*Bar) Finish() { fmt.Println() } diff --git a/libs/progressbar/progressbar_test.go b/internal/progressbar/progressbar_test.go similarity index 100% rename from libs/progressbar/progressbar_test.go rename to internal/progressbar/progressbar_test.go diff --git a/libs/protoio/io.go b/internal/protoio/io.go similarity index 96% rename from libs/protoio/io.go rename to internal/protoio/io.go index 6244afd97b6..d580f4b6a96 100644 --- a/libs/protoio/io.go +++ b/internal/protoio/io.go @@ -37,7 +37,7 @@ import ( ) type Writer interface { - WriteMsg(proto.Message) (int, error) + WriteMsg(msg proto.Message) (int, error) } type WriteCloser interface { @@ -58,7 +58,7 @@ type marshaler interface { MarshalTo(data []byte) (n int, err error) } -func getSize(v interface{}) (int, bool) { +func getSize(v any) (int, bool) { if sz, ok := v.(interface { Size() (n int) }); ok { @@ -67,9 +67,8 @@ func getSize(v interface{}) (int, bool) { ProtoSize() (n int) }); ok { return sz.ProtoSize(), true - } else { - return 0, false } + return 0, false } // byteReader wraps an io.Reader and implements io.ByteReader, required by diff --git a/libs/protoio/io_test.go b/internal/protoio/io_test.go similarity index 97% rename from libs/protoio/io_test.go rename to internal/protoio/io_test.go index c6d3c10654f..1565b7739de 100644 --- a/libs/protoio/io_test.go +++ b/internal/protoio/io_test.go @@ -41,7 +41,7 @@ import ( "github.com/cosmos/gogoproto/test" "github.com/stretchr/testify/require" - "github.com/cometbft/cometbft/libs/protoio" + "github.com/cometbft/cometbft/internal/protoio" ) func iotest(writer protoio.WriteCloser, reader protoio.ReadCloser) error { @@ -97,10 +97,7 @@ func iotest(writer protoio.WriteCloser, reader protoio.ReadCloser) error { if i != size { panic("not enough messages read") } - if err := reader.Close(); err != nil { - return err - } - return nil + return reader.Close() } type buffer struct { @@ -134,7 +131,7 @@ func TestVarintNoClose(t *testing.T) { require.NoError(t, err) } -// issue 32 +// issue 32. func TestVarintMaxSize(t *testing.T) { buf := newBuffer() writer := protoio.NewDelimitedWriter(buf) diff --git a/libs/protoio/reader.go b/internal/protoio/reader.go similarity index 100% rename from libs/protoio/reader.go rename to internal/protoio/reader.go diff --git a/libs/protoio/writer.go b/internal/protoio/writer.go similarity index 100% rename from libs/protoio/writer.go rename to internal/protoio/writer.go diff --git a/libs/pubsub/example_test.go b/internal/pubsub/example_test.go similarity index 87% rename from libs/pubsub/example_test.go rename to internal/pubsub/example_test.go index 33e9109861e..d6cf45a2c63 100644 --- a/libs/pubsub/example_test.go +++ b/internal/pubsub/example_test.go @@ -6,10 +6,9 @@ import ( "github.com/stretchr/testify/require" + "github.com/cometbft/cometbft/internal/pubsub" + "github.com/cometbft/cometbft/internal/pubsub/query" "github.com/cometbft/cometbft/libs/log" - - "github.com/cometbft/cometbft/libs/pubsub" - "github.com/cometbft/cometbft/libs/pubsub/query" ) func TestExample(t *testing.T) { diff --git a/libs/pubsub/pubsub.go b/internal/pubsub/pubsub.go similarity index 95% rename from libs/pubsub/pubsub.go rename to internal/pubsub/pubsub.go index c2a1ec060aa..239547337a5 100644 --- a/libs/pubsub/pubsub.go +++ b/internal/pubsub/pubsub.go @@ -38,8 +38,8 @@ import ( "errors" "fmt" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) type operation int @@ -81,7 +81,7 @@ type cmd struct { clientID string // publish - msg interface{} + msg any events map[string][]string } @@ -150,7 +150,8 @@ func (s *Server) Subscribe( ctx context.Context, clientID string, query Query, - outCapacity ...int) (*Subscription, error) { + outCapacity ...int, +) (*Subscription, error) { outCap := 1 if len(outCapacity) > 0 { if outCapacity[0] <= 0 { @@ -266,14 +267,14 @@ func (s *Server) NumClientSubscriptions(clientID string) int { // Publish publishes the given message. An error will be returned to the caller // if the context is canceled. -func (s *Server) Publish(ctx context.Context, msg interface{}) error { +func (s *Server) Publish(ctx context.Context, msg any) error { return s.PublishWithEvents(ctx, msg, make(map[string][]string)) } // PublishWithEvents publishes the given message with the set of events. The set // is matched with clients queries. If there is a match, the message is sent to // the client. -func (s *Server) PublishWithEvents(ctx context.Context, msg interface{}, events map[string][]string) error { +func (s *Server) PublishWithEvents(ctx context.Context, msg any, events map[string][]string) error { select { case s.cmds <- cmd{op: pub, msg: msg, events: events}: return nil @@ -289,7 +290,7 @@ func (s *Server) OnStop() { s.cmds <- cmd{op: shutdown} } -// NOTE: not goroutine safe +// NOTE: not goroutine safe. type state struct { // query string -> client -> subscription subscriptions map[string]map[string]*Subscription @@ -313,8 +314,8 @@ func (s *Server) OnStart() error { return nil } -// OnReset implements Service.OnReset -func (s *Server) OnReset() error { +// OnReset implements Service.OnReset. +func (*Server) OnReset() error { return nil } @@ -403,7 +404,7 @@ func (state *state) removeAll(reason error) { } } -func (state *state) send(msg interface{}, events map[string][]string) error { +func (state *state) send(msg any, events map[string][]string) error { for qStr, clientSubscriptions := range state.subscriptions { q := state.queries[qStr].q diff --git a/libs/pubsub/pubsub_test.go b/internal/pubsub/pubsub_test.go similarity index 91% rename from libs/pubsub/pubsub_test.go rename to internal/pubsub/pubsub_test.go index f14e9eff4a6..0db48203aad 100644 --- a/libs/pubsub/pubsub_test.go +++ b/internal/pubsub/pubsub_test.go @@ -10,10 +10,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/cometbft/cometbft/internal/pubsub" + "github.com/cometbft/cometbft/internal/pubsub/query" "github.com/cometbft/cometbft/libs/log" - - "github.com/cometbft/cometbft/libs/pubsub" - "github.com/cometbft/cometbft/libs/pubsub/query" ) const ( @@ -47,13 +46,13 @@ func TestSubscribe(t *testing.T) { defer close(published) err := s.Publish(ctx, "Quicksilver") - assert.NoError(t, err) + require.NoError(t, err) err = s.Publish(ctx, "Asylum") - assert.NoError(t, err) + require.NoError(t, err) err = s.Publish(ctx, "Ivan") - assert.NoError(t, err) + require.NoError(t, err) }() select { @@ -112,10 +111,10 @@ func TestSubscribeUnbuffered(t *testing.T) { defer close(published) err := s.Publish(ctx, "Ultron") - assert.NoError(t, err) + require.NoError(t, err) err = s.Publish(ctx, "Darkhawk") - assert.NoError(t, err) + require.NoError(t, err) }() select { @@ -206,7 +205,7 @@ func TestSubscribeDuplicateKeys(t *testing.T) { testCases := []struct { query string - expected interface{} + expected any }{ { "withdraw.rewards='17'", @@ -392,20 +391,21 @@ func TestBufferCapacity(t *testing.T) { ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond) defer cancel() err = s.Publish(ctx, "Ironclad") - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, context.DeadlineExceeded, err) } } -func Benchmark10Clients(b *testing.B) { benchmarkNClients(10, b) } -func Benchmark100Clients(b *testing.B) { benchmarkNClients(100, b) } -func Benchmark1000Clients(b *testing.B) { benchmarkNClients(1000, b) } +func Benchmark10Clients(b *testing.B) { benchmarkNClients(b, 10) } +func Benchmark100Clients(b *testing.B) { benchmarkNClients(b, 100) } +func Benchmark1000Clients(b *testing.B) { benchmarkNClients(b, 1000) } -func Benchmark10ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(10, b) } -func Benchmark100ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(100, b) } -func Benchmark1000ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(1000, b) } +func Benchmark10ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(b, 10) } +func Benchmark100ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(b, 100) } +func Benchmark1000ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(b, 1000) } -func benchmarkNClients(n int, b *testing.B) { +func benchmarkNClients(b *testing.B, n int) { + b.Helper() s := pubsub.NewServer() err := s.Start() require.NoError(b, err) @@ -450,7 +450,8 @@ func benchmarkNClients(n int, b *testing.B) { } } -func benchmarkNClientsOneQuery(n int, b *testing.B) { +func benchmarkNClientsOneQuery(b *testing.B, n int) { + b.Helper() s := pubsub.NewServer() err := s.Start() require.NoError(b, err) @@ -482,18 +483,21 @@ func benchmarkNClientsOneQuery(n int, b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - err = s.PublishWithEvents(ctx, "Gamora", map[string][]string{"abci.Account.Owner": {"Ivan"}, - "abci.Invoices.Number": {"1"}}) + err = s.PublishWithEvents(ctx, "Gamora", map[string][]string{ + "abci.Account.Owner": {"Ivan"}, + "abci.Invoices.Number": {"1"}, + }) require.NoError(b, err) } } // HELPERS -func assertReceive(t *testing.T, expected interface{}, ch <-chan pubsub.Message, msgAndArgs ...interface{}) { +func assertReceive(t *testing.T, expected any, ch <-chan pubsub.Message) { + t.Helper() select { case actual := <-ch: - assert.Equal(t, expected, actual.Data(), msgAndArgs...) + assert.Equal(t, expected, actual.Data()) case <-time.After(1 * time.Second): t.Errorf("expected to receive %v from the channel, got nothing after 1s", expected) debug.PrintStack() @@ -501,6 +505,7 @@ func assertReceive(t *testing.T, expected interface{}, ch <-chan pubsub.Message, } func assertCancelled(t *testing.T, subscription *pubsub.Subscription, err error) { + t.Helper() _, ok := <-subscription.Canceled() assert.False(t, ok) assert.Equal(t, err, subscription.Err()) diff --git a/libs/pubsub/query/.gitignore b/internal/pubsub/query/.gitignore similarity index 100% rename from libs/pubsub/query/.gitignore rename to internal/pubsub/query/.gitignore diff --git a/libs/pubsub/query/bench_test.go b/internal/pubsub/query/bench_test.go similarity index 92% rename from libs/pubsub/query/bench_test.go rename to internal/pubsub/query/bench_test.go index fcae0e00bd8..672321b34ee 100644 --- a/libs/pubsub/query/bench_test.go +++ b/internal/pubsub/query/bench_test.go @@ -3,7 +3,7 @@ package query_test import ( "testing" - "github.com/cometbft/cometbft/libs/pubsub/query" + "github.com/cometbft/cometbft/internal/pubsub/query" ) const testQuery = `tm.events.type='NewBlock' AND abci.account.name='Igor'` diff --git a/libs/pubsub/query/query.go b/internal/pubsub/query/query.go similarity index 80% rename from libs/pubsub/query/query.go rename to internal/pubsub/query/query.go index e1db675adc1..98438c68a97 100644 --- a/libs/pubsub/query/query.go +++ b/internal/pubsub/query/query.go @@ -10,13 +10,13 @@ package query import ( "fmt" + "math/big" "regexp" - "strconv" "strings" "time" "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query/syntax" + "github.com/cometbft/cometbft/internal/pubsub/query/syntax" ) // All is a query that matches all events. @@ -197,7 +197,7 @@ func compileCondition(cond syntax.Condition) (condition, error) { // Precompile the argument value matcher. argType := cond.Arg.Type - var argValue interface{} + var argValue any switch argType { case syntax.TString: @@ -218,13 +218,22 @@ func compileCondition(cond syntax.Condition) (condition, error) { return out, nil } -// TODO(creachadair): The existing implementation allows anything number shaped -// to be treated as a number. This preserves the parts of that behavior we had -// tests for, but we should probably get rid of that. +// We use this regex to support queries of the from "8atom", "6.5stake", +// which are actively used in production. +// The regex takes care of removing the non-number suffix. var extractNum = regexp.MustCompile(`^\d+(\.\d+)?`) -func parseNumber(s string) (float64, error) { - return strconv.ParseFloat(extractNum.FindString(s), 64) +func parseNumber(s string) (*big.Float, error) { + intVal := new(big.Int) + if _, ok := intVal.SetString(s, 10); !ok { + f, _, err := big.ParseFloat(extractNum.FindString(s), 10, 125, big.ToNearestEven) + if err != nil { + return nil, err + } + return f, err + } + f, _, err := big.ParseFloat(extractNum.FindString(s), 10, uint(intVal.BitLen()), big.ToNearestEven) + return f, err } // A map of operator ⇒ argtype ⇒ match-constructor. @@ -233,31 +242,31 @@ func parseNumber(s string) (float64, error) { // Disable the dupl lint for this map. The result isn't even correct. // //nolint:dupl -var opTypeMap = map[syntax.Token]map[syntax.Token]func(interface{}) func(string) bool{ +var opTypeMap = map[syntax.Token]map[syntax.Token]func(any) func(string) bool{ syntax.TContains: { - syntax.TString: func(v interface{}) func(string) bool { + syntax.TString: func(v any) func(string) bool { return func(s string) bool { return strings.Contains(s, v.(string)) } }, }, syntax.TEq: { - syntax.TString: func(v interface{}) func(string) bool { + syntax.TString: func(v any) func(string) bool { return func(s string) bool { return s == v.(string) } }, - syntax.TNumber: func(v interface{}) func(string) bool { + syntax.TNumber: func(v any) func(string) bool { return func(s string) bool { w, err := parseNumber(s) - return err == nil && w == v.(float64) + return err == nil && w.Cmp(v.(*big.Float)) == 0 } }, - syntax.TDate: func(v interface{}) func(string) bool { + syntax.TDate: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseDate(s) return err == nil && ts.Equal(v.(time.Time)) } }, - syntax.TTime: func(v interface{}) func(string) bool { + syntax.TTime: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseTime(s) return err == nil && ts.Equal(v.(time.Time)) @@ -265,19 +274,19 @@ var opTypeMap = map[syntax.Token]map[syntax.Token]func(interface{}) func(string) }, }, syntax.TLt: { - syntax.TNumber: func(v interface{}) func(string) bool { + syntax.TNumber: func(v any) func(string) bool { return func(s string) bool { w, err := parseNumber(s) - return err == nil && w < v.(float64) + return err == nil && w.Cmp(v.(*big.Float)) < 0 } }, - syntax.TDate: func(v interface{}) func(string) bool { + syntax.TDate: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseDate(s) return err == nil && ts.Before(v.(time.Time)) } }, - syntax.TTime: func(v interface{}) func(string) bool { + syntax.TTime: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseTime(s) return err == nil && ts.Before(v.(time.Time)) @@ -285,19 +294,19 @@ var opTypeMap = map[syntax.Token]map[syntax.Token]func(interface{}) func(string) }, }, syntax.TLeq: { - syntax.TNumber: func(v interface{}) func(string) bool { + syntax.TNumber: func(v any) func(string) bool { return func(s string) bool { w, err := parseNumber(s) - return err == nil && w <= v.(float64) + return err == nil && w.Cmp(v.(*big.Float)) <= 0 } }, - syntax.TDate: func(v interface{}) func(string) bool { + syntax.TDate: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseDate(s) return err == nil && !ts.After(v.(time.Time)) } }, - syntax.TTime: func(v interface{}) func(string) bool { + syntax.TTime: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseTime(s) return err == nil && !ts.After(v.(time.Time)) @@ -305,19 +314,19 @@ var opTypeMap = map[syntax.Token]map[syntax.Token]func(interface{}) func(string) }, }, syntax.TGt: { - syntax.TNumber: func(v interface{}) func(string) bool { + syntax.TNumber: func(v any) func(string) bool { return func(s string) bool { w, err := parseNumber(s) - return err == nil && w > v.(float64) + return err == nil && w.Cmp(v.(*big.Float)) > 0 } }, - syntax.TDate: func(v interface{}) func(string) bool { + syntax.TDate: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseDate(s) return err == nil && ts.After(v.(time.Time)) } }, - syntax.TTime: func(v interface{}) func(string) bool { + syntax.TTime: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseTime(s) return err == nil && ts.After(v.(time.Time)) @@ -325,19 +334,19 @@ var opTypeMap = map[syntax.Token]map[syntax.Token]func(interface{}) func(string) }, }, syntax.TGeq: { - syntax.TNumber: func(v interface{}) func(string) bool { + syntax.TNumber: func(v any) func(string) bool { return func(s string) bool { w, err := parseNumber(s) - return err == nil && w >= v.(float64) + return err == nil && w.Cmp(v.(*big.Float)) >= 0 } }, - syntax.TDate: func(v interface{}) func(string) bool { + syntax.TDate: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseDate(s) return err == nil && !ts.Before(v.(time.Time)) } }, - syntax.TTime: func(v interface{}) func(string) bool { + syntax.TTime: func(v any) func(string) bool { return func(s string) bool { ts, err := syntax.ParseTime(s) return err == nil && !ts.Before(v.(time.Time)) diff --git a/libs/pubsub/query/query_test.go b/internal/pubsub/query/query_test.go similarity index 63% rename from libs/pubsub/query/query_test.go rename to internal/pubsub/query/query_test.go index 68b270895ce..17fe1cbd1ae 100644 --- a/libs/pubsub/query/query_test.go +++ b/internal/pubsub/query/query_test.go @@ -11,9 +11,9 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub" - "github.com/cometbft/cometbft/libs/pubsub/query" - "github.com/cometbft/cometbft/libs/pubsub/query/syntax" + "github.com/cometbft/cometbft/internal/pubsub" + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/internal/pubsub/query/syntax" ) var _ pubsub.Query = (*query.Query)(nil) @@ -173,6 +173,104 @@ var apiTypeEvents = []types.Event{ }, } +func TestBigNumbers(t *testing.T) { + apiBigNumTest := map[string][]string{ + "big.value": { + "99999999999999999999", + }, + "big2.value": { + "18446744073709551615", // max(uint64) == 18446744073709551615 + }, + "big.floatvalue": { + "99999999999999999999.10", + }, + "big2.floatvalue": { + "18446744073709551615.6", // max(uint64) == 18446744073709551615 + }, + } + + testCases := []struct { + s string + events map[string][]string + matches bool + }{ + // Test cases for values that exceed the capacity if int64/float64. + { + `big.value >= 99999999999999999999`, + apiBigNumTest, + true, + }, + { + `big.value > 99999999999999999998`, + apiBigNumTest, + true, + }, + { + `big2.value <= 18446744073709551615`, + apiBigNumTest, true, + }, + { + `big.floatvalue >= 99999999999999999999`, + apiBigNumTest, + true, + }, + { + `big.floatvalue > 99999999999999999998.10`, + apiBigNumTest, + true, + }, + { + `big.floatvalue > 99999999999999999998`, + apiBigNumTest, + true, + }, + { + `big2.floatvalue <= 18446744073709551615.6`, + apiBigNumTest, + true, + }, + { + `big2.floatvalue <= 18446744073709551615.6`, + apiBigNumTest, + true, + }, + { + `big2.floatvalue >= 18446744073709551615`, + apiBigNumTest, + true, + }, + { + `big2.floatvalue >= 12.5`, + apiBigNumTest, + true, + }, + { + `big.value >= 10`, + apiBigNumTest, + true, + }, + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("%02d", i+1), func(t *testing.T) { + c, err := query.New(tc.s) + if err != nil { + t.Fatalf("NewCompiled %#q: unexpected error: %v", tc.s, err) + } + + got, err := c.Matches(tc.events) + if err != nil { + t.Errorf("Query: %#q\nInput: %+v\nMatches: got error %v", + tc.s, tc.events, err) + } + if got != tc.matches { + t.Errorf("Query: %#q\nInput: %+v\nMatches: got %v, want %v", + tc.s, tc.events, got, tc.matches) + } + }) + } +} + func TestCompiledMatches(t *testing.T) { var ( txDate = "2017-01-01" @@ -185,121 +283,201 @@ func TestCompiledMatches(t *testing.T) { events map[string][]string matches bool }{ - {`tm.events.type='NewBlock'`, + { + `tm.events.type='NewBlock'`, newTestEvents(`tm|events.type=NewBlock`), - true}, - {`tx.gas > 7`, + true, + }, + { + `tx.gas > 7`, newTestEvents(`tx|gas=8`), - true}, - {`transfer.amount > 7`, + true, + }, + { + `transfer.amount > 7`, newTestEvents(`transfer|amount=8stake`), - true}, - {`transfer.amount > 7`, + true, + }, + { + `transfer.amount > 7`, newTestEvents(`transfer|amount=8.045`), - true}, - {`transfer.amount > 7.043`, + true, + }, + { + `transfer.amount > 7.043`, newTestEvents(`transfer|amount=8.045stake`), - true}, - {`transfer.amount > 8.045`, + true, + }, + { + `transfer.amount > 8.045`, newTestEvents(`transfer|amount=8.045stake`), - false}, - {`tx.gas > 7 AND tx.gas < 9`, + false, + }, + { + `tx.gas > 7 AND tx.gas < 9`, newTestEvents(`tx|gas=8`), - true}, - {`body.weight >= 3.5`, + true, + }, + { + `body.weight >= 3.5`, newTestEvents(`body|weight=3.5`), - true}, - {`account.balance < 1000.0`, + true, + }, + { + `account.balance < 1000.0`, newTestEvents(`account|balance=900`), - true}, - {`apples.kg <= 4`, + true, + }, + { + `apples.kg <= 4`, newTestEvents(`apples|kg=4.0`), - true}, - {`body.weight >= 4.5`, + true, + }, + { + `body.weight >= 4.5`, newTestEvents(`body|weight=4.5`), - true}, - {`oranges.kg < 4 AND watermellons.kg > 10`, + true, + }, + { + `oranges.kg < 4 AND watermellons.kg > 10`, newTestEvents(`oranges|kg=3`, `watermellons|kg=12`), - true}, - {`peaches.kg < 4`, + true, + }, + { + `peaches.kg < 4`, newTestEvents(`peaches|kg=5`), - false}, - {`tx.date > DATE 2017-01-01`, + false, + }, + { + `tx.date > DATE 2017-01-01`, newTestEvents(`tx|date=` + time.Now().Format(syntax.DateFormat)), - true}, - {`tx.date = DATE 2017-01-01`, + true, + }, + { + `tx.date = DATE 2017-01-01`, newTestEvents(`tx|date=` + txDate), - true}, - {`tx.date = DATE 2018-01-01`, + true, + }, + { + `tx.date = DATE 2018-01-01`, newTestEvents(`tx|date=` + txDate), - false}, - {`tx.time >= TIME 2013-05-03T14:45:00Z`, + false, + }, + { + `tx.time >= TIME 2013-05-03T14:45:00Z`, newTestEvents(`tx|time=` + time.Now().Format(syntax.TimeFormat)), - true}, - {`tx.time = TIME 2013-05-03T14:45:00Z`, + true, + }, + { + `tx.time = TIME 2013-05-03T14:45:00Z`, newTestEvents(`tx|time=` + txTime), - false}, - {`abci.owner.name CONTAINS 'Igor'`, + false, + }, + { + `abci.owner.name CONTAINS 'Igor'`, newTestEvents(`abci|owner.name=Igor|owner.name=Ivan`), - true}, - {`abci.owner.name CONTAINS 'Igor'`, + true, + }, + { + `abci.owner.name CONTAINS 'Igor'`, newTestEvents(`abci|owner.name=Pavel|owner.name=Ivan`), - false}, - {`abci.owner.name = 'Igor'`, + false, + }, + { + `abci.owner.name = 'Igor'`, newTestEvents(`abci|owner.name=Igor|owner.name=Ivan`), - true}, - {`abci.owner.name = 'Ivan'`, + true, + }, + { + `abci.owner.name = 'Ivan'`, newTestEvents(`abci|owner.name=Igor|owner.name=Ivan`), - true}, - {`abci.owner.name = 'Ivan' AND abci.owner.name = 'Igor'`, + true, + }, + { + `abci.owner.name = 'Ivan' AND abci.owner.name = 'Igor'`, newTestEvents(`abci|owner.name=Igor|owner.name=Ivan`), - true}, - {`abci.owner.name = 'Ivan' AND abci.owner.name = 'John'`, + true, + }, + { + `abci.owner.name = 'Ivan' AND abci.owner.name = 'John'`, newTestEvents(`abci|owner.name=Igor|owner.name=Ivan`), - false}, - {`tm.events.type='NewBlock'`, + false, + }, + { + `tm.events.type='NewBlock'`, newTestEvents(`tm|events.type=NewBlock`, `app|name=fuzzed`), - true}, - {`app.name = 'fuzzed'`, + true, + }, + { + `app.name = 'fuzzed'`, newTestEvents(`tm|events.type=NewBlock`, `app|name=fuzzed`), - true}, - {`tm.events.type='NewBlock' AND app.name = 'fuzzed'`, + true, + }, + { + `tm.events.type='NewBlock' AND app.name = 'fuzzed'`, newTestEvents(`tm|events.type=NewBlock`, `app|name=fuzzed`), - true}, - {`tm.events.type='NewHeader' AND app.name = 'fuzzed'`, + true, + }, + { + `tm.events.type='NewHeader' AND app.name = 'fuzzed'`, newTestEvents(`tm|events.type=NewBlock`, `app|name=fuzzed`), - false}, - {`slash EXISTS`, + false, + }, + { + `slash EXISTS`, newTestEvents(`slash|reason=missing_signature|power=6000`), - true}, - {`slash EXISTS`, + true, + }, + { + `slash EXISTS`, newTestEvents(`transfer|recipient=cosmos1gu6y2a0ffteesyeyeesk23082c6998xyzmt9mz|sender=cosmos1crje20aj4gxdtyct7z3knxqry2jqt2fuaey6u5`), - false}, - {`slash.reason EXISTS AND slash.power > 1000`, + false, + }, + { + `slash.reason EXISTS AND slash.power > 1000`, newTestEvents(`slash|reason=missing_signature|power=6000`), - true}, - {`slash.reason EXISTS AND slash.power > 1000`, + true, + }, + { + `slash.reason EXISTS AND slash.power > 1000`, newTestEvents(`slash|reason=missing_signature|power=500`), - false}, - {`slash.reason EXISTS`, + false, + }, + { + `slash.reason EXISTS`, newTestEvents(`transfer|recipient=cosmos1gu6y2a0ffteesyeyeesk23082c6998xyzmt9mz|sender=cosmos1crje20aj4gxdtyct7z3knxqry2jqt2fuaey6u5`), - false}, + false, + }, // Test cases based on the OpenAPI examples. - {`tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA'`, - apiEvents, true}, - {`tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA' AND rewards.withdraw.source = 'SrcY'`, - apiEvents, true}, - {`tm.event = 'Tx' AND transfer.sender = 'AddrA'`, - apiEvents, false}, - {`tm.event = 'Tx' AND transfer.sender = 'AddrC'`, - apiEvents, true}, - {`tm.event = 'Tx' AND transfer.sender = 'AddrZ'`, - apiEvents, false}, - {`tm.event = 'Tx' AND rewards.withdraw.address = 'AddrZ'`, - apiEvents, false}, - {`tm.event = 'Tx' AND rewards.withdraw.source = 'W'`, - apiEvents, false}, + { + `tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA'`, + apiEvents, true, + }, + { + `tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA' AND rewards.withdraw.source = 'SrcY'`, + apiEvents, true, + }, + { + `tm.event = 'Tx' AND transfer.sender = 'AddrA'`, + apiEvents, false, + }, + { + `tm.event = 'Tx' AND transfer.sender = 'AddrC'`, + apiEvents, true, + }, + { + `tm.event = 'Tx' AND transfer.sender = 'AddrZ'`, + apiEvents, false, + }, + { + `tm.event = 'Tx' AND rewards.withdraw.address = 'AddrZ'`, + apiEvents, false, + }, + { + `tm.event = 'Tx' AND rewards.withdraw.source = 'W'`, + apiEvents, false, + }, } // NOTE: The original implementation allowed arbitrary prefix matches on diff --git a/libs/pubsub/query/syntax/doc.go b/internal/pubsub/query/syntax/doc.go similarity index 100% rename from libs/pubsub/query/syntax/doc.go rename to internal/pubsub/query/syntax/doc.go diff --git a/libs/pubsub/query/syntax/parser.go b/internal/pubsub/query/syntax/parser.go similarity index 87% rename from libs/pubsub/query/syntax/parser.go rename to internal/pubsub/query/syntax/parser.go index a100ec79c73..e64f94b7fc4 100644 --- a/libs/pubsub/query/syntax/parser.go +++ b/internal/pubsub/query/syntax/parser.go @@ -3,8 +3,7 @@ package syntax import ( "fmt" "io" - "math" - "strconv" + "math/big" "strings" "time" ) @@ -68,17 +67,34 @@ func (a *Arg) String() string { } } -// Number returns the value of the argument text as a number, or a NaN if the +// Number returns the value of the argument text as a number, or nil if the // text does not encode a valid number value. -func (a *Arg) Number() float64 { +func (a *Arg) Number() *big.Float { if a == nil { - return -1 + return nil } - v, err := strconv.ParseFloat(a.text, 64) - if err == nil && v >= 0 { - return v + intVal := new(big.Int) + if _, ok := intVal.SetString(a.text, 10); !ok { + f, _, err := big.ParseFloat(a.text, 10, 125, big.ToNearestEven) + if err != nil { + return nil + } + return f + } + // If it is indeed a big integer, we make sure to convert it to a float with enough precision + // to represent all the bits + bitLen := uint(intVal.BitLen()) + var f *big.Float + var err error + if bitLen <= 64 { + f, _, err = big.ParseFloat(a.text, 10, 0, big.ToNearestEven) + } else { + f, _, err = big.ParseFloat(a.text, 10, bitLen, big.ToNearestEven) + } + if err != nil { + return nil } - return math.NaN() + return f } // Time returns the value of the argument text as a time, or the zero value if diff --git a/libs/pubsub/query/syntax/scanner.go b/internal/pubsub/query/syntax/scanner.go similarity index 98% rename from libs/pubsub/query/syntax/scanner.go rename to internal/pubsub/query/syntax/scanner.go index 332e3f7b145..f8c0583f813 100644 --- a/libs/pubsub/query/syntax/scanner.go +++ b/internal/pubsub/query/syntax/scanner.go @@ -126,7 +126,7 @@ func (s *Scanner) Pos() int { return s.pos } func (s *Scanner) Err() error { return s.err } // scanNumber scans for numbers with optional fractional parts. -// Examples: 0, 1, 3.14 +// Examples: 0, 1, 3.14. func (s *Scanner) scanNumber(first rune) error { s.buf.WriteRune(first) if err := s.scanWhile(isDigit); err != nil { @@ -266,13 +266,14 @@ func (s *Scanner) scanDatestamp() error { func (s *Scanner) scanWhile(ok func(rune) bool) error { for { ch, err := s.rune() - if err == io.EOF { + switch { + case err == io.EOF: return nil - } else if err != nil { - return s.fail(err) - } else if !ok(ch) { + case !ok(ch): s.unrune() return nil + case err != nil: + return s.fail(err) } s.buf.WriteRune(ch) } diff --git a/libs/pubsub/query/syntax/syntax_test.go b/internal/pubsub/query/syntax/syntax_test.go similarity index 98% rename from libs/pubsub/query/syntax/syntax_test.go rename to internal/pubsub/query/syntax/syntax_test.go index 29a85aa9ec6..9228dbc2352 100644 --- a/libs/pubsub/query/syntax/syntax_test.go +++ b/internal/pubsub/query/syntax/syntax_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/cometbft/cometbft/libs/pubsub/query/syntax" + "github.com/cometbft/cometbft/internal/pubsub/query/syntax" ) func TestScanner(t *testing.T) { diff --git a/libs/pubsub/subscription.go b/internal/pubsub/subscription.go similarity index 91% rename from libs/pubsub/subscription.go rename to internal/pubsub/subscription.go index 8de570fefdd..3742e5bbf8f 100644 --- a/libs/pubsub/subscription.go +++ b/internal/pubsub/subscription.go @@ -3,7 +3,7 @@ package pubsub import ( "errors" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) var ( @@ -19,7 +19,7 @@ var ( // consists of three things: // 1) channel onto which messages and events are published // 2) channel which is closed if a client is too slow or choose to unsubscribe -// 3) err indicating the reason for (2) +// 3) err indicating the reason for (2). type Subscription struct { out chan Message @@ -72,16 +72,16 @@ func (s *Subscription) cancel(err error) { // Message glues data and events together. type Message struct { - data interface{} + data any events map[string][]string } -func NewMessage(data interface{}, events map[string][]string) Message { +func NewMessage(data any, events map[string][]string) Message { return Message{data, events} } // Data returns an original data published. -func (msg Message) Data() interface{} { +func (msg Message) Data() any { return msg.data } diff --git a/libs/rand/random.go b/internal/rand/random.go similarity index 94% rename from libs/rand/random.go rename to internal/rand/random.go index 73f56b76224..7ec366c177e 100644 --- a/libs/rand/random.go +++ b/internal/rand/random.go @@ -5,7 +5,7 @@ import ( mrand "math/rand" "time" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) const ( @@ -53,7 +53,7 @@ func (r *Rand) reset(seed int64) { r.rand = mrand.New(mrand.NewSource(seed)) } -//---------------------------------------- +// ---------------------------------------- // Global functions func Seed(seed int64) { @@ -140,7 +140,7 @@ func Perm(n int) []int { return grand.Perm(n) } -//---------------------------------------- +// ---------------------------------------- // Rand methods func (r *Rand) Seed(seed int64) { @@ -164,13 +164,12 @@ MAIN_LOOP: if v >= 62 { // only 62 characters in strChars val >>= 6 continue - } else { - chars = append(chars, strChars[v]) - if len(chars) == length { - break MAIN_LOOP - } - val >>= 6 } + chars = append(chars, strChars[v]) + if len(chars) == length { + break MAIN_LOOP + } + val >>= 6 } } @@ -285,7 +284,7 @@ func (r *Rand) Intn(n int) int { return i } -// Bool returns a uniformly random boolean +// Bool returns a uniformly random boolean. func (r *Rand) Bool() bool { // See https://github.com/golang/go/issues/23804#issuecomment-365370418 // for reasoning behind computing like this diff --git a/libs/rand/random_test.go b/internal/rand/random_test.go similarity index 89% rename from libs/rand/random_test.go rename to internal/rand/random_test.go index 10bb601b5e7..d485a350a59 100644 --- a/libs/rand/random_test.go +++ b/internal/rand/random_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "log" "sync" "testing" "time" @@ -14,20 +15,20 @@ import ( func TestRandStr(t *testing.T) { l := 243 s := Str(l) - assert.Equal(t, l, len(s)) + assert.Len(t, s, l) } func TestRandBytes(t *testing.T) { l := 243 b := Bytes(l) - assert.Equal(t, l, len(b)) + assert.Len(t, b, l) } func TestRandIntn(t *testing.T) { n := 243 for i := 0; i < 100; i++ { x := Intn(n) - assert.True(t, x < n) + assert.Less(t, x, n) } } @@ -54,7 +55,10 @@ func testThemAll() string { // Use it. out := new(bytes.Buffer) perm := Perm(10) - blob, _ := json.Marshal(perm) + blob, err := json.Marshal(perm) + if err != nil { + log.Fatalf("couldn't unmarshal perm: %v", err) + } fmt.Fprintf(out, "perm: %s\n", blob) fmt.Fprintf(out, "randInt: %d\n", Int()) fmt.Fprintf(out, "randUint: %d\n", Uint()) @@ -68,7 +72,7 @@ func testThemAll() string { return out.String() } -func TestRngConcurrencySafety(t *testing.T) { +func TestRngConcurrencySafety(_ *testing.T) { var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) @@ -104,10 +108,12 @@ func BenchmarkRandBytes100KiB(b *testing.B) { } func BenchmarkRandBytes1MiB(b *testing.B) { + b.Helper() benchmarkRandBytes(b, 1024*1024) } func benchmarkRandBytes(b *testing.B, n int) { + b.Helper() for i := 0; i < b.N; i++ { _ = Bytes(n) } diff --git a/internal/rpctrace/rpctrace.go b/internal/rpctrace/rpctrace.go new file mode 100644 index 00000000000..b24c91f488b --- /dev/null +++ b/internal/rpctrace/rpctrace.go @@ -0,0 +1,13 @@ +package rpctrace + +import "github.com/gofrs/uuid" + +// New returns a randomly generated string which can be used to assist in +// tracing RPC errors. +func New() (string, error) { + id, err := uuid.NewV4() + if err != nil { + return "", err + } + return id.String(), nil +} diff --git a/libs/service/service.go b/internal/service/service.go similarity index 95% rename from libs/service/service.go rename to internal/service/service.go index 7a46e5e20b4..131a071d1f7 100644 --- a/libs/service/service.go +++ b/internal/service/service.go @@ -49,7 +49,7 @@ type Service interface { String() string // SetLogger sets a logger. - SetLogger(log.Logger) + SetLogger(l log.Logger) } /* @@ -159,8 +159,8 @@ func (bs *BaseService) Start() error { // OnStart implements Service by doing nothing. // NOTE: Do not put anything in here, -// that way users don't need to call BaseService.OnStart() -func (bs *BaseService) OnStart() error { return nil } +// that way users don't need to call BaseService.OnStart(). +func (*BaseService) OnStart() error { return nil } // Stop implements Service by calling OnStop (if defined) and closing quit // channel. An error will be returned if the service is already stopped. @@ -192,8 +192,8 @@ func (bs *BaseService) Stop() error { // OnStop implements Service by doing nothing. // NOTE: Do not put anything in here, -// that way users don't need to call BaseService.OnStop() -func (bs *BaseService) OnStop() {} +// that way users don't need to call BaseService.OnStop(). +func (*BaseService) OnStop() {} // Reset implements Service by calling OnReset callback (if defined). An error // will be returned if the service is running. @@ -215,7 +215,7 @@ func (bs *BaseService) Reset() error { } // OnReset implements Service by panicking. -func (bs *BaseService) OnReset() error { +func (*BaseService) OnReset() error { panic("The service cannot be reset") } diff --git a/libs/service/service_test.go b/internal/service/service_test.go similarity index 94% rename from libs/service/service_test.go rename to internal/service/service_test.go index 7abc6f4fba8..f32525cfaa0 100644 --- a/libs/service/service_test.go +++ b/internal/service/service_test.go @@ -44,7 +44,7 @@ func TestBaseServiceReset(t *testing.T) { require.NoError(t, err) err = ts.Reset() - require.Error(t, err, "expected cant reset service error") + require.Error(t, err, "expected can't reset service error") err = ts.Stop() require.NoError(t, err) diff --git a/state/errors.go b/internal/state/errors.go similarity index 55% rename from state/errors.go rename to internal/state/errors.go index 91a6565c588..bbad8141aff 100644 --- a/state/errors.go +++ b/internal/state/errors.go @@ -51,6 +51,29 @@ type ( ErrNoABCIResponsesForHeight struct { Height int64 } + + ErrPrunerFailedToGetRetainHeight struct { + Which string + Err error + } + + ErrPrunerFailedToLoadState struct { + Err error + } + + ErrFailedToPruneBlocks struct { + Height int64 + Err error + } + + ErrFailedToPruneStates struct { + Height int64 + Err error + } + + ErrCannotLoadState struct { + Err error + } ) func (e ErrUnknownBlock) Error() string { @@ -103,4 +126,48 @@ func (e ErrNoABCIResponsesForHeight) Error() string { return fmt.Sprintf("could not find results for height #%d", e.Height) } -var ErrFinalizeBlockResponsesNotPersisted = errors.New("node is not persisting finalize block responses") +func (e ErrPrunerFailedToGetRetainHeight) Error() string { + return fmt.Sprintf("pruner failed to get existing %s retain height: %s", e.Which, e.Err.Error()) +} + +func (e ErrPrunerFailedToGetRetainHeight) Unwrap() error { + return e.Err +} + +func (e ErrPrunerFailedToLoadState) Error() string { + return "failed to load state, cannot prune: " + e.Err.Error() +} + +func (e ErrPrunerFailedToLoadState) Unwrap() error { + return e.Err +} + +func (e ErrFailedToPruneBlocks) Error() string { + return fmt.Sprintf("failed to prune blocks to height %d: %s", e.Height, e.Err.Error()) +} + +func (e ErrFailedToPruneBlocks) Unwrap() error { + return e.Err +} + +func (e ErrFailedToPruneStates) Error() string { + return fmt.Sprintf("failed to prune states to height %d: %s", e.Height, e.Err.Error()) +} + +func (e ErrFailedToPruneStates) Unwrap() error { + return e.Err +} + +var ( + ErrFinalizeBlockResponsesNotPersisted = errors.New("node is not persisting finalize block responses") + ErrPrunerCannotLowerRetainHeight = errors.New("cannot set a height lower than previously requested - heights might have already been pruned") + ErrInvalidRetainHeight = errors.New("retain height cannot be less or equal than 0") +) + +func (e ErrCannotLoadState) Error() string { + return fmt.Sprintf("cannot load state: %v", e.Err) +} + +func (e ErrCannotLoadState) Unwrap() error { + return e.Err +} diff --git a/state/execution.go b/internal/state/execution.go similarity index 79% rename from state/execution.go rename to internal/state/execution.go index 5c4aecdc7b7..ab341342b7f 100644 --- a/state/execution.go +++ b/internal/state/execution.go @@ -4,19 +4,19 @@ import ( "bytes" "context" "fmt" - "time" abci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" - "github.com/cometbft/cometbft/libs/fail" + "github.com/cometbft/cometbft/internal/fail" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/mempool" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/proxy" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // BlockExecutor handles block execution and state updates. // It exposes ApplyBlock(), which validates & executes the block, updates state w/ ABCI responses, // then commits and updates the mempool atomically, then saves state. @@ -29,6 +29,8 @@ type BlockExecutor struct { // use blockstore for the pruning functions. blockStore BlockStore + pruner *Pruner + // execute the app against this proxyApp proxy.AppConnConsensus @@ -47,6 +49,12 @@ type BlockExecutor struct { type BlockExecutorOption func(executor *BlockExecutor) +func BlockExecutorWithPruner(pruner *Pruner) BlockExecutorOption { + return func(blockExec *BlockExecutor) { + blockExec.pruner = pruner + } +} + func BlockExecutorWithMetrics(metrics *Metrics) BlockExecutorOption { return func(blockExec *BlockExecutor) { blockExec.metrics = metrics @@ -94,7 +102,7 @@ func (blockExec *BlockExecutor) SetEventBus(eventBus types.BlockEventPublisher) // CreateProposalBlock calls state.MakeBlock with evidence from the evpool // and txs from the mempool. The max bytes must be big enough to fit the commit. -// Up to 1/10th of the block space is allocated for maximum sized evidence. +// The block space is first allocated to outstanding evidence. // The rest is given to txs, up to the max gas. // // Contract: application will not return more bytes than are sent over the wire. @@ -105,24 +113,32 @@ func (blockExec *BlockExecutor) CreateProposalBlock( lastExtCommit *types.ExtendedCommit, proposerAddr []byte, ) (*types.Block, error) { - maxBytes := state.ConsensusParams.Block.MaxBytes + emptyMaxBytes := maxBytes == -1 + if emptyMaxBytes { + maxBytes = int64(types.MaxBlockSizeBytes) + } + maxGas := state.ConsensusParams.Block.MaxGas evidence, evSize := blockExec.evpool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) // Fetch a limited amount of valid txs maxDataBytes := types.MaxDataBytes(maxBytes, evSize, state.Validators.Size()) + maxReapBytes := maxDataBytes + if emptyMaxBytes { + maxReapBytes = -1 + } - txs := blockExec.mempool.ReapMaxBytesMaxGas(maxDataBytes, maxGas) + txs := blockExec.mempool.ReapMaxBytesMaxGas(maxReapBytes, maxGas) commit := lastExtCommit.ToCommit() block := state.MakeBlock(height, txs, commit, evidence, proposerAddr) rpp, err := blockExec.proxyApp.PrepareProposal( ctx, - &abci.RequestPrepareProposal{ + &abci.PrepareProposalRequest{ MaxTxBytes: maxDataBytes, Txs: block.Txs.ToSliceOfBytes(), - LocalLastCommit: buildExtendedCommitInfo(lastExtCommit, blockExec.store, state.InitialHeight, state.ConsensusParams.ABCI), + LocalLastCommit: buildExtendedCommitInfoFromStore(lastExtCommit, blockExec.store, state.InitialHeight, state.ConsensusParams.Feature), Misbehavior: block.Evidence.Evidence.ToABCI(), Height: block.Height, Time: block.Time, @@ -154,12 +170,12 @@ func (blockExec *BlockExecutor) ProcessProposal( block *types.Block, state State, ) (bool, error) { - resp, err := blockExec.proxyApp.ProcessProposal(context.TODO(), &abci.RequestProcessProposal{ + resp, err := blockExec.proxyApp.ProcessProposal(context.TODO(), &abci.ProcessProposalRequest{ Hash: block.Header.Hash(), Height: block.Header.Height, Time: block.Header.Time, Txs: block.Data.Txs.ToSliceOfBytes(), - ProposedLastCommit: buildLastCommitInfo(block, blockExec.store, state.InitialHeight), + ProposedLastCommit: buildLastCommitInfoFromStore(block, blockExec.store, state.InitialHeight), Misbehavior: block.Evidence.Evidence.ToABCI(), ProposerAddress: block.ProposerAddress, NextValidatorsHash: block.NextValidatorsHash, @@ -168,7 +184,7 @@ func (blockExec *BlockExecutor) ProcessProposal( return false, err } if resp.IsStatusUnknown() { - panic(fmt.Sprintf("ProcessProposal responded with status %s", resp.Status.String())) + panic("ProcessProposal responded with status " + resp.Status.String()) } return resp.IsAccepted(), nil @@ -186,6 +202,13 @@ func (blockExec *BlockExecutor) ValidateBlock(state State, block *types.Block) e return blockExec.evpool.CheckEvidence(block.Evidence.Evidence) } +// ApplyVerifiedBlock does the same as `ApplyBlock`, but skips verification. +func (blockExec *BlockExecutor) ApplyVerifiedBlock( + state State, blockID types.BlockID, block *types.Block, +) (State, error) { + return blockExec.applyBlock(state, blockID, block) +} + // ApplyBlock validates the block against the state, executes it against the app, // fires the relevant events, commits the app, and saves the new state and responses. // It returns the new state. @@ -195,24 +218,26 @@ func (blockExec *BlockExecutor) ValidateBlock(state State, block *types.Block) e func (blockExec *BlockExecutor) ApplyBlock( state State, blockID types.BlockID, block *types.Block, ) (State, error) { - if err := validateBlock(state, block); err != nil { return state, ErrInvalidBlock(err) } - commitInfo := buildLastCommitInfo(block, blockExec.store, state.InitialHeight) + return blockExec.applyBlock(state, blockID, block) +} - startTime := time.Now().UnixNano() - abciResponse, err := blockExec.proxyApp.FinalizeBlock(context.TODO(), &abci.RequestFinalizeBlock{ +func (blockExec *BlockExecutor) applyBlock(state State, blockID types.BlockID, block *types.Block) (State, error) { + startTime := cmttime.Now().UnixNano() + abciResponse, err := blockExec.proxyApp.FinalizeBlock(context.TODO(), &abci.FinalizeBlockRequest{ Hash: block.Hash(), NextValidatorsHash: block.NextValidatorsHash, ProposerAddress: block.ProposerAddress, Height: block.Height, - DecidedLastCommit: commitInfo, + Time: block.Time, + DecidedLastCommit: buildLastCommitInfoFromStore(block, blockExec.store, state.InitialHeight), Misbehavior: block.Evidence.Evidence.ToABCI(), Txs: block.Txs.ToSliceOfBytes(), }) - endTime := time.Now().UnixNano() + endTime := cmttime.Now().UnixNano() blockExec.metrics.BlockProcessingTime.Observe(float64(endTime-startTime) / 1000000) if err != nil { blockExec.logger.Error("error in proxyAppConn.FinalizeBlock", "err", err) @@ -232,7 +257,7 @@ func (blockExec *BlockExecutor) ApplyBlock( return state, fmt.Errorf("expected tx results length to match size of transactions in block. Expected %d, got %d", len(block.Data.Txs), len(abciResponse.TxResults)) } - blockExec.logger.Info("executed block", "height", block.Height, "app_hash", abciResponse.AppHash) + blockExec.logger.Info("executed block", "height", block.Height, "app_hash", fmt.Sprintf("%X", abciResponse.AppHash)) fail.Fail() // XXX @@ -246,7 +271,7 @@ func (blockExec *BlockExecutor) ApplyBlock( // validate the validator updates and convert to CometBFT types err = validateValidatorUpdates(abciResponse.ValidatorUpdates, state.ConsensusParams.Validator) if err != nil { - return state, fmt.Errorf("error in validator updates: %v", err) + return state, fmt.Errorf("error in validator updates: %w", err) } validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponse.ValidatorUpdates) @@ -254,7 +279,7 @@ func (blockExec *BlockExecutor) ApplyBlock( return state, err } if len(validatorUpdates) > 0 { - blockExec.logger.Debug("updates to validators", "updates", types.ValidatorListString(validatorUpdates)) + blockExec.logger.Info("updates to validators", "updates", types.ValidatorListString(validatorUpdates)) blockExec.metrics.ValidatorSetUpdates.Add(1) } if abciResponse.ConsensusParamUpdates != nil { @@ -264,13 +289,13 @@ func (blockExec *BlockExecutor) ApplyBlock( // Update the state with the block and responses. state, err = updateState(state, blockID, &block.Header, abciResponse, validatorUpdates) if err != nil { - return state, fmt.Errorf("commit failed for application: %v", err) + return state, fmt.Errorf("commit failed for application: %w", err) } // Lock mempool, commit app state, update mempoool. retainHeight, err := blockExec.Commit(state, block, abciResponse) if err != nil { - return state, fmt.Errorf("commit failed for application: %v", err) + return state, fmt.Errorf("commit failed for application: %w", err) } // Update evpool with the latest state. @@ -287,26 +312,41 @@ func (blockExec *BlockExecutor) ApplyBlock( fail.Fail() // XXX // Prune old heights, if requested by ABCI app. - if retainHeight > 0 { - pruned, err := blockExec.pruneBlocks(retainHeight, state) + if retainHeight > 0 && blockExec.pruner != nil { + err := blockExec.pruner.SetApplicationBlockRetainHeight(retainHeight) if err != nil { - blockExec.logger.Error("failed to prune blocks", "retain_height", retainHeight, "err", err) - } else { - blockExec.logger.Debug("pruned blocks", "pruned", pruned, "retain_height", retainHeight) + blockExec.logger.Error("Failed to set application block retain height", "retainHeight", retainHeight, "err", err) } } // Events are fired after everything else. - // NOTE: if we crash between Commit and Save, events wont be fired during replay + // NOTE: if we crash between Commit and Save, events won't be fired during replay fireEvents(blockExec.logger, blockExec.eventBus, block, blockID, abciResponse, validatorUpdates) return state, nil } -func (blockExec *BlockExecutor) ExtendVote(ctx context.Context, vote *types.Vote) ([]byte, error) { - req := abci.RequestExtendVote{ - Hash: vote.BlockID.Hash, - Height: vote.Height, +func (blockExec *BlockExecutor) ExtendVote( + ctx context.Context, + vote *types.Vote, + block *types.Block, + state State, +) ([]byte, error) { + if !block.HashesTo(vote.BlockID.Hash) { + panic(fmt.Sprintf("vote's hash does not match the block it is referring to %X!=%X", block.Hash(), vote.BlockID.Hash)) + } + if vote.Height != block.Height { + panic(fmt.Sprintf("vote's and block's heights do not match %d!=%d", block.Height, vote.Height)) + } + req := abci.ExtendVoteRequest{ + Hash: vote.BlockID.Hash, + Height: vote.Height, + Time: block.Time, + Txs: block.Txs.ToSliceOfBytes(), + ProposedLastCommit: buildLastCommitInfoFromStore(block, blockExec.store, state.InitialHeight), + Misbehavior: block.Evidence.Evidence.ToABCI(), + NextValidatorsHash: block.NextValidatorsHash, + ProposerAddress: block.ProposerAddress, } resp, err := blockExec.proxyApp.ExtendVote(ctx, &req) @@ -317,7 +357,7 @@ func (blockExec *BlockExecutor) ExtendVote(ctx context.Context, vote *types.Vote } func (blockExec *BlockExecutor) VerifyVoteExtension(ctx context.Context, vote *types.Vote) error { - req := abci.RequestVerifyVoteExtension{ + req := abci.VerifyVoteExtensionRequest{ Hash: vote.BlockID.Hash, ValidatorAddress: vote.ValidatorAddress, Height: vote.Height, @@ -329,7 +369,7 @@ func (blockExec *BlockExecutor) VerifyVoteExtension(ctx context.Context, vote *t panic(fmt.Errorf("VerifyVoteExtension call failed: %w", err)) } if resp.IsStatusUnknown() { - panic(fmt.Sprintf("VerifyVoteExtension responded with status %s", resp.Status.String())) + panic("VerifyVoteExtension responded with status " + resp.Status.String()) } if !resp.IsAccepted() { @@ -350,7 +390,7 @@ func (blockExec *BlockExecutor) VerifyVoteExtension(ctx context.Context, vote *t func (blockExec *BlockExecutor) Commit( state State, block *types.Block, - abciResponse *abci.ResponseFinalizeBlock, + abciResponse *abci.FinalizeBlockResponse, ) (int64, error) { blockExec.mempool.Lock() defer blockExec.mempool.Unlock() @@ -389,11 +429,11 @@ func (blockExec *BlockExecutor) Commit( return res.RetainHeight, err } -//--------------------------------------------------------- +// --------------------------------------------------------- // Helper functions for executing blocks and updating state -func buildLastCommitInfo(block *types.Block, store Store, initialHeight int64) abci.CommitInfo { - if block.Height == initialHeight { +func buildLastCommitInfoFromStore(block *types.Block, store Store, initialHeight int64) abci.CommitInfo { + if block.Height == initialHeight { // check for initial height before loading validators // there is no last commit for the initial height. // return an empty value. return abci.CommitInfo{} @@ -404,6 +444,19 @@ func buildLastCommitInfo(block *types.Block, store Store, initialHeight int64) a panic(fmt.Errorf("failed to load validator set at height %d: %w", block.Height-1, err)) } + return BuildLastCommitInfo(block, lastValSet, initialHeight) +} + +// BuildLastCommitInfo builds a CommitInfo from the given block and validator set. +// If you want to load the validator set from the store instead of providing it, +// use buildLastCommitInfoFromStore. +func BuildLastCommitInfo(block *types.Block, lastValSet *types.ValidatorSet, initialHeight int64) abci.CommitInfo { + if block.Height == initialHeight { + // there is no last commit for the initial height. + // return an empty value. + return abci.CommitInfo{} + } + var ( commitSize = block.LastCommit.Size() valSetLen = len(lastValSet.Validators) @@ -433,7 +486,7 @@ func buildLastCommitInfo(block *types.Block, store Store, initialHeight int64) a } } -// buildExtendedCommitInfo populates an ABCI extended commit from the +// buildExtendedCommitInfoFromStore populates an ABCI extended commit from the // corresponding CometBFT extended commit ec, using the stored validator set // from ec. It requires ec to include the original precommit votes along with // the vote extensions from the last commit. @@ -442,7 +495,7 @@ func buildLastCommitInfo(block *types.Block, store Store, initialHeight int64) a // data, it returns an empty record. // // Assumes that the commit signatures are sorted according to validator index. -func buildExtendedCommitInfo(ec *types.ExtendedCommit, store Store, initialHeight int64, ap types.ABCIParams) abci.ExtendedCommitInfo { +func buildExtendedCommitInfoFromStore(ec *types.ExtendedCommit, store Store, initialHeight int64, fp types.FeatureParams) abci.ExtendedCommitInfo { if ec.Height < initialHeight { // There are no extended commits for heights below the initial height. return abci.ExtendedCommitInfo{} @@ -453,6 +506,18 @@ func buildExtendedCommitInfo(ec *types.ExtendedCommit, store Store, initialHeigh panic(fmt.Errorf("failed to load validator set at height %d, initial height %d: %w", ec.Height, initialHeight, err)) } + return BuildExtendedCommitInfo(ec, valSet, initialHeight, fp) +} + +// BuildExtendedCommitInfo builds an ExtendedCommitInfo from the given block and validator set. +// If you want to load the validator set from the store instead of providing it, +// use buildExtendedCommitInfoFromStore. +func BuildExtendedCommitInfo(ec *types.ExtendedCommit, valSet *types.ValidatorSet, initialHeight int64, fp types.FeatureParams) abci.ExtendedCommitInfo { + if ec.Height < initialHeight { + // There are no extended commits for heights below the initial height. + return abci.ExtendedCommitInfo{} + } + var ( ecSize = ec.Size() valSetLen = len(valSet.Validators) @@ -484,7 +549,7 @@ func buildExtendedCommitInfo(ec *types.ExtendedCommit, store Store, initialHeigh // during that height, we ensure they are present and deliver the data to // the proposer. If they were not enabled during this previous height, we // will not deliver extension data. - if err := ecs.EnsureExtension(ap.VoteExtensionsEnabled(ec.Height)); err != nil { + if err := ecs.EnsureExtension(fp.VoteExtensionsEnabled(ec.Height)); err != nil { panic(fmt.Errorf("commit at height %d has problems with vote extension data; err %w", ec.Height, err)) } @@ -503,7 +568,8 @@ func buildExtendedCommitInfo(ec *types.ExtendedCommit, store Store, initialHeigh } func validateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, - params types.ValidatorParams) error { + params types.ValidatorParams, +) error { for _, valUpdate := range abciUpdates { if valUpdate.GetPower() < 0 { return fmt.Errorf("voting power can't be negative %v", valUpdate) @@ -532,10 +598,9 @@ func updateState( state State, blockID types.BlockID, header *types.Header, - abciResponse *abci.ResponseFinalizeBlock, + abciResponse *abci.FinalizeBlockResponse, validatorUpdates []*types.Validator, ) (State, error) { - // Copy the valset so we can apply changes from EndBlock // and update s.LastValidators and s.Validators. nValSet := state.NextValidators.Copy() @@ -547,7 +612,7 @@ func updateState( if err != nil { return state, fmt.Errorf("changing validator set: %w", err) } - // Change results from this height but only applies to the next next height. + // Change results from this height but only applies to the height + 2. lastHeightValsChanged = header.Height + 1 + 1 } @@ -606,7 +671,7 @@ func fireEvents( eventBus types.BlockEventPublisher, block *types.Block, blockID types.BlockID, - abciResponse *abci.ResponseFinalizeBlock, + abciResponse *abci.FinalizeBlockResponse, validatorUpdates []*types.Validator, ) { if err := eventBus.PublishEventNewBlock(types.EventDataNewBlock{ @@ -661,7 +726,7 @@ func fireEvents( } } -//---------------------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------------------- // Execute block without state. TODO: eliminate // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state. @@ -673,13 +738,14 @@ func ExecCommitBlock( store Store, initialHeight int64, ) ([]byte, error) { - commitInfo := buildLastCommitInfo(block, store, initialHeight) + commitInfo := buildLastCommitInfoFromStore(block, store, initialHeight) - resp, err := appConnConsensus.FinalizeBlock(context.TODO(), &abci.RequestFinalizeBlock{ + resp, err := appConnConsensus.FinalizeBlock(context.TODO(), &abci.FinalizeBlockRequest{ Hash: block.Hash(), NextValidatorsHash: block.NextValidatorsHash, ProposerAddress: block.ProposerAddress, Height: block.Height, + Time: block.Time, DecidedLastCommit: commitInfo, Misbehavior: block.Evidence.Evidence.ToABCI(), Txs: block.Txs.ToSliceOfBytes(), @@ -694,7 +760,7 @@ func ExecCommitBlock( return nil, fmt.Errorf("expected tx results length to match size of transactions in block. Expected %d, got %d", len(block.Data.Txs), len(resp.TxResults)) } - logger.Info("executed block", "height", block.Height, "app_hash", resp.AppHash) + logger.Info("executed block", "height", block.Height, "app_hash", fmt.Sprintf("%X", resp.AppHash)) // Commit block _, err = appConnConsensus.Commit(context.TODO()) @@ -706,21 +772,3 @@ func ExecCommitBlock( // ResponseCommit has no error or log return resp.AppHash, nil } - -func (blockExec *BlockExecutor) pruneBlocks(retainHeight int64, state State) (uint64, error) { - base := blockExec.blockStore.Base() - if retainHeight <= base { - return 0, nil - } - - amountPruned, prunedHeaderHeight, err := blockExec.blockStore.PruneBlocks(retainHeight, state) - if err != nil { - return 0, fmt.Errorf("failed to prune block store: %w", err) - } - - err = blockExec.Store().PruneStates(base, retainHeight, prunedHeaderHeight) - if err != nil { - return 0, fmt.Errorf("failed to prune state store: %w", err) - } - return amountPruned, nil -} diff --git a/state/execution_test.go b/internal/state/execution_test.go similarity index 86% rename from state/execution_test.go rename to internal/state/execution_test.go index a48954c56c3..7ac06d34ee5 100644 --- a/state/execution_test.go +++ b/internal/state/execution_test.go @@ -11,24 +11,23 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abciclientmocks "github.com/cometbft/cometbft/abci/client/mocks" abci "github.com/cometbft/cometbft/abci/types" abcimocks "github.com/cometbft/cometbft/abci/types/mocks" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" "github.com/cometbft/cometbft/crypto/tmhash" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/mocks" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" mpmocks "github.com/cometbft/cometbft/mempool/mocks" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" "github.com/cometbft/cometbft/proxy" pmocks "github.com/cometbft/cometbft/proxy/mocks" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/mocks" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" @@ -36,7 +35,7 @@ import ( var ( chainID = "execution_chain" - testPartSize uint32 = 65536 + testPartSize uint32 = types.BlockPartSizeBytes ) func TestApplyBlock(t *testing.T) { @@ -44,10 +43,10 @@ func TestApplyBlock(t *testing.T) { cc := proxy.NewLocalClientCreator(app) proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) err := proxyApp.Start() - require.Nil(t, err) + require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, _ := makeState(1, 1) + state, stateDB, _ := makeState(1, 1, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -73,7 +72,7 @@ func TestApplyBlock(t *testing.T) { blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} state, err = blockExec.ApplyBlock(state, blockID, block) - require.Nil(t, err) + require.NoError(t, err) // TODO check state and mempool assert.EqualValues(t, 1, state.Version.Consensus.App, "App version wasn't updated") @@ -85,13 +84,14 @@ func TestApplyBlock(t *testing.T) { // block. func TestFinalizeBlockDecidedLastCommit(t *testing.T) { app := &testApp{} + baseTime := cmttime.Now() cc := proxy.NewLocalClientCreator(app) proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) err := proxyApp.Start() require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, privVals := makeState(7, 1) + state, stateDB, privVals := makeState(7, 1, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -146,6 +146,7 @@ func TestFinalizeBlockDecidedLastCommit(t *testing.T) { blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} _, err = blockExec.ApplyBlock(state, blockID, block) require.NoError(t, err) + require.True(t, app.LastTime.After(baseTime)) // -> app receives a list of validators with a bool indicating if they signed for i, v := range app.CommitVotes { @@ -165,7 +166,7 @@ func TestFinalizeBlockValidators(t *testing.T) { require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // no need to check error again - state, stateDB, _ := makeState(2, 2) + state, stateDB, _ := makeState(2, 2, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -204,10 +205,11 @@ func TestFinalizeBlockValidators(t *testing.T) { desc string lastCommitSigs []types.ExtendedCommitSig expectedAbsentValidators []int + shouldHaveTime bool }{ - {"none absent", []types.ExtendedCommitSig{commitSig0, commitSig1}, []int{}}, - {"one absent", []types.ExtendedCommitSig{commitSig0, absentSig}, []int{1}}, - {"multiple absent", []types.ExtendedCommitSig{absentSig, absentSig}, []int{0, 1}}, + {"none absent", []types.ExtendedCommitSig{commitSig0, commitSig1}, []int{}, true}, + {"one absent", []types.ExtendedCommitSig{commitSig0, absentSig}, []int{1}, true}, + {"multiple absent", []types.ExtendedCommitSig{absentSig, absentSig}, []int{0, 1}, false}, } for _, tc := range testCases { @@ -221,18 +223,22 @@ func TestFinalizeBlockValidators(t *testing.T) { block := makeBlock(state, 2, lastCommit.ToCommit()) _, err = sm.ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), stateStore, 1) - require.Nil(t, err, tc.desc) + require.NoError(t, err, tc.desc) + require.True(t, + !tc.shouldHaveTime || + app.LastTime.Equal(now) || app.LastTime.After(now), + "'last_time' should be at or after 'now'; tc %v, last_time %v, now %v", tc.desc, app.LastTime, now, + ) // -> app receives a list of validators with a bool indicating if they signed ctr := 0 for i, v := range app.CommitVotes { if ctr < len(tc.expectedAbsentValidators) && tc.expectedAbsentValidators[ctr] == i { - - assert.Equal(t, v.BlockIdFlag, cmtproto.BlockIDFlagAbsent) + assert.Equal(t, cmtproto.BlockIDFlagAbsent, v.BlockIdFlag) ctr++ } else { - assert.NotEqual(t, v.BlockIdFlag, cmtproto.BlockIDFlagAbsent) + assert.NotEqual(t, cmtproto.BlockIDFlagAbsent, v.BlockIdFlag) } } } @@ -247,7 +253,7 @@ func TestFinalizeBlockMisbehavior(t *testing.T) { require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, privVals := makeState(1, 1) + state, stateDB, privVals := makeState(1, 1, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -287,7 +293,8 @@ func TestFinalizeBlockMisbehavior(t *testing.T) { BlockIDFlag: types.BlockIDFlagNil, ValidatorAddress: crypto.AddressHash([]byte("validator_address")), Timestamp: defaultEvidenceTime, - Signature: crypto.CRandBytes(types.MaxSignatureSize)}}, + Signature: crypto.CRandBytes(types.MaxSignatureSize), + }}, }, }, ValidatorSet: state.Validators, @@ -302,14 +309,14 @@ func TestFinalizeBlockMisbehavior(t *testing.T) { abciMb := []abci.Misbehavior{ { - Type: abci.MisbehaviorType_DUPLICATE_VOTE, + Type: abci.MISBEHAVIOR_TYPE_DUPLICATE_VOTE, Height: 3, Time: defaultEvidenceTime, Validator: types.TM2PB.Validator(state.Validators.Validators[0]), TotalVotingPower: 10, }, { - Type: abci.MisbehaviorType_LIGHT_CLIENT_ATTACK, + Type: abci.MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK, Height: 8, Time: defaultEvidenceTime, Validator: types.TM2PB.Validator(state.Validators.Validators[0]), @@ -359,7 +366,7 @@ func TestProcessProposal(t *testing.T) { logger := log.NewNopLogger() app := &abcimocks.Application{} - app.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil) + app.On("ProcessProposal", mock.Anything, mock.Anything).Return(&abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil) cc := proxy.NewLocalClientCreator(app) proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) @@ -367,7 +374,7 @@ func TestProcessProposal(t *testing.T) { require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, privVals := makeState(1, height) + state, stateDB, privVals := makeState(1, height, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -395,7 +402,7 @@ func TestProcessProposal(t *testing.T) { pk, err := privVal.GetPubKey() require.NoError(t, err) idx, _ := state.Validators.GetByAddress(pk.Address()) - vote := types.MakeVoteNoError(t, privVal, block0.Header.ChainID, idx, height-1, 0, 2, blockID, time.Now()) + vote := types.MakeVoteNoError(t, privVal, block0.Header.ChainID, idx, height-1, 0, 2, blockID, cmttime.Now()) addr := pk.Address() voteInfos = append(voteInfos, abci.VoteInfo{ @@ -415,7 +422,7 @@ func TestProcessProposal(t *testing.T) { block1.Txs = txs - expectedRpp := &abci.RequestProcessProposal{ + expectedRpp := &abci.ProcessProposalRequest{ Txs: block1.Txs.ToSliceOfBytes(), Hash: block1.Hash(), Height: block1.Header.Height, @@ -440,9 +447,9 @@ func TestValidateValidatorUpdates(t *testing.T) { pubkey1 := ed25519.GenPrivKey().PubKey() pubkey2 := ed25519.GenPrivKey().PubKey() pk1, err := cryptoenc.PubKeyToProto(pubkey1) - assert.NoError(t, err) + require.NoError(t, err) pk2, err := cryptoenc.PubKeyToProto(pubkey2) - assert.NoError(t, err) + require.NoError(t, err) defaultValidatorParams := types.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}} @@ -485,9 +492,9 @@ func TestValidateValidatorUpdates(t *testing.T) { t.Run(tc.name, func(t *testing.T) { err := sm.ValidateValidatorUpdates(tc.abciUpdates, tc.validatorParams) if tc.shouldErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -547,12 +554,12 @@ func TestUpdateValidators(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { updates, err := types.PB2TM.ValidatorUpdates(tc.abciUpdates) - assert.NoError(t, err) + require.NoError(t, err) err = tc.currentSet.UpdateWithChangeSet(updates) if tc.shouldErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) require.Equal(t, tc.resultingSet.Size(), tc.currentSet.Size()) assert.Equal(t, tc.resultingSet.TotalVotingPower(), tc.currentSet.TotalVotingPower()) @@ -575,7 +582,7 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) { require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, _ := makeState(1, 1) + state, stateDB, _ := makeState(1, 1, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -655,7 +662,7 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) { } // TestFinalizeBlockValidatorUpdatesResultingInEmptySet checks that processing validator updates that -// would result in empty set causes no panic, an error is raised and NextValidators is not updated +// would result in empty set causes no panic, an error is raised and NextValidators is not updated. func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { app := &testApp{} cc := proxy.NewLocalClientCreator(app) @@ -664,7 +671,7 @@ func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, _ := makeState(1, 1) + state, stateDB, _ := makeState(1, 1, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -691,7 +698,7 @@ func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { } assert.NotPanics(t, func() { state, err = blockExec.ApplyBlock(state, blockID, block) }) - assert.Error(t, err) + require.Error(t, err) assert.NotEmpty(t, state.NextValidators.Validators) } @@ -707,7 +714,7 @@ func TestEmptyPrepareProposal(t *testing.T) { require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, privVals := makeState(1, height) + state, stateDB, privVals := makeState(1, height, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -734,7 +741,7 @@ func TestEmptyPrepareProposal(t *testing.T) { blockStore, ) pa, _ := state.Validators.GetByIndex(0) - commit, _, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) require.NoError(t, err) _, err = blockExec.CreateProposalBlock(ctx, height, state, commit, pa) require.NoError(t, err) @@ -747,7 +754,7 @@ func TestPrepareProposalTxsAllIncluded(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - state, stateDB, privVals := makeState(1, height) + state, stateDB, privVals := makeState(1, height, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -760,7 +767,7 @@ func TestPrepareProposalTxsAllIncluded(t *testing.T) { mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(txs[2:]) app := &abcimocks.Application{} - app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{ + app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{ Txs: txs.ToSliceOfBytes(), }, nil) cc := proxy.NewLocalClientCreator(app) @@ -779,7 +786,7 @@ func TestPrepareProposalTxsAllIncluded(t *testing.T) { blockStore, ) pa, _ := state.Validators.GetByIndex(0) - commit, _, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) require.NoError(t, err) block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa) require.NoError(t, err) @@ -798,7 +805,7 @@ func TestPrepareProposalReorderTxs(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - state, stateDB, privVals := makeState(1, height) + state, stateDB, privVals := makeState(1, height, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -814,7 +821,7 @@ func TestPrepareProposalReorderTxs(t *testing.T) { txs = append(txs[len(txs)/2:], txs[:len(txs)/2]...) app := &abcimocks.Application{} - app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{ + app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{ Txs: txs.ToSliceOfBytes(), }, nil) @@ -834,7 +841,7 @@ func TestPrepareProposalReorderTxs(t *testing.T) { blockStore, ) pa, _ := state.Validators.GetByIndex(0) - commit, _, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) require.NoError(t, err) block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa) require.NoError(t, err) @@ -852,7 +859,7 @@ func TestPrepareProposalErrorOnTooManyTxs(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - state, stateDB, privVals := makeState(1, height) + state, stateDB, privVals := makeState(1, height, chainID) // limit max block size state.ConsensusParams.Block.MaxBytes = 60 * 1024 stateStore := sm.NewStore(stateDB, sm.StoreOptions{ @@ -870,7 +877,64 @@ func TestPrepareProposalErrorOnTooManyTxs(t *testing.T) { mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(txs) app := &abcimocks.Application{} - app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{ + app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{ + Txs: txs.ToSliceOfBytes(), + }, nil) + + cc := proxy.NewLocalClientCreator(app) + proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) + err := proxyApp.Start() + require.NoError(t, err) + defer proxyApp.Stop() //nolint:errcheck // ignore for tests + + blockStore := store.NewBlockStore(dbm.NewMemDB()) + blockExec := sm.NewBlockExecutor( + stateStore, + log.NewNopLogger(), + proxyApp.Consensus(), + mp, + evpool, + blockStore, + ) + pa, _ := state.Validators.GetByIndex(0) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + require.NoError(t, err) + block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa) + require.Nil(t, block) + require.ErrorContains(t, err, "transaction data size exceeds maximum") + + mp.AssertExpectations(t) +} + +// TestPrepareProposalCountSerializationOverhead tests that the block creation logic returns +// an error if the ResponsePrepareProposal returned from the application is at the limit of +// its size and will go beyond the limit upon serialization. +func TestPrepareProposalCountSerializationOverhead(t *testing.T) { + const height = 2 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + state, stateDB, privVals := makeState(1, height, chainID) + // limit max block size + var bytesPerTx int64 = 4 + const nValidators = 1 + nonDataSize := 5000 - types.MaxDataBytes(5000, 0, nValidators) + state.ConsensusParams.Block.MaxBytes = bytesPerTx*1024 + nonDataSize + maxDataBytes := types.MaxDataBytes(state.ConsensusParams.Block.MaxBytes, 0, nValidators) + + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + + evpool := &mocks.EvidencePool{} + evpool.On("PendingEvidence", mock.Anything).Return([]types.Evidence{}, int64(0)) + + txs := test.MakeNTxs(height, maxDataBytes/bytesPerTx) + mp := &mpmocks.Mempool{} + mp.On("ReapMaxBytesMaxGas", mock.Anything, mock.Anything).Return(txs) + + app := &abcimocks.Application{} + app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{ Txs: txs.ToSliceOfBytes(), }, nil) @@ -890,7 +954,7 @@ func TestPrepareProposalErrorOnTooManyTxs(t *testing.T) { blockStore, ) pa, _ := state.Validators.GetByIndex(0) - commit, _, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) require.NoError(t, err) block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa) require.Nil(t, block) @@ -906,7 +970,7 @@ func TestPrepareProposalErrorOnPrepareProposalError(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - state, stateDB, privVals := makeState(1, height) + state, stateDB, privVals := makeState(1, height, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -925,7 +989,10 @@ func TestPrepareProposalErrorOnPrepareProposalError(t *testing.T) { cm.On("PrepareProposal", mock.Anything, mock.Anything).Return(nil, errors.New("an injected error")).Once() cm.On("Stop").Return(nil) cc := &pmocks.ClientCreator{} - cc.On("NewABCIClient").Return(cm, nil) + cc.On("NewABCIQueryClient").Return(cm, nil) + cc.On("NewABCIMempoolClient").Return(cm, nil) + cc.On("NewABCISnapshotClient").Return(cm, nil) + cc.On("NewABCIConsensusClient").Return(cm, nil) proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) err := proxyApp.Start() require.NoError(t, err) @@ -941,7 +1008,7 @@ func TestPrepareProposalErrorOnPrepareProposalError(t *testing.T) { blockStore, ) pa, _ := state.Validators.GetByIndex(0) - commit, _, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) + commit, err := makeValidCommit(height, types.BlockID{}, state.Validators, privVals) require.NoError(t, err) block, err := blockExec.CreateProposalBlock(ctx, height, state, commit, pa) require.Nil(t, block) @@ -995,18 +1062,18 @@ func TestCreateProposalAbsentVoteExtensions(t *testing.T) { app := abcimocks.NewApplication(t) if !testCase.expectPanic { - app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.ResponsePrepareProposal{}, nil) + app.On("PrepareProposal", mock.Anything, mock.Anything).Return(&abci.PrepareProposalResponse{}, nil) } cc := proxy.NewLocalClientCreator(app) proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) err := proxyApp.Start() require.NoError(t, err) - state, stateDB, privVals := makeState(1, int(testCase.height-1)) + state, stateDB, privVals := makeState(1, int(testCase.height-1), chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) - state.ConsensusParams.ABCI.VoteExtensionsEnableHeight = testCase.extensionEnableHeight + state.ConsensusParams.Feature.VoteExtensionsEnableHeight = testCase.extensionEnableHeight mp := &mpmocks.Mempool{} mp.On("Lock").Return() mp.On("Unlock").Return() @@ -1035,7 +1102,7 @@ func TestCreateProposalAbsentVoteExtensions(t *testing.T) { require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} pa, _ := state.Validators.GetByIndex(0) - lastCommit, _, _ := makeValidCommit(testCase.height-1, blockID, state.Validators, privVals) + lastCommit, _ := makeValidCommit(testCase.height-1, blockID, state.Validators, privVals) stripSignatures(lastCommit) if testCase.expectPanic { require.Panics(t, func() { diff --git a/state/export_test.go b/internal/state/export_test.go similarity index 51% rename from state/export_test.go rename to internal/state/export_test.go index 24d76adb0f6..4e7b8d6d6cf 100644 --- a/state/export_test.go +++ b/internal/state/export_test.go @@ -2,7 +2,6 @@ package state import ( dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/types" ) @@ -26,7 +25,7 @@ func UpdateState( state State, blockID types.BlockID, header *types.Header, - resp *abci.ResponseFinalizeBlock, + resp *abci.FinalizeBlockResponse, validatorUpdates []*types.Validator, ) (State, error) { return updateState(state, blockID, header, resp, validatorUpdates) @@ -40,7 +39,54 @@ func ValidateValidatorUpdates(abciUpdates []abci.ValidatorUpdate, params types.V // SaveValidatorsInfo is an alias for the private saveValidatorsInfo method in // store.go, exported exclusively and explicitly for testing. -func SaveValidatorsInfo(db dbm.DB, height, lastHeightChanged int64, valSet *types.ValidatorSet) error { - stateStore := dbStore{db, StoreOptions{DiscardABCIResponses: false}} - return stateStore.saveValidatorsInfo(height, lastHeightChanged, valSet) +func SaveValidatorsInfo(db dbm.DB, height, lastHeightChanged int64, valSet *types.ValidatorSet, keyLayoutVersion string) error { + var keyLayout KeyLayout + switch keyLayoutVersion { + case "v1", "": + keyLayout = v1LegacyLayout{} + case "v2": + keyLayout = v2Layout{} + } + stateStore := dbStore{db, keyLayout, StoreOptions{DiscardABCIResponses: false, Metrics: NopMetrics()}} + batch := stateStore.db.NewBatch() + err := stateStore.saveValidatorsInfo(height, lastHeightChanged, valSet, batch) + if err != nil { + return err + } + err = batch.WriteSync() + if err != nil { + return err + } + return nil +} + +// FindMinBlockRetainHeight is an alias for the private +// findMinBlockRetainHeight method in pruner.go, exported exclusively and +// explicitly for testing. +func (p *Pruner) FindMinRetainHeight() int64 { + return p.findMinBlockRetainHeight() +} + +func (p *Pruner) PruneABCIResToRetainHeight(lastRetainHeight int64) int64 { + return p.pruneABCIResToRetainHeight(lastRetainHeight) +} + +func (p *Pruner) PruneTxIndexerToRetainHeight(lastRetainHeight int64) int64 { + return p.pruneTxIndexerToRetainHeight(lastRetainHeight) +} + +func (p *Pruner) PruneBlockIndexerToRetainHeight(lastRetainHeight int64) int64 { + return p.pruneBlockIndexerToRetainHeight(lastRetainHeight) +} + +func (p *Pruner) PruneBlocksToHeight(height int64) (uint64, int64, error) { + return p.pruneBlocksToHeight(height) +} + +func Int64ToBytes(val int64) []byte { + return int64ToBytes(val) +} + +func Int64FromBytes(val []byte) int64 { + return int64FromBytes(val) } diff --git a/state/helpers_test.go b/internal/state/helpers_test.go similarity index 74% rename from state/helpers_test.go rename to internal/state/helpers_test.go index f0de48bbadc..0f50bbc70a7 100644 --- a/state/helpers_test.go +++ b/internal/state/helpers_test.go @@ -3,19 +3,16 @@ package state_test import ( "bytes" "context" - "fmt" - "testing" "time" dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" + sm "github.com/cometbft/cometbft/internal/state" "github.com/cometbft/cometbft/internal/test" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -47,7 +44,7 @@ func makeAndCommitGoodBlock( } // Simulate a lastCommit for this block from all validators for the next height - commit, _, err := makeValidCommit(height, blockID, state.Validators, privVals) + commit, err := makeValidCommit(height, blockID, state.Validators, privVals) if err != nil { return state, types.BlockID{}, nil, err } @@ -92,7 +89,7 @@ func makeValidCommit( blockID types.BlockID, vals *types.ValidatorSet, privVals map[string]types.PrivValidator, -) (*types.ExtendedCommit, []*types.Vote, error) { +) (*types.ExtendedCommit, error) { sigs := make([]types.ExtendedCommitSig, vals.Size()) votes := make([]*types.Vote, vals.Size()) for i := 0; i < vals.Size(); i++ { @@ -103,12 +100,12 @@ func makeValidCommit( int32(i), height, 0, - cmtproto.PrecommitType, + types.PrecommitType, blockID, - time.Now(), + cmttime.Now(), ) if err != nil { - return nil, nil, err + return nil, err } sigs[i] = vote.ExtendedCommitSig() votes[i] = vote @@ -117,47 +114,7 @@ func makeValidCommit( Height: height, BlockID: blockID, ExtendedSignatures: sigs, - }, votes, nil -} - -func makeState(nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValidator) { - vals := make([]types.GenesisValidator, nVals) - privVals := make(map[string]types.PrivValidator, nVals) - for i := 0; i < nVals; i++ { - secret := []byte(fmt.Sprintf("test%d", i)) - pk := ed25519.GenPrivKeyFromSecret(secret) - valAddr := pk.PubKey().Address() - vals[i] = types.GenesisValidator{ - Address: valAddr, - PubKey: pk.PubKey(), - Power: 1000, - Name: fmt.Sprintf("test%d", i), - } - privVals[valAddr.String()] = types.NewMockPVWithParams(pk, false, false) - } - s, _ := sm.MakeGenesisState(&types.GenesisDoc{ - ChainID: chainID, - Validators: vals, - AppHash: nil, - }) - - stateDB := dbm.NewMemDB() - stateStore := sm.NewStore(stateDB, sm.StoreOptions{ - DiscardABCIResponses: false, - }) - if err := stateStore.Save(s); err != nil { - panic(err) - } - - for i := 1; i < height; i++ { - s.LastBlockHeight++ - s.LastValidators = s.Validators.Copy() - if err := stateStore.Save(s); err != nil { - panic(err) - } - } - - return s, stateDB, privVals + }, nil } func genValSet(size int) *types.ValidatorSet { @@ -169,12 +126,11 @@ func genValSet(size int) *types.ValidatorSet { } func makeHeaderPartsResponsesValPubKeyChange( - t *testing.T, state sm.State, pubkey crypto.PubKey, -) (types.Header, types.BlockID, *abci.ResponseFinalizeBlock) { +) (types.Header, types.BlockID, *abci.FinalizeBlockResponse) { block := makeBlock(state, state.LastBlockHeight+1, new(types.Commit)) - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} // If the pubkey is new, remove the old and add the new. _, val := state.NextValidators.GetByIndex(0) if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) { @@ -188,12 +144,11 @@ func makeHeaderPartsResponsesValPubKeyChange( } func makeHeaderPartsResponsesValPowerChange( - t *testing.T, state sm.State, power int64, -) (types.Header, types.BlockID, *abci.ResponseFinalizeBlock) { +) (types.Header, types.BlockID, *abci.FinalizeBlockResponse) { block := makeBlock(state, state.LastBlockHeight+1, new(types.Commit)) - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} // If the pubkey is new, remove the old and add the new. _, val := state.NextValidators.GetByIndex(0) @@ -207,12 +162,11 @@ func makeHeaderPartsResponsesValPowerChange( } func makeHeaderPartsResponsesParams( - t *testing.T, state sm.State, params cmtproto.ConsensusParams, -) (types.Header, types.BlockID, *abci.ResponseFinalizeBlock) { +) (types.Header, types.BlockID, *abci.FinalizeBlockResponse) { block := makeBlock(state, state.LastBlockHeight+1, new(types.Commit)) - abciResponses := &abci.ResponseFinalizeBlock{ + abciResponses := &abci.FinalizeBlockResponse{ ConsensusParamUpdates: ¶ms, } return block.Header, types.BlockID{Hash: block.Hash(), PartSetHeader: types.PartSetHeader{}}, abciResponses @@ -235,22 +189,24 @@ func randomGenesisDoc() *types.GenesisDoc { } } -//---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- type testApp struct { abci.BaseApplication CommitVotes []abci.VoteInfo Misbehavior []abci.Misbehavior + LastTime time.Time ValidatorUpdates []abci.ValidatorUpdate AppHash []byte } var _ abci.Application = (*testApp)(nil) -func (app *testApp) FinalizeBlock(_ context.Context, req *abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) { +func (app *testApp) FinalizeBlock(_ context.Context, req *abci.FinalizeBlockRequest) (*abci.FinalizeBlockResponse, error) { app.CommitVotes = req.DecidedLastCommit.Votes app.Misbehavior = req.Misbehavior + app.LastTime = req.Time txResults := make([]*abci.ExecTxResult, len(req.Txs)) for idx := range req.Txs { txResults[idx] = &abci.ExecTxResult{ @@ -258,7 +214,7 @@ func (app *testApp) FinalizeBlock(_ context.Context, req *abci.RequestFinalizeBl } } - return &abci.ResponseFinalizeBlock{ + return &abci.FinalizeBlockResponse{ ValidatorUpdates: app.ValidatorUpdates, ConsensusParamUpdates: &cmtproto.ConsensusParams{ Version: &cmtproto.VersionParams{ @@ -270,14 +226,14 @@ func (app *testApp) FinalizeBlock(_ context.Context, req *abci.RequestFinalizeBl }, nil } -func (app *testApp) Commit(_ context.Context, _ *abci.RequestCommit) (*abci.ResponseCommit, error) { - return &abci.ResponseCommit{RetainHeight: 1}, nil +func (*testApp) Commit(_ context.Context, _ *abci.CommitRequest) (*abci.CommitResponse, error) { + return &abci.CommitResponse{RetainHeight: 1}, nil } -func (app *testApp) PrepareProposal( +func (*testApp) PrepareProposal( _ context.Context, - req *abci.RequestPrepareProposal, -) (*abci.ResponsePrepareProposal, error) { + req *abci.PrepareProposalRequest, +) (*abci.PrepareProposalResponse, error) { txs := make([][]byte, 0, len(req.Txs)) var totalBytes int64 for _, tx := range req.Txs { @@ -290,17 +246,50 @@ func (app *testApp) PrepareProposal( } txs = append(txs, tx) } - return &abci.ResponsePrepareProposal{Txs: txs}, nil + return &abci.PrepareProposalResponse{Txs: txs}, nil } -func (app *testApp) ProcessProposal( +func (*testApp) ProcessProposal( _ context.Context, - req *abci.RequestProcessProposal, -) (*abci.ResponseProcessProposal, error) { + req *abci.ProcessProposalRequest, +) (*abci.ProcessProposalResponse, error) { for _, tx := range req.Txs { if len(tx) == 0 { - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + return &abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_REJECT}, nil } } - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil + return &abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil +} + +func makeStateWithParams(nVals, height int, params *types.ConsensusParams, chainID string) (sm.State, dbm.DB, map[string]types.PrivValidator) { + vals, privVals := test.GenesisValidatorSet(nVals) + + s, _ := sm.MakeGenesisState(&types.GenesisDoc{ + ChainID: chainID, + Validators: vals, + AppHash: nil, + ConsensusParams: params, + }) + + stateDB := dbm.NewMemDB() + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + if err := stateStore.Save(s); err != nil { + panic(err) + } + + for i := 1; i < height; i++ { + s.LastBlockHeight++ + s.LastValidators = s.Validators.Copy() + if err := stateStore.Save(s); err != nil { + panic(err) + } + } + + return s, stateDB, privVals +} + +func makeState(nVals, height int, chainID string) (sm.State, dbm.DB, map[string]types.PrivValidator) { + return makeStateWithParams(nVals, height, test.ConsensusParams(), chainID) } diff --git a/state/indexer/block.go b/internal/state/indexer/block.go similarity index 61% rename from state/indexer/block.go rename to internal/state/indexer/block.go index b79d66f9a3c..f889f59183c 100644 --- a/state/indexer/block.go +++ b/internal/state/indexer/block.go @@ -3,11 +3,12 @@ package indexer import ( "context" - "github.com/cometbft/cometbft/libs/pubsub/query" + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/types" ) -//go:generate ../../scripts/mockery_generate.sh BlockIndexer +//go:generate ../../../scripts/mockery_generate.sh BlockIndexer // BlockIndexer defines an interface contract for indexing block events. type BlockIndexer interface { @@ -16,9 +17,17 @@ type BlockIndexer interface { Has(height int64) (bool, error) // Index indexes FinalizeBlock events for a given block by its height. - Index(types.EventDataNewBlockEvents) error + Index(events types.EventDataNewBlockEvents) error // Search performs a query for block heights that match a given FinalizeBlock // event search criteria. Search(ctx context.Context, q *query.Query) ([]int64, error) + + SetLogger(l log.Logger) + + Prune(retainHeight int64) (int64, int64, error) + + SetRetainHeight(retainHeight int64) error + + GetRetainHeight() (int64, error) } diff --git a/state/indexer/block/indexer.go b/internal/state/indexer/block/indexer.go similarity index 64% rename from state/indexer/block/indexer.go rename to internal/state/indexer/block/indexer.go index b489e022daf..64f2c05018e 100644 --- a/state/indexer/block/indexer.go +++ b/internal/state/indexer/block/indexer.go @@ -5,15 +5,14 @@ import ( "fmt" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/state/indexer" - blockidxkv "github.com/cometbft/cometbft/state/indexer/block/kv" - blockidxnull "github.com/cometbft/cometbft/state/indexer/block/null" - "github.com/cometbft/cometbft/state/indexer/sink/psql" - "github.com/cometbft/cometbft/state/txindex" - "github.com/cometbft/cometbft/state/txindex/kv" - "github.com/cometbft/cometbft/state/txindex/null" + "github.com/cometbft/cometbft/internal/state/indexer" + blockidxkv "github.com/cometbft/cometbft/internal/state/indexer/block/kv" + blockidxnull "github.com/cometbft/cometbft/internal/state/indexer/block/null" + "github.com/cometbft/cometbft/internal/state/indexer/sink/psql" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/internal/state/txindex/kv" + "github.com/cometbft/cometbft/internal/state/txindex/null" ) // EventSinksFromConfig constructs a slice of indexer.EventSink using the provided @@ -28,7 +27,7 @@ func IndexerFromConfig(cfg *config.Config, dbProvider config.DBProvider, chainID return nil, nil, err } - return kv.NewTxIndex(store), blockidxkv.New(dbm.NewPrefixDB(store, []byte("block_events"))), nil + return kv.NewTxIndex(store), blockidxkv.New(dbm.NewPrefixDB(store, []byte("block_events")), blockidxkv.WithCompaction(cfg.Storage.Compact, cfg.Storage.CompactionInterval)), nil case "psql": conn := cfg.TxIndex.PsqlConn diff --git a/internal/state/indexer/block/kv/export_test.go b/internal/state/indexer/block/kv/export_test.go new file mode 100644 index 00000000000..28e484e4905 --- /dev/null +++ b/internal/state/indexer/block/kv/export_test.go @@ -0,0 +1,5 @@ +package kv + +func GetKeys(indexer BlockerIndexer) [][]byte { + return getKeys(indexer) +} diff --git a/state/indexer/block/kv/kv.go b/internal/state/indexer/block/kv/kv.go similarity index 66% rename from state/indexer/block/kv/kv.go rename to internal/state/indexer/block/kv/kv.go index 6128bd37fc5..0d791883c74 100644 --- a/state/indexer/block/kv/kv.go +++ b/internal/state/indexer/block/kv/kv.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "math/big" "sort" "strconv" "strings" @@ -12,15 +13,21 @@ import ( "github.com/google/orderedcode" dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" - "github.com/cometbft/cometbft/libs/pubsub/query/syntax" - "github.com/cometbft/cometbft/state/indexer" + idxutil "github.com/cometbft/cometbft/internal/indexer" + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/internal/pubsub/query/syntax" + "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/types" ) -var _ indexer.BlockIndexer = (*BlockerIndexer)(nil) +var ( + LastBlockIndexerRetainHeightKey = []byte("LastBlockIndexerRetainHeightKey") + BlockIndexerRetainHeightKey = []byte("BlockIndexerRetainHeightKey") + ErrInvalidHeightValue = errors.New("invalid height value") +) // BlockerIndexer implements a block indexer, indexing FinalizeBlock // events with an underlying KV store. Block events are indexed by their height, @@ -31,12 +38,36 @@ type BlockerIndexer struct { // Add unique event identifier to use when querying // Matching will be done both on height AND eventSeq eventSeq int64 + log log.Logger + + compact bool + compactionInterval int64 + lastPruned int64 +} +type IndexerOption func(*BlockerIndexer) + +// WithCompaction sets the compaciton parameters. +func WithCompaction(compact bool, compactionInterval int64) IndexerOption { + return func(idx *BlockerIndexer) { + idx.compact = compact + idx.compactionInterval = compactionInterval + } } -func New(store dbm.DB) *BlockerIndexer { - return &BlockerIndexer{ +func New(store dbm.DB, options ...IndexerOption) *BlockerIndexer { + bsIndexer := &BlockerIndexer{ store: store, } + + for _, option := range options { + option(bsIndexer) + } + + return bsIndexer +} + +func (idx *BlockerIndexer) SetLogger(l log.Logger) { + idx.log = l } // Has returns true if the given height has been indexed. An error is returned @@ -54,7 +85,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|eventSeq) => 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() @@ -71,13 +102,144 @@ func (idx *BlockerIndexer) Index(bh types.EventDataNewBlockEvents) error { } // 2. index block events - if err := idx.indexEvents(batch, bh.Events, "finalize_block", height); err != nil { + if err := idx.indexEvents(batch, bh.Events, height); err != nil { return fmt.Errorf("failed to index FinalizeBlock events: %w", err) } - return batch.WriteSync() } +func getKeys(indexer BlockerIndexer) [][]byte { + var keys [][]byte + + itr, err := indexer.store.Iterator(nil, nil) + if err != nil { + panic(err) + } + for ; itr.Valid(); itr.Next() { + keys = append(keys, itr.Key()) + } + return keys +} + +func (idx *BlockerIndexer) Prune(retainHeight int64) (numPruned int64, newRetainHeight int64, err error) { + // Returns numPruned, newRetainHeight, err + // numPruned: the number of heights pruned or 0 in case of error. E.x. if heights {1, 3, 7} were pruned and there was no error, numPruned == 3 + // newRetainHeight: new retain height after pruning or lastRetainHeight in case of error + // err: error + + lastRetainHeight, err := idx.getLastRetainHeight() + if err != nil { + return 0, 0, fmt.Errorf("failed to look up last block indexer retain height: %w", err) + } + if lastRetainHeight == 0 { + lastRetainHeight = 1 + } + + batch := idx.store.NewBatch() + closeBatch := func(batch dbm.Batch) { + err := batch.Close() + if err != nil { + idx.log.Error(fmt.Sprintf("Error when closing block indexer pruning batch: %v", err)) + } + } + defer closeBatch(batch) + + flush := func(batch dbm.Batch) error { + err := batch.WriteSync() + if err != nil { + return fmt.Errorf("failed to flush block indexer pruning batch %w", err) + } + err = batch.Close() + if err != nil { + idx.log.Error(fmt.Sprintf("Error when closing block indexer pruning batch: %v", err)) + } + return nil + } + + itr, err := idx.store.Iterator(nil, nil) + if err != nil { + return 0, lastRetainHeight, err + } + deleted := int64(0) + affectedHeights := make(map[int64]struct{}) + for ; itr.Valid(); itr.Next() { + if keyBelongsToHeightRange(itr.Key(), lastRetainHeight, retainHeight) { + err := batch.Delete(itr.Key()) + if err != nil { + return 0, lastRetainHeight, err + } + height := getHeightFromKey(itr.Key()) + affectedHeights[height] = struct{}{} + deleted++ + } + if deleted%1000 == 0 && deleted != 0 { + err = flush(batch) + if err != nil { + return 0, lastRetainHeight, err + } + batch = idx.store.NewBatch() + defer closeBatch(batch) + } + } + + errSetLastRetainHeight := idx.setLastRetainHeight(retainHeight, batch) + if errSetLastRetainHeight != nil { + return 0, lastRetainHeight, errSetLastRetainHeight + } + errWriteBatch := batch.WriteSync() + if errWriteBatch != nil { + return 0, lastRetainHeight, errWriteBatch + } + + if idx.compact && idx.lastPruned+deleted >= idx.compactionInterval { + err = idx.store.Compact(nil, nil) + idx.lastPruned = 0 + } + idx.lastPruned += deleted + + return int64(len(affectedHeights)), retainHeight, err +} + +func (idx *BlockerIndexer) SetRetainHeight(retainHeight int64) error { + return idx.store.SetSync(BlockIndexerRetainHeightKey, int64ToBytes(retainHeight)) +} + +func (idx *BlockerIndexer) GetRetainHeight() (int64, error) { + buf, err := idx.store.Get(BlockIndexerRetainHeightKey) + if err != nil { + return 0, err + } + if buf == nil { + return 0, state.ErrKeyNotFound + } + height := int64FromBytes(buf) + + if height < 0 { + return 0, state.ErrInvalidHeightValue + } + + return height, nil +} + +func (*BlockerIndexer) setLastRetainHeight(height int64, batch dbm.Batch) error { + return batch.Set(LastBlockIndexerRetainHeightKey, int64ToBytes(height)) +} + +func (idx *BlockerIndexer) getLastRetainHeight() (int64, error) { + bz, err := idx.store.Get(LastBlockIndexerRetainHeightKey) + if err != nil { + return 0, err + } + if bz == nil { + return 0, nil + } + height := int64FromBytes(bz) + if height < 0 { + return 0, ErrInvalidHeightValue + } + return height, nil +} + // Search performs a query for block heights that match a given FinalizeBlock // event search criteria. The given query can match against zero, // one or more block heights. In the case of height queries, i.e. block.height=H, @@ -149,7 +311,6 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, // additional constraint on events) continue - } prefix, err := orderedcode.Append(nil, qr.Key) if err != nil { @@ -229,7 +390,6 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, select { case <-ctx.Done(): - break default: } @@ -285,26 +445,51 @@ LOOP: continue } - if _, ok := qr.AnyBound().(int64); ok { - v, err := strconv.ParseInt(eventValue, 10, 64) - if err != nil { - continue LOOP + if _, ok := qr.AnyBound().(*big.Float); ok { + v := new(big.Int) + v, ok := v.SetString(eventValue, 10) + var vF *big.Float + if !ok { + // The precision here is 125. For numbers bigger than this, the value + // will not be parsed properly + vF, _, err = big.ParseFloat(eventValue, 10, 125, big.ToNearestEven) + if err != nil { + continue LOOP + } } if qr.Key != types.BlockHeightKey { keyHeight, err := parseHeightFromEventKey(it.Key()) - if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + if err != nil { + idx.log.Error("failure to parse height from key:", err) + continue LOOP + } + withinHeight, err := checkHeightConditions(heightInfo, keyHeight) + if err != nil { + idx.log.Error("failure checking for height bounds:", err) + continue LOOP + } + if !withinHeight { continue LOOP } } - if checkBounds(qr, v) { + + var withinBounds bool + var err error + if !ok { + withinBounds, err = idxutil.CheckBounds(qr, vF) + } else { + withinBounds, err = idxutil.CheckBounds(qr, v) + } + if err != nil { + idx.log.Error("failed to parse bounds:", err) + } else if withinBounds { idx.setTmpHeights(tmpHeights, it) } } select { case <-ctx.Done(): - break default: } @@ -337,7 +522,6 @@ LOOP: select { case <-ctx.Done(): - break default: } @@ -347,28 +531,12 @@ LOOP: return filteredHeights, nil } -func (idx *BlockerIndexer) setTmpHeights(tmpHeights map[string][]byte, it dbm.Iterator) { +func (*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 @@ -402,9 +570,17 @@ func (idx *BlockerIndexer) match( defer it.Close() for ; it.Valid(); it.Next() { - keyHeight, err := parseHeightFromEventKey(it.Key()) - if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + if err != nil { + idx.log.Error("failure to parse height from key:", err) + continue + } + withinHeight, err := checkHeightConditions(heightInfo, keyHeight) + if err != nil { + idx.log.Error("failure checking for height bounds:", err) + continue + } + if !withinHeight { continue } @@ -433,9 +609,19 @@ func (idx *BlockerIndexer) match( for ; it.Valid(); it.Next() { keyHeight, err := parseHeightFromEventKey(it.Key()) - if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + if err != nil { + idx.log.Error("failure to parse height from key:", err) continue } + withinHeight, err := checkHeightConditions(heightInfo, keyHeight) + if err != nil { + idx.log.Error("failure checking for height bounds:", err) + continue + } + if !withinHeight { + continue + } + idx.setTmpHeights(tmpHeights, it) select { @@ -470,7 +656,16 @@ func (idx *BlockerIndexer) match( if strings.Contains(eventValue, c.Arg.Value()) { keyHeight, err := parseHeightFromEventKey(it.Key()) - if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + if err != nil { + idx.log.Error("failure to parse height from key:", err) + continue + } + withinHeight, err := checkHeightConditions(heightInfo, keyHeight) + if err != nil { + idx.log.Error("failure checking for height bounds:", err) + continue + } + if !withinHeight { continue } idx.setTmpHeights(tmpHeights, it) @@ -511,7 +706,6 @@ func (idx *BlockerIndexer) match( select { case <-ctx.Done(): - break default: } @@ -521,11 +715,11 @@ func (idx *BlockerIndexer) match( return filteredHeights, nil } -func (idx *BlockerIndexer) indexEvents(batch dbm.Batch, events []abci.Event, typ string, height int64) error { +func (idx *BlockerIndexer) indexEvents(batch dbm.Batch, events []abci.Event, height int64) error { heightBz := int64ToBytes(height) for _, event := range events { - idx.eventSeq = idx.eventSeq + 1 + idx.eventSeq++ // only index events with a non-empty type if len(event.Type) == 0 { continue @@ -543,7 +737,7 @@ func (idx *BlockerIndexer) indexEvents(batch dbm.Batch, events []abci.Event, typ } if attr.GetIndex() { - key, err := eventKey(compositeKey, typ, attr.Value, height, idx.eventSeq) + key, err := eventKey(compositeKey, attr.Value, height, idx.eventSeq) if err != nil { return fmt.Errorf("failed to create block index key: %w", err) } @@ -554,6 +748,5 @@ func (idx *BlockerIndexer) indexEvents(batch dbm.Batch, events []abci.Event, typ } } } - return nil } diff --git a/state/indexer/block/kv/kv_test.go b/internal/state/indexer/block/kv/kv_test.go similarity index 53% rename from state/indexer/block/kv/kv_test.go rename to internal/state/indexer/block/kv/kv_test.go index e28cf6ec02a..99df2ceaa1e 100644 --- a/state/indexer/block/kv/kv_test.go +++ b/internal/state/indexer/block/kv/kv_test.go @@ -1,20 +1,94 @@ package kv_test import ( + "bytes" "context" "fmt" + "os" + "strconv" "testing" + "time" "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" db "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" - blockidxkv "github.com/cometbft/cometbft/state/indexer/block/kv" + "github.com/cometbft/cometbft/internal/pubsub/query" + blockidxkv "github.com/cometbft/cometbft/internal/state/indexer/block/kv" + "github.com/cometbft/cometbft/internal/state/txindex/kv" + "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/types" ) +func TestBlockerIndexer_Prune(t *testing.T) { + store := db.NewPrefixDB(db.NewMemDB(), []byte("block_events")) + indexer := blockidxkv.New(store) + + events1 := getEventsForTesting(1) + events2 := getEventsForTesting(2) + + metaKeys := [][]byte{ + kv.LastTxIndexerRetainHeightKey, + blockidxkv.LastBlockIndexerRetainHeightKey, + kv.TxIndexerRetainHeightKey, + blockidxkv.BlockIndexerRetainHeightKey, + } + + err := indexer.Index(events1) + require.NoError(t, err) + + keys1 := blockidxkv.GetKeys(*indexer) + + err = indexer.Index(events2) + require.NoError(t, err) + + keys2 := blockidxkv.GetKeys(*indexer) + + require.True(t, isSubset(keys1, keys2)) + + numPruned, retainedHeight, err := indexer.Prune(2) + require.NoError(t, err) + require.Equal(t, int64(1), numPruned) + require.Equal(t, int64(2), retainedHeight) + + keys3 := blockidxkv.GetKeys(*indexer) + require.True(t, isEqualSets(setDiff(keys2, keys1), setDiff(keys3, metaKeys))) + require.True(t, emptyIntersection(keys1, keys3)) +} + +func BenchmarkBlockerIndexer_Prune(_ *testing.B) { + config := test.ResetTestRoot("block_indexer") + defer func() { + err := os.RemoveAll(config.RootDir) + if err != nil { + panic(err) + } + }() + + store, err := db.NewDB("block", db.GoLevelDBBackend, config.DBDir()) + if err != nil { + panic(err) + } + indexer := blockidxkv.New(store) + + maxHeight := 10000 + for h := 1; h < maxHeight; h++ { + event := getEventsForTesting(int64(h)) + err := indexer.Index(event) + if err != nil { + panic(err) + } + } + + startTime := time.Now() + + for h := 1; h <= maxHeight; h++ { + _, _, _ = indexer.Prune(int64(h)) + } + fmt.Println(time.Since(startTime)) +} + func TestBlockIndexer(t *testing.T) { store := db.NewPrefixDB(db.NewMemDB(), []byte("block_events")) indexer := blockidxkv.New(store) @@ -69,7 +143,7 @@ func TestBlockIndexer(t *testing.T) { Attributes: []abci.EventAttribute{ { Key: "foo", - Value: fmt.Sprintf("%d", i), + Value: strconv.Itoa(i), Index: index, }, }, @@ -224,31 +298,18 @@ func TestBlockIndexerMulti(t *testing.T) { 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}, @@ -261,10 +322,6 @@ func TestBlockIndexerMulti(t *testing.T) { 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{}, @@ -281,7 +338,7 @@ func TestBlockIndexerMulti(t *testing.T) { q: query.MustCompile("block.height = 2 AND end_event.foo < 300"), results: []int64{2}, }, - "deduplication test - match.events multiple 2": { + "match attributes across events with height constraint": { q: query.MustCompile("end_event.foo = 100 AND end_event.bar = 400 AND block.height = 2"), results: []int64{}, }, @@ -293,10 +350,6 @@ func TestBlockIndexerMulti(t *testing.T) { 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}, @@ -320,3 +373,204 @@ func TestBlockIndexerMulti(t *testing.T) { }) } } + +func TestBigInt(t *testing.T) { + bigInt := "10000000000000000000" + bigFloat := bigInt + ".76" + bigFloatLower := bigInt + ".1" + bigIntSmaller := "9999999999999999999" + 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: bigFloat, + Index: true, + }, + { + Key: "bar_lower", + Value: bigFloatLower, + Index: true, + }, + }, + }, + { + Type: "end_event", + Attributes: []abci.EventAttribute{ + { + Key: "foo", + Value: bigInt, + Index: true, + }, + { + Key: "bar", + Value: "500", + Index: true, + }, + { + Key: "bla", + Value: "500.5", + 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 (deduplicate height)": { + 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 matches fields with big int and height - no match": { + q: query.MustCompile("end_event.foo = " + bigInt + " AND end_event.bar = 500 AND block.height = 2"), + results: []int64{}, + }, + "query matches fields with big int with less and height - no match": { + q: query.MustCompile("end_event.foo <= " + bigInt + " AND end_event.bar = 500 AND block.height = 2"), + results: []int64{}, + }, + "query matches fields with big int and height - match": { + q: query.MustCompile("end_event.foo = " + bigInt + " AND end_event.bar = 500 AND block.height = 1"), + results: []int64{1}, + }, + "query matches big int in range": { + q: query.MustCompile("end_event.foo = " + bigInt), + results: []int64{1}, + }, + "query matches big int in range with float with equality ": { + q: query.MustCompile("end_event.bar >= " + bigInt), + results: []int64{1}, + }, + "query matches big int in range with float ": { + q: query.MustCompile("end_event.bar > " + bigInt), + results: []int64{1}, + }, + "query matches big int in range with float lower dec point ": { + q: query.MustCompile("end_event.bar_lower > " + bigInt), + results: []int64{1}, + }, + "query matches big int in range with float with less - found": { + q: query.MustCompile("end_event.foo <= " + bigInt), + results: []int64{1}, + }, + "query matches big int in range with float with less with height range - found": { + q: query.MustCompile("end_event.foo <= " + bigInt + " AND block.height > 0"), + results: []int64{1}, + }, + "query matches big int in range with float with less - not found": { + q: query.MustCompile("end_event.foo < " + bigInt + " AND end_event.foo > 100"), + results: []int64{}, + }, + "query does not parse float": { + q: query.MustCompile("end_event.bla >= 500"), + results: []int64{1}, + }, + "query condition float": { + q: query.MustCompile("end_event.bla < " + bigFloat), + results: []int64{1}, + }, + "query condition big int plus one": { + q: query.MustCompile("end_event.foo > " + bigIntSmaller), + results: []int64{1}, + }, + } + 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 getEventsForTesting(height int64) types.EventDataNewBlockEvents { + return types.EventDataNewBlockEvents{ + Height: height, + Events: []abci.Event{ + { + Type: "begin_event", + Attributes: []abci.EventAttribute{ + { + Key: "proposer", + Value: "FCAA001", + Index: true, + }, + }, + }, + { + Type: "end_event", + Attributes: []abci.EventAttribute{ + { + Key: "foo", + Value: "100", + Index: true, + }, + }, + }, + }, + } +} + +func isSubset(smaller [][]byte, bigger [][]byte) bool { + for _, elem := range smaller { + if !slices.ContainsFunc(bigger, func(i []byte) bool { + return bytes.Equal(i, elem) + }) { + return false + } + } + return true +} + +func isEqualSets(x [][]byte, y [][]byte) bool { + return isSubset(x, y) && isSubset(y, x) +} + +func emptyIntersection(x [][]byte, y [][]byte) bool { + for _, elem := range x { + if slices.ContainsFunc(y, func(i []byte) bool { + return bytes.Equal(i, elem) + }) { + return false + } + } + return true +} + +func setDiff(bigger [][]byte, smaller [][]byte) [][]byte { + var diff [][]byte + for _, elem := range bigger { + if !slices.ContainsFunc(smaller, func(i []byte) bool { + return bytes.Equal(i, elem) + }) { + diff = append(diff, elem) + } + } + return diff +} diff --git a/internal/state/indexer/block/kv/util.go b/internal/state/indexer/block/kv/util.go new file mode 100644 index 00000000000..d2c18b0848c --- /dev/null +++ b/internal/state/indexer/block/kv/util.go @@ -0,0 +1,258 @@ +package kv + +import ( + "encoding/binary" + "errors" + "fmt" + "math/big" + "strconv" + + "github.com/google/orderedcode" + + idxutil "github.com/cometbft/cometbft/internal/indexer" + "github.com/cometbft/cometbft/internal/pubsub/query/syntax" + "github.com/cometbft/cometbft/internal/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 { + return true + } + } + + return false +} + +func int64FromBytes(bz []byte) int64 { + v, _ := binary.Varint(bz) + return v +} + +func int64ToBytes(i int64) []byte { + buf := make([]byte, binary.MaxVarintLen64) + n := binary.PutVarint(buf, i) + return buf[:n] +} + +func heightKey(height int64) ([]byte, error) { + return orderedcode.Append( + nil, + types.BlockHeightKey, + height, + ) +} + +// keyBelongsToHeightRange checks whether the passed key belongs to the specified height range. +// That might not be the case for two reasons: the key belongs to the height out of the specified range, +// or the key doesn't belong to any height, meaning it's neither heightKey nor eventKey. +func keyBelongsToHeightRange(key []byte, left, right int64) bool { + // left included, right excluded + eventHeight, err := parseHeightFromEventKey(key) + if err == nil { + return left <= eventHeight && eventHeight < right + } + + var ( + blockHeightKeyPrefix string + possibleHeight int64 + ) + remaining, err := orderedcode.Parse(string(key), &blockHeightKeyPrefix, &possibleHeight) + if err != nil { + return false + } + return len(remaining) == 0 && + blockHeightKeyPrefix == types.BlockHeightKey && + left <= possibleHeight && + possibleHeight < right +} + +// getHeightFromKey requires its argument key to be the key with height (either heightKey or eventKey). +// Provided that, it extracts the height. +func getHeightFromKey(key []byte) int64 { + // Must be called with either heightKey or eventKey + eventHeight, err := parseHeightFromEventKey(key) + if err == nil { + return eventHeight + } + + var ( + blockHeightKeyPrefix string + possibleHeight int64 + ) + remaining, err := orderedcode.Parse(string(key), &blockHeightKeyPrefix, &possibleHeight) + if err != nil { + panic(err) + } + if len(remaining) == 0 && blockHeightKeyPrefix == types.BlockHeightKey { + return possibleHeight + } + panic(errors.New("key must be either heightKey or eventKey")) +} + +func eventKey(compositeKey, eventValue string, height int64, eventSeq int64) ([]byte, error) { + return orderedcode.Append( + nil, + compositeKey, + eventValue, + height, + eventSeq, + ) +} + +func parseValueFromPrimaryKey(key []byte) (string, error) { + var ( + compositeKey string + height int64 + ) + + remaining, err := orderedcode.Parse(string(key), &compositeKey, &height) + if err != nil { + return "", fmt.Errorf("failed to parse event key: %w", err) + } + + if len(remaining) != 0 { + return "", fmt.Errorf("unexpected remainder in key: %s", remaining) + } + + return strconv.FormatInt(height, 10), nil +} + +func parseValueFromEventKey(key []byte) (string, error) { + var ( + compositeKey, eventValue string + height int64 + ) + + _, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height) + if err != nil { + return "", fmt.Errorf("failed to parse event key: %w", err) + } + + return eventValue, nil +} + +func parseHeightFromEventKey(key []byte) (int64, error) { + var ( + compositeKey, eventValue string + height int64 + ) + + _, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height) + 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, eventValue string + height int64 + eventSeq int64 + ) + + remaining, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height) + if err != nil { + return 0, fmt.Errorf("failed to parse event sequence: %w", err) + } + + // We either have an event sequence or a function type (potentially) followed by an event sequence. + // Potential scenarios: + // 1. Events indexed with v0.38.x and later, will only have an event sequence + // 2. Events indexed between v0.34.27 and v0.37.x will have a function type and an event sequence + // 3. Events indexed before v0.34.27 will only have a function type + // function_type = 'being_block_event' | 'end_block_event' + + if len(remaining) == 0 { // The event was not properly indexed + return 0, errors.New("failed to parse event sequence, invalid event format") + } + var typ string + remaining2, err := orderedcode.Parse(remaining, &typ) // Check if we have scenarios 2. or 3. (described above). + if err != nil { // If it cannot parse the event function type, it could be 1. + remaining, err2 := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &eventSeq) + if err2 != nil || len(remaining) != 0 { // We should not have anything else after the eventSeq. + return 0, fmt.Errorf("failed to parse event sequence: %w; and %w", err, err2) + } + } else if len(remaining2) != 0 { // Are we in case 2 or 3 + remaining, err2 := orderedcode.Parse(remaining2, &eventSeq) // the event follows the scenario in 2., + // retrieve the eventSeq + // there should be no error + if err2 != nil || len(remaining) != 0 { // We should not have anything else after the eventSeq if in 2. + return 0, fmt.Errorf("failed to parse event sequence: %w", err2) + } + } + return eventSeq, nil +} + +// 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 { + if c.Op == syntax.TEq { + if found || heightRangeExists { + continue + } + hFloat := c.Arg.Number() + if hFloat != nil { + h, _ := hFloat.Int64() + heightInfo.height = h + heightCondition = append(heightCondition, c) + 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 +} + +func checkHeightConditions(heightInfo HeightInfo, keyHeight int64) (bool, error) { + if heightInfo.heightRange.Key != "" { + withinBounds, err := idxutil.CheckBounds(heightInfo.heightRange, big.NewInt(keyHeight)) + if err != nil || !withinBounds { + return false, err + } + } else if heightInfo.height != 0 && keyHeight != heightInfo.height { + return false, nil + } + + return true, nil +} diff --git a/internal/state/indexer/block/null/null.go b/internal/state/indexer/block/null/null.go new file mode 100644 index 00000000000..0ab91e50fec --- /dev/null +++ b/internal/state/indexer/block/null/null.go @@ -0,0 +1,43 @@ +package null + +import ( + "context" + "errors" + + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/libs/log" + "github.com/cometbft/cometbft/types" +) + +var _ indexer.BlockIndexer = (*BlockerIndexer)(nil) + +// TxIndex implements a no-op block indexer. +type BlockerIndexer struct{} + +func (*BlockerIndexer) SetRetainHeight(_ int64) error { + return nil +} + +func (*BlockerIndexer) GetRetainHeight() (int64, error) { + return 0, nil +} + +func (*BlockerIndexer) Prune(_ int64) (numPruned, newRetainHeight int64, err error) { + return 0, 0, nil +} + +func (*BlockerIndexer) Has(int64) (bool, error) { + return false, errors.New(`indexing is disabled (set 'tx_index = "kv"' in config)`) +} + +func (*BlockerIndexer) Index(types.EventDataNewBlockEvents) error { + return nil +} + +func (*BlockerIndexer) Search(context.Context, *query.Query) ([]int64, error) { + return []int64{}, nil +} + +func (*BlockerIndexer) SetLogger(log.Logger) { +} diff --git a/internal/state/indexer/mocks/block_indexer.go b/internal/state/indexer/mocks/block_indexer.go new file mode 100644 index 00000000000..4034997ba16 --- /dev/null +++ b/internal/state/indexer/mocks/block_indexer.go @@ -0,0 +1,196 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + context "context" + + log "github.com/cometbft/cometbft/libs/log" + + mock "github.com/stretchr/testify/mock" + + query "github.com/cometbft/cometbft/internal/pubsub/query" + + types "github.com/cometbft/cometbft/types" +) + +// BlockIndexer is an autogenerated mock type for the BlockIndexer type +type BlockIndexer struct { + mock.Mock +} + +// GetRetainHeight provides a mock function with given fields: +func (_m *BlockIndexer) GetRetainHeight() (int64, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetRetainHeight") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func() (int64, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Has provides a mock function with given fields: height +func (_m *BlockIndexer) Has(height int64) (bool, error) { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for Has") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(int64) (bool, error)); ok { + return rf(height) + } + if rf, ok := ret.Get(0).(func(int64) bool); ok { + r0 = rf(height) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(int64) error); ok { + r1 = rf(height) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Index provides a mock function with given fields: events +func (_m *BlockIndexer) Index(events types.EventDataNewBlockEvents) error { + ret := _m.Called(events) + + if len(ret) == 0 { + panic("no return value specified for Index") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.EventDataNewBlockEvents) error); ok { + r0 = rf(events) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Prune provides a mock function with given fields: retainHeight +func (_m *BlockIndexer) Prune(retainHeight int64) (int64, int64, error) { + ret := _m.Called(retainHeight) + + if len(ret) == 0 { + panic("no return value specified for Prune") + } + + var r0 int64 + var r1 int64 + var r2 error + if rf, ok := ret.Get(0).(func(int64) (int64, int64, error)); ok { + return rf(retainHeight) + } + if rf, ok := ret.Get(0).(func(int64) int64); ok { + r0 = rf(retainHeight) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(int64) int64); ok { + r1 = rf(retainHeight) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(int64) error); ok { + r2 = rf(retainHeight) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// Search provides a mock function with given fields: ctx, q +func (_m *BlockIndexer) Search(ctx context.Context, q *query.Query) ([]int64, error) { + ret := _m.Called(ctx, q) + + if len(ret) == 0 { + panic("no return value specified for Search") + } + + var r0 []int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *query.Query) ([]int64, error)); ok { + return rf(ctx, q) + } + if rf, ok := ret.Get(0).(func(context.Context, *query.Query) []int64); ok { + r0 = rf(ctx, q) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]int64) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *query.Query) error); ok { + r1 = rf(ctx, q) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SetLogger provides a mock function with given fields: l +func (_m *BlockIndexer) SetLogger(l log.Logger) { + _m.Called(l) +} + +// SetRetainHeight provides a mock function with given fields: retainHeight +func (_m *BlockIndexer) SetRetainHeight(retainHeight int64) error { + ret := _m.Called(retainHeight) + + if len(ret) == 0 { + panic("no return value specified for SetRetainHeight") + } + + var r0 error + if rf, ok := ret.Get(0).(func(int64) error); ok { + r0 = rf(retainHeight) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// NewBlockIndexer creates a new instance of BlockIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBlockIndexer(t interface { + mock.TestingT + Cleanup(func()) +}) *BlockIndexer { + mock := &BlockIndexer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/state/indexer/query_range.go b/internal/state/indexer/query_range.go similarity index 80% rename from state/indexer/query_range.go rename to internal/state/indexer/query_range.go index e3cfdc6fda0..a6537375a74 100644 --- a/state/indexer/query_range.go +++ b/internal/state/indexer/query_range.go @@ -1,28 +1,29 @@ package indexer import ( + "math/big" "time" - "github.com/cometbft/cometbft/libs/pubsub/query/syntax" + "github.com/cometbft/cometbft/internal/pubsub/query/syntax" "github.com/cometbft/cometbft/types" ) // QueryRanges defines a mapping between a composite event key and a QueryRange. // -// e.g.account.number => queryRange{lowerBound: 1, upperBound: 5} +// e.g.account.number => queryRange{lowerBound: 1, upperBound: 5}. type QueryRanges map[string]QueryRange // QueryRange defines a range within a query condition. type QueryRange struct { - LowerBound interface{} // int || time.Time - UpperBound interface{} // int || time.Time + LowerBound any // int || time.Time + UpperBound any // int || time.Time Key string IncludeLowerBound bool IncludeUpperBound bool } // AnyBound returns either the lower bound if non-nil, otherwise the upper bound. -func (qr QueryRange) AnyBound() interface{} { +func (qr QueryRange) AnyBound() any { if qr.LowerBound != nil { return qr.LowerBound } @@ -32,7 +33,7 @@ func (qr QueryRange) AnyBound() interface{} { // LowerBoundValue returns the value for the lower bound. If the lower bound is // nil, nil will be returned. -func (qr QueryRange) LowerBoundValue() interface{} { +func (qr QueryRange) LowerBoundValue() any { if qr.LowerBound == nil { return nil } @@ -44,7 +45,17 @@ func (qr QueryRange) LowerBoundValue() interface{} { switch t := qr.LowerBound.(type) { case int64: return t + 1 - + case *big.Int: + tmp := new(big.Int) + return tmp.Add(t, big.NewInt(1)) + + case *big.Float: + // For floats we cannot simply add one as the float to float + // comparison is more finegrained. + // When comparing to integers, adding one is also incorrect: + // example: x >100.2 ; x = 101 float increased to 101.2 and condition + // is not satisfied + return t case time.Time: return t.Unix() + 1 @@ -55,7 +66,7 @@ func (qr QueryRange) LowerBoundValue() interface{} { // UpperBoundValue returns the value for the upper bound. If the upper bound is // nil, nil will be returned. -func (qr QueryRange) UpperBoundValue() interface{} { +func (qr QueryRange) UpperBoundValue() any { if qr.UpperBound == nil { return nil } @@ -67,7 +78,11 @@ func (qr QueryRange) UpperBoundValue() interface{} { switch t := qr.UpperBound.(type) { case int64: return t - 1 - + case *big.Int: + tmp := new(big.Int) + return tmp.Sub(t, big.NewInt(1)) + case *big.Float: + return t case time.Time: return t.Unix() - 1 @@ -81,14 +96,13 @@ func (qr QueryRange) UpperBoundValue() interface{} { 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) { + heightKey := c.Tag == types.BlockHeightKey || c.Tag == types.TxHeightKey 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 } } @@ -130,7 +144,7 @@ func LookForRangesWithHeight(conditions []syntax.Condition) (queryRange QueryRan return queryRange, indexes, heightRange } -// Deprecated: This function is not used anymore and will be replaced with LookForRangesWithHeight +// 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 { @@ -176,13 +190,13 @@ func IsRangeOperation(op syntax.Token) bool { } } -func conditionArg(c syntax.Condition) interface{} { +func conditionArg(c syntax.Condition) any { if c.Arg == nil { return nil } switch c.Arg.Type { case syntax.TNumber: - return int64(c.Arg.Number()) + return c.Arg.Number() case syntax.TTime, syntax.TDate: return c.Arg.Time() default: diff --git a/state/indexer/sink/psql/backport.go b/internal/state/indexer/sink/psql/backport.go similarity index 79% rename from state/indexer/sink/psql/backport.go rename to internal/state/indexer/sink/psql/backport.go index 429cf03d310..3791f1258a7 100644 --- a/state/indexer/sink/psql/backport.go +++ b/internal/state/indexer/sink/psql/backport.go @@ -18,15 +18,12 @@ import ( "errors" abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" - "github.com/cometbft/cometbft/state/txindex" + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/types" ) -const ( - eventTypeFinalizeBlock = "finalize_block" -) - // TxIndexer returns a bridge from es to the CometBFT v0.34 transaction indexer. func (es *EventSink) TxIndexer() BackportTxIndexer { return BackportTxIndexer{psql: es} @@ -36,6 +33,19 @@ func (es *EventSink) TxIndexer() BackportTxIndexer { // indexing operations to an underlying PostgreSQL event sink. type BackportTxIndexer struct{ psql *EventSink } +func (BackportTxIndexer) GetRetainHeight() (int64, error) { + return 0, nil +} + +func (BackportTxIndexer) SetRetainHeight(_ int64) error { + return nil +} + +func (BackportTxIndexer) Prune(_ int64) (numPruned, newRetainHeight int64, err error) { + // Not implemented + return 0, 0, nil +} + // AddBatch indexes a batch of transactions in Postgres, as part of TxIndexer. func (b BackportTxIndexer) AddBatch(batch *txindex.Batch) error { return b.psql.IndexTxEvents(batch.Ops) @@ -58,6 +68,8 @@ func (BackportTxIndexer) Search(context.Context, *query.Query) ([]*abci.TxResult return nil, errors.New("the TxIndexer.Search method is not supported") } +func (BackportTxIndexer) SetLogger(log.Logger) {} + // BlockIndexer returns a bridge that implements the CometBFT v0.34 block // indexer interface, using the Postgres event sink as a backing store. func (es *EventSink) BlockIndexer() BackportBlockIndexer { @@ -68,9 +80,22 @@ func (es *EventSink) BlockIndexer() BackportBlockIndexer { // delegating indexing operations to an underlying PostgreSQL event sink. type BackportBlockIndexer struct{ psql *EventSink } +func (BackportBlockIndexer) SetRetainHeight(_ int64) error { + return nil +} + +func (BackportBlockIndexer) GetRetainHeight() (int64, error) { + return 0, nil +} + +func (BackportBlockIndexer) Prune(_ int64) (numPruned, newRetainHeight int64, err error) { + // Not implemented + return 0, 0, nil +} + // Has is implemented to satisfy the BlockIndexer interface, but it is not // supported by the psql event sink and reports an error for all inputs. -func (BackportBlockIndexer) Has(height int64) (bool, error) { +func (BackportBlockIndexer) Has(_ int64) (bool, error) { return false, errors.New("the BlockIndexer.Has method is not supported") } @@ -85,3 +110,5 @@ func (b BackportBlockIndexer) Index(block types.EventDataNewBlockEvents) error { func (BackportBlockIndexer) Search(context.Context, *query.Query) ([]int64, error) { return nil, errors.New("the BlockIndexer.Search method is not supported") } + +func (BackportBlockIndexer) SetLogger(log.Logger) {} diff --git a/state/indexer/sink/psql/backport_test.go b/internal/state/indexer/sink/psql/backport_test.go similarity index 53% rename from state/indexer/sink/psql/backport_test.go rename to internal/state/indexer/sink/psql/backport_test.go index d8ff29e808b..f56d8aa4003 100644 --- a/state/indexer/sink/psql/backport_test.go +++ b/internal/state/indexer/sink/psql/backport_test.go @@ -1,8 +1,8 @@ package psql import ( - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/state/txindex" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/txindex" ) var ( diff --git a/internal/state/indexer/sink/psql/psql.go b/internal/state/indexer/sink/psql/psql.go new file mode 100644 index 00000000000..a6a84a12984 --- /dev/null +++ b/internal/state/indexer/sink/psql/psql.go @@ -0,0 +1,275 @@ +// Package psql implements an event sink backed by a PostgreSQL database. +package psql + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strconv" + "strings" + "time" + + "github.com/cosmos/gogoproto/proto" + "github.com/lib/pq" + + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/types" +) + +const ( + tableBlocks = "blocks" + tableTxResults = "tx_results" + tableEvents = "events" + tableAttributes = "attributes" + driverName = "postgres" +) + +// EventSink is an indexer backend providing the tx/block index services. This +// implementation stores records in a PostgreSQL database using the schema +// defined in state/indexer/sink/psql/schema.sql. +type EventSink struct { + store *sql.DB + chainID string +} + +// NewEventSink constructs an event sink associated with the PostgreSQL +// database specified by connStr. Events written to the sink are attributed to +// the specified chainID. +func NewEventSink(connStr, chainID string) (*EventSink, error) { + db, err := sql.Open(driverName, connStr) + if err != nil { + return nil, err + } + return &EventSink{ + store: db, + chainID: chainID, + }, nil +} + +// DB returns the underlying Postgres connection used by the sink. +// This is exported to support testing. +func (es *EventSink) DB() *sql.DB { return es.store } + +// runInTransaction executes query in a fresh database transaction. +// If query reports an error, the transaction is rolled back and the +// error from query is reported to the caller. +// Otherwise, the result of committing the transaction is returned. +func runInTransaction(db *sql.DB, query func(*sql.Tx) error) error { + dbtx, err := db.Begin() + if err != nil { + return err + } + if err := query(dbtx); err != nil { + _ = dbtx.Rollback() // report the initial error, not the rollback + return err + } + return dbtx.Commit() +} + +func runBulkInsert(db *sql.DB, tableName string, columns []string, inserts [][]any) error { + return runInTransaction(db, func(tx *sql.Tx) error { + stmt, err := tx.Prepare(pq.CopyIn(tableName, columns...)) + if err != nil { + return fmt.Errorf("preparing bulk insert statement: %w", err) + } + defer stmt.Close() + for _, insert := range inserts { + if _, err := stmt.Exec(insert...); err != nil { + return fmt.Errorf("executing insert statement: %w", err) + } + } + if _, err := stmt.Exec(); err != nil { + return fmt.Errorf("flushing bulk insert: %w", err) + } + return nil + }) +} + +func randomBigserial() int64 { + return rand.Int63() +} + +var ( + txrInsertColumns = []string{"rowid", "block_id", "index", "created_at", "tx_hash", "tx_result"} + eventInsertColumns = []string{"rowid", "block_id", "tx_id", "type"} + attrInsertColumns = []string{"event_id", "key", "composite_key", "value"} +) + +func bulkInsertEvents(blockID, txID int64, events []abci.Event) (eventInserts, attrInserts [][]any) { + // Populate the transaction ID field iff one is defined (> 0). + var txIDArg any + if txID > 0 { + txIDArg = txID + } + for _, event := range events { + // Skip events with an empty type. + if event.Type == "" { + continue + } + eventID := randomBigserial() + eventInserts = append(eventInserts, []any{eventID, blockID, txIDArg, event.Type}) + for _, attr := range event.Attributes { + if !attr.Index { + continue + } + compositeKey := event.Type + "." + attr.Key + attrInserts = append(attrInserts, []any{eventID, attr.Key, compositeKey, attr.Value}) + } + } + return eventInserts, attrInserts +} + +// makeIndexedEvent constructs an event from the specified composite key and +// value. If the key has the form "type.name", the event will have a single +// attribute with that name and the value; otherwise the event will have only +// a type and no attributes. +func makeIndexedEvent(compositeKey, value string) abci.Event { + i := strings.Index(compositeKey, ".") + if i < 0 { + return abci.Event{Type: compositeKey} + } + return abci.Event{Type: compositeKey[:i], Attributes: []abci.EventAttribute{ + {Key: compositeKey[i+1:], Value: value, Index: true}, + }} +} + +// IndexBlockEvents indexes the specified block header, part of the +// indexer.EventSink interface. +func (es *EventSink) IndexBlockEvents(h types.EventDataNewBlockEvents) error { + ts := time.Now().UTC() + + // Add the block to the blocks table and report back its row ID for use + // in indexing the events for the block. + var blockID int64 + //nolint:execinquery + err := es.store.QueryRow(` +INSERT INTO `+tableBlocks+` (height, chain_id, created_at) + VALUES ($1, $2, $3) + ON CONFLICT DO NOTHING + RETURNING rowid; +`, h.Height, es.chainID, ts).Scan(&blockID) + if err == sql.ErrNoRows { + return nil // we already saw this block; quietly succeed + } else if err != nil { + return fmt.Errorf("indexing block header: %w", err) + } + + // Insert the special block meta-event for height. + events := append([]abci.Event{makeIndexedEvent(types.BlockHeightKey, strconv.FormatInt(h.Height, 10))}, h.Events...) + // Insert all the block events. Order is important here, + eventInserts, attrInserts := bulkInsertEvents(blockID, 0, events) + if err := runBulkInsert(es.store, tableEvents, eventInsertColumns, eventInserts); err != nil { + return fmt.Errorf("failed bulk insert of events: %w", err) + } + if err := runBulkInsert(es.store, tableAttributes, attrInsertColumns, attrInserts); err != nil { + return fmt.Errorf("failed bulk insert of attributes: %w", err) + } + return nil +} + +// getBlockIDs returns corresponding block ids for the provided heights. +func (es *EventSink) getBlockIDs(heights []int64) ([]int64, error) { + var blockIDs pq.Int64Array + if err := es.store.QueryRow(` +SELECT array_agg(( + SELECT rowid FROM `+tableBlocks+` WHERE height = txr.height AND chain_id = $1 +)) FROM unnest($2::bigint[]) AS txr(height);`, + es.chainID, pq.Array(heights)).Scan(&blockIDs); err != nil { + return nil, fmt.Errorf("getting block ids for txs from sql: %w", err) + } + return blockIDs, nil +} + +func prefetchTxrExistence(db *sql.DB, blockIDs []int64, indexes []uint32) ([]bool, error) { + var existence []bool + if err := db.QueryRow(` +SELECT array_agg(( + SELECT EXISTS(SELECT 1 FROM `+tableTxResults+` WHERE block_id = txr.block_id AND index = txr.index) +)) FROM UNNEST($1::bigint[], $2::integer[]) as txr(block_id, index);`, + pq.Array(blockIDs), pq.Array(indexes)).Scan((*pq.BoolArray)(&existence)); err != nil { + return nil, fmt.Errorf("fetching already indexed txrs: %w", err) + } + return existence, nil +} + +func (es *EventSink) IndexTxEvents(txrs []*abci.TxResult) error { + ts := time.Now().UTC() + heights := make([]int64, len(txrs)) + indexes := make([]uint32, len(txrs)) + for i, txr := range txrs { + heights[i] = txr.Height + indexes[i] = txr.Index + } + // prefetch blockIDs for all txrs. Every block header must have been indexed + // prior to the transactions belonging to it. + blockIDs, err := es.getBlockIDs(heights) + if err != nil { + return fmt.Errorf("getting block ids for txs: %w", err) + } + alreadyIndexed, err := prefetchTxrExistence(es.store, blockIDs, indexes) + if err != nil { + return fmt.Errorf("failed to prefetch which txrs were already indexed: %w", err) + } + txrInserts, attrInserts, eventInserts := make([][]any, 0, len(txrs)), make([][]any, 0, len(txrs)), make([][]any, 0, len(txrs)) + for i, txr := range txrs { + if alreadyIndexed[i] { + continue + } + // Encode the result message in protobuf wire format for indexing. + resultData, err := proto.Marshal(txr) + if err != nil { + return fmt.Errorf("marshaling tx_result: %w", err) + } + // Index the hash of the underlying transaction as a hex string. + txHash := fmt.Sprintf("%X", types.Tx(txr.Tx).Hash()) + // Generate random ID for this tx_result and insert a record for it + txID := randomBigserial() + txrInserts = append(txrInserts, []any{txID, blockIDs[i], txr.Index, ts, txHash, resultData}) + // Insert the special transaction meta-events for hash and height. + events := append([]abci.Event{ + makeIndexedEvent(types.TxHashKey, txHash), + makeIndexedEvent(types.TxHeightKey, strconv.FormatInt(txr.Height, 10)), + }, + txr.Result.Events..., + ) + newEventInserts, newAttrInserts := bulkInsertEvents(blockIDs[i], txID, events) + eventInserts = append(eventInserts, newEventInserts...) + attrInserts = append(attrInserts, newAttrInserts...) + } + if err := runBulkInsert(es.store, tableTxResults, txrInsertColumns, txrInserts); err != nil { + return fmt.Errorf("bulk inserting txrs: %w", err) + } + if err := runBulkInsert(es.store, tableEvents, eventInsertColumns, eventInserts); err != nil { + return fmt.Errorf("bulk inserting events: %w", err) + } + if err := runBulkInsert(es.store, tableAttributes, attrInsertColumns, attrInserts); err != nil { + return fmt.Errorf("bulk inserting attributes: %w", err) + } + return nil +} + +// SearchBlockEvents is not implemented by this sink, and reports an error for all queries. +func (*EventSink) SearchBlockEvents(_ context.Context, _ *query.Query) ([]int64, error) { + return nil, errors.New("block search is not supported via the postgres event sink") +} + +// SearchTxEvents is not implemented by this sink, and reports an error for all queries. +func (*EventSink) SearchTxEvents(_ context.Context, _ *query.Query) ([]*abci.TxResult, error) { + return nil, errors.New("tx search is not supported via the postgres event sink") +} + +// GetTxByHash is not implemented by this sink, and reports an error for all queries. +func (*EventSink) GetTxByHash(_ []byte) (*abci.TxResult, error) { + return nil, errors.New("getTxByHash is not supported via the postgres event sink") +} + +// HasBlock is not implemented by this sink, and reports an error for all queries. +func (*EventSink) HasBlock(_ int64) (bool, error) { + return false, errors.New("hasBlock is not supported via the postgres event sink") +} + +// Stop closes the underlying PostgreSQL database. +func (es *EventSink) Stop() error { return es.store.Close() } diff --git a/state/indexer/sink/psql/psql_test.go b/internal/state/indexer/sink/psql/psql_test.go similarity index 98% rename from state/indexer/sink/psql/psql_test.go rename to internal/state/indexer/sink/psql/psql_test.go index 04bc704e84e..172c42c4de0 100644 --- a/state/indexer/sink/psql/psql_test.go +++ b/internal/state/indexer/sink/psql/psql_test.go @@ -18,13 +18,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + _ "github.com/lib/pq" + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/state/txindex" tmlog "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/state/txindex" "github.com/cometbft/cometbft/types" - - // Register the Postgres database driver. - _ "github.com/lib/pq" ) var ( @@ -46,6 +45,8 @@ const ( viewBlockEvents = "block_events" viewTxEvents = "tx_events" + + eventTypeFinalizeBlock = "finalize_block" ) func TestMain(m *testing.M) { @@ -269,7 +270,7 @@ func newTestBlockEvents() types.EventDataNewBlockEvents { } } -// readSchema loads the indexing database schema file +// readSchema loads the indexing database schema file. func readSchema() ([]*schema.Migration, error) { const filename = "schema.sql" contents, err := os.ReadFile(filename) @@ -338,6 +339,7 @@ SELECT DISTINCT %[1]s.created_at } func verifyBlock(t *testing.T, height int64) { + t.Helper() // Check that the blocks table contains an entry for this height. if err := testDB().QueryRow(` SELECT height FROM `+tableBlocks+` WHERE height = $1; @@ -368,7 +370,7 @@ func verifyNotImplemented(t *testing.T, label string, f func() (bool, error)) { want := label + " is not supported via the postgres event sink" ok, err := f() assert.False(t, ok) - require.NotNil(t, err) + require.Error(t, err) assert.Equal(t, want, err.Error()) } diff --git a/state/indexer/sink/psql/schema.sql b/internal/state/indexer/sink/psql/schema.sql similarity index 100% rename from state/indexer/sink/psql/schema.sql rename to internal/state/indexer/sink/psql/schema.sql diff --git a/internal/state/metrics.gen.go b/internal/state/metrics.gen.go new file mode 100644 index 00000000000..5e39e05e03a --- /dev/null +++ b/internal/state/metrics.gen.go @@ -0,0 +1,118 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package state + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + BlockProcessingTime: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_processing_time", + Help: "Time spent processing FinalizeBlock", + + Buckets: stdprometheus.LinearBuckets(1, 10, 10), + }, labels).With(labelsAndValues...), + ConsensusParamUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "consensus_param_updates", + Help: "Number of consensus parameter updates returned by the application since process start.", + }, labels).With(labelsAndValues...), + ValidatorSetUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "validator_set_updates", + Help: "Number of validator set updates returned by the application since process start.", + }, labels).With(labelsAndValues...), + PruningServiceBlockRetainHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "pruning_service_block_retain_height", + Help: "PruningServiceBlockRetainHeight is the accepted block retain height set by the data companion", + }, labels).With(labelsAndValues...), + PruningServiceBlockResultsRetainHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "pruning_service_block_results_retain_height", + Help: "PruningServiceBlockResultsRetainHeight is the accepted block results retain height set by the data companion", + }, labels).With(labelsAndValues...), + PruningServiceTxIndexerRetainHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "pruning_service_tx_indexer_retain_height", + Help: "PruningServiceTxIndexerRetainHeight is the accepted transactions indices retain height set by the data companion", + }, labels).With(labelsAndValues...), + PruningServiceBlockIndexerRetainHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "pruning_service_block_indexer_retain_height", + Help: "PruningServiceBlockIndexerRetainHeight is the accepted blocks indices retain height set by the data companion", + }, labels).With(labelsAndValues...), + ApplicationBlockRetainHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "application_block_retain_height", + Help: "ApplicationBlockRetainHeight is the accepted block retain height set by the application", + }, labels).With(labelsAndValues...), + BlockStoreBaseHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_store_base_height", + Help: "BlockStoreBaseHeight shows the first height at which a block is available", + }, labels).With(labelsAndValues...), + ABCIResultsBaseHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "abciresults_base_height", + Help: "ABCIResultsBaseHeight shows the first height at which abci results are available", + }, labels).With(labelsAndValues...), + TxIndexerBaseHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "tx_indexer_base_height", + Help: "TxIndexerBaseHeight shows the first height at which tx indices are available", + }, labels).With(labelsAndValues...), + BlockIndexerBaseHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_indexer_base_height", + Help: "BlockIndexerBaseHeight shows the first height at which block indices are available", + }, labels).With(labelsAndValues...), + StoreAccessDurationSeconds: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "store_access_duration_seconds", + Help: "The duration of accesses to the state store labeled by which method was called on the store.", + + Buckets: stdprometheus.ExponentialBuckets(0.0002, 10, 5), + }, append(labels, "method")).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + BlockProcessingTime: discard.NewHistogram(), + ConsensusParamUpdates: discard.NewCounter(), + ValidatorSetUpdates: discard.NewCounter(), + PruningServiceBlockRetainHeight: discard.NewGauge(), + PruningServiceBlockResultsRetainHeight: discard.NewGauge(), + PruningServiceTxIndexerRetainHeight: discard.NewGauge(), + PruningServiceBlockIndexerRetainHeight: discard.NewGauge(), + ApplicationBlockRetainHeight: discard.NewGauge(), + BlockStoreBaseHeight: discard.NewGauge(), + ABCIResultsBaseHeight: discard.NewGauge(), + TxIndexerBaseHeight: discard.NewGauge(), + BlockIndexerBaseHeight: discard.NewGauge(), + StoreAccessDurationSeconds: discard.NewHistogram(), + } +} diff --git a/internal/state/metrics.go b/internal/state/metrics.go new file mode 100644 index 00000000000..3b253483ee6 --- /dev/null +++ b/internal/state/metrics.go @@ -0,0 +1,69 @@ +package state + +import ( + "github.com/go-kit/kit/metrics" +) + +const ( + // MetricsSubsystem is a subsystem shared by all metrics exposed by this + // package. + MetricsSubsystem = "state" +) + +//go:generate go run ../../scripts/metricsgen -struct=Metrics + +// Metrics contains metrics exposed by this package. +type Metrics struct { + // Time spent processing FinalizeBlock + BlockProcessingTime metrics.Histogram `metrics_bucketsizes:"1, 10, 10" metrics_buckettype:"lin"` + + // ConsensusParamUpdates is the total number of times the application has + // updated the consensus params since process start. + // metrics:Number of consensus parameter updates returned by the application since process start. + ConsensusParamUpdates metrics.Counter + + // ValidatorSetUpdates is the total number of times the application has + // updated the validator set since process start. + // metrics:Number of validator set updates returned by the application since process start. + ValidatorSetUpdates metrics.Counter + + // PruningServiceBlockRetainHeight is the accepted block + // retain height set by the data companion + PruningServiceBlockRetainHeight metrics.Gauge + + // PruningServiceBlockResultsRetainHeight is the accepted block results + // retain height set by the data companion + PruningServiceBlockResultsRetainHeight metrics.Gauge + + // PruningServiceTxIndexerRetainHeight is the accepted transactions indices + // retain height set by the data companion + PruningServiceTxIndexerRetainHeight metrics.Gauge + + // PruningServiceBlockIndexerRetainHeight is the accepted blocks indices + // retain height set by the data companion + PruningServiceBlockIndexerRetainHeight metrics.Gauge + + // ApplicationBlockRetainHeight is the accepted block + // retain height set by the application + ApplicationBlockRetainHeight metrics.Gauge + + // BlockStoreBaseHeight shows the first height at which + // a block is available + BlockStoreBaseHeight metrics.Gauge + + // ABCIResultsBaseHeight shows the first height at which + // abci results are available + ABCIResultsBaseHeight metrics.Gauge + + // TxIndexerBaseHeight shows the first height at which + // tx indices are available + TxIndexerBaseHeight metrics.Gauge + + // BlockIndexerBaseHeight shows the first height at which + // block indices are available + BlockIndexerBaseHeight metrics.Gauge + + // The duration of accesses to the state store labeled by which method + // was called on the store. + StoreAccessDurationSeconds metrics.Histogram `metrics_bucketsizes:"0.0002, 10, 5" metrics_buckettype:"exp" metrics_labels:"method"` +} diff --git a/state/mocks/block_store.go b/internal/state/mocks/block_store.go similarity index 74% rename from state/mocks/block_store.go rename to internal/state/mocks/block_store.go index d7467eeb708..8a703962c5b 100644 --- a/state/mocks/block_store.go +++ b/internal/state/mocks/block_store.go @@ -3,7 +3,7 @@ package mocks import ( - state "github.com/cometbft/cometbft/state" + state "github.com/cometbft/cometbft/internal/state" mock "github.com/stretchr/testify/mock" types "github.com/cometbft/cometbft/types" @@ -18,6 +18,10 @@ type BlockStore struct { func (_m *BlockStore) Base() int64 { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Base") + } + var r0 int64 if rf, ok := ret.Get(0).(func() int64); ok { r0 = rf() @@ -32,6 +36,10 @@ func (_m *BlockStore) Base() int64 { func (_m *BlockStore) Close() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Close") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -46,6 +54,10 @@ func (_m *BlockStore) Close() error { func (_m *BlockStore) DeleteLatestBlock() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for DeleteLatestBlock") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -60,6 +72,10 @@ func (_m *BlockStore) DeleteLatestBlock() error { func (_m *BlockStore) Height() int64 { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Height") + } + var r0 int64 if rf, ok := ret.Get(0).(func() int64); ok { r0 = rf() @@ -74,6 +90,10 @@ func (_m *BlockStore) Height() int64 { func (_m *BlockStore) LoadBaseMeta() *types.BlockMeta { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for LoadBaseMeta") + } + var r0 *types.BlockMeta if rf, ok := ret.Get(0).(func() *types.BlockMeta); ok { r0 = rf() @@ -87,10 +107,18 @@ func (_m *BlockStore) LoadBaseMeta() *types.BlockMeta { } // LoadBlock provides a mock function with given fields: height -func (_m *BlockStore) LoadBlock(height int64) *types.Block { +func (_m *BlockStore) LoadBlock(height int64) (*types.Block, *types.BlockMeta) { ret := _m.Called(height) + if len(ret) == 0 { + panic("no return value specified for LoadBlock") + } + var r0 *types.Block + var r1 *types.BlockMeta + if rf, ok := ret.Get(0).(func(int64) (*types.Block, *types.BlockMeta)); ok { + return rf(height) + } if rf, ok := ret.Get(0).(func(int64) *types.Block); ok { r0 = rf(height) } else { @@ -99,14 +127,30 @@ func (_m *BlockStore) LoadBlock(height int64) *types.Block { } } - return r0 + if rf, ok := ret.Get(1).(func(int64) *types.BlockMeta); ok { + r1 = rf(height) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*types.BlockMeta) + } + } + + return r0, r1 } // LoadBlockByHash provides a mock function with given fields: hash -func (_m *BlockStore) LoadBlockByHash(hash []byte) *types.Block { +func (_m *BlockStore) LoadBlockByHash(hash []byte) (*types.Block, *types.BlockMeta) { ret := _m.Called(hash) + if len(ret) == 0 { + panic("no return value specified for LoadBlockByHash") + } + var r0 *types.Block + var r1 *types.BlockMeta + if rf, ok := ret.Get(0).(func([]byte) (*types.Block, *types.BlockMeta)); ok { + return rf(hash) + } if rf, ok := ret.Get(0).(func([]byte) *types.Block); ok { r0 = rf(hash) } else { @@ -115,13 +159,25 @@ func (_m *BlockStore) LoadBlockByHash(hash []byte) *types.Block { } } - return r0 + if rf, ok := ret.Get(1).(func([]byte) *types.BlockMeta); ok { + r1 = rf(hash) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*types.BlockMeta) + } + } + + return r0, r1 } // LoadBlockCommit provides a mock function with given fields: height func (_m *BlockStore) LoadBlockCommit(height int64) *types.Commit { ret := _m.Called(height) + if len(ret) == 0 { + panic("no return value specified for LoadBlockCommit") + } + var r0 *types.Commit if rf, ok := ret.Get(0).(func(int64) *types.Commit); ok { r0 = rf(height) @@ -138,6 +194,10 @@ func (_m *BlockStore) LoadBlockCommit(height int64) *types.Commit { func (_m *BlockStore) LoadBlockExtendedCommit(height int64) *types.ExtendedCommit { ret := _m.Called(height) + if len(ret) == 0 { + panic("no return value specified for LoadBlockExtendedCommit") + } + var r0 *types.ExtendedCommit if rf, ok := ret.Get(0).(func(int64) *types.ExtendedCommit); ok { r0 = rf(height) @@ -154,6 +214,10 @@ func (_m *BlockStore) LoadBlockExtendedCommit(height int64) *types.ExtendedCommi func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta { ret := _m.Called(height) + if len(ret) == 0 { + panic("no return value specified for LoadBlockMeta") + } + var r0 *types.BlockMeta if rf, ok := ret.Get(0).(func(int64) *types.BlockMeta); ok { r0 = rf(height) @@ -170,6 +234,10 @@ func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta { func (_m *BlockStore) LoadBlockMetaByHash(hash []byte) *types.BlockMeta { ret := _m.Called(hash) + if len(ret) == 0 { + panic("no return value specified for LoadBlockMetaByHash") + } + var r0 *types.BlockMeta if rf, ok := ret.Get(0).(func([]byte) *types.BlockMeta); ok { r0 = rf(hash) @@ -186,6 +254,10 @@ func (_m *BlockStore) LoadBlockMetaByHash(hash []byte) *types.BlockMeta { func (_m *BlockStore) LoadBlockPart(height int64, index int) *types.Part { ret := _m.Called(height, index) + if len(ret) == 0 { + panic("no return value specified for LoadBlockPart") + } + var r0 *types.Part if rf, ok := ret.Get(0).(func(int64, int) *types.Part); ok { r0 = rf(height, index) @@ -202,6 +274,10 @@ func (_m *BlockStore) LoadBlockPart(height int64, index int) *types.Part { func (_m *BlockStore) LoadSeenCommit(height int64) *types.Commit { ret := _m.Called(height) + if len(ret) == 0 { + panic("no return value specified for LoadSeenCommit") + } + var r0 *types.Commit if rf, ok := ret.Get(0).(func(int64) *types.Commit); ok { r0 = rf(height) @@ -218,6 +294,10 @@ func (_m *BlockStore) LoadSeenCommit(height int64) *types.Commit { func (_m *BlockStore) PruneBlocks(height int64, _a1 state.State) (uint64, int64, error) { ret := _m.Called(height, _a1) + if len(ret) == 0 { + panic("no return value specified for PruneBlocks") + } + var r0 uint64 var r1 int64 var r2 error @@ -259,6 +339,10 @@ func (_m *BlockStore) SaveBlockWithExtendedCommit(block *types.Block, blockParts func (_m *BlockStore) Size() int64 { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Size") + } + var r0 int64 if rf, ok := ret.Get(0).(func() int64); ok { r0 = rf() @@ -269,13 +353,12 @@ func (_m *BlockStore) Size() int64 { return r0 } -type mockConstructorTestingTNewBlockStore interface { +// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBlockStore(t interface { mock.TestingT Cleanup(func()) -} - -// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBlockStore(t mockConstructorTestingTNewBlockStore) *BlockStore { +}) *BlockStore { mock := &BlockStore{} mock.Mock.Test(t) diff --git a/state/mocks/evidence_pool.go b/internal/state/mocks/evidence_pool.go similarity index 61% rename from state/mocks/evidence_pool.go rename to internal/state/mocks/evidence_pool.go index b5a3a8ac14c..abc87e6076b 100644 --- a/state/mocks/evidence_pool.go +++ b/internal/state/mocks/evidence_pool.go @@ -3,7 +3,7 @@ package mocks import ( - state "github.com/cometbft/cometbft/state" + state "github.com/cometbft/cometbft/internal/state" mock "github.com/stretchr/testify/mock" types "github.com/cometbft/cometbft/types" @@ -14,13 +14,17 @@ type EvidencePool struct { mock.Mock } -// AddEvidence provides a mock function with given fields: _a0 -func (_m *EvidencePool) AddEvidence(_a0 types.Evidence) error { - ret := _m.Called(_a0) +// AddEvidence provides a mock function with given fields: ev +func (_m *EvidencePool) AddEvidence(ev types.Evidence) error { + ret := _m.Called(ev) + + if len(ret) == 0 { + panic("no return value specified for AddEvidence") + } var r0 error if rf, ok := ret.Get(0).(func(types.Evidence) error); ok { - r0 = rf(_a0) + r0 = rf(ev) } else { r0 = ret.Error(0) } @@ -28,13 +32,17 @@ func (_m *EvidencePool) AddEvidence(_a0 types.Evidence) error { return r0 } -// CheckEvidence provides a mock function with given fields: _a0 -func (_m *EvidencePool) CheckEvidence(_a0 types.EvidenceList) error { - ret := _m.Called(_a0) +// CheckEvidence provides a mock function with given fields: evList +func (_m *EvidencePool) CheckEvidence(evList types.EvidenceList) error { + ret := _m.Called(evList) + + if len(ret) == 0 { + panic("no return value specified for CheckEvidence") + } var r0 error if rf, ok := ret.Get(0).(func(types.EvidenceList) error); ok { - r0 = rf(_a0) + r0 = rf(evList) } else { r0 = ret.Error(0) } @@ -46,6 +54,10 @@ func (_m *EvidencePool) CheckEvidence(_a0 types.EvidenceList) error { func (_m *EvidencePool) PendingEvidence(maxBytes int64) ([]types.Evidence, int64) { ret := _m.Called(maxBytes) + if len(ret) == 0 { + panic("no return value specified for PendingEvidence") + } + var r0 []types.Evidence var r1 int64 if rf, ok := ret.Get(0).(func(int64) ([]types.Evidence, int64)); ok { @@ -68,18 +80,17 @@ func (_m *EvidencePool) PendingEvidence(maxBytes int64) ([]types.Evidence, int64 return r0, r1 } -// Update provides a mock function with given fields: _a0, _a1 -func (_m *EvidencePool) Update(_a0 state.State, _a1 types.EvidenceList) { - _m.Called(_a0, _a1) +// Update provides a mock function with given fields: _a0, evList +func (_m *EvidencePool) Update(_a0 state.State, evList types.EvidenceList) { + _m.Called(_a0, evList) } -type mockConstructorTestingTNewEvidencePool interface { +// NewEvidencePool creates a new instance of EvidencePool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewEvidencePool(t interface { mock.TestingT Cleanup(func()) -} - -// NewEvidencePool creates a new instance of EvidencePool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewEvidencePool(t mockConstructorTestingTNewEvidencePool) *EvidencePool { +}) *EvidencePool { mock := &EvidencePool{} mock.Mock.Test(t) diff --git a/internal/state/mocks/store.go b/internal/state/mocks/store.go new file mode 100644 index 00000000000..8bb139151ec --- /dev/null +++ b/internal/state/mocks/store.go @@ -0,0 +1,552 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + state "github.com/cometbft/cometbft/internal/state" + mock "github.com/stretchr/testify/mock" + + types "github.com/cometbft/cometbft/types" + + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" +) + +// Store is an autogenerated mock type for the Store type +type Store struct { + mock.Mock +} + +// Bootstrap provides a mock function with given fields: _a0 +func (_m *Store) Bootstrap(_a0 state.State) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Bootstrap") + } + + var r0 error + if rf, ok := ret.Get(0).(func(state.State) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Close provides a mock function with given fields: +func (_m *Store) Close() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Close") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetABCIResRetainHeight provides a mock function with given fields: +func (_m *Store) GetABCIResRetainHeight() (int64, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetABCIResRetainHeight") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func() (int64, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetApplicationRetainHeight provides a mock function with given fields: +func (_m *Store) GetApplicationRetainHeight() (int64, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetApplicationRetainHeight") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func() (int64, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetCompanionBlockRetainHeight provides a mock function with given fields: +func (_m *Store) GetCompanionBlockRetainHeight() (int64, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetCompanionBlockRetainHeight") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func() (int64, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetOfflineStateSyncHeight provides a mock function with given fields: +func (_m *Store) GetOfflineStateSyncHeight() (int64, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetOfflineStateSyncHeight") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func() (int64, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Load provides a mock function with given fields: +func (_m *Store) Load() (state.State, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Load") + } + + var r0 state.State + var r1 error + if rf, ok := ret.Get(0).(func() (state.State, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() state.State); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(state.State) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LoadConsensusParams provides a mock function with given fields: height +func (_m *Store) LoadConsensusParams(height int64) (types.ConsensusParams, error) { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for LoadConsensusParams") + } + + var r0 types.ConsensusParams + var r1 error + if rf, ok := ret.Get(0).(func(int64) (types.ConsensusParams, error)); ok { + return rf(height) + } + if rf, ok := ret.Get(0).(func(int64) types.ConsensusParams); ok { + r0 = rf(height) + } else { + r0 = ret.Get(0).(types.ConsensusParams) + } + + if rf, ok := ret.Get(1).(func(int64) error); ok { + r1 = rf(height) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LoadFinalizeBlockResponse provides a mock function with given fields: height +func (_m *Store) LoadFinalizeBlockResponse(height int64) (*v1.FinalizeBlockResponse, error) { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for LoadFinalizeBlockResponse") + } + + var r0 *v1.FinalizeBlockResponse + var r1 error + if rf, ok := ret.Get(0).(func(int64) (*v1.FinalizeBlockResponse, error)); ok { + return rf(height) + } + if rf, ok := ret.Get(0).(func(int64) *v1.FinalizeBlockResponse); ok { + r0 = rf(height) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*v1.FinalizeBlockResponse) + } + } + + if rf, ok := ret.Get(1).(func(int64) error); ok { + r1 = rf(height) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LoadFromDBOrGenesisDoc provides a mock function with given fields: doc +func (_m *Store) LoadFromDBOrGenesisDoc(doc *types.GenesisDoc) (state.State, error) { + ret := _m.Called(doc) + + if len(ret) == 0 { + panic("no return value specified for LoadFromDBOrGenesisDoc") + } + + var r0 state.State + var r1 error + if rf, ok := ret.Get(0).(func(*types.GenesisDoc) (state.State, error)); ok { + return rf(doc) + } + if rf, ok := ret.Get(0).(func(*types.GenesisDoc) state.State); ok { + r0 = rf(doc) + } else { + r0 = ret.Get(0).(state.State) + } + + if rf, ok := ret.Get(1).(func(*types.GenesisDoc) error); ok { + r1 = rf(doc) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LoadFromDBOrGenesisFile provides a mock function with given fields: filepath +func (_m *Store) LoadFromDBOrGenesisFile(filepath string) (state.State, error) { + ret := _m.Called(filepath) + + if len(ret) == 0 { + panic("no return value specified for LoadFromDBOrGenesisFile") + } + + var r0 state.State + var r1 error + if rf, ok := ret.Get(0).(func(string) (state.State, error)); ok { + return rf(filepath) + } + if rf, ok := ret.Get(0).(func(string) state.State); ok { + r0 = rf(filepath) + } else { + r0 = ret.Get(0).(state.State) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(filepath) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LoadLastFinalizeBlockResponse provides a mock function with given fields: height +func (_m *Store) LoadLastFinalizeBlockResponse(height int64) (*v1.FinalizeBlockResponse, error) { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for LoadLastFinalizeBlockResponse") + } + + var r0 *v1.FinalizeBlockResponse + var r1 error + if rf, ok := ret.Get(0).(func(int64) (*v1.FinalizeBlockResponse, error)); ok { + return rf(height) + } + if rf, ok := ret.Get(0).(func(int64) *v1.FinalizeBlockResponse); ok { + r0 = rf(height) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*v1.FinalizeBlockResponse) + } + } + + if rf, ok := ret.Get(1).(func(int64) error); ok { + r1 = rf(height) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LoadValidators provides a mock function with given fields: height +func (_m *Store) LoadValidators(height int64) (*types.ValidatorSet, error) { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for LoadValidators") + } + + var r0 *types.ValidatorSet + var r1 error + if rf, ok := ret.Get(0).(func(int64) (*types.ValidatorSet, error)); ok { + return rf(height) + } + if rf, ok := ret.Get(0).(func(int64) *types.ValidatorSet); ok { + r0 = rf(height) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ValidatorSet) + } + } + + if rf, ok := ret.Get(1).(func(int64) error); ok { + r1 = rf(height) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PruneABCIResponses provides a mock function with given fields: targetRetainHeight, forceCompact +func (_m *Store) PruneABCIResponses(targetRetainHeight int64, forceCompact bool) (int64, int64, error) { + ret := _m.Called(targetRetainHeight, forceCompact) + + if len(ret) == 0 { + panic("no return value specified for PruneABCIResponses") + } + + var r0 int64 + var r1 int64 + var r2 error + if rf, ok := ret.Get(0).(func(int64, bool) (int64, int64, error)); ok { + return rf(targetRetainHeight, forceCompact) + } + if rf, ok := ret.Get(0).(func(int64, bool) int64); ok { + r0 = rf(targetRetainHeight, forceCompact) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(int64, bool) int64); ok { + r1 = rf(targetRetainHeight, forceCompact) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(int64, bool) error); ok { + r2 = rf(targetRetainHeight, forceCompact) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// PruneStates provides a mock function with given fields: fromHeight, toHeight, evidenceThresholdHeight, previouslyPrunedStates +func (_m *Store) PruneStates(fromHeight int64, toHeight int64, evidenceThresholdHeight int64, previouslyPrunedStates uint64) (uint64, error) { + ret := _m.Called(fromHeight, toHeight, evidenceThresholdHeight, previouslyPrunedStates) + + if len(ret) == 0 { + panic("no return value specified for PruneStates") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(int64, int64, int64, uint64) (uint64, error)); ok { + return rf(fromHeight, toHeight, evidenceThresholdHeight, previouslyPrunedStates) + } + if rf, ok := ret.Get(0).(func(int64, int64, int64, uint64) uint64); ok { + r0 = rf(fromHeight, toHeight, evidenceThresholdHeight, previouslyPrunedStates) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(int64, int64, int64, uint64) error); ok { + r1 = rf(fromHeight, toHeight, evidenceThresholdHeight, previouslyPrunedStates) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Save provides a mock function with given fields: _a0 +func (_m *Store) Save(_a0 state.State) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Save") + } + + var r0 error + if rf, ok := ret.Get(0).(func(state.State) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SaveABCIResRetainHeight provides a mock function with given fields: height +func (_m *Store) SaveABCIResRetainHeight(height int64) error { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for SaveABCIResRetainHeight") + } + + var r0 error + if rf, ok := ret.Get(0).(func(int64) error); ok { + r0 = rf(height) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SaveApplicationRetainHeight provides a mock function with given fields: height +func (_m *Store) SaveApplicationRetainHeight(height int64) error { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for SaveApplicationRetainHeight") + } + + var r0 error + if rf, ok := ret.Get(0).(func(int64) error); ok { + r0 = rf(height) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SaveCompanionBlockRetainHeight provides a mock function with given fields: height +func (_m *Store) SaveCompanionBlockRetainHeight(height int64) error { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for SaveCompanionBlockRetainHeight") + } + + var r0 error + if rf, ok := ret.Get(0).(func(int64) error); ok { + r0 = rf(height) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SaveFinalizeBlockResponse provides a mock function with given fields: height, res +func (_m *Store) SaveFinalizeBlockResponse(height int64, res *v1.FinalizeBlockResponse) error { + ret := _m.Called(height, res) + + if len(ret) == 0 { + panic("no return value specified for SaveFinalizeBlockResponse") + } + + var r0 error + if rf, ok := ret.Get(0).(func(int64, *v1.FinalizeBlockResponse) error); ok { + r0 = rf(height, res) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SetOfflineStateSyncHeight provides a mock function with given fields: height +func (_m *Store) SetOfflineStateSyncHeight(height int64) error { + ret := _m.Called(height) + + if len(ret) == 0 { + panic("no return value specified for SetOfflineStateSyncHeight") + } + + var r0 error + if rf, ok := ret.Get(0).(func(int64) error); ok { + r0 = rf(height) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// NewStore creates a new instance of Store. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStore(t interface { + mock.TestingT + Cleanup(func()) +}) *Store { + mock := &Store{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/state/pruner.go b/internal/state/pruner.go new file mode 100644 index 00000000000..f8d7fb226f6 --- /dev/null +++ b/internal/state/pruner.go @@ -0,0 +1,520 @@ +package state + +import ( + "errors" + "sync" + "time" + + "github.com/cometbft/cometbft/config" + "github.com/cometbft/cometbft/internal/service" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/libs/log" +) + +var ( + AppRetainHeightKey = []byte("AppRetainHeightKey") + CompanionBlockRetainHeightKey = []byte("DCBlockRetainHeightKey") + ABCIResultsRetainHeightKey = []byte("ABCIResRetainHeightKey") +) + +// Pruner is a service that reads the retain heights for blocks, state and ABCI +// results from the database and prunes the corresponding data based on the +// minimum retain height set. The service sleeps between each run based on the +// configured pruner interval, and re-evaluates the retain height. +type Pruner struct { + service.BaseService + logger log.Logger + + mtx sync.Mutex + // Must the pruner respect the retain heights set by the data companion? + dcEnabled bool + // DB to which we save the retain heights + bs BlockStore + // State store to prune state from + stateStore Store + blockIndexer indexer.BlockIndexer + txIndexer txindex.TxIndexer + interval time.Duration + observer PrunerObserver + metrics *Metrics + + // Preserve the number of state entries pruned. + // Used to calculated correctly when to trigger compactions + prunedStates uint64 +} + +type prunerConfig struct { + dcEnabled bool + interval time.Duration + observer PrunerObserver + metrics *Metrics +} + +func defaultPrunerConfig() *prunerConfig { + return &prunerConfig{ + dcEnabled: false, + interval: config.DefaultPruningInterval, + observer: &NoopPrunerObserver{}, + metrics: NopMetrics(), + } +} + +type PrunerOption func(*prunerConfig) + +// WithPrunerCompanionEnabled indicates to the pruner that it must respect the +// retain heights set by the data companion. By default, if this option is not +// supplied, the pruner will ignore any retain heights set by the data +// companion. +func WithPrunerCompanionEnabled() PrunerOption { + return func(p *prunerConfig) { + p.dcEnabled = true + } +} + +// WithPrunerInterval allows control over the interval between each run of the +// pruner. +func WithPrunerInterval(t time.Duration) PrunerOption { + return func(p *prunerConfig) { p.interval = t } +} + +func WithPrunerObserver(obs PrunerObserver) PrunerOption { + return func(p *prunerConfig) { p.observer = obs } +} + +func WithPrunerMetrics(metrics *Metrics) PrunerOption { + return func(p *prunerConfig) { + p.metrics = metrics + } +} + +// NewPruner creates a service that controls background pruning of node data. +// +// Assumes that the initial application and data companion retain heights have +// already been configured in the state store. +func NewPruner( + stateStore Store, + bs BlockStore, + blockIndexer indexer.BlockIndexer, + txIndexer txindex.TxIndexer, + logger log.Logger, + options ...PrunerOption, +) *Pruner { + cfg := defaultPrunerConfig() + for _, opt := range options { + opt(cfg) + } + p := &Pruner{ + bs: bs, + txIndexer: txIndexer, + blockIndexer: blockIndexer, + stateStore: stateStore, + logger: logger, + interval: cfg.interval, + observer: cfg.observer, + metrics: cfg.metrics, + dcEnabled: cfg.dcEnabled, + } + p.BaseService = *service.NewBaseService(logger, "Pruner", p) + return p +} + +func (p *Pruner) SetObserver(obs PrunerObserver) { + p.observer = obs +} + +func (p *Pruner) OnStart() error { + go p.pruneBlocks() + // We only care about pruning ABCI results if the data companion has been + // enabled. + if p.dcEnabled { + go p.pruneABCIResponses() + go p.pruneIndexesRoutine() + } + p.observer.PrunerStarted(p.interval) + return nil +} + +// SetApplicationBlockRetainHeight sets the application block retain height +// with some basic checks on the requested height. +// +// If a higher retain height is already set, we cannot accept the requested +// height because the blocks might have been pruned. +func (p *Pruner) SetApplicationBlockRetainHeight(height int64) error { + // Ensure that all requests to set retain heights via the application are + // serialized. + p.mtx.Lock() + defer p.mtx.Unlock() + + if !p.heightWithinBounds(height) { + return ErrInvalidHeightValue + } + curRetainHeight, err := p.stateStore.GetApplicationRetainHeight() + if err != nil { + return ErrPrunerFailedToGetRetainHeight{Which: "application block", Err: err} + } + if height < curRetainHeight { + return ErrPrunerCannotLowerRetainHeight + } + if err := p.stateStore.SaveApplicationRetainHeight(height); err != nil { + return err + } + p.metrics.ApplicationBlockRetainHeight.Set(float64(height)) + return nil +} + +func (p *Pruner) heightWithinBounds(height int64) bool { + if height < p.bs.Base() || height > p.bs.Height() { + return false + } + return true +} + +// SetCompanionBlockRetainHeight sets the application block retain height with +// some basic checks on the requested height. +// +// If a higher retain height is already set, we cannot accept the requested +// height because the blocks might have been pruned. +func (p *Pruner) SetCompanionBlockRetainHeight(height int64) error { + // Ensure that all requests to set retain heights via the pruner are + // serialized. + p.mtx.Lock() + defer p.mtx.Unlock() + + if !p.heightWithinBounds(height) { + return ErrInvalidHeightValue + } + curRetainHeight, err := p.stateStore.GetCompanionBlockRetainHeight() + if err != nil { + return ErrPrunerFailedToGetRetainHeight{Which: "companion block", Err: err} + } + if height < curRetainHeight { + return ErrPrunerCannotLowerRetainHeight + } + if err := p.stateStore.SaveCompanionBlockRetainHeight(height); err != nil { + return err + } + p.metrics.PruningServiceBlockRetainHeight.Set(float64(height)) + return nil +} + +// SetABCIResRetainHeight sets the retain height for ABCI responses. +// +// If the application has set the DiscardABCIResponses flag to true, nothing +// will be pruned. +func (p *Pruner) SetABCIResRetainHeight(height int64) error { + // Ensure that all requests to set retain heights via the pruner are + // serialized. + p.mtx.Lock() + defer p.mtx.Unlock() + + if !p.heightWithinBounds(height) { + return ErrInvalidHeightValue + } + curRetainHeight, err := p.stateStore.GetABCIResRetainHeight() + if err != nil { + return ErrPrunerFailedToGetRetainHeight{Which: "ABCI results", Err: err} + } + if height < curRetainHeight { + return ErrPrunerCannotLowerRetainHeight + } + if err := p.stateStore.SaveABCIResRetainHeight(height); err != nil { + return err + } + p.metrics.PruningServiceBlockResultsRetainHeight.Set(float64(height)) + return nil +} + +func (p *Pruner) SetTxIndexerRetainHeight(height int64) error { + // Ensure that all requests to set retain heights via the application are + // serialized. + p.mtx.Lock() + defer p.mtx.Unlock() + if height <= 0 { + return ErrInvalidHeightValue + } + + currentRetainHeight, err := p.txIndexer.GetRetainHeight() + if err != nil { + if !errors.Is(err, ErrKeyNotFound) { + return err + } + return p.txIndexer.SetRetainHeight(height) + } + if currentRetainHeight > height { + return ErrPrunerCannotLowerRetainHeight + } + if err := p.txIndexer.SetRetainHeight(height); err != nil { + return err + } + p.metrics.PruningServiceTxIndexerRetainHeight.Set(float64(height)) + return nil +} + +func (p *Pruner) SetBlockIndexerRetainHeight(height int64) error { + // Ensure that all requests to set retain heights via the application are + // serialized. + p.mtx.Lock() + defer p.mtx.Unlock() + if height <= 0 { + return ErrInvalidHeightValue + } + + currentRetainHeight, err := p.blockIndexer.GetRetainHeight() + if err != nil { + if !errors.Is(err, ErrKeyNotFound) { + return err + } + return p.blockIndexer.SetRetainHeight(height) + } + if currentRetainHeight > height { + return ErrPrunerCannotLowerRetainHeight + } + if err := p.blockIndexer.SetRetainHeight(height); err != nil { + return err + } + p.metrics.PruningServiceBlockIndexerRetainHeight.Set(float64(height)) + return nil +} + +// GetApplicationRetainHeight is a convenience method for accessing the +// GetApplicationRetainHeight method of the underlying state store. +func (p *Pruner) GetApplicationRetainHeight() (int64, error) { + return p.stateStore.GetApplicationRetainHeight() +} + +// GetCompanionBlockRetainHeight is a convenience method for accessing the +// GetCompanionBlockRetainHeight method of the underlying state store. +func (p *Pruner) GetCompanionBlockRetainHeight() (int64, error) { + return p.stateStore.GetCompanionBlockRetainHeight() +} + +// GetABCIResRetainHeight is a convenience method for accessing the +// GetABCIResRetainHeight method of the underlying state store. +func (p *Pruner) GetABCIResRetainHeight() (int64, error) { + return p.stateStore.GetABCIResRetainHeight() +} + +// GetTxIndexerRetainHeight is a convenience method for accessing the +// GetTxIndexerRetainHeight method of the underlying indexer. +func (p *Pruner) GetTxIndexerRetainHeight() (int64, error) { + return p.txIndexer.GetRetainHeight() +} + +// GetBlockIndexerRetainHeight is a convenience method for accessing the +// GetBlockIndexerRetainHeight method of the underlying state store. +func (p *Pruner) GetBlockIndexerRetainHeight() (int64, error) { + return p.blockIndexer.GetRetainHeight() +} + +func (p *Pruner) pruneABCIResponses() { + p.logger.Info("Started pruning ABCI responses", "interval", p.interval.String()) + lastRetainHeight := int64(0) + for { + select { + case <-p.Quit(): + return + default: + newRetainHeight := p.pruneABCIResToRetainHeight(lastRetainHeight) + if newRetainHeight != lastRetainHeight { + p.observer.PrunerPrunedABCIRes(&ABCIResponsesPrunedInfo{ + FromHeight: lastRetainHeight, + ToHeight: newRetainHeight - 1, + }) + } + lastRetainHeight = newRetainHeight + time.Sleep(p.interval) + } + } +} + +func (p *Pruner) pruneBlocks() { + p.logger.Info("Started pruning blocks", "interval", p.interval.String()) + lastRetainHeight := int64(0) + for { + select { + case <-p.Quit(): + return + default: + newRetainHeight := p.pruneBlocksToRetainHeight(lastRetainHeight) + if newRetainHeight != lastRetainHeight { + p.observer.PrunerPrunedBlocks(&BlocksPrunedInfo{ + FromHeight: lastRetainHeight, + ToHeight: newRetainHeight - 1, + }) + } + lastRetainHeight = newRetainHeight + time.Sleep(p.interval) + } + } +} + +func (p *Pruner) pruneIndexesRoutine() { + p.logger.Info("Index pruner started", "interval", p.interval.String()) + lastTxIndexerRetainHeight := int64(0) + lastBlockIndexerRetainHeight := int64(0) + for { + select { + case <-p.Quit(): + return + default: + lastTxIndexerRetainHeight = p.pruneTxIndexerToRetainHeight(lastTxIndexerRetainHeight) + lastBlockIndexerRetainHeight = p.pruneBlockIndexerToRetainHeight(lastBlockIndexerRetainHeight) + // TODO call observer + time.Sleep(p.interval) + } + } +} + +func (p *Pruner) pruneTxIndexerToRetainHeight(lastRetainHeight int64) int64 { + targetRetainHeight, err := p.GetTxIndexerRetainHeight() + if err != nil { + // Indexer retain height has not yet been set - do not log any + // errors at this time. + if errors.Is(err, ErrKeyNotFound) { + return 0 + } + p.logger.Error("Failed to get Indexer retain height", "err", err) + return lastRetainHeight + } + + if lastRetainHeight >= targetRetainHeight { + return lastRetainHeight + } + + numPrunedTxIndexer, newTxIndexerRetainHeight, err := p.txIndexer.Prune(targetRetainHeight) + if err != nil { + p.logger.Error("Failed to prune tx indexer", "err", err, "targetRetainHeight", targetRetainHeight, "newTxIndexerRetainHeight", newTxIndexerRetainHeight) + } else if numPrunedTxIndexer > 0 { + p.metrics.TxIndexerBaseHeight.Set(float64(newTxIndexerRetainHeight)) + p.logger.Debug("Pruned tx indexer", "count", numPrunedTxIndexer, "newTxIndexerRetainHeight", newTxIndexerRetainHeight) + } + return newTxIndexerRetainHeight +} + +func (p *Pruner) pruneBlockIndexerToRetainHeight(lastRetainHeight int64) int64 { + targetRetainHeight, err := p.GetBlockIndexerRetainHeight() + if err != nil { + // Indexer retain height has not yet been set - do not log any + // errors at this time. + if errors.Is(err, ErrKeyNotFound) { + return 0 + } + p.logger.Error("Failed to get Indexer retain height", "err", err) + return lastRetainHeight + } + + if lastRetainHeight >= targetRetainHeight { + return lastRetainHeight + } + + numPrunedBlockIndexer, newBlockIndexerRetainHeight, err := p.blockIndexer.Prune(targetRetainHeight) + if err != nil { + p.logger.Error("Failed to prune block indexer", "err", err, "targetRetainHeight", targetRetainHeight, "newBlockIndexerRetainHeight", newBlockIndexerRetainHeight) + } else if numPrunedBlockIndexer > 0 { + p.metrics.BlockIndexerBaseHeight.Set(float64(newBlockIndexerRetainHeight)) + p.logger.Debug("Pruned block indexer", "count", numPrunedBlockIndexer, "newBlockIndexerRetainHeight", newBlockIndexerRetainHeight) + } + return newBlockIndexerRetainHeight +} + +func (p *Pruner) pruneBlocksToRetainHeight(lastRetainHeight int64) int64 { + targetRetainHeight := p.findMinBlockRetainHeight() + if targetRetainHeight == lastRetainHeight { + return lastRetainHeight + } + pruned, evRetainHeight, err := p.pruneBlocksToHeight(targetRetainHeight) + // The new retain height is the current lowest point of the block store + // indicated by Base() + newRetainHeight := p.bs.Base() + if err != nil { + p.logger.Error("Failed to prune blocks", "err", err, "targetRetainHeight", targetRetainHeight, "newRetainHeight", newRetainHeight) + } else if pruned > 0 { + p.metrics.BlockStoreBaseHeight.Set(float64(newRetainHeight)) + p.logger.Debug("Pruned blocks", "count", pruned, "evidenceRetainHeight", evRetainHeight, "newRetainHeight", newRetainHeight) + } + return newRetainHeight +} + +func (p *Pruner) pruneABCIResToRetainHeight(lastRetainHeight int64) int64 { + targetRetainHeight, err := p.stateStore.GetABCIResRetainHeight() + if err != nil { + p.logger.Error("Failed to get ABCI response retain height", "err", err) + if errors.Is(err, ErrKeyNotFound) { + return 0 + } + return lastRetainHeight + } + + if lastRetainHeight == targetRetainHeight { + return lastRetainHeight + } + + // If the block retain height is 0, pruning of the block and state stores might be disabled + // This should not prevent Comet from pruning ABCI results if needed. + // We could by default always compact when pruning the responses, but in case the state store + // is being compacted we introduce an overhead that might cause performance penalties. + forceCompact := p.findMinBlockRetainHeight() == 0 + // newRetainHeight is the height just after that which we have successfully + // pruned. In case of an error it will be 0, but then it will also be + // ignored. + numPruned, newRetainHeight, err := p.stateStore.PruneABCIResponses(targetRetainHeight, forceCompact) + if err != nil { + p.logger.Error("Failed to prune ABCI responses", "err", err, "targetRetainHeight", targetRetainHeight) + return lastRetainHeight + } + if numPruned > 0 { + p.logger.Info("Pruned ABCI responses", "heights", numPruned, "newRetainHeight", newRetainHeight) + p.metrics.ABCIResultsBaseHeight.Set(float64(newRetainHeight)) + } + return newRetainHeight +} + +func (p *Pruner) findMinBlockRetainHeight() int64 { + appRetainHeight, err := p.stateStore.GetApplicationRetainHeight() + if err != nil { + p.logger.Error("Unexpected error fetching application retain height", "err", err) + return 0 + } + // We only care about the companion retain height if pruning is configured + // to respect the companion's retain height. + if !p.dcEnabled { + return appRetainHeight + } + dcRetainHeight, err := p.stateStore.GetCompanionBlockRetainHeight() + if err != nil { + p.logger.Error("Unexpected error fetching data companion retain height", "err", err) + return 0 + } + // If we are here, both heights were set and the companion is enabled, so + // we pick the minimum. + if appRetainHeight < dcRetainHeight { + return appRetainHeight + } + return dcRetainHeight +} + +func (p *Pruner) pruneBlocksToHeight(height int64) (uint64, int64, error) { + if height <= 0 { + return 0, 0, ErrInvalidRetainHeight + } + + base := p.bs.Base() + + state, err := p.stateStore.Load() + if err != nil { + return 0, 0, ErrPrunerFailedToLoadState{Err: err} + } + pruned, evRetainHeight, err := p.bs.PruneBlocks(height, state) + if err != nil { + return 0, 0, ErrFailedToPruneBlocks{Height: height, Err: err} + } + if pruned > 0 { + prunedStates, err := p.stateStore.PruneStates(base, height, evRetainHeight, p.prunedStates) + p.prunedStates += prunedStates + if err != nil { + return 0, 0, ErrFailedToPruneStates{Height: height, Err: err} + } + } + return pruned, evRetainHeight, err +} diff --git a/internal/state/pruner_observer.go b/internal/state/pruner_observer.go new file mode 100644 index 00000000000..db8d69266f3 --- /dev/null +++ b/internal/state/pruner_observer.go @@ -0,0 +1,45 @@ +package state + +import ( + "time" +) + +// PrunerObserver allows an external observer to be notified of certain events +// generated by the [Pruner]. +type PrunerObserver interface { + // PrunerStarted is called when the pruner's background pruning routine has + // been started. + PrunerStarted(interval time.Duration) + // PrunerPrunedABCIRes is called after each successful pruning of ABCI results. + PrunerPrunedABCIRes(prunedInfo *ABCIResponsesPrunedInfo) + // PrunerPrunedBlocks is called after each successful pruning of blocks. + PrunerPrunedBlocks(prunedInfo *BlocksPrunedInfo) +} + +// BlocksPrunedInfo provides information about blocks pruned during a single +// run of the pruner. +type BlocksPrunedInfo struct { + FromHeight int64 // The height from which blocks were pruned (inclusive). + ToHeight int64 // The height to which blocks were pruned (inclusive). +} + +// ABCIResponsesPrunedInfo provides information about ABCI responses pruned +// during a single run of the pruner. +type ABCIResponsesPrunedInfo struct { + FromHeight int64 // The height from which ABCI responses were pruned (inclusive). + ToHeight int64 // The height to which ABCI responses were pruned (inclusive). +} + +// NoopPrunerObserver does nothing. +type NoopPrunerObserver struct{} + +var _ PrunerObserver = NoopPrunerObserver{} + +// PrunerPrunedABCIRes implements PrunerObserver. +func (NoopPrunerObserver) PrunerPrunedABCIRes(*ABCIResponsesPrunedInfo) {} + +// PrunerPrunedBlocks implements PrunerObserver. +func (NoopPrunerObserver) PrunerPrunedBlocks(*BlocksPrunedInfo) {} + +// PrunerStarted implements PrunerObserver. +func (NoopPrunerObserver) PrunerStarted(time.Duration) {} diff --git a/internal/state/pruner_test.go b/internal/state/pruner_test.go new file mode 100644 index 00000000000..d5a66bd6aef --- /dev/null +++ b/internal/state/pruner_test.go @@ -0,0 +1,278 @@ +package state_test + +import ( + "context" + "fmt" + "os" + "testing" + "time" + + "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" + + db "github.com/cometbft/cometbft-db" + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/pubsub/query" + sm "github.com/cometbft/cometbft/internal/state" + blockidxkv "github.com/cometbft/cometbft/internal/state/indexer/block/kv" + "github.com/cometbft/cometbft/internal/state/txindex/kv" + "github.com/cometbft/cometbft/internal/store" + "github.com/cometbft/cometbft/internal/test" + "github.com/cometbft/cometbft/libs/log" + "github.com/cometbft/cometbft/types" +) + +func TestPruneBlockIndexerToRetainHeight(t *testing.T) { + pruner, _, blockIndexer := createTestSetup(t) + + for height := int64(1); height <= 4; height++ { + events, _, _ := getEventsAndResults(height) + err := blockIndexer.Index(events) + require.NoError(t, err) + } + err := pruner.SetBlockIndexerRetainHeight(2) + require.NoError(t, err) + actual, err := pruner.GetBlockIndexerRetainHeight() + require.NoError(t, err) + require.Equal(t, int64(2), actual) + + heights, err := blockIndexer.Search(context.Background(), query.MustCompile("block.height <= 2")) + require.NoError(t, err) + require.Equal(t, []int64{1, 2}, heights) + + newRetainHeight := pruner.PruneBlockIndexerToRetainHeight(0) + require.Equal(t, int64(2), newRetainHeight) + + heights, err = blockIndexer.Search(context.Background(), query.MustCompile("block.height <= 2")) + require.NoError(t, err) + require.Equal(t, []int64{2}, heights) + + err = pruner.SetBlockIndexerRetainHeight(int64(4)) + require.NoError(t, err) + actual, err = pruner.GetBlockIndexerRetainHeight() + require.NoError(t, err) + require.Equal(t, int64(4), actual) + + heights, err = blockIndexer.Search(context.Background(), query.MustCompile("block.height <= 4")) + require.NoError(t, err) + require.Equal(t, []int64{2, 3, 4}, heights) + + pruner.PruneBlockIndexerToRetainHeight(2) + + heights, err = blockIndexer.Search(context.Background(), query.MustCompile("block.height <= 4")) + require.NoError(t, err) + require.Equal(t, []int64{4}, heights) + + events, _, _ := getEventsAndResults(1) + + err = blockIndexer.Index(events) + require.NoError(t, err) + + heights, err = blockIndexer.Search(context.Background(), query.MustCompile("block.height <= 4")) + require.NoError(t, err) + require.Equal(t, []int64{1, 4}, heights) + + pruner.PruneBlockIndexerToRetainHeight(4) + + heights, err = blockIndexer.Search(context.Background(), query.MustCompile("block.height <= 4")) + require.NoError(t, err) + require.Equal(t, []int64{1, 4}, heights) +} + +func TestPruneTxIndexerToRetainHeight(t *testing.T) { + pruner, txIndexer, _ := createTestSetup(t) + + for height := int64(1); height <= 4; height++ { + _, txResult1, txResult2 := getEventsAndResults(height) + err := txIndexer.Index(txResult1) + require.NoError(t, err) + err = txIndexer.Index(txResult2) + require.NoError(t, err) + } + + err := pruner.SetTxIndexerRetainHeight(2) + require.NoError(t, err) + actual, err := pruner.GetTxIndexerRetainHeight() + require.NoError(t, err) + require.Equal(t, int64(2), actual) + + results, err := txIndexer.Search(context.Background(), query.MustCompile("tx.height < 2")) + require.NoError(t, err) + require.True(t, containsAllTxs(results, []string{"foo1", "bar1"})) + + newRetainHeight := pruner.PruneTxIndexerToRetainHeight(0) + require.Equal(t, int64(2), newRetainHeight) + + results, err = txIndexer.Search(context.Background(), query.MustCompile("tx.height < 2")) + require.NoError(t, err) + require.Empty(t, results) + + err = pruner.SetTxIndexerRetainHeight(int64(4)) + require.NoError(t, err) + actual, err = pruner.GetTxIndexerRetainHeight() + require.NoError(t, err) + require.Equal(t, int64(4), actual) + + results, err = txIndexer.Search(context.Background(), query.MustCompile("tx.height < 4")) + require.NoError(t, err) + require.True(t, containsAllTxs(results, []string{"foo2", "bar2", "foo3", "bar3"})) + + pruner.PruneTxIndexerToRetainHeight(2) + + results, err = txIndexer.Search(context.Background(), query.MustCompile("tx.height < 4")) + require.NoError(t, err) + require.Empty(t, results) + + _, txResult1, txResult2 := getEventsAndResults(1) + err = txIndexer.Index(txResult1) + require.NoError(t, err) + err = txIndexer.Index(txResult2) + require.NoError(t, err) + + results, err = txIndexer.Search(context.Background(), query.MustCompile("tx.height <= 4")) + require.NoError(t, err) + require.True(t, containsAllTxs(results, []string{"foo1", "bar1", "foo4", "bar4"})) + + pruner.PruneTxIndexerToRetainHeight(4) + + results, err = txIndexer.Search(context.Background(), query.MustCompile("tx.height <= 4")) + require.NoError(t, err) + require.True(t, containsAllTxs(results, []string{"foo1", "bar1", "foo4", "bar4"})) +} + +func containsAllTxs(results []*abci.TxResult, txs []string) bool { + for _, tx := range txs { + if !slices.ContainsFunc(results, func(result *abci.TxResult) bool { + return string(result.Tx) == tx + }) { + return false + } + } + return true +} + +func createTestSetup(t *testing.T) (*sm.Pruner, *kv.TxIndex, blockidxkv.BlockerIndexer) { + t.Helper() + config := test.ResetTestRoot("pruner_test") + t.Cleanup(func() { + err := os.RemoveAll(config.RootDir) + if err != nil { + t.Error(err) + } + }) + // event bus + eventBus := types.NewEventBus() + eventBus.SetLogger(log.TestingLogger()) + err := eventBus.Start() + require.NoError(t, err) + + t.Cleanup(func() { + if err := eventBus.Stop(); err != nil { + t.Error(err) + } + err := os.RemoveAll(config.RootDir) + if err != nil { + t.Error(err) + } + }) + + // tx indexer + memDB := db.NewMemDB() + txIndexer := kv.NewTxIndex(memDB) + blockIndexer := blockidxkv.New(db.NewPrefixDB(memDB, []byte("block_events"))) + + blockDB := db.NewMemDB() + stateDB := db.NewMemDB() + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + bs := store.NewBlockStore(blockDB) + pruner := sm.NewPruner(stateStore, bs, blockIndexer, txIndexer, log.TestingLogger()) + + return pruner, txIndexer, *blockIndexer +} + +func getEventsAndResults(height int64) (types.EventDataNewBlockEvents, *abci.TxResult, *abci.TxResult) { + events := types.EventDataNewBlockEvents{ + Height: height, + Events: []abci.Event{ + { + Type: "begin_event", + Attributes: []abci.EventAttribute{ + { + Key: "proposer", + Value: "FCAA001", + Index: true, + }, + }, + }, + }, + NumTxs: int64(2), + } + txResult1 := &abci.TxResult{ + Height: height, + Index: uint32(0), + Tx: types.Tx(fmt.Sprintf("foo%d", height)), + Result: abci.ExecTxResult{Code: 0}, + } + txResult2 := &abci.TxResult{ + Height: height, + Index: uint32(1), + Tx: types.Tx(fmt.Sprintf("bar%d", height)), + Result: abci.ExecTxResult{Code: 0}, + } + return events, txResult1, txResult2 +} + +// When trying to prune the only block in the store it should not succeed +// State should also not be pruned. +func TestPruningWithHeight1(t *testing.T) { + config := test.ResetTestRoot("blockchain_reactor_pruning_test") + defer os.RemoveAll(config.RootDir) + state, bs, txIndexer, blockIndexer, cleanup, stateStore := makeStateAndBlockStoreAndIndexers() + defer cleanup() + require.EqualValues(t, 0, bs.Base()) + require.EqualValues(t, 0, bs.Height()) + require.EqualValues(t, 0, bs.Size()) + + err := initStateStoreRetainHeights(stateStore) + require.NoError(t, err) + + obs := newPrunerObserver(1) + + pruner := sm.NewPruner( + stateStore, + bs, + blockIndexer, + txIndexer, + log.TestingLogger(), + sm.WithPrunerInterval(time.Second*1), + sm.WithPrunerObserver(obs), + sm.WithPrunerCompanionEnabled(), + ) + + err = pruner.SetApplicationBlockRetainHeight(1) + require.Error(t, err) + err = pruner.SetApplicationBlockRetainHeight(0) + require.NoError(t, err) + + block := state.MakeBlock(1, test.MakeNTxs(1, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) + partSet, err := block.MakePartSet(2) + require.NoError(t, err) + + bs.SaveBlock(block, partSet, &types.Commit{Height: 1}) + require.EqualValues(t, 1, bs.Base()) + require.EqualValues(t, 1, bs.Height()) + + err = stateStore.Save(state) + require.NoError(t, err) + + err = pruner.SetApplicationBlockRetainHeight(1) + require.NoError(t, err) + err = pruner.SetCompanionBlockRetainHeight(1) + require.NoError(t, err) + + pruned, _, err := pruner.PruneBlocksToHeight(1) + require.Equal(t, uint64(0), pruned) + require.NoError(t, err) +} diff --git a/state/rollback.go b/internal/state/rollback.go similarity index 93% rename from state/rollback.go rename to internal/state/rollback.go index 6420192cf72..05ea03d2af5 100644 --- a/state/rollback.go +++ b/internal/state/rollback.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - cmtstate "github.com/cometbft/cometbft/proto/tendermint/state" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" + cmtstate "github.com/cometbft/cometbft/api/cometbft/state/v1" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/version" ) @@ -65,10 +65,11 @@ func Rollback(bs BlockStore, ss Store, removeBlock bool) (int64, []byte, error) return -1, nil, err } + nextHeight := rollbackHeight + 1 valChangeHeight := invalidState.LastHeightValidatorsChanged // this can only happen if the validator set changed since the last block - if valChangeHeight > rollbackHeight { - valChangeHeight = rollbackHeight + 1 + if valChangeHeight > nextHeight+1 { + valChangeHeight = nextHeight + 1 } paramsChangeHeight := invalidState.LastHeightConsensusParamsChanged @@ -84,7 +85,7 @@ func Rollback(bs BlockStore, ss Store, removeBlock bool) (int64, []byte, error) Block: version.BlockProtocol, App: previousParams.Version.App, }, - Software: version.TMCoreSemVer, + Software: version.CMTSemVer, }, // immutable fields ChainID: invalidState.ChainID, diff --git a/state/rollback_test.go b/internal/state/rollback_test.go similarity index 93% rename from state/rollback_test.go rename to internal/state/rollback_test.go index 9495cb4649f..e4f056622b6 100644 --- a/state/rollback_test.go +++ b/internal/state/rollback_test.go @@ -8,15 +8,15 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - + cmtstate "github.com/cometbft/cometbft/api/cometbft/state/v1" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/tmhash" - cmtstate "github.com/cometbft/cometbft/proto/tendermint/state" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" - "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/mocks" - "github.com/cometbft/cometbft/store" + "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/mocks" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) @@ -124,7 +124,7 @@ func TestRollbackHard(t *testing.T) { currState := state.State{ Version: cmtstate.Version{ Consensus: block.Header.Version, - Software: version.TMCoreSemVer, + Software: version.CMTSemVer, }, LastBlockHeight: block.Height, LastBlockTime: block.Time, @@ -181,7 +181,7 @@ func TestRollbackHard(t *testing.T) { nextState := state.State{ Version: cmtstate.Version{ Consensus: block.Header.Version, - Software: version.TMCoreSemVer, + Software: version.CMTSemVer, }, LastBlockHeight: nextBlock.Height, LastBlockTime: nextBlock.Time, @@ -235,10 +235,11 @@ func TestRollbackDifferentStateHeight(t *testing.T) { _, _, err := state.Rollback(blockStore, stateStore, false) require.Error(t, err) - require.Equal(t, err.Error(), "statestore height (100) is not one below or equal to blockstore height (102)") + require.Equal(t, "statestore height (100) is not one below or equal to blockstore height (102)", err.Error()) } func setupStateStore(t *testing.T, height int64) state.Store { + t.Helper() stateStore := state.NewStore(dbm.NewMemDB(), state.StoreOptions{DiscardABCIResponses: false}) valSet, _ := types.RandValidatorSet(5, 10) @@ -251,7 +252,7 @@ func setupStateStore(t *testing.T, height int64) state.Store { Block: version.BlockProtocol, App: 10, }, - Software: version.TMCoreSemVer, + Software: version.CMTSemVer, }, ChainID: "test-chain", InitialHeight: 10, @@ -259,11 +260,11 @@ func setupStateStore(t *testing.T, height int64) state.Store { AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), LastBlockHeight: height, - LastBlockTime: time.Now(), + LastBlockTime: cmttime.Now(), LastValidators: valSet, Validators: valSet.CopyIncrementProposerPriority(1), NextValidators: valSet.CopyIncrementProposerPriority(2), - LastHeightValidatorsChanged: height + 1, + LastHeightValidatorsChanged: height + 1 + 1, ConsensusParams: *params, LastHeightConsensusParamsChanged: height + 1, } diff --git a/state/services.go b/internal/state/services.go similarity index 61% rename from state/services.go rename to internal/state/services.go index b1506e9efb4..d5498b11c36 100644 --- a/state/services.go +++ b/internal/state/services.go @@ -4,15 +4,15 @@ import ( "github.com/cometbft/cometbft/types" ) -//------------------------------------------------------ +// ------------------------------------------------------ // blockchain services types // NOTE: Interfaces used by RPC must be thread safe! -//------------------------------------------------------ +// ------------------------------------------------------ -//------------------------------------------------------ +// ------------------------------------------------------ // blockstore -//go:generate ../scripts/mockery_generate.sh BlockStore +//go:generate ../../scripts/mockery_generate.sh BlockStore // BlockStore defines the interface used by the ConsensusState. type BlockStore interface { @@ -22,14 +22,14 @@ type BlockStore interface { LoadBaseMeta() *types.BlockMeta LoadBlockMeta(height int64) *types.BlockMeta - LoadBlock(height int64) *types.Block + LoadBlock(height int64) (*types.Block, *types.BlockMeta) SaveBlock(block *types.Block, blockParts *types.PartSet, seenCommit *types.Commit) SaveBlockWithExtendedCommit(block *types.Block, blockParts *types.PartSet, seenCommit *types.ExtendedCommit) PruneBlocks(height int64, state State) (uint64, int64, error) - LoadBlockByHash(hash []byte) *types.Block + LoadBlockByHash(hash []byte) (*types.Block, *types.BlockMeta) LoadBlockMetaByHash(hash []byte) *types.BlockMeta LoadBlockPart(height int64, index int) *types.Part @@ -42,27 +42,27 @@ type BlockStore interface { Close() error } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // evidence pool -//go:generate ../scripts/mockery_generate.sh EvidencePool +//go:generate ../../scripts/mockery_generate.sh EvidencePool // EvidencePool defines the EvidencePool interface used by State. type EvidencePool interface { PendingEvidence(maxBytes int64) (ev []types.Evidence, size int64) - AddEvidence(types.Evidence) error - Update(State, types.EvidenceList) - CheckEvidence(types.EvidenceList) error + AddEvidence(ev types.Evidence) error + Update(state State, evList types.EvidenceList) + CheckEvidence(evList types.EvidenceList) error } // EmptyEvidencePool is an empty implementation of EvidencePool, useful for testing. It also complies -// to the consensus evidence pool interface +// to the consensus evidence pool interface. type EmptyEvidencePool struct{} -func (EmptyEvidencePool) PendingEvidence(maxBytes int64) (ev []types.Evidence, size int64) { +func (EmptyEvidencePool) PendingEvidence(int64) (ev []types.Evidence, size int64) { return nil, 0 } func (EmptyEvidencePool) AddEvidence(types.Evidence) error { return nil } func (EmptyEvidencePool) Update(State, types.EvidenceList) {} -func (EmptyEvidencePool) CheckEvidence(evList types.EvidenceList) error { return nil } -func (EmptyEvidencePool) ReportConflictingVotes(voteA, voteB *types.Vote) {} +func (EmptyEvidencePool) CheckEvidence(types.EvidenceList) error { return nil } +func (EmptyEvidencePool) ReportConflictingVotes(*types.Vote, *types.Vote) {} diff --git a/state/state.go b/internal/state/state.go similarity index 83% rename from state/state.go rename to internal/state/state.go index 15fb8e5e62b..ab43f2a2899 100644 --- a/state/state.go +++ b/internal/state/state.go @@ -9,19 +9,19 @@ import ( "github.com/cosmos/gogoproto/proto" - cmtstate "github.com/cometbft/cometbft/proto/tendermint/state" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" + cmtstate "github.com/cometbft/cometbft/api/cometbft/state/v1" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) -// database keys +// database keys. var ( stateKey = []byte("stateKey") ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // InitStateVersion sets the Consensus.Block and Software versions, // but leaves the Consensus.App version blank. @@ -32,10 +32,10 @@ var InitStateVersion = cmtstate.Version{ Block: version.BlockProtocol, App: 0, }, - Software: version.TMCoreSemVer, + Software: version.CMTSemVer, } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // State is a short description of the latest committed block of the consensus protocol. // It keeps all information necessary to validate new blocks, @@ -81,7 +81,6 @@ type State struct { // Copy makes a copy of the State for mutating. func (state State) Copy() State { - return State{ Version: state.Version, ChainID: state.ChainID, @@ -130,7 +129,7 @@ func (state State) IsEmpty() bool { return state.Validators == nil // XXX can't compare to Empty } -// ToProto takes the local state type and returns the equivalent proto type +// ToProto takes the local state type and returns the equivalent proto type. func (state *State) ToProto() (*cmtstate.State, error) { if state == nil { return nil, errors.New("state is nil") @@ -174,7 +173,7 @@ func (state *State) ToProto() (*cmtstate.State, error) { return sm, nil } -// FromProto takes a state proto message & returns the local state type +// FromProto takes a state proto message & returns the local state type. func FromProto(pb *cmtstate.State) (*State, error) { //nolint:golint if pb == nil { return nil, errors.New("nil State") @@ -225,7 +224,7 @@ func FromProto(pb *cmtstate.State) (*State, error) { //nolint:golint return state, nil } -//------------------------------------------------------------------------ +// ------------------------------------------------------------------------ // Create a block from the latest state // MakeBlock builds a block from the current state with the given txs, commit, @@ -238,16 +237,18 @@ func (state State) MakeBlock( evidence []types.Evidence, proposerAddress []byte, ) *types.Block { - // Build base block with block data. block := types.MakeBlock(height, txs, lastCommit, evidence) // Set time. var timestamp time.Time - if height == state.InitialHeight { + switch { + case state.ConsensusParams.Feature.PbtsEnabled(height): + timestamp = cmttime.Now() + case height == state.InitialHeight: timestamp = state.LastBlockTime // genesis time - } else { - timestamp = MedianTime(lastCommit, state.LastValidators) + default: + timestamp = lastCommit.MedianTime(state.LastValidators) } // Fill rest of header with state data. @@ -262,30 +263,7 @@ func (state State) MakeBlock( return block } -// MedianTime computes a median time for a given Commit (based on Timestamp field of votes messages) and the -// corresponding validator set. The computed time is always between timestamps of -// the votes sent by honest processes, i.e., a faulty processes can not arbitrarily increase or decrease the -// computed value. -func MedianTime(commit *types.Commit, validators *types.ValidatorSet) time.Time { - weightedTimes := make([]*cmttime.WeightedTime, len(commit.Signatures)) - totalVotingPower := int64(0) - - for i, commitSig := range commit.Signatures { - if commitSig.BlockIDFlag == types.BlockIDFlagAbsent { - continue - } - _, validator := validators.GetByAddress(commitSig.ValidatorAddress) - // If there's no condition, TestValidateBlockCommit panics; not needed normally. - if validator != nil { - totalVotingPower += validator.VotingPower - weightedTimes[i] = cmttime.NewWeightedTime(commitSig.Timestamp, validator.VotingPower) - } - } - - return cmttime.WeightedMedian(weightedTimes, totalVotingPower) -} - -//------------------------------------------------------------------------ +// ------------------------------------------------------------------------ // Genesis // MakeGenesisStateFromFile reads and unmarshals state from the given @@ -304,11 +282,11 @@ func MakeGenesisStateFromFile(genDocFile string) (State, error) { func MakeGenesisDocFromFile(genDocFile string) (*types.GenesisDoc, error) { genDocJSON, err := os.ReadFile(genDocFile) if err != nil { - return nil, fmt.Errorf("couldn't read GenesisDoc file: %v", err) + return nil, fmt.Errorf("couldn't read GenesisDoc file: %w", err) } genDoc, err := types.GenesisDocFromJSON(genDocJSON) if err != nil { - return nil, fmt.Errorf("error reading GenesisDoc: %v", err) + return nil, fmt.Errorf("error reading GenesisDoc: %w", err) } return genDoc, nil } diff --git a/state/state_test.go b/internal/state/state_test.go similarity index 90% rename from state/state_test.go rename to internal/state/state_test.go index 2e6be6ea915..0c7c3132486 100644 --- a/state/state_test.go +++ b/internal/state/state_test.go @@ -6,24 +6,25 @@ import ( "math" "math/big" "os" + "strconv" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/crypto/ed25519" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" + cmtrand "github.com/cometbft/cometbft/internal/rand" + sm "github.com/cometbft/cometbft/internal/state" "github.com/cometbft/cometbft/internal/test" - cmtrand "github.com/cometbft/cometbft/libs/rand" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" ) // setupTestCase does setup common to all test cases. func setupTestCase(t *testing.T) (func(t *testing.T), dbm.DB, sm.State) { + t.Helper() config := test.ResetTestRoot("state_") dbType := dbm.BackendType(config.DBBackend) stateDB, err := dbm.NewDB("state", dbType, config.DBDir()) @@ -32,17 +33,21 @@ func setupTestCase(t *testing.T) (func(t *testing.T), dbm.DB, sm.State) { }) require.NoError(t, err) state, err := stateStore.LoadFromDBOrGenesisFile(config.GenesisFile()) - assert.NoError(t, err, "expected no error on LoadStateFromDBOrGenesisFile") + require.NoError(t, err, "expected no error on LoadStateFromDBOrGenesisFile") err = stateStore.Save(state) require.NoError(t, err) - tearDown := func(t *testing.T) { os.RemoveAll(config.RootDir) } + tearDown := func(t *testing.T) { + t.Helper() + os.RemoveAll(config.RootDir) + } return tearDown, stateDB, state } // TestStateCopy tests the correct copying behavior of State. func TestStateCopy(t *testing.T) { + t.Helper() tearDown, _, state := setupTestCase(t) defer tearDown(t) assert := assert.New(t) @@ -65,11 +70,11 @@ func TestMakeGenesisStateNilValidators(t *testing.T) { ChainID: "dummy", Validators: nil, } - require.Nil(t, doc.ValidateAndComplete()) + require.NoError(t, doc.ValidateAndComplete()) state, err := sm.MakeGenesisState(&doc) - require.Nil(t, err) - require.Equal(t, 0, len(state.Validators.Validators)) - require.Equal(t, 0, len(state.NextValidators.Validators)) + require.NoError(t, err) + require.Empty(t, state.Validators.Validators) + require.Empty(t, state.NextValidators.Validators) } // TestStateSaveLoad tests saving and loading State from a db. @@ -107,7 +112,7 @@ func TestFinalizeBlockResponsesSaveLoad1(t *testing.T) { // Build mock responses. block := makeBlock(state, 2, new(types.Commit)) - abciResponses := new(abci.ResponseFinalizeBlock) + abciResponses := new(abci.FinalizeBlockResponse) dtxs := make([]*abci.ExecTxResult, 2) abciResponses.TxResults = dtxs @@ -120,7 +125,7 @@ func TestFinalizeBlockResponsesSaveLoad1(t *testing.T) { err := stateStore.SaveFinalizeBlockResponse(block.Height, abciResponses) require.NoError(t, err) loadedABCIResponses, err := stateStore.LoadFinalizeBlockResponse(block.Height) - assert.NoError(err) + require.NoError(t, err) assert.Equal(abciResponses, loadedABCIResponses) } @@ -185,15 +190,15 @@ func TestFinalizeBlockResponsesSaveLoad2(t *testing.T) { for i := range cases { h := int64(i + 1) res, err := stateStore.LoadFinalizeBlockResponse(h) - assert.Error(err, "%d: %#v", i, res) + require.Error(t, err, "%d: %#v", i, res) } // Add all cases. for i, tc := range cases { h := int64(i + 1) // last block height, one below what we save - responses := &abci.ResponseFinalizeBlock{ + responses := &abci.FinalizeBlockResponse{ TxResults: tc.added, - AppHash: []byte(fmt.Sprintf("%d", h)), + AppHash: []byte(strconv.FormatInt(h, 10)), } err := stateStore.SaveFinalizeBlockResponse(h, responses) require.NoError(t, err) @@ -203,11 +208,11 @@ func TestFinalizeBlockResponsesSaveLoad2(t *testing.T) { for i, tc := range cases { h := int64(i + 1) res, err := stateStore.LoadFinalizeBlockResponse(h) - if assert.NoError(err, "%d", i) { + if assert.NoError(err, "%d", i) { //nolint:testifylint // require.Error doesn't work with the conditional here t.Log(res) - responses := &abci.ResponseFinalizeBlock{ + responses := &abci.FinalizeBlockResponse{ TxResults: tc.expected, - AppHash: []byte(fmt.Sprintf("%d", h)), + AppHash: []byte(strconv.FormatInt(h, 10)), } assert.Equal(sm.TxResultsHash(responses.TxResults), sm.TxResultsHash(res.TxResults), "%d", i) } @@ -230,12 +235,12 @@ func TestValidatorSimpleSaveLoad(t *testing.T) { // Should be able to load for height 1. v, err := statestore.LoadValidators(1) - assert.Nil(err, "expected no err at height 1") + require.NoError(t, err, "expected no err at height 1") assert.Equal(v.Hash(), state.Validators.Hash(), "expected validator hashes to match") // Should be able to load for height 2. v, err = statestore.LoadValidators(2) - assert.Nil(err, "expected no err at height 2") + require.NoError(t, err, "expected no err at height 2") assert.Equal(v.Hash(), state.NextValidators.Hash(), "expected validator hashes to match") // Increment height, save; should be able to load for next & next next height. @@ -244,9 +249,9 @@ func TestValidatorSimpleSaveLoad(t *testing.T) { err = statestore.Save(state) require.NoError(t, err) vp0, err := statestore.LoadValidators(nextHeight + 0) - assert.Nil(err, "expected no err") + require.NoError(t, err) vp1, err := statestore.LoadValidators(nextHeight + 1) - assert.Nil(err, "expected no err") + require.NoError(t, err) assert.Equal(vp0.Hash(), state.Validators.Hash(), "expected validator hashes to match") assert.Equal(vp1.Hash(), state.NextValidators.Hash(), "expected next validator hashes to match") } @@ -261,11 +266,11 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) { // Change vals at these heights. changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20} - N := len(changeHeights) + n := len(changeHeights) // Build the validator history by running updateState // with the right validator set for each height. - highestHeight := changeHeights[N-1] + 5 + highestHeight := changeHeights[n-1] + 5 changeIndex := 0 _, val := state.Validators.GetByIndex(0) power := val.VotingPower @@ -277,7 +282,7 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) { changeIndex++ power++ } - header, blockID, responses := makeHeaderPartsResponsesValPowerChange(t, state, power) + header, blockID, responses := makeHeaderPartsResponsesValPowerChange(state, power) validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.ValidatorUpdates) require.NoError(t, err) state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates) @@ -302,8 +307,8 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) { for i, power := range testCases { v, err := stateStore.LoadValidators(int64(i + 1 + 1)) // +1 because vset changes delayed by 1 block. - assert.Nil(t, err, fmt.Sprintf("expected no err at height %d", i)) - assert.Equal(t, v.Size(), 1, "validator set size is greater than 1: %d", v.Size()) + require.NoError(t, err, "expected no err at height %d", i) + assert.Equal(t, 1, v.Size(), "validator set size is greater than 1: %d", v.Size()) _, val := v.GetByIndex(0) assert.Equal(t, val.VotingPower, power, fmt.Sprintf(`unexpected powerat @@ -363,10 +368,10 @@ func TestProposerFrequency(t *testing.T) { maxPower := 1000 nTestCases := 5 for i := 0; i < nTestCases; i++ { - N := cmtrand.Int()%maxVals + 1 - vals := make([]*types.Validator, N) + n := cmtrand.Int()%maxVals + 1 + vals := make([]*types.Validator, n) totalVotePower := int64(0) - for j := 0; j < N; j++ { + for j := 0; j < n; j++ { // make sure votePower > 0 votePower := int64(cmtrand.Int()%maxPower) + 1 totalVotePower += votePower @@ -383,7 +388,7 @@ func TestProposerFrequency(t *testing.T) { } } -// new val set with given powers and random initial priorities +// new val set with given powers and random initial priorities. func genValSetWithPowers(powers []int64) *types.ValidatorSet { size := len(powers) vals := make([]*types.Validator, size) @@ -399,15 +404,16 @@ func genValSetWithPowers(powers []int64) *types.ValidatorSet { return valSet } -// test a proposer appears as frequently as expected +// test a proposer appears as frequently as expected. func testProposerFreq(t *testing.T, caseNum int, valSet *types.ValidatorSet) { - N := valSet.Size() + t.Helper() + n := valSet.Size() totalPower := valSet.TotalVotingPower() // run the proposer selection and track frequencies runMult := 1 runs := int(totalPower) * runMult - freqs := make([]int, N) + freqs := make([]int, n) for i := 0; i < runs; i++ { prop := valSet.GetProposer() idx, _ := valSet.GetByAddress(prop.Address) @@ -426,11 +432,11 @@ func testProposerFreq(t *testing.T, caseNum int, valSet *types.ValidatorSet) { // to be 1 for the 2 validator case in // https://github.com/cwgoes/tm-proposer-idris // and inferred to generalize to N-1 - bound := N - 1 - require.True( + bound := n - 1 + require.LessOrEqual( t, - abs <= bound, - fmt.Sprintf("Case %d val %d (%d): got %d, expected %d", caseNum, i, N, gotFreq, expectFreq), + abs, bound, + fmt.Sprintf("Case %d val %d (%d): got %d, expected %d", caseNum, i, n, gotFreq, expectFreq), ) } } @@ -454,11 +460,11 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { bps, err := block.MakePartSet(testPartSize) require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.ValidatorUpdates) require.NoError(t, err) updatedState, err := sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates) - assert.NoError(t, err) + require.NoError(t, err) curTotal := val1VotingPower // one increment step and one validator: 0 + power - total_power == 0 assert.Equal(t, 0+val1VotingPower-curTotal, updatedState.NextValidators.Validators[0].ProposerPriority) @@ -471,11 +477,11 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val2VotingPower} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal}) - assert.NoError(t, err) + require.NoError(t, err) updatedState2, err := sm.UpdateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates) - assert.NoError(t, err) + require.NoError(t, err) - require.Equal(t, len(updatedState2.NextValidators.Validators), 2) + require.Len(t, updatedState2.NextValidators.Validators, 2) _, updatedVal1 := updatedState2.NextValidators.GetByAddress(val1PubKey.Address()) _, addedVal2 := updatedState2.NextValidators.GetByAddress(val2PubKey.Address()) @@ -507,14 +513,14 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { updatedVotingPowVal2 := int64(1) updateVal := abci.ValidatorUpdate{PubKey: fvp, Power: updatedVotingPowVal2} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateVal}) - assert.NoError(t, err) + require.NoError(t, err) // this will cause the diff of priorities (77) // to be larger than threshold == 2*totalVotingPower (22): updatedState3, err := sm.UpdateState(updatedState2, blockID, &block.Header, abciResponses, validatorUpdates) - assert.NoError(t, err) + require.NoError(t, err) - require.Equal(t, len(updatedState3.NextValidators.Validators), 2) + require.Len(t, updatedState3.NextValidators.Validators, 2) _, prevVal1 := updatedState3.Validators.GetByAddress(val1PubKey.Address()) _, prevVal2 := updatedState3.Validators.GetByAddress(val2PubKey.Address()) _, updatedVal1 = updatedState3.NextValidators.GetByAddress(val1PubKey.Address()) @@ -568,12 +574,12 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} // no updates: - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.ValidatorUpdates) require.NoError(t, err) updatedState, err := sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates) - assert.NoError(t, err) + require.NoError(t, err) // 0 + 10 (initial prio) - 10 (avg) - 10 (mostest - total) = -10 totalPower := val1VotingPower @@ -587,12 +593,12 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { require.NoError(t, err) updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val1VotingPower} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal}) - assert.NoError(t, err) + require.NoError(t, err) updatedState2, err := sm.UpdateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates) - assert.NoError(t, err) + require.NoError(t, err) - require.Equal(t, len(updatedState2.NextValidators.Validators), 2) + require.Len(t, updatedState2.NextValidators.Validators, 2) assert.Equal(t, updatedState2.Validators, updatedState.NextValidators) // val1 will still be proposer as val2 just got added: @@ -633,7 +639,7 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { require.NoError(t, err) updatedState3, err := sm.UpdateState(updatedState2, blockID, &block.Header, abciResponses, validatorUpdates) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, updatedState3.Validators.Proposer.Address, updatedState3.NextValidators.Proposer.Address) @@ -668,12 +674,12 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { // no changes in voting power and both validators have same voting power // -> proposers should alternate: oldState := updatedState3 - abciResponses = &abci.ResponseFinalizeBlock{} + abciResponses = &abci.FinalizeBlockResponse{} validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.ValidatorUpdates) require.NoError(t, err) oldState, err = sm.UpdateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates) - assert.NoError(t, err) + require.NoError(t, err) expectedVal1Prio2 = 1 expectedVal2Prio2 = -1 expectedVal1Prio = -9 @@ -681,12 +687,12 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { for i := 0; i < 1000; i++ { // no validator updates: - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.ValidatorUpdates) require.NoError(t, err) updatedState, err := sm.UpdateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates) - assert.NoError(t, err) + require.NoError(t, err) // alternate (and cyclic priorities): assert.NotEqual( t, @@ -729,14 +735,14 @@ func TestLargeGenesisValidator(t *testing.T) { // reset state validators to above validator state.Validators = types.NewValidatorSet([]*types.Validator{genesisVal}) state.NextValidators = state.Validators - require.True(t, len(state.Validators.Validators) == 1) + require.Len(t, state.Validators.Validators, 1) // update state a few times with no validator updates // asserts that the single validator's ProposerPrio stays the same oldState := state for i := 0; i < 10; i++ { // no updates: - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.ValidatorUpdates) require.NoError(t, err) @@ -766,8 +772,8 @@ func TestLargeGenesisValidator(t *testing.T) { require.NoError(t, err) firstAddedVal := abci.ValidatorUpdate{PubKey: fvp, Power: firstAddedValVotingPower} validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{firstAddedVal}) - assert.NoError(t, err) - abciResponses := &abci.ResponseFinalizeBlock{ + require.NoError(t, err) + abciResponses := &abci.FinalizeBlockResponse{ ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal}, } block := makeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) @@ -782,7 +788,7 @@ func TestLargeGenesisValidator(t *testing.T) { lastState := updatedState for i := 0; i < 200; i++ { // no updates: - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.ValidatorUpdates) require.NoError(t, err) @@ -807,8 +813,8 @@ func TestLargeGenesisValidator(t *testing.T) { _, addedOldVal := oldState.NextValidators.GetByAddress(firstAddedValPubKey.Address()) _, addedNewVal := state.NextValidators.GetByAddress(firstAddedValPubKey.Address()) // expect large negative proposer priority for both (genesis validator decreased, 2nd validator increased): - assert.True(t, oldGenesisVal.ProposerPriority > newGenesisVal.ProposerPriority) - assert.True(t, addedOldVal.ProposerPriority < addedNewVal.ProposerPriority) + assert.Greater(t, oldGenesisVal.ProposerPriority, newGenesisVal.ProposerPriority) + assert.Less(t, addedOldVal.ProposerPriority, addedNewVal.ProposerPriority) // add 10 validators with the same voting power as the one added directly after genesis: for i := 0; i < 10; i++ { @@ -817,9 +823,9 @@ func TestLargeGenesisValidator(t *testing.T) { require.NoError(t, err) addedVal := abci.ValidatorUpdate{PubKey: ap, Power: firstAddedValVotingPower} validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{addedVal}) - assert.NoError(t, err) + require.NoError(t, err) - abciResponses := &abci.ResponseFinalizeBlock{ + abciResponses := &abci.FinalizeBlockResponse{ ValidatorUpdates: []abci.ValidatorUpdate{addedVal}, } block := makeBlock(oldState, oldState.LastBlockHeight+1, new(types.Commit)) @@ -830,13 +836,13 @@ func TestLargeGenesisValidator(t *testing.T) { state, err = sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates) require.NoError(t, err) } - require.Equal(t, 10+2, len(state.NextValidators.Validators)) + require.Len(t, state.NextValidators.Validators, 10+2) // remove genesis validator: gp, err := cryptoenc.PubKeyToProto(genesisPubKey) require.NoError(t, err) removeGenesisVal := abci.ValidatorUpdate{PubKey: gp, Power: 0} - abciResponses = &abci.ResponseFinalizeBlock{ + abciResponses = &abci.FinalizeBlockResponse{ ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}, } @@ -852,7 +858,7 @@ func TestLargeGenesisValidator(t *testing.T) { updatedState, err = sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates) require.NoError(t, err) // only the first added val (not the genesis val) should be left - assert.Equal(t, 11, len(updatedState.NextValidators.Validators)) + require.Len(t, updatedState.NextValidators.Validators, 11) // call update state until the effect for the 3rd added validator // being proposer for a long time after the genesis validator left wears off: @@ -860,7 +866,7 @@ func TestLargeGenesisValidator(t *testing.T) { count := 0 isProposerUnchanged := true for isProposerUnchanged { - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.ValidatorUpdates) require.NoError(t, err) block = makeBlock(curState, curState.LastBlockHeight+1, new(types.Commit)) @@ -885,7 +891,7 @@ func TestLargeGenesisValidator(t *testing.T) { proposers := make([]*types.Validator, numVals) for i := 0; i < 100; i++ { // no updates: - abciResponses := &abci.ResponseFinalizeBlock{} + abciResponses := &abci.FinalizeBlockResponse{} validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.ValidatorUpdates) require.NoError(t, err) @@ -923,11 +929,11 @@ func TestStoreLoadValidatorsIncrementsProposerPriority(t *testing.T) { nextHeight := state.LastBlockHeight + 1 v0, err := stateStore.LoadValidators(nextHeight) - assert.Nil(t, err) + require.NoError(t, err) acc0 := v0.Validators[0].ProposerPriority v1, err := stateStore.LoadValidators(nextHeight + 1) - assert.Nil(t, err) + require.NoError(t, err) acc1 := v1.Validators[0].ProposerPriority assert.NotEqual(t, acc1, acc0, "expected ProposerPriority value to change between heights") @@ -953,21 +959,21 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) { pubkey := ed25519.GenPrivKey().PubKey() // Swap the first validator with a new one (validator set size stays the same). - header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(t, state, pubkey) + header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(state, pubkey) // Save state etc. var validatorUpdates []*types.Validator validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.ValidatorUpdates) require.NoError(t, err) state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates) - require.Nil(t, err) + require.NoError(t, err) nextHeight := state.LastBlockHeight + 1 err = stateStore.Save(state) require.NoError(t, err) // Load nextheight, it should be the oldpubkey. v0, err := stateStore.LoadValidators(nextHeight) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, valSetSize, v0.Size()) index, val := v0.GetByAddress(pubkeyOld.Address()) assert.NotNil(t, val) @@ -977,7 +983,7 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) { // Load nextheight+1, it should be the new pubkey. v1, err := stateStore.LoadValidators(nextHeight + 1) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, valSetSize, v1.Size()) index, val = v1.GetByAddress(pubkey.Address()) assert.NotNil(t, val) @@ -1011,21 +1017,22 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { // Change vals at these heights. changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20} - N := len(changeHeights) + n := len(changeHeights) // Each valset is just one validator. // create list of them. - params := make([]types.ConsensusParams, N+1) + params := make([]types.ConsensusParams, n+1) params[0] = state.ConsensusParams - for i := 1; i < N+1; i++ { + for i := 1; i < n+1; i++ { params[i] = *types.DefaultConsensusParams() + // FIXME: shouldn't PBTS be enabled by default? + params[i].Feature.PbtsEnableHeight = 1 params[i].Block.MaxBytes += int64(i) - } // Build the params history by running updateState // with the right params set for each height. - highestHeight := changeHeights[N-1] + 5 + highestHeight := changeHeights[n-1] + 5 changeIndex := 0 cp := params[changeIndex] var err error @@ -1036,7 +1043,7 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { changeIndex++ cp = params[changeIndex] } - header, blockID, responses := makeHeaderPartsResponsesParams(t, state, cp.ToProto()) + header, blockID, responses := makeHeaderPartsResponsesParams(state, cp.ToProto()) validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.ValidatorUpdates) require.NoError(t, err) state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates) @@ -1062,7 +1069,7 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { for _, testCase := range testCases { p, err := stateStore.LoadConsensusParams(testCase.height) - assert.Nil(t, err, fmt.Sprintf("expected no err at height %d", testCase.height)) + require.NoError(t, err, "expected no err at height %d", testCase.height) assert.EqualValues(t, testCase.params, p, fmt.Sprintf(`unexpected consensus params at height %d`, testCase.height)) } @@ -1087,9 +1094,9 @@ func TestStateProto(t *testing.T) { tt := tt pbs, err := tt.state.ToProto() if !tt.expPass1 { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err, tt.testName) + require.NoError(t, err, tt.testName) } smt, err := sm.FromProto(pbs) diff --git a/internal/state/store.go b/internal/state/store.go new file mode 100644 index 00000000000..c78ab040e5b --- /dev/null +++ b/internal/state/store.go @@ -0,0 +1,1107 @@ +package state + +import ( + "encoding/binary" + "errors" + "fmt" + "time" + + "github.com/cosmos/gogoproto/proto" + "github.com/go-kit/kit/metrics" + "github.com/google/orderedcode" + + dbm "github.com/cometbft/cometbft-db" + abci "github.com/cometbft/cometbft/abci/types" + cmtstate "github.com/cometbft/cometbft/api/cometbft/state/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtos "github.com/cometbft/cometbft/internal/os" + "github.com/cometbft/cometbft/libs/log" + cmtmath "github.com/cometbft/cometbft/libs/math" + "github.com/cometbft/cometbft/types" +) + +const ( + // persist validators every valSetCheckpointInterval blocks to avoid + // LoadValidators taking too much time. + // https://github.com/tendermint/tendermint/pull/3438 + // 100000 results in ~ 100ms to get 100 validators (see BenchmarkLoadValidators). + valSetCheckpointInterval = 100000 +) + +var ( + ErrKeyNotFound = errors.New("key not found") + ErrInvalidHeightValue = errors.New("invalid height value") +) + +// ------------------------------------------------------------------------. +type KeyLayout interface { + CalcValidatorsKey(height int64) []byte + + CalcConsensusParamsKey(height int64) []byte + + CalcABCIResponsesKey(height int64) []byte +} + +type v1LegacyLayout struct{} + +// CalcABCIResponsesKey implements StateKeyLayout. +func (v1LegacyLayout) CalcABCIResponsesKey(height int64) []byte { + return []byte(fmt.Sprintf("abciResponsesKey:%v", height)) +} + +// store.StoreOptions.DBKeyLayout.calcConsensusParamsKey implements StateKeyLayout. +func (v1LegacyLayout) CalcConsensusParamsKey(height int64) []byte { + return []byte(fmt.Sprintf("consensusParamsKey:%v", height)) +} + +// store.StoreOptions.DBKeyLayout.CalcValidatorsKey implements StateKeyLayout. +func (v1LegacyLayout) CalcValidatorsKey(height int64) []byte { + return []byte(fmt.Sprintf("validatorsKey:%v", height)) +} + +var _ KeyLayout = (*v1LegacyLayout)(nil) + +// ---------------------- + +var ( + lastABCIResponseKey = []byte("lastABCIResponseKey") // DEPRECATED + lastABCIResponsesRetainHeightKey = []byte("lastABCIResponsesRetainHeight") + offlineStateSyncHeight = []byte("offlineStateSyncHeightKey") +) + +var ( + // prefixes must be unique across all db's. + prefixValidators = int64(6) + prefixConsensusParams = int64(7) + prefixABCIResponses = int64(8) +) + +type v2Layout struct{} + +func (v2Layout) encodeKey(prefix, height int64) []byte { + res, err := orderedcode.Append(nil, prefix, height) + if err != nil { + panic(err) + } + return res +} + +// CalcABCIResponsesKey implements StateKeyLayout. +func (v2l v2Layout) CalcABCIResponsesKey(height int64) []byte { + return v2l.encodeKey(prefixABCIResponses, height) +} + +// CalcConsensusParamsKey implements StateKeyLayout. +func (v2l v2Layout) CalcConsensusParamsKey(height int64) []byte { + return v2l.encodeKey(prefixConsensusParams, height) +} + +// CalcValidatorsKey implements StateKeyLayout. +func (v2l v2Layout) CalcValidatorsKey(height int64) []byte { + return v2l.encodeKey(prefixValidators, height) +} + +var _ KeyLayout = (*v2Layout)(nil) + +//go:generate ../../scripts/mockery_generate.sh Store + +// Store defines the state store interface +// +// It is used to retrieve current state and save and load ABCI responses, +// validators and consensus parameters. +type Store interface { + // LoadFromDBOrGenesisFile loads the most recent state. + // If the chain is new it will use the genesis file from the provided genesis file path as the current state. + LoadFromDBOrGenesisFile(filepath string) (State, error) + // LoadFromDBOrGenesisDoc loads the most recent state. + // If the chain is new it will use the genesis doc as the current state. + LoadFromDBOrGenesisDoc(doc *types.GenesisDoc) (State, error) + // Load loads the current state of the blockchain + Load() (State, error) + // LoadValidators loads the validator set at a given height + LoadValidators(height int64) (*types.ValidatorSet, error) + // LoadFinalizeBlockResponse loads the abciResponse for a given height + LoadFinalizeBlockResponse(height int64) (*abci.FinalizeBlockResponse, error) + // LoadLastABCIResponse loads the last abciResponse for a given height + LoadLastFinalizeBlockResponse(height int64) (*abci.FinalizeBlockResponse, error) + // LoadConsensusParams loads the consensus params for a given height + LoadConsensusParams(height int64) (types.ConsensusParams, error) + // Save overwrites the previous state with the updated one + Save(state State) error + // SaveFinalizeBlockResponse saves ABCIResponses for a given height + SaveFinalizeBlockResponse(height int64, res *abci.FinalizeBlockResponse) error + // Bootstrap is used for bootstrapping state when not starting from a initial height. + Bootstrap(state State) error + // PruneStates takes the height from which to start pruning and which height stop at + PruneStates(fromHeight, toHeight, evidenceThresholdHeight int64, previouslyPrunedStates uint64) (uint64, error) + // PruneABCIResponses will prune all ABCI responses below the given height. + PruneABCIResponses(targetRetainHeight int64, forceCompact bool) (int64, int64, error) + // SaveApplicationRetainHeight persists the application retain height from the application + SaveApplicationRetainHeight(height int64) error + // GetApplicationRetainHeight returns the retain height set by the application + GetApplicationRetainHeight() (int64, error) + // SaveCompanionBlockRetainHeight saves the retain height set by the data companion + SaveCompanionBlockRetainHeight(height int64) error + // GetCompanionBlockRetainHeight returns the retain height set by the data companion + GetCompanionBlockRetainHeight() (int64, error) + // SaveABCIResRetainHeight persists the retain height for ABCI results set by the data companion + SaveABCIResRetainHeight(height int64) error + // GetABCIResRetainHeight returns the last saved retain height for ABCI results set by the data companion + GetABCIResRetainHeight() (int64, error) + // Saves the height at which the store is bootstrapped after out of band statesync + SetOfflineStateSyncHeight(height int64) error + // Gets the height at which the store is bootstrapped after out of band statesync + GetOfflineStateSyncHeight() (int64, error) + // Close closes the connection with the database + Close() error +} + +// dbStore wraps a db (github.com/cometbft/cometbft-db). +type dbStore struct { + db dbm.DB + + DBKeyLayout KeyLayout + + StoreOptions +} + +type StoreOptions struct { + // DiscardABCIResponses determines whether or not the store + // retains all ABCIResponses. If DiscardABCIResponses is enabled, + // the store will maintain only the response object from the latest + // height. + DiscardABCIResponses bool + + Compact bool + + CompactionInterval int64 + + // Metrics defines the metrics collector to use for the state store. + // if none is specified then a NopMetrics collector is used. + Metrics *Metrics + + Logger log.Logger + + DBKeyLayout string +} + +var _ Store = (*dbStore)(nil) + +func IsEmpty(store dbStore) (bool, error) { + state, err := store.Load() + if err != nil { + return false, err + } + return state.IsEmpty(), nil +} + +func setDBKeyLayout(store *dbStore, dbKeyLayoutVersion string) string { + empty, _ := IsEmpty(*store) + if !empty { + version, err := store.db.Get([]byte("version")) + if err != nil { + // WARN: This is because currently cometBFT DB does not return an error if the key does not exist + // If this behavior changes we need to account for that. + panic(err) + } + if len(version) != 0 { + dbKeyLayoutVersion = string(version) + } + } + + switch dbKeyLayoutVersion { + case "v1", "": + store.DBKeyLayout = &v1LegacyLayout{} + dbKeyLayoutVersion = "v1" + case "v2": + store.DBKeyLayout = &v2Layout{} + dbKeyLayoutVersion = "v2" + default: + panic("Unknown version. Expected v1 or v2, given " + dbKeyLayoutVersion) + } + + if err := store.db.SetSync([]byte("version"), []byte(dbKeyLayoutVersion)); err != nil { + panic(err) + } + return dbKeyLayoutVersion +} + +// NewStore creates the dbStore of the state pkg. +func NewStore(db dbm.DB, options StoreOptions) Store { + if options.Metrics == nil { + options.Metrics = NopMetrics() + } + + store := dbStore{ + db: db, + StoreOptions: options, + } + + dbKeyLayoutVersion := setDBKeyLayout(&store, options.DBKeyLayout) + + if options.Logger != nil { + options.Logger.Info("State store key layout version ", "version", "v"+dbKeyLayoutVersion) + } + + return store +} + +// LoadStateFromDBOrGenesisFile loads the most recent state from the database, +// or creates a new one from the given genesisFilePath. +func (store dbStore) LoadFromDBOrGenesisFile(genesisFilePath string) (State, error) { + defer addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "load_from_db_or_genesis_file"), time.Now())() + state, err := store.Load() + if err != nil { + return State{}, err + } + if state.IsEmpty() { + var err error + state, err = MakeGenesisStateFromFile(genesisFilePath) + if err != nil { + return state, err + } + } + + return state, nil +} + +// LoadStateFromDBOrGenesisDoc loads the most recent state from the database, +// or creates a new one from the given genesisDoc. +func (store dbStore) LoadFromDBOrGenesisDoc(genesisDoc *types.GenesisDoc) (State, error) { + defer addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "load_from_db_or_genesis_doc"), time.Now())() + state, err := store.Load() + if err != nil { + return State{}, err + } + + if state.IsEmpty() { + var err error + state, err = MakeGenesisState(genesisDoc) + if err != nil { + return state, err + } + } + + return state, nil +} + +// LoadState loads the State from the database. +func (store dbStore) Load() (State, error) { + return store.loadState(stateKey) +} + +func (store dbStore) loadState(key []byte) (state State, err error) { + start := time.Now() + buf, err := store.db.Get(key) + if err != nil { + return state, err + } + + addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "load"), start)() + + if len(buf) == 0 { + return state, nil + } + + sp := new(cmtstate.State) + + err = proto.Unmarshal(buf, sp) + if err != nil { + // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED + cmtos.Exit(fmt.Sprintf(`LoadState: Data has been corrupted or its spec has changed: + %v\n`, err)) + } + + sm, err := FromProto(sp) + if err != nil { + return state, err + } + return *sm, nil +} + +// Save persists the State, the ValidatorsInfo, and the ConsensusParamsInfo to the database. +// This flushes the writes (e.g. calls SetSync). +func (store dbStore) Save(state State) error { + return store.save(state, stateKey) +} + +func (store dbStore) save(state State, key []byte) error { + start := time.Now() + + batch := store.db.NewBatch() + defer func(batch dbm.Batch) { + err := batch.Close() + if err != nil { + panic(err) + } + }(batch) + nextHeight := state.LastBlockHeight + 1 + // If first block, save validators for the block. + if nextHeight == 1 { + nextHeight = state.InitialHeight + // This extra logic due to validator set changes being delayed 1 block. + // It may get overwritten due to InitChain validator updates. + if err := store.saveValidatorsInfo(nextHeight, nextHeight, state.Validators, batch); err != nil { + return err + } + } + // Save next validators. + if err := store.saveValidatorsInfo(nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators, batch); err != nil { + return err + } + // Save next consensus params. + if err := store.saveConsensusParamsInfo(nextHeight, + state.LastHeightConsensusParamsChanged, state.ConsensusParams, batch); err != nil { + return err + } + + // Counting the amount of time taken to marshall the state. + // In case the state is big this can impact the metrics reporting + stateMarshallTime := time.Now() + stateBytes := state.Bytes() + stateMarshallDiff := time.Since(stateMarshallTime).Seconds() + + if err := batch.Set(key, stateBytes); err != nil { + return err + } + if err := batch.WriteSync(); err != nil { + panic(err) + } + store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "save").Observe(time.Since(start).Seconds() - stateMarshallDiff) + return nil +} + +// BootstrapState saves a new state, used e.g. by state sync when starting from non-zero height. +func (store dbStore) Bootstrap(state State) error { + batch := store.db.NewBatch() + defer func(batch dbm.Batch) { + err := batch.Close() + if err != nil { + panic(err) + } + }(batch) + height := state.LastBlockHeight + 1 + defer addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "bootstrap"), time.Now())() + if height == 1 { + height = state.InitialHeight + } + + if height > 1 && !state.LastValidators.IsNilOrEmpty() { + if err := store.saveValidatorsInfo(height-1, height-1, state.LastValidators, batch); err != nil { + return err + } + } + + if err := store.saveValidatorsInfo(height, height, state.Validators, batch); err != nil { + return err + } + + if err := store.saveValidatorsInfo(height+1, height+1, state.NextValidators, batch); err != nil { + return err + } + + if err := store.saveConsensusParamsInfo(height, + state.LastHeightConsensusParamsChanged, state.ConsensusParams, batch); err != nil { + return err + } + + if err := batch.Set(stateKey, state.Bytes()); err != nil { + return err + } + + if err := batch.WriteSync(); err != nil { + panic(err) + } + + return batch.Close() +} + +// PruneStates deletes states between the given heights (including from, excluding to). It is not +// guaranteed to delete all states, since the last checkpointed state and states being pointed to by +// e.g. `LastHeightChanged` must remain. The state at to must also exist. +// +// The from parameter is necessary since we can't do a key scan in a performant way due to the key +// encoding not preserving ordering: https://github.com/tendermint/tendermint/issues/4567 +// This will cause some old states to be left behind when doing incremental partial prunes, +// specifically older checkpoints and LastHeightChanged targets. +func (store dbStore) PruneStates(from int64, to int64, evidenceThresholdHeight int64, previosulyPrunedStates uint64) (uint64, error) { + defer addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "prune_states"), time.Now())() + if from <= 0 || to <= 0 { + return 0, fmt.Errorf("from height %v and to height %v must be greater than 0", from, to) + } + if from >= to { + return 0, fmt.Errorf("from height %v must be lower than to height %v", from, to) + } + + valInfo, elapsedTime, err := loadValidatorsInfo(store.db, store.DBKeyLayout.CalcValidatorsKey(min(to, evidenceThresholdHeight))) + if err != nil { + return 0, fmt.Errorf("validators at height %v not found: %w", to, err) + } + + paramsInfo, err := store.loadConsensusParamsInfo(to) + if err != nil { + return 0, fmt.Errorf("consensus params at height %v not found: %w", to, err) + } + + keepVals := make(map[int64]bool) + if valInfo.ValidatorSet == nil { + keepVals[valInfo.LastHeightChanged] = true + keepVals[lastStoredHeightFor(to, valInfo.LastHeightChanged)] = true // keep last checkpoint too + } + keepParams := make(map[int64]bool) + if paramsInfo.ConsensusParams.Equal(&cmtproto.ConsensusParams{}) { + keepParams[paramsInfo.LastHeightChanged] = true + } + + batch := store.db.NewBatch() + defer batch.Close() + pruned := uint64(0) + + // We have to delete in reverse order, to avoid deleting previous heights that have validator + // sets and consensus params that we may need to retrieve. + for h := to - 1; h >= from; h-- { + // For heights we keep, we must make sure they have the full validator set or consensus + // params, otherwise they will panic if they're retrieved directly (instead of + // indirectly via a LastHeightChanged pointer). + if keepVals[h] { + v, tmpTime, err := loadValidatorsInfo(store.db, store.DBKeyLayout.CalcValidatorsKey(h)) + elapsedTime += tmpTime + if err != nil || v.ValidatorSet == nil { + vip, err := store.LoadValidators(h) + if err != nil { + return pruned, err + } + + pvi, err := vip.ToProto() + if err != nil { + return pruned, err + } + + v.ValidatorSet = pvi + v.LastHeightChanged = h + + bz, err := v.Marshal() + if err != nil { + return pruned, err + } + err = batch.Set(store.DBKeyLayout.CalcValidatorsKey(h), bz) + if err != nil { + return pruned, err + } + } + } else if h < evidenceThresholdHeight { + err = batch.Delete(store.DBKeyLayout.CalcValidatorsKey(h)) + if err != nil { + return pruned, err + } + } + // else we keep the validator set because we might need + // it later on for evidence verification + + if keepParams[h] { + p, err := store.loadConsensusParamsInfo(h) + if err != nil { + return pruned, err + } + + if p.ConsensusParams.Equal(&cmtproto.ConsensusParams{}) { + params, err := store.LoadConsensusParams(h) + if err != nil { + return pruned, err + } + p.ConsensusParams = params.ToProto() + + p.LastHeightChanged = h + bz, err := p.Marshal() + if err != nil { + return pruned, err + } + + err = batch.Set(store.DBKeyLayout.CalcConsensusParamsKey(h), bz) + if err != nil { + return pruned, err + } + } + } else { + err = batch.Delete(store.DBKeyLayout.CalcConsensusParamsKey(h)) + if err != nil { + return pruned, err + } + } + + err = batch.Delete(store.DBKeyLayout.CalcABCIResponsesKey(h)) + if err != nil { + return pruned, err + } + pruned++ + + // avoid batches growing too large by flushing to database regularly + if pruned%1000 == 0 && pruned > 0 { + err := batch.Write() + if err != nil { + return pruned, err + } + batch.Close() + batch = store.db.NewBatch() + defer batch.Close() + } + } + + err = batch.WriteSync() + if err != nil { + return pruned, err + } + + // We do not want to panic or interrupt consensus on compaction failure + if store.StoreOptions.Compact && previosulyPrunedStates+pruned >= uint64(store.StoreOptions.CompactionInterval) { + // When the range is nil,nil, the database will try to compact + // ALL levels. Another option is to set a predefined range of + // specific keys. + err = store.db.Compact(nil, nil) + } + + store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "pruning_load_validator_info").Observe(elapsedTime) + return pruned, err +} + +// PruneABCIResponses attempts to prune all ABCI responses up to, but not +// including, the given height. On success, returns the number of heights +// pruned and the new retain height. +func (store dbStore) PruneABCIResponses(targetRetainHeight int64, forceCompact bool) (pruned int64, newRetainHeight int64, err error) { + if store.DiscardABCIResponses { + return 0, 0, nil + } + defer addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "prune_abci_responses"), time.Now())() + lastRetainHeight, err := store.getLastABCIResponsesRetainHeight() + if err != nil { + return 0, 0, fmt.Errorf("failed to look up last ABCI responses retain height: %w", err) + } + if lastRetainHeight == 0 { + lastRetainHeight = 1 + } + + batch := store.db.NewBatch() + defer batch.Close() + + batchPruned := int64(0) + + for h := lastRetainHeight; h < targetRetainHeight; h++ { + if err := batch.Delete(store.DBKeyLayout.CalcABCIResponsesKey(h)); err != nil { + return pruned, lastRetainHeight + pruned, fmt.Errorf("failed to delete ABCI responses at height %d: %w", h, err) + } + batchPruned++ + if batchPruned >= 1000 { + if err := batch.Write(); err != nil { + return pruned, lastRetainHeight + pruned, fmt.Errorf("failed to write ABCI responses deletion batch at height %d: %w", h, err) + } + batch.Close() + + pruned += batchPruned + batchPruned = 0 + if err := store.setLastABCIResponsesRetainHeight(h); err != nil { + return pruned, lastRetainHeight + pruned, fmt.Errorf("failed to set last ABCI responses retain height: %w", err) + } + + batch = store.db.NewBatch() + defer batch.Close() + } + } + + if err = batch.WriteSync(); err != nil { + return pruned + batchPruned, targetRetainHeight, err + } + + if forceCompact && store.Compact { + if pruned+batchPruned >= store.CompactionInterval || targetRetainHeight-lastRetainHeight >= store.CompactionInterval { + err = store.db.Compact(nil, nil) + } + } + return pruned + batchPruned, targetRetainHeight, err +} + +// ------------------------------------------------------------------------ + +// TxResultsHash returns the root hash of a Merkle tree of +// ExecTxResulst responses (see ABCIResults.Hash) +// +// See merkle.SimpleHashFromByteSlices. +func TxResultsHash(txResults []*abci.ExecTxResult) []byte { + return types.NewResults(txResults).Hash() +} + +// LoadFinalizeBlockResponse loads the DiscardABCIResponses for the given height from the +// database. If the node has D set to true, ErrFinalizeBlockResponsesNotPersisted +// is persisted. If not found, ErrNoABCIResponsesForHeight is returned. +func (store dbStore) LoadFinalizeBlockResponse(height int64) (*abci.FinalizeBlockResponse, error) { + if store.DiscardABCIResponses { + return nil, ErrFinalizeBlockResponsesNotPersisted + } + + start := time.Now() + buf, err := store.db.Get(store.DBKeyLayout.CalcABCIResponsesKey(height)) + if err != nil { + return nil, err + } + + addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "load_abci_responses"), start)() + + if len(buf) == 0 { + return nil, ErrNoABCIResponsesForHeight{height} + } + + resp := new(abci.FinalizeBlockResponse) + err = resp.Unmarshal(buf) + if err != nil { + // The data might be of the legacy ABCI response type, so + // we try to unmarshal that + legacyResp := new(cmtstate.LegacyABCIResponses) + rerr := legacyResp.Unmarshal(buf) + if rerr != nil { + cmtos.Exit(fmt.Sprintf(`LoadFinalizeBlockResponse: Data has been corrupted or its spec has + changed: %v\n`, err)) + } + // The state store contains the old format. Migrate to + // the new FinalizeBlockResponse format. Note that the + // new struct expects the AppHash which we don't have. + return responseFinalizeBlockFromLegacy(legacyResp), nil + } + + // TODO: ensure that buf is completely read. + + return resp, nil +} + +// LoadLastFinalizeBlockResponses loads the FinalizeBlockResponses from the most recent height. +// The height parameter is used to ensure that the response corresponds to the latest height. +// If not, an error is returned. +// +// This method is used for recovering in the case that we called the Commit ABCI +// method on the application but crashed before persisting the results. +func (store dbStore) LoadLastFinalizeBlockResponse(height int64) (*abci.FinalizeBlockResponse, error) { + start := time.Now() + buf, err := store.db.Get(store.DBKeyLayout.CalcABCIResponsesKey(height)) + if err != nil { + return nil, err + } + addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "load_last_abci_response"), start)() + if len(buf) == 0 { + // DEPRECATED lastABCIResponseKey + // It is possible if this is called directly after an upgrade that + // `lastABCIResponseKey` contains the last ABCI responses. + bz, err := store.db.Get(lastABCIResponseKey) + if err == nil && len(bz) > 0 { + info := new(cmtstate.ABCIResponsesInfo) + err = info.Unmarshal(bz) + if err != nil { + cmtos.Exit(fmt.Sprintf(`LoadLastFinalizeBlockResponse: Data has been corrupted or its spec has changed: %v\n`, err)) + } + // Here we validate the result by comparing its height to the expected height. + if height != info.GetHeight() { + return nil, fmt.Errorf("expected height %d but last stored abci responses was at height %d", height, info.GetHeight()) + } + if info.FinalizeBlock == nil { + // sanity check + if info.LegacyAbciResponses == nil { + panic("state store contains last abci response but it is empty") + } + return responseFinalizeBlockFromLegacy(info.LegacyAbciResponses), nil + } + return info.FinalizeBlock, nil + } + // END OF DEPRECATED lastABCIResponseKey + return nil, fmt.Errorf("expected last ABCI responses at height %d, but none are found", height) + } + resp := new(abci.FinalizeBlockResponse) + err = resp.Unmarshal(buf) + if err != nil { + cmtos.Exit(fmt.Sprintf(`LoadLastFinalizeBlockResponse: Data has been corrupted or its spec has changed: %v\n`, err)) + } + return resp, nil +} + +// SaveFinalizeBlockResponse persists the FinalizeBlockResponse to the database. +// This is useful in case we crash after app.Commit and before s.Save(). +// Responses are indexed by height so they can also be loaded later to produce +// Merkle proofs. +// +// CONTRACT: height must be monotonically increasing every time this is called. +func (store dbStore) SaveFinalizeBlockResponse(height int64, resp *abci.FinalizeBlockResponse) error { + var dtxs []*abci.ExecTxResult + // strip nil values, + for _, tx := range resp.TxResults { + if tx != nil { + dtxs = append(dtxs, tx) + } + } + resp.TxResults = dtxs + + bz, err := resp.Marshal() + if err != nil { + return err + } + + // Save the ABCI response. + // + // We always save the last ABCI response for crash recovery. + // If `store.DiscardABCIResponses` is true, then we delete the previous ABCI response. + start := time.Now() + if store.DiscardABCIResponses && height > 1 { + if err := store.db.Delete(store.DBKeyLayout.CalcABCIResponsesKey(height - 1)); err != nil { + return err + } + } + if err := store.db.SetSync(store.DBKeyLayout.CalcABCIResponsesKey(height), bz); err != nil { + return err + } + addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "save_abci_responses"), start)() + return nil +} + +func (store dbStore) getValue(key []byte) ([]byte, error) { + bz, err := store.db.Get(key) + if err != nil { + return nil, err + } + + if len(bz) == 0 { + return nil, ErrKeyNotFound + } + return bz, nil +} + +// ApplicationRetainHeight. +func (store dbStore) SaveApplicationRetainHeight(height int64) error { + return store.db.SetSync(AppRetainHeightKey, int64ToBytes(height)) +} + +func (store dbStore) GetApplicationRetainHeight() (int64, error) { + buf, err := store.getValue(AppRetainHeightKey) + if err != nil { + return 0, err + } + height := int64FromBytes(buf) + + if height < 0 { + return 0, ErrInvalidHeightValue + } + + return height, nil +} + +// DataCompanionRetainHeight. +func (store dbStore) SaveCompanionBlockRetainHeight(height int64) error { + return store.db.SetSync(CompanionBlockRetainHeightKey, int64ToBytes(height)) +} + +func (store dbStore) GetCompanionBlockRetainHeight() (int64, error) { + buf, err := store.getValue(CompanionBlockRetainHeightKey) + if err != nil { + return 0, err + } + height := int64FromBytes(buf) + + if height < 0 { + return 0, ErrInvalidHeightValue + } + + return height, nil +} + +// DataCompanionRetainHeight. +func (store dbStore) SaveABCIResRetainHeight(height int64) error { + return store.db.SetSync(ABCIResultsRetainHeightKey, int64ToBytes(height)) +} + +func (store dbStore) GetABCIResRetainHeight() (int64, error) { + buf, err := store.getValue(ABCIResultsRetainHeightKey) + if err != nil { + return 0, err + } + height := int64FromBytes(buf) + + if height < 0 { + return 0, ErrInvalidHeightValue + } + + return height, nil +} + +func (store dbStore) getLastABCIResponsesRetainHeight() (int64, error) { + bz, err := store.getValue(lastABCIResponsesRetainHeightKey) + if errors.Is(err, ErrKeyNotFound) { + return 0, nil + } + height := int64FromBytes(bz) + if height < 0 { + return 0, ErrInvalidHeightValue + } + return height, nil +} + +func (store dbStore) setLastABCIResponsesRetainHeight(height int64) error { + return store.db.SetSync(lastABCIResponsesRetainHeightKey, int64ToBytes(height)) +} + +// ----------------------------------------------------------------------------- + +// LoadValidators loads the ValidatorSet for a given height. +// Returns ErrNoValSetForHeight if the validator set can't be found for this height. +func (store dbStore) LoadValidators(height int64) (*types.ValidatorSet, error) { + valInfo, elapsedTime, err := loadValidatorsInfo(store.db, store.DBKeyLayout.CalcValidatorsKey(height)) + if err != nil { + return nil, ErrNoValSetForHeight{height} + } + // (WARN) This includes time to unmarshal the validator info + if valInfo.ValidatorSet == nil { + lastStoredHeight := lastStoredHeightFor(height, valInfo.LastHeightChanged) + valInfo2, tmpTime, err := loadValidatorsInfo(store.db, store.DBKeyLayout.CalcValidatorsKey(lastStoredHeight)) + elapsedTime += tmpTime + if err != nil || valInfo2.ValidatorSet == nil { + return nil, + fmt.Errorf("couldn't find validators at height %d (height %d was originally requested): %w", + lastStoredHeight, + height, + err, + ) + } + + vs, err := types.ValidatorSetFromProto(valInfo2.ValidatorSet) + if err != nil { + return nil, err + } + + vs.IncrementProposerPriority(cmtmath.SafeConvertInt32(height - lastStoredHeight)) // mutate + vi2, err := vs.ToProto() + if err != nil { + return nil, err + } + + valInfo2.ValidatorSet = vi2 + valInfo = valInfo2 + } + + vip, err := types.ValidatorSetFromProto(valInfo.ValidatorSet) + if err != nil { + return nil, err + } + store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "load_validators").Observe(elapsedTime) + return vip, nil +} + +func lastStoredHeightFor(height, lastHeightChanged int64) int64 { + checkpointHeight := height - height%valSetCheckpointInterval + return cmtmath.MaxInt64(checkpointHeight, lastHeightChanged) +} + +// CONTRACT: Returned ValidatorsInfo can be mutated. +func loadValidatorsInfo(db dbm.DB, valInfoKey []byte) (*cmtstate.ValidatorsInfo, float64, error) { + start := time.Now() + buf, err := db.Get(valInfoKey) + if err != nil { + return nil, 0, err + } + + elapsedTime := time.Since(start).Seconds() + + if len(buf) == 0 { + return nil, 0, errors.New("value retrieved from db is empty") + } + + v := new(cmtstate.ValidatorsInfo) + err = v.Unmarshal(buf) + if err != nil { + // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED + cmtos.Exit(fmt.Sprintf(`LoadValidators: Data has been corrupted or its spec has changed: + %v\n`, err)) + } + // TODO: ensure that buf is completely read. + + return v, elapsedTime, nil +} + +// saveValidatorsInfo persists the validator set. +// +// `height` is the effective height for which the validator is responsible for +// signing. It should be called from s.Save(), right before the state itself is +// persisted. +func (store dbStore) saveValidatorsInfo(height, lastHeightChanged int64, valSet *types.ValidatorSet, batch dbm.Batch) error { + if lastHeightChanged > height { + return errors.New("lastHeightChanged cannot be greater than ValidatorsInfo height") + } + valInfo := &cmtstate.ValidatorsInfo{ + LastHeightChanged: lastHeightChanged, + } + // Only persist validator set if it was updated or checkpoint height (see + // valSetCheckpointInterval) is reached. + if height == lastHeightChanged || height%valSetCheckpointInterval == 0 { + pv, err := valSet.ToProto() + if err != nil { + return err + } + valInfo.ValidatorSet = pv + } + + bz, err := valInfo.Marshal() + if err != nil { + return err + } + start := time.Now() + err = batch.Set(store.DBKeyLayout.CalcValidatorsKey(height), bz) + if err != nil { + return err + } + defer addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "saveValidatorsInfo"), start)() + + return nil +} + +// ----------------------------------------------------------------------------- + +// ConsensusParamsInfo represents the latest consensus params, or the last height it changed + +// LoadConsensusParams loads the ConsensusParams for a given height. +func (store dbStore) LoadConsensusParams(height int64) (types.ConsensusParams, error) { + var ( + empty = types.ConsensusParams{} + emptypb = cmtproto.ConsensusParams{} + ) + paramsInfo, err := store.loadConsensusParamsInfo(height) + if err != nil { + return empty, fmt.Errorf("could not find consensus params for height #%d: %w", height, err) + } + + if paramsInfo.ConsensusParams.Equal(&emptypb) { + paramsInfo2, err := store.loadConsensusParamsInfo(paramsInfo.LastHeightChanged) + if err != nil { + return empty, fmt.Errorf( + "couldn't find consensus params at height %d as last changed from height %d: %w", + paramsInfo.LastHeightChanged, + height, + err, + ) + } + + paramsInfo = paramsInfo2 + } + + return types.ConsensusParamsFromProto(paramsInfo.ConsensusParams), nil +} + +func (store dbStore) loadConsensusParamsInfo(height int64) (*cmtstate.ConsensusParamsInfo, error) { + start := time.Now() + buf, err := store.db.Get(store.DBKeyLayout.CalcConsensusParamsKey(height)) + if err != nil { + return nil, err + } + + addTimeSample(store.StoreOptions.Metrics.StoreAccessDurationSeconds.With("method", "load_consensus_params"), start)() + + if len(buf) == 0 { + return nil, errors.New("value retrieved from db is empty") + } + + paramsInfo := new(cmtstate.ConsensusParamsInfo) + if err = paramsInfo.Unmarshal(buf); err != nil { + // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED + cmtos.Exit(fmt.Sprintf(`LoadConsensusParams: Data has been corrupted or its spec has changed: + %v\n`, err)) + } + // TODO: ensure that buf is completely read. + + return paramsInfo, nil +} + +// saveConsensusParamsInfo persists the consensus params for the next block to disk. +// It should be called from s.Save(), right before the state itself is persisted. +// If the consensus params did not change after processing the latest block, +// only the last height for which they changed is persisted. +func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params types.ConsensusParams, batch dbm.Batch) error { + paramsInfo := &cmtstate.ConsensusParamsInfo{ + LastHeightChanged: changeHeight, + } + + if changeHeight == nextHeight { + paramsInfo.ConsensusParams = params.ToProto() + } + bz, err := paramsInfo.Marshal() + if err != nil { + return err + } + + err = batch.Set(store.DBKeyLayout.CalcConsensusParamsKey(nextHeight), bz) + if err != nil { + return err + } + + return nil +} + +func (store dbStore) SetOfflineStateSyncHeight(height int64) error { + err := store.db.SetSync(offlineStateSyncHeight, int64ToBytes(height)) + if err != nil { + return err + } + return nil +} + +// Gets the height at which the store is bootstrapped after out of band statesync. +func (store dbStore) GetOfflineStateSyncHeight() (int64, error) { + buf, err := store.db.Get(offlineStateSyncHeight) + if err != nil { + return 0, err + } + + if len(buf) == 0 { + return 0, errors.New("value empty") + } + + height := int64FromBytes(buf) + if height < 0 { + return 0, errors.New("invalid value for height: height cannot be negative") + } + return height, nil +} + +func (store dbStore) Close() error { + return store.db.Close() +} + +func min(a int64, b int64) int64 { + if a < b { + return a + } + return b +} + +// responseFinalizeBlockFromLegacy is a convenience function that takes the old abci responses and morphs +// it to the finalize block response. Note that the app hash is missing. +func responseFinalizeBlockFromLegacy(legacyResp *cmtstate.LegacyABCIResponses) *abci.FinalizeBlockResponse { + return &abci.FinalizeBlockResponse{ + TxResults: legacyResp.DeliverTxs, + ValidatorUpdates: legacyResp.EndBlock.ValidatorUpdates, + ConsensusParamUpdates: legacyResp.EndBlock.ConsensusParamUpdates, + Events: append(legacyResp.BeginBlock.Events, legacyResp.EndBlock.Events...), + // NOTE: AppHash is missing in the response but will + // be caught and filled in consensus/replay.go + } +} + +// ----- Util. +func int64FromBytes(bz []byte) int64 { + v, _ := binary.Varint(bz) + return v +} + +func int64ToBytes(i int64) []byte { + buf := make([]byte, binary.MaxVarintLen64) + n := binary.PutVarint(buf, i) + return buf[:n] +} + +// addTimeSample returns a function that, when called, adds an observation to m. +// The observation added to m is the number of seconds elapsed since addTimeSample +// was initially called. addTimeSample is meant to be called in a defer to calculate +// the amount of time a function takes to complete. +func addTimeSample(m metrics.Histogram, start time.Time) func() { + return func() { m.Observe(time.Since(start).Seconds()) } +} diff --git a/internal/state/store_test.go b/internal/state/store_test.go new file mode 100644 index 00000000000..bec95bcd3f4 --- /dev/null +++ b/internal/state/store_test.go @@ -0,0 +1,635 @@ +package state_test + +import ( + "fmt" + "os" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + dbm "github.com/cometbft/cometbft-db" + abci "github.com/cometbft/cometbft/abci/types" + cmtstate "github.com/cometbft/cometbft/api/cometbft/state/v1" + cfg "github.com/cometbft/cometbft/config" + "github.com/cometbft/cometbft/crypto/ed25519" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/indexer/block" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/internal/store" + "github.com/cometbft/cometbft/internal/test" + "github.com/cometbft/cometbft/libs/log" + "github.com/cometbft/cometbft/types" +) + +func TestStoreLoadValidators(t *testing.T) { + stateDB := dbm.NewMemDB() + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + DBKeyLayout: "v2", + }) + val, _ := types.RandValidator(true, 10) + vals := types.NewValidatorSet([]*types.Validator{val}) + + // 1) LoadValidators loads validators using a height where they were last changed + err := sm.SaveValidatorsInfo(stateDB, 1, 1, vals, "v2") + require.NoError(t, err) + + // The store was initialized with v2 so we cannot find a validator using the representation + // used by v1 + err = sm.SaveValidatorsInfo(stateDB, 2, 1, vals, "v1") + require.NoError(t, err) + _, err = stateStore.LoadValidators(2) + require.Error(t, err) + + err = sm.SaveValidatorsInfo(stateDB, 2, 1, vals, "v2") + require.NoError(t, err) + loadedVals, err := stateStore.LoadValidators(2) + require.NoError(t, err) + + assert.NotZero(t, loadedVals.Size()) + + // 2) LoadValidators loads validators using a checkpoint height + + err = sm.SaveValidatorsInfo(stateDB, sm.ValSetCheckpointInterval, 1, vals, "v2") + require.NoError(t, err) + + loadedVals, err = stateStore.LoadValidators(sm.ValSetCheckpointInterval) + require.NoError(t, err) + assert.NotZero(t, loadedVals.Size()) +} + +func BenchmarkLoadValidators(b *testing.B) { + const valSetSize = 100 + + config := test.ResetTestRoot("state_") + defer os.RemoveAll(config.RootDir) + dbType := dbm.BackendType(config.DBBackend) + stateDB, err := dbm.NewDB("state", dbType, config.DBDir()) + require.NoError(b, err) + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + state, err := stateStore.LoadFromDBOrGenesisFile(config.GenesisFile()) + if err != nil { + b.Fatal(err) + } + + state.Validators = genValSet(valSetSize) + state.NextValidators = state.Validators.CopyIncrementProposerPriority(1) + err = stateStore.Save(state) + require.NoError(b, err) + + for i := 10; i < 10000000000; i *= 10 { // 10, 100, 1000, ... + i := i + if err := sm.SaveValidatorsInfo(stateDB, + int64(i), state.LastHeightValidatorsChanged, state.NextValidators, "v2"); err != nil { + b.Fatal(err) + } + + b.Run(fmt.Sprintf("height=%d", i), func(b *testing.B) { + for n := 0; n < b.N; n++ { + _, err := stateStore.LoadValidators(int64(i)) + if err != nil { + b.Fatal(err) + } + } + }) + } +} + +func TestPruneStates(t *testing.T) { + testcases := map[string]struct { + makeHeights int64 + pruneFrom int64 + pruneTo int64 + evidenceThresholdHeight int64 + expectErr bool + expectVals []int64 + expectParams []int64 + expectABCI []int64 + }{ + "error on pruning from 0": {100, 0, 5, 100, true, nil, nil, nil}, + "error when from > to": {100, 3, 2, 2, true, nil, nil, nil}, + "error when from == to": {100, 3, 3, 3, true, nil, nil, nil}, + "error when to does not exist": {100, 1, 101, 101, true, nil, nil, nil}, + "prune all": {100, 1, 100, 100, false, []int64{93, 100}, []int64{95, 100}, []int64{100}}, + "prune some": { + 10, 2, 8, 8, false, + []int64{1, 3, 8, 9, 10}, + []int64{1, 5, 8, 9, 10}, + []int64{1, 8, 9, 10}, + }, + "prune across checkpoint": { + 100001, 1, 100001, 100001, false, + []int64{99993, 100000, 100001}, + []int64{99995, 100001}, + []int64{100001}, + }, + "prune when evidence height < height": {20, 1, 18, 17, false, []int64{13, 17, 18, 19, 20}, []int64{15, 18, 19, 20}, []int64{18, 19, 20}}, + } + for name, tc := range testcases { + tc := tc + t.Run(name, func(t *testing.T) { + db := dbm.NewMemDB() + stateStore := sm.NewStore(db, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + pk := ed25519.GenPrivKey().PubKey() + + // Generate a bunch of state data. Validators change for heights ending with 3, and + // parameters when ending with 5. + validator := &types.Validator{Address: pk.Address(), VotingPower: 100, PubKey: pk} + validatorSet := &types.ValidatorSet{ + Validators: []*types.Validator{validator}, + Proposer: validator, + } + valsChanged := int64(0) + paramsChanged := int64(0) + + for h := int64(1); h <= tc.makeHeights; h++ { + if valsChanged == 0 || h%10 == 2 { + valsChanged = h + 1 // Have to add 1, since NextValidators is what's stored + } + if paramsChanged == 0 || h%10 == 5 { + paramsChanged = h + } + + state := sm.State{ + InitialHeight: 1, + LastBlockHeight: h - 1, + Validators: validatorSet, + NextValidators: validatorSet, + ConsensusParams: types.ConsensusParams{ + Block: types.BlockParams{MaxBytes: 10e6}, + }, + LastHeightValidatorsChanged: valsChanged, + LastHeightConsensusParamsChanged: paramsChanged, + } + + if state.LastBlockHeight >= 1 { + state.LastValidators = state.Validators + } + + err := stateStore.Save(state) + require.NoError(t, err) + + err = stateStore.SaveFinalizeBlockResponse(h, &abci.FinalizeBlockResponse{ + TxResults: []*abci.ExecTxResult{ + {Data: []byte{1}}, + {Data: []byte{2}}, + {Data: []byte{3}}, + }, + }) + require.NoError(t, err) + } + + // Test assertions + _, err := stateStore.PruneStates(tc.pruneFrom, tc.pruneTo, tc.evidenceThresholdHeight, 0) + if tc.expectErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + expectVals := sliceToMap(tc.expectVals) + expectParams := sliceToMap(tc.expectParams) + expectABCI := sliceToMap(tc.expectABCI) + + for h := int64(1); h <= tc.makeHeights; h++ { + vals, err := stateStore.LoadValidators(h) + if expectVals[h] { + require.NoError(t, err, "validators height %v", h) + require.NotNil(t, vals) + } else { + require.Error(t, err, "validators height %v", h) + require.Equal(t, sm.ErrNoValSetForHeight{Height: h}, err) + } + + params, err := stateStore.LoadConsensusParams(h) + if expectParams[h] { + require.NoError(t, err, "params height %v", h) + require.NotEmpty(t, params) + } else { + require.Error(t, err, "params height %v", h) + require.Empty(t, params) + } + + abci, err := stateStore.LoadFinalizeBlockResponse(h) + if expectABCI[h] { + require.NoError(t, err, "abci height %v", h) + require.NotNil(t, abci) + } else { + require.Error(t, err, "abci height %v", h) + require.Equal(t, sm.ErrNoABCIResponsesForHeight{Height: h}, err) + } + } + }) + } +} + +func TestTxResultsHash(t *testing.T) { + txResults := []*abci.ExecTxResult{ + {Code: 32, Data: []byte("Hello"), Log: "Huh?"}, + } + + root := sm.TxResultsHash(txResults) + + // root should be Merkle tree root of ExecTxResult responses + results := types.NewResults(txResults) + assert.Equal(t, root, results.Hash()) + + // test we can prove first ExecTxResult + proof := results.ProveResult(0) + bz, err := results[0].Marshal() + require.NoError(t, err) + require.NoError(t, proof.Verify(root, bz)) +} + +func sliceToMap(s []int64) map[int64]bool { + m := make(map[int64]bool, len(s)) + for _, i := range s { + m[i] = true + } + return m +} + +func makeStateAndBlockStoreAndIndexers() (sm.State, *store.BlockStore, txindex.TxIndexer, indexer.BlockIndexer, func(), sm.Store) { + config := test.ResetTestRoot("blockchain_reactor_test") + blockDB := dbm.NewMemDB() + stateDB := dbm.NewMemDB() + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + state, err := sm.MakeGenesisStateFromFile(config.GenesisFile()) + if err != nil { + panic("error constructing state from genesis file: " + err.Error()) + } + + txIndexer, blockIndexer, err := block.IndexerFromConfig(config, cfg.DefaultDBProvider, "test") + if err != nil { + panic(err) + } + + return state, store.NewBlockStore(blockDB), txIndexer, blockIndexer, func() { os.RemoveAll(config.RootDir) }, stateStore +} + +func initStateStoreRetainHeights(stateStore sm.Store) error { + appBlockRH := int64(0) + dcBlockRH := int64(0) + dcBlockResultsRH := int64(0) + if err := stateStore.SaveApplicationRetainHeight(appBlockRH); err != nil { + return fmt.Errorf("failed to set initial application block retain height: %w", err) + } + if err := stateStore.SaveCompanionBlockRetainHeight(dcBlockRH); err != nil { + return fmt.Errorf("failed to set initial companion block retain height: %w", err) + } + if err := stateStore.SaveABCIResRetainHeight(dcBlockResultsRH); err != nil { + return fmt.Errorf("failed to set initial ABCI results retain height: %w", err) + } + return nil +} + +func fillStore(t *testing.T, height int64, stateStore sm.Store, bs *store.BlockStore, state sm.State, response1 *abci.FinalizeBlockResponse) { + t.Helper() + if response1 != nil { + for h := int64(1); h <= height; h++ { + err := stateStore.SaveFinalizeBlockResponse(h, response1) + require.NoError(t, err) + } + // search for the last finalize block response and check if it has saved. + lastResponse, err := stateStore.LoadLastFinalizeBlockResponse(height) + require.NoError(t, err) + // check to see if the saved response height is the same as the loaded height. + assert.Equal(t, lastResponse, response1) + // check if the abci response didn't save in the abciresponses. + responses, err := stateStore.LoadFinalizeBlockResponse(height) + require.NoError(t, err, responses) + require.Equal(t, response1, responses) + } + b1 := state.MakeBlock(state.LastBlockHeight+1, test.MakeNTxs(state.LastBlockHeight+1, 10), new(types.Commit), nil, nil) + partSet, err := b1.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) + bs.SaveBlock(b1, partSet, &types.Commit{Height: state.LastBlockHeight + 1}) +} + +func TestSaveRetainHeight(t *testing.T) { + state, bs, txIndexer, blockIndexer, callbackF, stateStore := makeStateAndBlockStoreAndIndexers() + defer callbackF() + height := int64(10) + state.LastBlockHeight = height - 1 + + fillStore(t, height, stateStore, bs, state, nil) + pruner := sm.NewPruner(stateStore, bs, blockIndexer, txIndexer, log.TestingLogger()) + err := initStateStoreRetainHeights(stateStore) + require.NoError(t, err) + + // We should not save a height that is 0 + err = pruner.SetApplicationBlockRetainHeight(0) + require.Error(t, err) + + // We should not save a height above the block store's height. + err = pruner.SetApplicationBlockRetainHeight(11) + require.Error(t, err) + + // We should allow saving a retain height equal to the block store's + // height. + err = pruner.SetApplicationBlockRetainHeight(10) + require.NoError(t, err) + + err = pruner.SetCompanionBlockRetainHeight(10) + require.NoError(t, err) +} + +func TestMinRetainHeight(t *testing.T) { + _, bs, txIndexer, blockIndexer, callbackF, stateStore := makeStateAndBlockStoreAndIndexers() + defer callbackF() + pruner := sm.NewPruner(stateStore, bs, blockIndexer, txIndexer, log.TestingLogger(), sm.WithPrunerCompanionEnabled()) + + require.NoError(t, initStateStoreRetainHeights(stateStore)) + minHeight := pruner.FindMinRetainHeight() + require.Equal(t, int64(0), minHeight) + + err := stateStore.SaveApplicationRetainHeight(10) + require.NoError(t, err) + minHeight = pruner.FindMinRetainHeight() + require.Equal(t, int64(0), minHeight) + + err = stateStore.SaveCompanionBlockRetainHeight(11) + require.NoError(t, err) + minHeight = pruner.FindMinRetainHeight() + require.Equal(t, int64(10), minHeight) +} + +func TestABCIResPruningStandalone(t *testing.T) { + stateDB := dbm.NewMemDB() + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + + responses, err := stateStore.LoadFinalizeBlockResponse(1) + require.Error(t, err) + require.Nil(t, responses) + // stub the abciresponses. + response1 := &abci.FinalizeBlockResponse{ + TxResults: []*abci.ExecTxResult{ + {Code: 32, Data: []byte("Hello"), Log: "Huh?"}, + }, + } + _, bs, txIndexer, blockIndexer, callbackF, stateStore := makeStateAndBlockStoreAndIndexers() + defer callbackF() + + for height := int64(1); height <= 10; height++ { + err := stateStore.SaveFinalizeBlockResponse(height, response1) + require.NoError(t, err) + } + pruner := sm.NewPruner(stateStore, bs, blockIndexer, txIndexer, log.TestingLogger()) + + retainHeight := int64(2) + err = stateStore.SaveABCIResRetainHeight(retainHeight) + require.NoError(t, err) + abciResRetainHeight, err := stateStore.GetABCIResRetainHeight() + require.NoError(t, err) + require.Equal(t, retainHeight, abciResRetainHeight) + newRetainHeight := pruner.PruneABCIResToRetainHeight(0) + require.Equal(t, retainHeight, newRetainHeight) + + _, err = stateStore.LoadFinalizeBlockResponse(1) + require.Error(t, err) + + for h := retainHeight; h <= 10; h++ { + _, err = stateStore.LoadFinalizeBlockResponse(h) + require.NoError(t, err) + } + + // This should not have any impact because the retain height is still 2 and we will not prune blocks to 3 + newRetainHeight = pruner.PruneABCIResToRetainHeight(3) + require.Equal(t, retainHeight, newRetainHeight) + + retainHeight = 3 + err = stateStore.SaveABCIResRetainHeight(retainHeight) + require.NoError(t, err) + newRetainHeight = pruner.PruneABCIResToRetainHeight(2) + require.Equal(t, retainHeight, newRetainHeight) + + _, err = stateStore.LoadFinalizeBlockResponse(2) + require.Error(t, err) + for h := retainHeight; h <= 10; h++ { + _, err = stateStore.LoadFinalizeBlockResponse(h) + require.NoError(t, err) + } + + retainHeight = 10 + err = stateStore.SaveABCIResRetainHeight(retainHeight) + require.NoError(t, err) + newRetainHeight = pruner.PruneABCIResToRetainHeight(2) + require.Equal(t, retainHeight, newRetainHeight) + + for h := int64(0); h < 10; h++ { + _, err = stateStore.LoadFinalizeBlockResponse(h) + require.Error(t, err) + } + _, err = stateStore.LoadFinalizeBlockResponse(10) + require.NoError(t, err) +} + +type prunerObserver struct { + sm.NoopPrunerObserver + prunedABCIResInfoCh chan *sm.ABCIResponsesPrunedInfo + prunedBlocksResInfoCh chan *sm.BlocksPrunedInfo +} + +func newPrunerObserver(infoChCap int) *prunerObserver { + return &prunerObserver{ + prunedABCIResInfoCh: make(chan *sm.ABCIResponsesPrunedInfo, infoChCap), + prunedBlocksResInfoCh: make(chan *sm.BlocksPrunedInfo, infoChCap), + } +} + +func (o *prunerObserver) PrunerPrunedABCIRes(info *sm.ABCIResponsesPrunedInfo) { + o.prunedABCIResInfoCh <- info +} + +func (o *prunerObserver) PrunerPrunedBlocks(info *sm.BlocksPrunedInfo) { + o.prunedBlocksResInfoCh <- info +} + +func TestFinalizeBlockResponsePruning(t *testing.T) { + t.Run("Persisting responses", func(t *testing.T) { + stateDB := dbm.NewMemDB() + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + responses, err := stateStore.LoadFinalizeBlockResponse(1) + require.Error(t, err) + require.Nil(t, responses) + // stub the abciresponses. + response1 := &abci.FinalizeBlockResponse{ + TxResults: []*abci.ExecTxResult{ + {Code: 32, Data: []byte("Hello"), Log: "Huh?"}, + }, + } + state, bs, txIndexer, blockIndexer, callbackF, stateStore := makeStateAndBlockStoreAndIndexers() + defer callbackF() + height := int64(10) + state.LastBlockHeight = height - 1 + + fillStore(t, height, stateStore, bs, state, response1) + err = initStateStoreRetainHeights(stateStore) + require.NoError(t, err) + + obs := newPrunerObserver(1) + pruner := sm.NewPruner( + stateStore, + bs, + blockIndexer, + txIndexer, + log.TestingLogger(), + sm.WithPrunerInterval(1*time.Second), + sm.WithPrunerObserver(obs), + sm.WithPrunerCompanionEnabled(), + ) + + // Check that we have written a finalize block result at height 'height - 1' + _, err = stateStore.LoadFinalizeBlockResponse(height - 1) + require.NoError(t, err) + require.NoError(t, pruner.SetABCIResRetainHeight(height)) + require.NoError(t, pruner.Start()) + select { + case info := <-obs.prunedABCIResInfoCh: + require.Equal(t, height-1, info.ToHeight) + t.Log("Done pruning ABCI results ") + case <-time.After(5 * time.Second): + require.Fail(t, "timed out waiting for pruning run to complete") + } + + // Check that the response at height h - 1 has been deleted + _, err = stateStore.LoadFinalizeBlockResponse(height - 1) + require.Error(t, err) + _, err = stateStore.LoadFinalizeBlockResponse(height) + require.NoError(t, err) + }) +} + +func TestLastFinalizeBlockResponses(t *testing.T) { + t.Run("persisting responses", func(t *testing.T) { + stateDB := dbm.NewMemDB() + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: false, + }) + + responses, err := stateStore.LoadFinalizeBlockResponse(1) + require.Error(t, err) + require.Nil(t, responses) + + response1 := &abci.FinalizeBlockResponse{ + TxResults: []*abci.ExecTxResult{ + {Code: 32, Data: []byte("Hello"), Log: "Huh?"}, + }, + } + + stateDB = dbm.NewMemDB() + stateStore = sm.NewStore(stateDB, sm.StoreOptions{DiscardABCIResponses: false}) + height := int64(10) + + // save the last abci response. + err = stateStore.SaveFinalizeBlockResponse(height, response1) + require.NoError(t, err) + + // search for the last finalize block response and check if it has saved. + lastResponse, err := stateStore.LoadLastFinalizeBlockResponse(height) + require.NoError(t, err) + + assert.Equal(t, lastResponse, response1) + + // use an incorrect height to make sure the state store errors. + _, err = stateStore.LoadLastFinalizeBlockResponse(height + 1) + require.Error(t, err) + + // check if the abci response didn't save in the abciresponses. + responses, err = stateStore.LoadFinalizeBlockResponse(height) + require.NoError(t, err, responses) + require.Equal(t, response1, responses) + }) + + t.Run("not persisting responses", func(t *testing.T) { + stateDB := dbm.NewMemDB() + height := int64(10) + + response2 := &abci.FinalizeBlockResponse{ + TxResults: []*abci.ExecTxResult{ + {Code: 44, Data: []byte("Hello again"), Log: "????"}, + }, + } + + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: true, + }) + + err := stateStore.SaveFinalizeBlockResponse(height+1, response2) + require.NoError(t, err) + + // check to see if the response saved by calling the last response. + lastResponse2, err := stateStore.LoadLastFinalizeBlockResponse(height + 1) + require.NoError(t, err) + + assert.Equal(t, response2, lastResponse2) + + // should error as we are no longer saving the response. + _, err = stateStore.LoadFinalizeBlockResponse(height + 1) + assert.Equal(t, sm.ErrFinalizeBlockResponsesNotPersisted, err) + }) +} + +func TestFinalizeBlockRecoveryUsingLegacyABCIResponses(t *testing.T) { + var ( + height int64 = 10 + lastABCIResponseKey = []byte("lastABCIResponseKey") + memDB = dbm.NewMemDB() + cp = types.DefaultConsensusParams().ToProto() + legacyResp = cmtstate.ABCIResponsesInfo{ + LegacyAbciResponses: &cmtstate.LegacyABCIResponses{ + BeginBlock: &cmtstate.ResponseBeginBlock{ + Events: []abci.Event{{ + Type: "begin_block", + Attributes: []abci.EventAttribute{{ + Key: "key", + Value: "value", + }}, + }}, + }, + DeliverTxs: []*abci.ExecTxResult{{ + Events: []abci.Event{{ + Type: "tx", + Attributes: []abci.EventAttribute{{ + Key: "key", + Value: "value", + }}, + }}, + }}, + EndBlock: &cmtstate.ResponseEndBlock{ + ConsensusParamUpdates: &cp, + }, + }, + Height: height, + } + ) + bz, err := legacyResp.Marshal() + require.NoError(t, err) + // should keep this in parity with state/store.go + require.NoError(t, memDB.Set(lastABCIResponseKey, bz)) + stateStore := sm.NewStore(memDB, sm.StoreOptions{DiscardABCIResponses: false}) + resp, err := stateStore.LoadLastFinalizeBlockResponse(height) + require.NoError(t, err) + require.Equal(t, resp.ConsensusParamUpdates, &cp) + require.Equal(t, resp.Events, legacyResp.LegacyAbciResponses.BeginBlock.Events) + require.Equal(t, resp.TxResults[0], legacyResp.LegacyAbciResponses.DeliverTxs[0]) +} + +func TestIntConversion(t *testing.T) { + x := int64(10) + b := sm.Int64ToBytes(x) + require.Equal(t, x, sm.Int64FromBytes(b)) +} diff --git a/state/tx_filter.go b/internal/state/tx_filter.go similarity index 84% rename from state/tx_filter.go rename to internal/state/tx_filter.go index 8be843ee905..337a7a5e7fd 100644 --- a/state/tx_filter.go +++ b/internal/state/tx_filter.go @@ -8,8 +8,12 @@ import ( // TxPreCheck returns a function to filter transactions before processing. // The function limits the size of a transaction to the block's maximum data size. func TxPreCheck(state State) mempl.PreCheckFunc { + maxBytes := state.ConsensusParams.Block.MaxBytes + if maxBytes == -1 { + maxBytes = int64(types.MaxBlockSizeBytes) + } maxDataBytes := types.MaxDataBytesNoEvidence( - state.ConsensusParams.Block.MaxBytes, + maxBytes, state.Validators.Size(), ) return mempl.PreCheckMaxBytes(maxDataBytes) diff --git a/state/tx_filter_test.go b/internal/state/tx_filter_test.go similarity index 75% rename from state/tx_filter_test.go rename to internal/state/tx_filter_test.go index 4c5384720a6..1923052bc1b 100644 --- a/state/tx_filter_test.go +++ b/internal/state/tx_filter_test.go @@ -4,13 +4,11 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - - cmtrand "github.com/cometbft/cometbft/libs/rand" - sm "github.com/cometbft/cometbft/state" + cmtrand "github.com/cometbft/cometbft/internal/rand" + sm "github.com/cometbft/cometbft/internal/state" "github.com/cometbft/cometbft/types" ) @@ -25,8 +23,8 @@ func TestTxFilter(t *testing.T) { tx types.Tx isErr bool }{ - {types.Tx(cmtrand.Bytes(2155)), false}, - {types.Tx(cmtrand.Bytes(2156)), true}, + {types.Tx(cmtrand.Bytes(2122)), false}, + {types.Tx(cmtrand.Bytes(2123)), true}, {types.Tx(cmtrand.Bytes(3000)), true}, } @@ -41,9 +39,9 @@ func TestTxFilter(t *testing.T) { f := sm.TxPreCheck(state) if tc.isErr { - assert.NotNil(t, f(tc.tx), "#%v", i) + require.Error(t, f(tc.tx), "#%v", i) } else { - assert.Nil(t, f(tc.tx), "#%v", i) + require.NoError(t, f(tc.tx), "#%v", i) } } } diff --git a/state/txindex/indexer.go b/internal/state/txindex/indexer.go similarity index 79% rename from state/txindex/indexer.go rename to internal/state/txindex/indexer.go index a70c461c2f6..4828c45f2ca 100644 --- a/state/txindex/indexer.go +++ b/internal/state/txindex/indexer.go @@ -5,12 +5,13 @@ import ( "errors" abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/libs/log" ) // XXX/TODO: These types should be moved to the indexer package. -//go:generate ../../scripts/mockery_generate.sh TxIndexer +//go:generate ../../../scripts/mockery_generate.sh TxIndexer // TxIndexer interface defines methods to index and search transactions. type TxIndexer interface { @@ -26,6 +27,15 @@ type TxIndexer interface { // Search allows you to query for transactions. Search(ctx context.Context, q *query.Query) ([]*abci.TxResult, error) + + // Set Logger + SetLogger(l log.Logger) + + Prune(retainHeight int64) (int64, int64, error) + + GetRetainHeight() (int64, error) + + SetRetainHeight(retainHeight int64) error } // Batch groups together multiple Index operations to be performed at the same time. @@ -52,5 +62,5 @@ func (b *Batch) Size() int { return len(b.Ops) } -// ErrorEmptyHash indicates empty hash +// ErrorEmptyHash indicates empty hash. var ErrorEmptyHash = errors.New("transaction hash cannot be empty") diff --git a/state/txindex/indexer_service.go b/internal/state/txindex/indexer_service.go similarity index 90% rename from state/txindex/indexer_service.go rename to internal/state/txindex/indexer_service.go index 6d31b38d92e..e2d8a229956 100644 --- a/state/txindex/indexer_service.go +++ b/internal/state/txindex/indexer_service.go @@ -3,8 +3,8 @@ package txindex import ( "context" - "github.com/cometbft/cometbft/libs/service" - "github.com/cometbft/cometbft/state/indexer" + "github.com/cometbft/cometbft/internal/service" + "github.com/cometbft/cometbft/internal/state/indexer" "github.com/cometbft/cometbft/types" ) @@ -32,8 +32,12 @@ func NewIndexerService( eventBus *types.EventBus, terminateOnError bool, ) *IndexerService { - - is := &IndexerService{txIdxr: txIdxr, blockIdxr: blockIdxr, eventBus: eventBus, terminateOnError: terminateOnError} + is := &IndexerService{ + txIdxr: txIdxr, + blockIdxr: blockIdxr, + eventBus: eventBus, + terminateOnError: terminateOnError, + } is.BaseService = *service.NewBaseService(nil, "IndexerService", is) return is } @@ -82,7 +86,7 @@ func (is *IndexerService) OnStart() error { ) if is.terminateOnError { - if err := is.Stop(); err != nil { + if err := is.Stop(); err != nil { //nolint:revive // suppress max-control-nesting linter is.Logger.Error("failed to stop", "err", err) } return diff --git a/state/txindex/indexer_service_test.go b/internal/state/txindex/indexer_service_test.go similarity index 60% rename from state/txindex/indexer_service_test.go rename to internal/state/txindex/indexer_service_test.go index 399cd728085..5d21d7cdcfc 100644 --- a/state/txindex/indexer_service_test.go +++ b/internal/state/txindex/indexer_service_test.go @@ -1,22 +1,55 @@ package txindex_test import ( + "fmt" "testing" "time" "github.com/stretchr/testify/require" db "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/state/indexer" + blockidxkv "github.com/cometbft/cometbft/internal/state/indexer/block/kv" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/internal/state/txindex/kv" "github.com/cometbft/cometbft/libs/log" - blockidxkv "github.com/cometbft/cometbft/state/indexer/block/kv" - "github.com/cometbft/cometbft/state/txindex" - "github.com/cometbft/cometbft/state/txindex/kv" "github.com/cometbft/cometbft/types" ) func TestIndexerServiceIndexesBlocks(t *testing.T) { + _, txIndexer, blockIndexer, eventBus := createTestSetup(t) + + height := int64(1) + + events, txResult1, txResult2 := getEventsAndResults(height) + // publish block with events + err := eventBus.PublishEventNewBlockEvents(events) + require.NoError(t, err) + + err = eventBus.PublishEventTx(types.EventDataTx{TxResult: *txResult1}) + require.NoError(t, err) + + err = eventBus.PublishEventTx(types.EventDataTx{TxResult: *txResult2}) + require.NoError(t, err) + + time.Sleep(100 * time.Millisecond) + + res, err := txIndexer.Get(types.Tx(fmt.Sprintf("foo%d", height)).Hash()) + require.NoError(t, err) + require.Equal(t, txResult1, res) + + ok, err := blockIndexer.Has(height) + require.NoError(t, err) + require.True(t, ok) + + res, err = txIndexer.Get(types.Tx(fmt.Sprintf("bar%d", height)).Hash()) + require.NoError(t, err) + require.Equal(t, txResult2, res) +} + +func createTestSetup(t *testing.T) (*txindex.IndexerService, *kv.TxIndex, indexer.BlockIndexer, *types.EventBus) { + t.Helper() // event bus eventBus := types.NewEventBus() eventBus.SetLogger(log.TestingLogger()) @@ -42,10 +75,12 @@ func TestIndexerServiceIndexesBlocks(t *testing.T) { t.Error(err) } }) + return service, txIndexer, blockIndexer, eventBus +} - // publish block with events - err = eventBus.PublishEventNewBlockEvents(types.EventDataNewBlockEvents{ - Height: 1, +func getEventsAndResults(height int64) (types.EventDataNewBlockEvents, *abci.TxResult, *abci.TxResult) { + events := types.EventDataNewBlockEvents{ + Height: height, Events: []abci.Event{ { Type: "begin_event", @@ -59,36 +94,18 @@ func TestIndexerServiceIndexesBlocks(t *testing.T) { }, }, NumTxs: int64(2), - }) - require.NoError(t, err) + } txResult1 := &abci.TxResult{ - Height: 1, + Height: height, Index: uint32(0), - Tx: types.Tx("foo"), + Tx: types.Tx(fmt.Sprintf("foo%d", height)), Result: abci.ExecTxResult{Code: 0}, } - err = eventBus.PublishEventTx(types.EventDataTx{TxResult: *txResult1}) - require.NoError(t, err) txResult2 := &abci.TxResult{ - Height: 1, + Height: height, Index: uint32(1), - Tx: types.Tx("bar"), + Tx: types.Tx(fmt.Sprintf("bar%d", height)), Result: abci.ExecTxResult{Code: 0}, } - err = eventBus.PublishEventTx(types.EventDataTx{TxResult: *txResult2}) - require.NoError(t, err) - - time.Sleep(100 * time.Millisecond) - - res, err := txIndexer.Get(types.Tx("foo").Hash()) - require.NoError(t, err) - require.Equal(t, txResult1, res) - - ok, err := blockIndexer.Has(1) - require.NoError(t, err) - require.True(t, ok) - - res, err = txIndexer.Get(types.Tx("bar").Hash()) - require.NoError(t, err) - require.Equal(t, txResult2, res) + return events, txResult1, txResult2 } diff --git a/internal/state/txindex/kv/export_test.go b/internal/state/txindex/kv/export_test.go new file mode 100644 index 00000000000..bc0cbc48699 --- /dev/null +++ b/internal/state/txindex/kv/export_test.go @@ -0,0 +1,5 @@ +package kv + +func GetKeys(indexer *TxIndex) [][]byte { + return getKeys(indexer) +} diff --git a/state/txindex/kv/kv.go b/internal/state/txindex/kv/kv.go similarity index 64% rename from state/txindex/kv/kv.go rename to internal/state/txindex/kv/kv.go index 17440530428..71bd8d5307d 100644 --- a/state/txindex/kv/kv.go +++ b/internal/state/txindex/kv/kv.go @@ -4,19 +4,25 @@ import ( "bytes" "context" "encoding/hex" + "errors" "fmt" + "math" + "math/big" + "sort" "strconv" "strings" "github.com/cosmos/gogoproto/proto" dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" - "github.com/cometbft/cometbft/libs/pubsub/query/syntax" - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/state/txindex" + idxutil "github.com/cometbft/cometbft/internal/indexer" + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/internal/pubsub/query/syntax" + "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/types" ) @@ -25,20 +31,184 @@ const ( eventSeqSeparator = "$es$" ) -var _ txindex.TxIndexer = (*TxIndex)(nil) +var ( + LastTxIndexerRetainHeightKey = []byte("LastTxIndexerRetainHeightKey") + TxIndexerRetainHeightKey = []byte("TxIndexerRetainHeightKey") +) // 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 + + log log.Logger + + compact bool + compactionInterval int64 + lastPruned int64 +} + +type IndexerOption func(*TxIndex) + +// WithCompaction sets the compaciton parameters. +func WithCompaction(compact bool, compactionInterval int64) IndexerOption { + return func(txi *TxIndex) { + txi.compact = compact + txi.compactionInterval = compactionInterval + } +} + +func (txi *TxIndex) Prune(retainHeight int64) (numPruned int64, newRetainHeight int64, err error) { + // Returns numPruned, newRetainHeight, err + // numPruned: the number of heights pruned. E.x. if heights {1, 3, 7} were pruned, numPruned == 3 + // newRetainHeight: new retain height after pruning + // err: error + + lastRetainHeight, err := txi.getIndexerRetainHeight() + if err != nil { + return 0, 0, fmt.Errorf("failed to look up last block indexer retain height: %w", err) + } + if lastRetainHeight == 0 { + lastRetainHeight = 1 + } + + ctx := context.Background() + results, err := txi.Search(ctx, query.MustCompile( + fmt.Sprintf("tx.height < %d AND tx.height >= %d", retainHeight, lastRetainHeight))) + if err != nil { + return 0, lastRetainHeight, err + } + if len(results) == 0 { + return 0, lastRetainHeight, nil + } + + batch := txi.store.NewBatch() + closeBatch := func(batch dbm.Batch) { + err := batch.Close() + if err != nil { + txi.log.Error(fmt.Sprintf("Error when closing tx indexer pruning batch: %v", err)) + } + } + defer closeBatch(batch) + pruned := uint64(0) + flush := func(batch dbm.Batch) error { + err := batch.WriteSync() + if err != nil { + return fmt.Errorf("failed to flush tx indexer pruning batch %w", err) + } + err = batch.Close() + if err != nil { + txi.log.Error(fmt.Sprintf("Error when closing tx indexer pruning batch: %v", err)) + } + return nil + } + + sort.Sort(TxResultByHeight(results)) + numHeightsBatchPruned := int64(0) // number of heights pruned if counting batched + currentBatchRetainedHeight := results[0].Height // height retained if counting batched + numHeightsPersistentlyPruned := int64(0) // number of heights pruned persistently + currentPersistentlyRetainedHeight := lastRetainHeight // height retained persistently + for i, result := range results { + errDeleteResult := txi.deleteResult(result, batch) + if errDeleteResult != nil { + // If we crashed in the middle of pruning the height, + // we assume this height is retained + errSetLastRetainHeight := txi.setIndexerRetainHeight(result.Height, batch) + if errSetLastRetainHeight != nil { + return 0, lastRetainHeight, fmt.Errorf("error setting last retain height '%v' while handling result deletion error '%v' for tx indexer", errSetLastRetainHeight, errDeleteResult) + } + errWriteBatch := batch.WriteSync() + if errWriteBatch != nil { + return 0, lastRetainHeight, fmt.Errorf("error writing tx indexer batch '%v' while handling result deletion error '%v'", errWriteBatch, errDeleteResult) + } + return result.Height - lastRetainHeight, result.Height, errDeleteResult + } + if i == len(results)-1 || results[i+1].Height > result.Height { + numHeightsBatchPruned++ + currentBatchRetainedHeight = result.Height + 1 + } + // flush every 1000 blocks to avoid batches becoming too large + if pruned%1000 == 0 && pruned > 0 { + err := flush(batch) + if err != nil { + return numHeightsPersistentlyPruned, currentPersistentlyRetainedHeight, err + } + numHeightsPersistentlyPruned = numHeightsBatchPruned + currentPersistentlyRetainedHeight = currentBatchRetainedHeight + batch = txi.store.NewBatch() + defer closeBatch(batch) + } + } + + err = flush(batch) + if err != nil { + return numHeightsPersistentlyPruned, currentPersistentlyRetainedHeight, err + } + numHeightsPersistentlyPruned = numHeightsBatchPruned + currentPersistentlyRetainedHeight = currentBatchRetainedHeight + + txi.lastPruned += numHeightsBatchPruned + if txi.compact && txi.lastPruned >= txi.compactionInterval { + err = txi.store.Compact(nil, nil) + txi.lastPruned = 0 + } + + return numHeightsPersistentlyPruned, currentPersistentlyRetainedHeight, err +} + +func (txi *TxIndex) SetRetainHeight(retainHeight int64) error { + return txi.store.SetSync(TxIndexerRetainHeightKey, int64ToBytes(retainHeight)) +} + +func (txi *TxIndex) GetRetainHeight() (int64, error) { + buf, err := txi.store.Get(TxIndexerRetainHeightKey) + if err != nil { + return 0, err + } + if buf == nil { + return 0, state.ErrKeyNotFound + } + height := int64FromBytes(buf) + + if height < 0 { + return 0, state.ErrInvalidHeightValue + } + + return height, nil +} + +func (*TxIndex) setIndexerRetainHeight(height int64, batch dbm.Batch) error { + return batch.Set(LastTxIndexerRetainHeightKey, int64ToBytes(height)) +} + +func (txi *TxIndex) getIndexerRetainHeight() (int64, error) { + bz, err := txi.store.Get(LastTxIndexerRetainHeightKey) + if errors.Is(err, state.ErrKeyNotFound) { + return 0, nil + } + height := int64FromBytes(bz) + if height < 0 { + return 0, state.ErrInvalidHeightValue + } + return height, nil } // NewTxIndex creates new KV indexer. -func NewTxIndex(store dbm.DB) *TxIndex { - return &TxIndex{ +func NewTxIndex(store dbm.DB, options ...IndexerOption) *TxIndex { + txIndex := &TxIndex{ store: store, } + + for _, option := range options { + option(txIndex) + } + + return txIndex +} + +func (txi *TxIndex) SetLogger(l log.Logger) { + txi.log = l } // Get gets transaction from the TxIndex storage and returns it or nil if the @@ -102,6 +272,23 @@ func (txi *TxIndex) AddBatch(b *txindex.Batch) error { return storeBatch.WriteSync() } +func (txi *TxIndex) deleteResult(result *abci.TxResult, batch dbm.Batch) error { + hash := types.Tx(result.Tx).Hash() + err := txi.deleteEvents(result, batch) + if err != nil { + return err + } + err = batch.Delete(keyForHeight(result)) + if err != nil { + return err + } + err = batch.Delete(hash) + if err != nil { + return err + } + return nil +} + // Index indexes a single transaction using the given list of events. Each key // that indexed from the tx's events is a composite of the event type and the // respective attribute's key delimited by a "." (eg. "account.number"). @@ -155,9 +342,41 @@ func (txi *TxIndex) Index(result *abci.TxResult) error { return b.WriteSync() } +func (txi *TxIndex) deleteEvents(result *abci.TxResult, batch dbm.Batch) error { + for _, event := range result.Result.Events { + // only delete events with a non-empty type + if len(event.Type) == 0 { + continue + } + + for _, attr := range event.Attributes { + if len(attr.Key) == 0 { + continue + } + + compositeTag := fmt.Sprintf("%s.%s", event.Type, attr.Key) + if attr.GetIndex() { + zeroKey := keyForEvent(compositeTag, attr.Value, result, 0) + endKey := keyForEvent(compositeTag, attr.Value, result, math.MaxInt64) + itr, err := txi.store.Iterator(zeroKey, endKey) + if err != nil { + return err + } + for ; itr.Valid(); itr.Next() { + err := batch.Delete(itr.Key()) + if err != nil { + return err + } + } + } + } + } + return nil +} + func (txi *TxIndex) indexEvents(result *abci.TxResult, hash []byte, store dbm.Batch) error { for _, event := range result.Result.Events { - txi.eventSeq = txi.eventSeq + 1 + txi.eventSeq++ // only index events with a non-empty type if len(event.Type) == 0 { continue @@ -248,7 +467,6 @@ func (txi *TxIndex) Search(ctx context.Context, q *query.Query) ([]*abci.TxResul 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 @@ -297,7 +515,6 @@ func (txi *TxIndex) Search(ctx context.Context, q *query.Query) ([]*abci.TxResul 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) @@ -325,10 +542,10 @@ func lookForHash(conditions []syntax.Condition) (hash []byte, ok bool, err error return decoded, true, err } } - return + return nil, false, nil } -func (txi *TxIndex) setTmpHashes(tmpHeights map[string][]byte, it dbm.Iterator) { +func (*TxIndex) setTmpHashes(tmpHeights map[string][]byte, it dbm.Iterator) { eventSeq := extractEventSeqFromKey(it.Key()) tmpHeights[string(it.Value())+eventSeq] = it.Value() } @@ -364,14 +581,21 @@ func (txi *TxIndex) match( EQ_LOOP: for ; it.Valid(); it.Next() { - // 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) { + if err != nil { + txi.log.Error("failure to parse height from key:", err) + continue + } + withinBounds, err := checkHeightConditions(heightInfo, keyHeight) + if err != nil { + txi.log.Error("failure checking for height bounds:", err) + continue + } + if !withinBounds { continue } - txi.setTmpHashes(tmpHashes, it) // Potentially exit early. select { @@ -396,7 +620,16 @@ func (txi *TxIndex) match( EXISTS_LOOP: for ; it.Valid(); it.Next() { keyHeight, err := extractHeightFromKey(it.Key()) - if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + if err != nil { + txi.log.Error("failure to parse height from key:", err) + continue + } + withinBounds, err := checkHeightConditions(heightInfo, keyHeight) + if err != nil { + txi.log.Error("failure checking for height bounds:", err) + continue + } + if !withinBounds { continue } txi.setTmpHashes(tmpHashes, it) @@ -430,7 +663,16 @@ func (txi *TxIndex) match( if strings.Contains(extractValueFromKey(it.Key()), c.Arg.Value()) { keyHeight, err := extractHeightFromKey(it.Key()) - if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + if err != nil { + txi.log.Error("failure to parse height from key:", err) + continue + } + withinBounds, err := checkHeightConditions(heightInfo, keyHeight) + if err != nil { + txi.log.Error("failure checking for height bounds:", err) + continue + } + if !withinBounds { continue } txi.setTmpHashes(tmpHashes, it) @@ -514,19 +756,41 @@ LOOP: continue } - if _, ok := qr.AnyBound().(int64); ok { - v, err := strconv.ParseInt(extractValueFromKey(it.Key()), 10, 64) - if err != nil { - continue LOOP + if _, ok := qr.AnyBound().(*big.Float); ok { + v := new(big.Int) + v, ok := v.SetString(extractValueFromKey(it.Key()), 10) + var vF *big.Float + if !ok { + vF, _, err = big.ParseFloat(extractValueFromKey(it.Key()), 10, 125, big.ToNearestEven) + if err != nil { + continue LOOP + } } if qr.Key != types.TxHeightKey { keyHeight, err := extractHeightFromKey(it.Key()) - if err != nil || !checkHeightConditions(heightInfo, keyHeight) { - continue LOOP + if err != nil { + txi.log.Error("failure to parse height from key:", err) + continue + } + withinBounds, err := checkHeightConditions(heightInfo, keyHeight) + if err != nil { + txi.log.Error("failure checking for height bounds:", err) + continue + } + if !withinBounds { + continue } - } - if checkBounds(qr, v) { + var withinBounds bool + var err error + if !ok { + withinBounds, err = idxutil.CheckBounds(qr, vF) + } else { + withinBounds, err = idxutil.CheckBounds(qr, v) + } + if err != nil { + txi.log.Error("failed to parse bounds:", err) + } else if withinBounds { txi.setTmpHashes(tmpHashes, it) } @@ -592,13 +856,14 @@ func isTagKey(key []byte) bool { } func extractHeightFromKey(key []byte) (int64, error) { - parts := strings.SplitN(string(key), tagKeySeparator, -1) + parts := strings.Split(string(key), tagKeySeparator) return strconv.ParseInt(parts[len(parts)-2], 10, 64) } + func extractValueFromKey(key []byte) string { keyString := string(key) - parts := strings.SplitN(keyString, tagKeySeparator, -1) + parts := strings.Split(keyString, tagKeySeparator) partsLen := len(parts) value := strings.TrimPrefix(keyString, parts[0]+tagKeySeparator) @@ -609,11 +874,10 @@ func extractValueFromKey(key []byte) string { suffix = tagKeySeparator + parts[partsLen-i] + suffix } return strings.TrimSuffix(value, suffix) - } func extractEventSeqFromKey(key []byte) string { - parts := strings.SplitN(string(key), tagKeySeparator, -1) + parts := strings.Split(string(key), tagKeySeparator) lastEl := parts[len(parts)-1] @@ -622,6 +886,7 @@ func extractEventSeqFromKey(key []byte) string { } return "0" } + func keyForEvent(key string, value string, result *abci.TxResult, eventSeq int64) []byte { return []byte(fmt.Sprintf("%s/%s/%d/%d%s", key, @@ -651,25 +916,10 @@ func startKeyForCondition(c syntax.Condition, height int64) []byte { return startKey(c.Tag, c.Arg.Value()) } -func startKey(fields ...interface{}) []byte { +func startKey(fields ...any) []byte { var b bytes.Buffer for _, f := range fields { - b.Write([]byte(fmt.Sprintf("%v", f) + tagKeySeparator)) + b.WriteString(fmt.Sprintf("%v", f) + tagKeySeparator) } 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_bench_test.go b/internal/state/txindex/kv/kv_bench_test.go similarity index 96% rename from state/txindex/kv/kv_bench_test.go rename to internal/state/txindex/kv/kv_bench_test.go index 035948c2ce6..31b41943552 100644 --- a/state/txindex/kv/kv_bench_test.go +++ b/internal/state/txindex/kv/kv_bench_test.go @@ -8,9 +8,8 @@ import ( "testing" dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" + "github.com/cometbft/cometbft/internal/pubsub/query" "github.com/cometbft/cometbft/types" ) diff --git a/state/txindex/kv/kv_test.go b/internal/state/txindex/kv/kv_test.go similarity index 64% rename from state/txindex/kv/kv_test.go rename to internal/state/txindex/kv/kv_test.go index 899a099892e..cec0190aeca 100644 --- a/state/txindex/kv/kv_test.go +++ b/internal/state/txindex/kv/kv_test.go @@ -1,6 +1,7 @@ package kv import ( + "bytes" "context" "fmt" "os" @@ -9,13 +10,14 @@ import ( "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" db "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" - cmtrand "github.com/cometbft/cometbft/libs/rand" - "github.com/cometbft/cometbft/state/txindex" + "github.com/cometbft/cometbft/internal/pubsub/query" + cmtrand "github.com/cometbft/cometbft/internal/rand" + blockidxkv "github.com/cometbft/cometbft/internal/state/indexer/block/kv" + "github.com/cometbft/cometbft/internal/state/txindex" "github.com/cometbft/cometbft/types" ) @@ -65,6 +67,81 @@ func TestTxIndex(t *testing.T) { assert.True(t, proto.Equal(txResult2, loadedTxResult2)) } +func TestTxIndex_Prune(t *testing.T) { + indexer := NewTxIndex(db.NewMemDB()) + + metaKeys := [][]byte{ + LastTxIndexerRetainHeightKey, + blockidxkv.LastBlockIndexerRetainHeightKey, + TxIndexerRetainHeightKey, + blockidxkv.BlockIndexerRetainHeightKey, + } + + tx := types.Tx("HELLO WORLD") + events := []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: "", Attributes: []abci.EventAttribute{{Key: "not_allowed", Value: "Vlad", Index: true}}}, + } + txResult := &abci.TxResult{ + Height: 1, + Index: 0, + Tx: tx, + Result: abci.ExecTxResult{ + Data: []byte{0}, + Code: abci.CodeTypeOK, + Log: "", + Events: events, + }, + } + + batch := txindex.NewBatch(1) + if err := batch.Add(txResult); err != nil { + t.Error(err) + } + err := indexer.AddBatch(batch) + require.NoError(t, err) + + keys1 := GetKeys(indexer) + + tx2 := types.Tx("BYE BYE WORLD") + txResult2 := &abci.TxResult{ + Height: 2, + Index: 0, + Tx: tx2, + Result: abci.ExecTxResult{ + Data: []byte{0}, + Code: abci.CodeTypeOK, + Log: "", + Events: events, + }, + } + hash2 := tx2.Hash() + + batch = txindex.NewBatch(1) + if err := batch.Add(txResult2); err != nil { + t.Error(err) + } + err = indexer.AddBatch(batch) + require.NoError(t, err) + + keys2 := GetKeys(indexer) + assert.True(t, isSubset(keys1, keys2)) + + numPruned, retainedHeight, err := indexer.Prune(2) + require.NoError(t, err) + assert.Equal(t, int64(1), numPruned) + assert.Equal(t, int64(2), retainedHeight) + + keys3 := GetKeys(indexer) + assert.True(t, isEqualSets(setDiff(keys2, keys1), setDiff(keys3, metaKeys))) + assert.True(t, emptyIntersection(keys1, keys3)) + + loadedTxResult2, err := indexer.Get(hash2) + require.NoError(t, err) + assert.True(t, proto.Equal(txResult2, loadedTxResult2)) +} + func TestTxSearch(t *testing.T) { indexer := NewTxIndex(db.NewMemDB()) @@ -142,7 +219,7 @@ func TestTxSearch(t *testing.T) { tc := tc t.Run(tc.q, func(t *testing.T) { results, err := indexer.Search(ctx, query.MustCompile(tc.q)) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, results, tc.resultsLength) if tc.resultsLength > 0 { @@ -155,7 +232,6 @@ func TestTxSearch(t *testing.T) { } func TestTxSearchEventMatch(t *testing.T) { - indexer := NewTxIndex(db.NewMemDB()) txResult := txResultWithEvents([]abci.Event{ @@ -212,23 +288,19 @@ func TestTxSearchEventMatch(t *testing.T) { 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": { + " Match range with special character": { q: "account.number < 2 AND account.owner = '/Ivan/.test'", resultsLength: 0, }, - " Match range with match events 2": { + " Match range with special character 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": { + " Match range with 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": { + " Match range with contains": { q: "account.number <= 2 AND account.owner CONTAINS 'an' AND tx.height > 0", resultsLength: 1, }, @@ -240,7 +312,7 @@ func TestTxSearchEventMatch(t *testing.T) { tc := tc t.Run(tc.q, func(t *testing.T) { results, err := indexer.Search(ctx, query.MustCompile(tc.q)) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, results, tc.resultsLength) if tc.resultsLength > 0 { @@ -251,6 +323,88 @@ func TestTxSearchEventMatch(t *testing.T) { }) } } + +func TestTxSearchEventMatchByHeight(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}}}, + }) + + err := indexer.Index(txResult) + require.NoError(t, err) + + txResult10 := txResultWithEvents([]abci.Event{ + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: "1", Index: true}, {Key: "owner", Value: "/Ivan/.test", Index: true}}}, + }) + txResult10.Tx = types.Tx("HELLO WORLD 10") + txResult10.Height = 10 + + err = indexer.Index(txResult10) + require.NoError(t, err) + + testCases := map[string]struct { + q string + resultsLength int + }{ + "Return all events from a height 1": { + q: "tx.height = 1", + resultsLength: 1, + }, + "Return all events from a height 10": { + q: "tx.height = 10", + resultsLength: 1, + }, + "Return all events from a height 5": { + q: "tx.height = 5", + resultsLength: 0, + }, + "Return all events from a height in [2; 5]": { + q: "tx.height >= 2 AND tx.height <= 5", + resultsLength: 0, + }, + "Return all events from a height in [1; 5]": { + q: "tx.height >= 1 AND tx.height <= 5", + resultsLength: 1, + }, + "Return all events from a height in [1; 10]": { + q: "tx.height >= 1 AND tx.height <= 10", + resultsLength: 2, + }, + "Return all events from a height in [1; 5] by account.number": { + q: "tx.height >= 1 AND tx.height <= 5 AND account.number=1", + resultsLength: 1, + }, + "Return all events from a height in [1; 10] by account.number 2": { + q: "tx.height >= 1 AND tx.height <= 10 AND account.number=1", + resultsLength: 2, + }, + } + + 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)) + require.NoError(t, err) + + assert.Len(t, results, tc.resultsLength) + if tc.resultsLength > 0 { + for _, txr := range results { + if txr.Height == 1 { + assert.True(t, proto.Equal(txResult, txr)) + } else if txr.Height == 10 { + assert.True(t, proto.Equal(txResult10, txr)) + } else { + assert.True(t, false) + } + } + } + }) + } +} + func TestTxSearchWithCancelation(t *testing.T) { indexer := NewTxIndex(db.NewMemDB()) @@ -265,7 +419,7 @@ func TestTxSearchWithCancelation(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() results, err := indexer.Search(ctx, query.MustCompile(`account.number = 1`)) - assert.NoError(t, err) + require.NoError(t, err) assert.Empty(t, results) } @@ -361,6 +515,7 @@ func TestTxSearchOneTxWithMultipleSameTagsButDifferentValues(t *testing.T) { require.NoError(t, err) testCases := []struct { + name string q string found bool }{ @@ -420,14 +575,13 @@ func TestTxSearchOneTxWithMultipleSameTagsButDifferentValues(t *testing.T) { for _, tc := range testCases { results, err := indexer.Search(ctx, query.MustCompile(tc.q)) - assert.NoError(t, err) - len := 0 + require.NoError(t, err) + n := 0 if tc.found { - len = 1 + n = 1 } - assert.Len(t, results, len) + assert.Len(t, results, n) assert.True(t, !tc.found || proto.Equal(txResult, results[0])) - } } @@ -577,7 +731,7 @@ func TestTxSearchMultipleTxs(t *testing.T) { ctx := context.Background() results, err := indexer.Search(ctx, query.MustCompile(`account.number >= 1`)) - assert.NoError(t, err) + require.NoError(t, err) require.Len(t, results, 3) } @@ -597,7 +751,8 @@ func txResultWithEvents(events []abci.Event) *abci.TxResult { } } -func benchmarkTxIndex(txsCount int64, b *testing.B) { +func benchmarkTxIndex(b *testing.B, txsCount int64) { + b.Helper() dir, err := os.MkdirTemp("", "tx_index_db") require.NoError(b, err) defer os.RemoveAll(dir) @@ -637,8 +792,138 @@ func benchmarkTxIndex(txsCount int64, b *testing.B) { } } -func BenchmarkTxIndex1(b *testing.B) { benchmarkTxIndex(1, b) } -func BenchmarkTxIndex500(b *testing.B) { benchmarkTxIndex(500, b) } -func BenchmarkTxIndex1000(b *testing.B) { benchmarkTxIndex(1000, b) } -func BenchmarkTxIndex2000(b *testing.B) { benchmarkTxIndex(2000, b) } -func BenchmarkTxIndex10000(b *testing.B) { benchmarkTxIndex(10000, b) } +func TestBigInt(t *testing.T) { + indexer := NewTxIndex(db.NewMemDB()) + + bigInt := "10000000000000000000" + bigIntPlus1 := "10000000000000000001" + bigFloat := bigInt + ".76" + bigFloatLower := bigInt + ".1" + bigFloatSmaller := "9999999999999999999" + ".1" + bigIntSmaller := "9999999999999999999" + + txResult := txResultWithEvents([]abci.Event{ + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: bigInt, Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: bigFloatSmaller, Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: bigIntPlus1, Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: bigFloatLower, 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() + + err := indexer.Index(txResult) + + require.NoError(t, err) + + txResult2 := txResultWithEvents([]abci.Event{ + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: bigFloat, Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: bigFloat, Index: true}, {Key: "amount", Value: "5", Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: bigIntSmaller, Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: bigInt, Index: true}, {Key: "amount", Value: "3", Index: true}}}, + }) + + txResult2.Tx = types.Tx("NEW TX") + txResult2.Height = 2 + txResult2.Index = 2 + + hash2 := types.Tx(txResult2.Tx).Hash() + + err = indexer.Index(txResult2) + require.NoError(t, err) + testCases := []struct { + q string + txRes *abci.TxResult + resultsLength int + }{ + // search by hash + {fmt.Sprintf("tx.hash = '%X'", hash), txResult, 1}, + // search by hash (lower) + {fmt.Sprintf("tx.hash = '%x'", hash), txResult, 1}, + {fmt.Sprintf("tx.hash = '%x'", hash2), txResult2, 1}, + // search by exact match (one key) - bigint + {"account.number >= " + bigInt, nil, 2}, + // search by exact match (one key) - bigint range + {"account.number >= " + bigInt + " AND tx.height > 0", nil, 2}, + {"account.number >= " + bigInt + " AND tx.height > 0 AND account.owner = '/Ivan/'", nil, 0}, + // Floats are not parsed + {"account.number >= " + bigInt + " AND tx.height > 0 AND account.amount > 4", txResult2, 1}, + {"account.number >= " + bigInt + " AND tx.height > 0 AND account.amount = 5", txResult2, 1}, + {"account.number >= " + bigInt + " AND account.amount <= 5", txResult2, 1}, + {"account.number > " + bigFloatSmaller + " AND account.amount = 3", txResult2, 1}, + {"account.number < " + bigInt + " AND tx.height >= 1", nil, 2}, + {"account.number < " + bigInt + " AND tx.height = 1", nil, 1}, + {"account.number < " + bigInt + " AND tx.height = 2", nil, 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)) + require.NoError(t, err) + assert.Len(t, results, tc.resultsLength) + if tc.resultsLength > 0 && tc.txRes != nil { + assert.True(t, proto.Equal(results[0], tc.txRes)) + } + }) + } +} + +func BenchmarkTxIndex(b *testing.B) { + testCases := []struct { + name string + txsCount int64 + }{ + {"1", 1}, + {"500", 500}, + {"1000", 1000}, + {"2000", 2000}, + {"10000", 10000}, + } + + for _, tc := range testCases { + b.Run(tc.name, func(b *testing.B) { + benchmarkTxIndex(b, tc.txsCount) + }) + } +} + +func isSubset(smaller [][]byte, bigger [][]byte) bool { + for _, elem := range smaller { + if !slices.ContainsFunc(bigger, func(i []byte) bool { + return bytes.Equal(i, elem) + }) { + return false + } + } + return true +} + +func isEqualSets(x [][]byte, y [][]byte) bool { + return isSubset(x, y) && isSubset(y, x) +} + +func emptyIntersection(x [][]byte, y [][]byte) bool { + for _, elem := range x { + if slices.ContainsFunc(y, func(i []byte) bool { + return bytes.Equal(i, elem) + }) { + return false + } + } + return true +} + +func setDiff(bigger [][]byte, smaller [][]byte) [][]byte { + var diff [][]byte + for _, elem := range bigger { + if !slices.ContainsFunc(smaller, func(i []byte) bool { + return bytes.Equal(i, elem) + }) { + diff = append(diff, elem) + } + } + return diff +} diff --git a/state/txindex/kv/utils.go b/internal/state/txindex/kv/utils.go similarity index 62% rename from state/txindex/kv/utils.go rename to internal/state/txindex/kv/utils.go index 3f00d342be4..9d8def47263 100644 --- a/state/txindex/kv/utils.go +++ b/internal/state/txindex/kv/utils.go @@ -1,12 +1,17 @@ package kv import ( + "encoding/binary" "fmt" + "math/big" - cmtsyntax "github.com/cometbft/cometbft/libs/pubsub/query/syntax" - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/types" "github.com/google/orderedcode" + + abci "github.com/cometbft/cometbft/abci/types" + idxutil "github.com/cometbft/cometbft/internal/indexer" + cmtsyntax "github.com/cometbft/cometbft/internal/pubsub/query/syntax" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/types" ) type HeightInfo struct { @@ -45,6 +50,7 @@ func ParseEventSeqFromEventKey(key []byte) (int64, error) { return eventSeq, nil } + func dedupHeight(conditions []cmtsyntax.Condition) (dedupConditions []cmtsyntax.Condition, heightInfo HeightInfo) { heightInfo.heightEqIdx = -1 heightRangeExists := false @@ -57,10 +63,13 @@ func dedupHeight(conditions []cmtsyntax.Condition) (dedupConditions []cmtsyntax. if c.Op == cmtsyntax.TEq { if heightRangeExists || found { continue - } else { + } + hFloat := c.Arg.Number() + if hFloat != nil { + h, _ := hFloat.Int64() + heightInfo.height = h found = true heightCondition = append(heightCondition, c) - heightInfo.height = int64(c.Arg.Number()) } } else { heightInfo.onlyHeightEq = false @@ -87,15 +96,45 @@ func dedupHeight(conditions []cmtsyntax.Condition) (dedupConditions []cmtsyntax. return dedupConditions, heightInfo } -func checkHeightConditions(heightInfo HeightInfo, keyHeight int64) bool { +func checkHeightConditions(heightInfo HeightInfo, keyHeight int64) (bool, error) { if heightInfo.heightRange.Key != "" { - if !checkBounds(heightInfo.heightRange, keyHeight) { - return false - } - } else { - if heightInfo.height != 0 && keyHeight != heightInfo.height { - return false + withinBounds, err := idxutil.CheckBounds(heightInfo.heightRange, big.NewInt(keyHeight)) + if err != nil || !withinBounds { + return false, err } + } else if heightInfo.height != 0 && keyHeight != heightInfo.height { + return false, nil + } + + return true, nil +} + +func int64FromBytes(bz []byte) int64 { + v, _ := binary.Varint(bz) + return v +} + +func int64ToBytes(i int64) []byte { + buf := make([]byte, binary.MaxVarintLen64) + n := binary.PutVarint(buf, i) + return buf[:n] +} + +func getKeys(indexer *TxIndex) [][]byte { + var keys [][]byte + + itr, err := indexer.store.Iterator(nil, nil) + if err != nil { + panic(err) + } + for ; itr.Valid(); itr.Next() { + keys = append(keys, itr.Key()) } - return true + return keys } + +type TxResultByHeight []*abci.TxResult + +func (a TxResultByHeight) Len() int { return len(a) } +func (a TxResultByHeight) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a TxResultByHeight) Less(i, j int) bool { return a[i].Height < a[j].Height } diff --git a/state/txindex/kv/utils_test.go b/internal/state/txindex/kv/utils_test.go similarity index 100% rename from state/txindex/kv/utils_test.go rename to internal/state/txindex/kv/utils_test.go diff --git a/internal/state/txindex/mocks/tx_indexer.go b/internal/state/txindex/mocks/tx_indexer.go new file mode 100644 index 00000000000..e0e31afbcfe --- /dev/null +++ b/internal/state/txindex/mocks/tx_indexer.go @@ -0,0 +1,217 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + context "context" + + log "github.com/cometbft/cometbft/libs/log" + mock "github.com/stretchr/testify/mock" + + query "github.com/cometbft/cometbft/internal/pubsub/query" + + txindex "github.com/cometbft/cometbft/internal/state/txindex" + + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" +) + +// TxIndexer is an autogenerated mock type for the TxIndexer type +type TxIndexer struct { + mock.Mock +} + +// AddBatch provides a mock function with given fields: b +func (_m *TxIndexer) AddBatch(b *txindex.Batch) error { + ret := _m.Called(b) + + if len(ret) == 0 { + panic("no return value specified for AddBatch") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*txindex.Batch) error); ok { + r0 = rf(b) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Get provides a mock function with given fields: hash +func (_m *TxIndexer) Get(hash []byte) (*v1.TxResult, error) { + ret := _m.Called(hash) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 *v1.TxResult + var r1 error + if rf, ok := ret.Get(0).(func([]byte) (*v1.TxResult, error)); ok { + return rf(hash) + } + if rf, ok := ret.Get(0).(func([]byte) *v1.TxResult); ok { + r0 = rf(hash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*v1.TxResult) + } + } + + if rf, ok := ret.Get(1).(func([]byte) error); ok { + r1 = rf(hash) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetRetainHeight provides a mock function with given fields: +func (_m *TxIndexer) GetRetainHeight() (int64, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetRetainHeight") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func() (int64, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() int64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Index provides a mock function with given fields: result +func (_m *TxIndexer) Index(result *v1.TxResult) error { + ret := _m.Called(result) + + if len(ret) == 0 { + panic("no return value specified for Index") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*v1.TxResult) error); ok { + r0 = rf(result) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Prune provides a mock function with given fields: retainHeight +func (_m *TxIndexer) Prune(retainHeight int64) (int64, int64, error) { + ret := _m.Called(retainHeight) + + if len(ret) == 0 { + panic("no return value specified for Prune") + } + + var r0 int64 + var r1 int64 + var r2 error + if rf, ok := ret.Get(0).(func(int64) (int64, int64, error)); ok { + return rf(retainHeight) + } + if rf, ok := ret.Get(0).(func(int64) int64); ok { + r0 = rf(retainHeight) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(int64) int64); ok { + r1 = rf(retainHeight) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(int64) error); ok { + r2 = rf(retainHeight) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// Search provides a mock function with given fields: ctx, q +func (_m *TxIndexer) Search(ctx context.Context, q *query.Query) ([]*v1.TxResult, error) { + ret := _m.Called(ctx, q) + + if len(ret) == 0 { + panic("no return value specified for Search") + } + + var r0 []*v1.TxResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *query.Query) ([]*v1.TxResult, error)); ok { + return rf(ctx, q) + } + if rf, ok := ret.Get(0).(func(context.Context, *query.Query) []*v1.TxResult); ok { + r0 = rf(ctx, q) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*v1.TxResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *query.Query) error); ok { + r1 = rf(ctx, q) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SetLogger provides a mock function with given fields: l +func (_m *TxIndexer) SetLogger(l log.Logger) { + _m.Called(l) +} + +// SetRetainHeight provides a mock function with given fields: retainHeight +func (_m *TxIndexer) SetRetainHeight(retainHeight int64) error { + ret := _m.Called(retainHeight) + + if len(ret) == 0 { + panic("no return value specified for SetRetainHeight") + } + + var r0 error + if rf, ok := ret.Get(0).(func(int64) error); ok { + r0 = rf(retainHeight) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// NewTxIndexer creates a new instance of TxIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewTxIndexer(t interface { + mock.TestingT + Cleanup(func()) +}) *TxIndexer { + mock := &TxIndexer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/state/txindex/null/null.go b/internal/state/txindex/null/null.go new file mode 100644 index 00000000000..297fe45474d --- /dev/null +++ b/internal/state/txindex/null/null.go @@ -0,0 +1,50 @@ +package null + +import ( + "context" + "errors" + + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/libs/log" +) + +var _ txindex.TxIndexer = (*TxIndex)(nil) + +// TxIndex acts as a /dev/null. +type TxIndex struct{} + +func (*TxIndex) SetRetainHeight(_ int64) error { + return nil +} + +func (*TxIndex) GetRetainHeight() (int64, error) { + return 0, nil +} + +func (*TxIndex) Prune(_ int64) (numPruned, newRetainHeight int64, err error) { + return 0, 0, nil +} + +// Get on a TxIndex is disabled and panics when invoked. +func (*TxIndex) Get(_ []byte) (*abci.TxResult, error) { + return nil, errors.New(`indexing is disabled (set 'tx_index = "kv"' in config)`) +} + +// AddBatch is a noop and always returns nil. +func (*TxIndex) AddBatch(_ *txindex.Batch) error { + return nil +} + +// Index is a noop and always returns nil. +func (*TxIndex) Index(_ *abci.TxResult) error { + return nil +} + +func (*TxIndex) Search(_ context.Context, _ *query.Query) ([]*abci.TxResult, error) { + return []*abci.TxResult{}, nil +} + +func (*TxIndex) SetLogger(log.Logger) { +} diff --git a/state/validation.go b/internal/state/validation.go similarity index 85% rename from state/validation.go rename to internal/state/validation.go index 287aec31aaa..f5d17a35d41 100644 --- a/state/validation.go +++ b/internal/state/validation.go @@ -4,12 +4,14 @@ import ( "bytes" "errors" "fmt" + "time" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" ) -//----------------------------------------------------- +// ----------------------------------------------------- // Validate block func validateBlock(state State, block *types.Block) error { @@ -34,7 +36,7 @@ func validateBlock(state State, block *types.Block) error { } if state.LastBlockHeight == 0 && block.Height != state.InitialHeight { return fmt.Errorf("wrong Block.Header.Height. Expected %v for initial block, got %v", - block.Height, state.InitialHeight) + state.InitialHeight, block.Height) } if state.LastBlockHeight > 0 && block.Height != state.LastBlockHeight+1 { return fmt.Errorf("wrong Block.Header.Height. Expected %v, got %v", @@ -111,6 +113,10 @@ func validateBlock(state State, block *types.Block) error { } // Validate block Time + if block.Time != cmttime.Canonical(block.Time) { + return fmt.Errorf("block time %v is not canonical", block.Time) + } + switch { case block.Height > state.InitialHeight: if !block.Time.After(state.LastBlockTime) { @@ -119,18 +125,20 @@ func validateBlock(state State, block *types.Block) error { state.LastBlockTime, ) } - medianTime := MedianTime(block.LastCommit, state.LastValidators) - if !block.Time.Equal(medianTime) { - return fmt.Errorf("invalid block time. Expected %v, got %v", - medianTime, - block.Time, - ) + if !state.ConsensusParams.Feature.PbtsEnabled(block.Height) { + medianTime := block.LastCommit.MedianTime(state.LastValidators) + if !block.Time.Equal(medianTime) { + return fmt.Errorf("invalid block time. Expected %v, got %v", + medianTime.Format(time.RFC3339Nano), + block.Time.Format(time.RFC3339Nano), + ) + } } case block.Height == state.InitialHeight: genesisTime := state.LastBlockTime - if !block.Time.Equal(genesisTime) { - return fmt.Errorf("block time %v is not equal to genesis time %v", + if block.Time.Before(genesisTime) { + return fmt.Errorf("block time %v is before genesis time %v", block.Time, genesisTime, ) diff --git a/state/validation_test.go b/internal/state/validation_test.go similarity index 88% rename from state/validation_test.go rename to internal/state/validation_test.go index b4efcd75989..7d012825258 100644 --- a/state/validation_test.go +++ b/internal/state/validation_test.go @@ -9,18 +9,17 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/crypto/tmhash" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/mocks" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" mpmocks "github.com/cometbft/cometbft/mempool/mocks" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/mocks" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -31,7 +30,11 @@ func TestValidateBlockHeader(t *testing.T) { require.NoError(t, proxyApp.Start()) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, privVals := makeState(3, 1) + cp := test.ConsensusParams() + pbtsEnableHeight := validationTestsStopHeight / 2 + cp.Feature.PbtsEnableHeight = pbtsEnableHeight + + state, stateDB, privVals := makeStateWithParams(3, 1, cp, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -76,7 +79,14 @@ func TestValidateBlockHeader(t *testing.T) { {"Version wrong2", func(block *types.Block) { block.Version = wrongVersion2 }}, {"ChainID wrong", func(block *types.Block) { block.ChainID = "not-the-real-one" }}, {"Height wrong", func(block *types.Block) { block.Height += 10 }}, - {"Time wrong", func(block *types.Block) { block.Time = block.Time.Add(-time.Second * 1) }}, + {"Time non-monotonic", func(block *types.Block) { block.Time = block.Time.Add(-2 * time.Second) }}, + {"Time wrong", func(block *types.Block) { + if block.Height > 1 && block.Height < pbtsEnableHeight { + block.Time = block.Time.Add(time.Millisecond) // BFT Time + } else { + block.Time = time.Now() // not canonical + } + }}, {"LastBlockID wrong", func(block *types.Block) { block.LastBlockID.PartSetHeader.Total += 10 }}, {"LastCommitHash wrong", func(block *types.Block) { block.LastCommitHash = wrongHash }}, @@ -128,7 +138,7 @@ func TestValidateBlockCommit(t *testing.T) { require.NoError(t, proxyApp.Start()) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, privVals := makeState(1, 1) + state, stateDB, privVals := makeState(1, 1, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -176,7 +186,7 @@ func TestValidateBlockCommit(t *testing.T) { 0, 2, state.LastBlockID, - time.Now(), + cmttime.Now(), ) wrongHeightCommit := &types.Commit{ Height: wrongHeightVote.Height, @@ -186,7 +196,7 @@ func TestValidateBlockCommit(t *testing.T) { } block := makeBlock(state, height, wrongHeightCommit) err := blockExec.ValidateBlock(state, block) - _, isErrInvalidCommitHeight := err.(types.ErrInvalidCommitHeight) + _, isErrInvalidCommitHeight := err.(cmterrors.ErrInvalidCommitHeight) require.True(t, isErrInvalidCommitHeight, "expected ErrInvalidCommitHeight at height %d but got: %v", height, err) /* @@ -194,7 +204,7 @@ func TestValidateBlockCommit(t *testing.T) { */ block = makeBlock(state, height, wrongSigsCommit) err = blockExec.ValidateBlock(state, block) - _, isErrInvalidCommitSignatures := err.(types.ErrInvalidCommitSignatures) + _, isErrInvalidCommitSignatures := err.(cmterrors.ErrInvalidCommitSignatures) require.True(t, isErrInvalidCommitSignatures, "expected ErrInvalidCommitSignatures at height %d, but got: %v", height, @@ -230,9 +240,9 @@ func TestValidateBlockCommit(t *testing.T) { idx, height, 0, - cmtproto.PrecommitType, + types.PrecommitType, blockID, - time.Now(), + cmttime.Now(), ) bpvPubKey, err := badPrivVal.GetPubKey() @@ -244,16 +254,16 @@ func TestValidateBlockCommit(t *testing.T) { Height: height, Round: 0, Timestamp: cmttime.Now(), - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, BlockID: blockID, } g := goodVote.ToProto() b := badVote.ToProto() - err = badPrivVal.SignVote(chainID, g) + err = badPrivVal.SignVote(chainID, g, false) require.NoError(t, err, "height %d", height) - err = badPrivVal.SignVote(chainID, b) + err = badPrivVal.SignVote(chainID, b, false) require.NoError(t, err, "height %d", height) goodVote.Signature, badVote.Signature = g.Signature, b.Signature @@ -272,7 +282,7 @@ func TestValidateBlockEvidence(t *testing.T) { require.NoError(t, proxyApp.Start()) defer proxyApp.Stop() //nolint:errcheck // ignore for tests - state, stateDB, privVals := makeState(4, 1) + state, stateDB, privVals := makeState(4, 1, chainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) @@ -320,7 +330,7 @@ func TestValidateBlockEvidence(t *testing.T) { var currentBytes int64 // more bytes than the maximum allowed for evidence for currentBytes <= maxBytesEvidence { - newEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), + newEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, cmttime.Now(), privVals[proposerAddr.String()], chainID) require.NoError(t, err) evidence = append(evidence, newEv) @@ -329,7 +339,7 @@ func TestValidateBlockEvidence(t *testing.T) { block := state.MakeBlock(height, test.MakeNTxs(height, 10), lastCommit, evidence, proposerAddr) err := blockExec.ValidateBlock(state, block) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here _, ok := err.(*types.ErrEvidenceOverflow) require.True(t, ok, "expected error to be of type ErrEvidenceOverflow at height %d but got %v", height, err) } @@ -364,6 +374,5 @@ func TestValidateBlockEvidence(t *testing.T) { ) require.NoError(t, err, "height %d", height) lastCommit = lastExtCommit.ToCommit() - } } diff --git a/statesync/chunks.go b/internal/statesync/chunks.go similarity index 98% rename from statesync/chunks.go rename to internal/statesync/chunks.go index d392b708a1d..ecb6e6e8167 100644 --- a/statesync/chunks.go +++ b/internal/statesync/chunks.go @@ -8,7 +8,7 @@ import ( "strconv" "time" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/p2p" ) @@ -83,7 +83,7 @@ func (q *chunkQueue) Add(chunk *chunk) (bool, error) { } path := filepath.Join(q.dir, strconv.FormatUint(uint64(chunk.Index), 10)) - err := os.WriteFile(path, chunk.Chunk, 0600) + err := os.WriteFile(path, chunk.Chunk, 0o600) if err != nil { return false, fmt.Errorf("failed to save chunk %v to file %v: %w", chunk.Index, path, err) } diff --git a/statesync/chunks_test.go b/internal/statesync/chunks_test.go similarity index 99% rename from statesync/chunks_test.go rename to internal/statesync/chunks_test.go index 5c893c5233f..7f79abce277 100644 --- a/statesync/chunks_test.go +++ b/internal/statesync/chunks_test.go @@ -11,6 +11,7 @@ import ( ) func setupChunkQueue(t *testing.T) (*chunkQueue, func()) { + t.Helper() snapshot := &snapshot{ Height: 3, Format: 1, @@ -50,7 +51,7 @@ func TestNewChunkQueue_TempDir(t *testing.T) { files, err = os.ReadDir(dir) require.NoError(t, err) - assert.Len(t, files, 0) + assert.Empty(t, files) } func TestChunkQueue(t *testing.T) { diff --git a/statesync/messages.go b/internal/statesync/messages.go similarity index 89% rename from statesync/messages.go rename to internal/statesync/messages.go index eff6646106d..e9287f166bb 100644 --- a/statesync/messages.go +++ b/internal/statesync/messages.go @@ -6,13 +6,13 @@ import ( "github.com/cosmos/gogoproto/proto" - ssproto "github.com/cometbft/cometbft/proto/tendermint/statesync" + ssproto "github.com/cometbft/cometbft/api/cometbft/statesync/v1" ) const ( - // snapshotMsgSize is the maximum size of a snapshotResponseMessage + // snapshotMsgSize is the maximum size of a snapshotResponseMessage. snapshotMsgSize = int(4e6) - // chunkMsgSize is the maximum size of a chunkResponseMessage + // chunkMsgSize is the maximum size of a chunkResponseMessage. chunkMsgSize = int(16e6) ) diff --git a/statesync/messages_test.go b/internal/statesync/messages_test.go similarity index 89% rename from statesync/messages_test.go rename to internal/statesync/messages_test.go index 97a888aba01..de516280c7a 100644 --- a/statesync/messages_test.go +++ b/internal/statesync/messages_test.go @@ -7,9 +7,9 @@ import ( "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/require" - "github.com/cometbft/cometbft/p2p" - ssproto "github.com/cometbft/cometbft/proto/tendermint/statesync" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + ssproto "github.com/cometbft/cometbft/api/cometbft/statesync/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/types" ) func TestValidateMsg(t *testing.T) { @@ -27,49 +27,63 @@ func TestValidateMsg(t *testing.T) { "ChunkResponse valid": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: []byte{1}}, - true}, + true, + }, "ChunkResponse 0 height": { &ssproto.ChunkResponse{Height: 0, Format: 1, Index: 1, Chunk: []byte{1}}, - false}, + false, + }, "ChunkResponse 0 format": { &ssproto.ChunkResponse{Height: 1, Format: 0, Index: 1, Chunk: []byte{1}}, - true}, + true, + }, "ChunkResponse 0 chunk": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 0, Chunk: []byte{1}}, - true}, + true, + }, "ChunkResponse empty body": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: []byte{}}, - true}, + true, + }, "ChunkResponse nil body": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: nil}, - false}, + false, + }, "ChunkResponse missing": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Missing: true}, - true}, + true, + }, "ChunkResponse missing with empty": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Missing: true, Chunk: []byte{}}, - true}, + true, + }, "ChunkResponse missing with body": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Missing: true, Chunk: []byte{1}}, - false}, + false, + }, "SnapshotsRequest valid": {&ssproto.SnapshotsRequest{}, true}, "SnapshotsResponse valid": { &ssproto.SnapshotsResponse{Height: 1, Format: 1, Chunks: 2, Hash: []byte{1}}, - true}, + true, + }, "SnapshotsResponse 0 height": { &ssproto.SnapshotsResponse{Height: 0, Format: 1, Chunks: 2, Hash: []byte{1}}, - false}, + false, + }, "SnapshotsResponse 0 format": { &ssproto.SnapshotsResponse{Height: 1, Format: 0, Chunks: 2, Hash: []byte{1}}, - true}, + true, + }, "SnapshotsResponse 0 chunks": { &ssproto.SnapshotsResponse{Height: 1, Format: 1, Hash: []byte{1}}, - false}, + false, + }, "SnapshotsResponse no hash": { &ssproto.SnapshotsResponse{Height: 1, Format: 1, Chunks: 2, Hash: []byte{}}, - false}, + false, + }, } for name, tc := range testcases { tc := tc @@ -86,7 +100,6 @@ func TestValidateMsg(t *testing.T) { //nolint:lll // ignore line length func TestStateSyncVectors(t *testing.T) { - testCases := []struct { testName string msg proto.Message @@ -100,7 +113,7 @@ func TestStateSyncVectors(t *testing.T) { for _, tc := range testCases { tc := tc - w := tc.msg.(p2p.Wrapper).Wrap() + w := tc.msg.(types.Wrapper).Wrap() bz, err := proto.Marshal(w) require.NoError(t, err) diff --git a/statesync/metrics.gen.go b/internal/statesync/metrics.gen.go similarity index 100% rename from statesync/metrics.gen.go rename to internal/statesync/metrics.gen.go diff --git a/statesync/metrics.go b/internal/statesync/metrics.go similarity index 85% rename from statesync/metrics.go rename to internal/statesync/metrics.go index 9a4d7fcefab..71e29ca8cf8 100644 --- a/statesync/metrics.go +++ b/internal/statesync/metrics.go @@ -10,7 +10,7 @@ const ( MetricsSubsystem = "statesync" ) -//go:generate go run ../scripts/metricsgen -struct=Metrics +//go:generate go run ../../scripts/metricsgen -struct=Metrics // Metrics contains metrics exposed by this package. type Metrics struct { diff --git a/statesync/mocks/state_provider.go b/internal/statesync/mocks/state_provider.go similarity index 86% rename from statesync/mocks/state_provider.go rename to internal/statesync/mocks/state_provider.go index cbbe3c0b5a5..41177757069 100644 --- a/statesync/mocks/state_provider.go +++ b/internal/statesync/mocks/state_provider.go @@ -5,7 +5,7 @@ package mocks import ( context "context" - state "github.com/cometbft/cometbft/state" + state "github.com/cometbft/cometbft/internal/state" mock "github.com/stretchr/testify/mock" types "github.com/cometbft/cometbft/types" @@ -20,6 +20,10 @@ type StateProvider struct { func (_m *StateProvider) AppHash(ctx context.Context, height uint64) ([]byte, error) { ret := _m.Called(ctx, height) + if len(ret) == 0 { + panic("no return value specified for AppHash") + } + var r0 []byte var r1 error if rf, ok := ret.Get(0).(func(context.Context, uint64) ([]byte, error)); ok { @@ -46,6 +50,10 @@ func (_m *StateProvider) AppHash(ctx context.Context, height uint64) ([]byte, er func (_m *StateProvider) Commit(ctx context.Context, height uint64) (*types.Commit, error) { ret := _m.Called(ctx, height) + if len(ret) == 0 { + panic("no return value specified for Commit") + } + var r0 *types.Commit var r1 error if rf, ok := ret.Get(0).(func(context.Context, uint64) (*types.Commit, error)); ok { @@ -72,6 +80,10 @@ func (_m *StateProvider) Commit(ctx context.Context, height uint64) (*types.Comm func (_m *StateProvider) State(ctx context.Context, height uint64) (state.State, error) { ret := _m.Called(ctx, height) + if len(ret) == 0 { + panic("no return value specified for State") + } + var r0 state.State var r1 error if rf, ok := ret.Get(0).(func(context.Context, uint64) (state.State, error)); ok { @@ -92,13 +104,12 @@ func (_m *StateProvider) State(ctx context.Context, height uint64) (state.State, return r0, r1 } -type mockConstructorTestingTNewStateProvider interface { +// NewStateProvider creates a new instance of StateProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStateProvider(t interface { mock.TestingT Cleanup(func()) -} - -// NewStateProvider creates a new instance of StateProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewStateProvider(t mockConstructorTestingTNewStateProvider) *StateProvider { +}) *StateProvider { mock := &StateProvider{} mock.Mock.Test(t) diff --git a/statesync/reactor.go b/internal/statesync/reactor.go similarity index 92% rename from statesync/reactor.go rename to internal/statesync/reactor.go index dfc911be722..0cbe7659f5a 100644 --- a/statesync/reactor.go +++ b/internal/statesync/reactor.go @@ -7,19 +7,19 @@ import ( "time" abci "github.com/cometbft/cometbft/abci/types" + ssproto "github.com/cometbft/cometbft/api/cometbft/statesync/v1" "github.com/cometbft/cometbft/config" - cmtsync "github.com/cometbft/cometbft/libs/sync" + sm "github.com/cometbft/cometbft/internal/state" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/p2p" - ssproto "github.com/cometbft/cometbft/proto/tendermint/statesync" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" ) const ( - // SnapshotChannel exchanges snapshot metadata + // SnapshotChannel exchanges snapshot metadata. SnapshotChannel = byte(0x60) - // ChunkChannel exchanges chunk contents + // ChunkChannel exchanges chunk contents. ChunkChannel = byte(0x61) // recentSnapshots is the number of recent snapshots to send and receive per peer. recentSnapshots = 10 @@ -47,10 +47,8 @@ func NewReactor( cfg config.StateSyncConfig, conn proxy.AppConnSnapshot, connQuery proxy.AppConnQuery, - tempDir string, metrics *Metrics, ) *Reactor { - r := &Reactor{ cfg: cfg, conn: conn, @@ -63,7 +61,7 @@ func NewReactor( } // GetChannels implements p2p.Reactor. -func (r *Reactor) GetChannels() []*p2p.ChannelDescriptor { +func (*Reactor) GetChannels() []*p2p.ChannelDescriptor { return []*p2p.ChannelDescriptor{ { ID: SnapshotChannel, @@ -83,7 +81,7 @@ func (r *Reactor) GetChannels() []*p2p.ChannelDescriptor { } // OnStart implements p2p.Reactor. -func (r *Reactor) OnStart() error { +func (*Reactor) OnStart() error { return nil } @@ -97,7 +95,7 @@ func (r *Reactor) AddPeer(peer p2p.Peer) { } // RemovePeer implements p2p.Reactor. -func (r *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) { +func (r *Reactor) RemovePeer(peer p2p.Peer, _ any) { r.mtx.RLock() defer r.mtx.RUnlock() if r.syncer != nil { @@ -173,7 +171,7 @@ func (r *Reactor) Receive(e p2p.Envelope) { case *ssproto.ChunkRequest: r.Logger.Debug("Received chunk request", "height", msg.Height, "format", msg.Format, "chunk", msg.Index, "peer", e.Src.ID()) - resp, err := r.conn.LoadSnapshotChunk(context.TODO(), &abci.RequestLoadSnapshotChunk{ + resp, err := r.conn.LoadSnapshotChunk(context.TODO(), &abci.LoadSnapshotChunkRequest{ Height: msg.Height, Format: msg.Format, Chunk: msg.Index, @@ -227,9 +225,9 @@ func (r *Reactor) Receive(e p2p.Envelope) { } } -// recentSnapshots fetches the n most recent snapshots from the app +// recentSnapshots fetches the n most recent snapshots from the app. func (r *Reactor) recentSnapshots(n uint32) ([]*snapshot, error) { - resp, err := r.conn.ListSnapshots(context.TODO(), &abci.RequestListSnapshots{}) + resp, err := r.conn.ListSnapshots(context.TODO(), &abci.ListSnapshotsRequest{}) if err != nil { return nil, err } diff --git a/statesync/reactor_test.go b/internal/statesync/reactor_test.go similarity index 91% rename from statesync/reactor_test.go rename to internal/statesync/reactor_test.go index e5678111d61..af1b664088c 100644 --- a/statesync/reactor_test.go +++ b/internal/statesync/reactor_test.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/require" abci "github.com/cometbft/cometbft/abci/types" + ssproto "github.com/cometbft/cometbft/api/cometbft/statesync/v1" "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/p2p" p2pmocks "github.com/cometbft/cometbft/p2p/mocks" - ssproto "github.com/cometbft/cometbft/proto/tendermint/statesync" proxymocks "github.com/cometbft/cometbft/proxy/mocks" ) @@ -26,11 +26,13 @@ func TestReactor_Receive_ChunkRequest(t *testing.T) { "chunk is returned": { &ssproto.ChunkRequest{Height: 1, Format: 1, Index: 1}, []byte{1, 2, 3}, - &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: []byte{1, 2, 3}}}, + &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: []byte{1, 2, 3}}, + }, "empty chunk is returned, as nil": { &ssproto.ChunkRequest{Height: 1, Format: 1, Index: 1}, []byte{}, - &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: nil}}, + &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: nil}, + }, "nil (missing) chunk is returned as missing": { &ssproto.ChunkRequest{Height: 1, Format: 1, Index: 1}, nil, @@ -43,18 +45,18 @@ func TestReactor_Receive_ChunkRequest(t *testing.T) { t.Run(name, func(t *testing.T) { // Mock ABCI connection to return local snapshots conn := &proxymocks.AppConnSnapshot{} - conn.On("LoadSnapshotChunk", mock.Anything, &abci.RequestLoadSnapshotChunk{ + conn.On("LoadSnapshotChunk", mock.Anything, &abci.LoadSnapshotChunkRequest{ Height: tc.request.Height, Format: tc.request.Format, Chunk: tc.request.Index, - }).Return(&abci.ResponseLoadSnapshotChunk{Chunk: tc.chunk}, nil) + }).Return(&abci.LoadSnapshotChunkResponse{Chunk: tc.chunk}, nil) // Mock peer to store response, if found peer := &p2pmocks.Peer{} peer.On("ID").Return(p2p.ID("id")) var response *ssproto.ChunkResponse if tc.expectResponse != nil { - peer.On("Send", mock.MatchedBy(func(i interface{}) bool { + peer.On("Send", mock.MatchedBy(func(i any) bool { e, ok := i.(p2p.Envelope) return ok && e.ChannelID == ChunkChannel })).Run(func(args mock.Arguments) { @@ -71,7 +73,7 @@ func TestReactor_Receive_ChunkRequest(t *testing.T) { // Start a reactor and send a ssproto.ChunkRequest, then wait for and check response cfg := config.DefaultStateSyncConfig() - r := NewReactor(*cfg, conn, nil, "", NopMetrics()) + r := NewReactor(*cfg, conn, nil, NopMetrics()) err := r.Start() require.NoError(t, err) t.Cleanup(func() { @@ -135,7 +137,7 @@ func TestReactor_Receive_SnapshotsRequest(t *testing.T) { t.Run(name, func(t *testing.T) { // Mock ABCI connection to return local snapshots conn := &proxymocks.AppConnSnapshot{} - conn.On("ListSnapshots", mock.Anything, &abci.RequestListSnapshots{}).Return(&abci.ResponseListSnapshots{ + conn.On("ListSnapshots", mock.Anything, &abci.ListSnapshotsRequest{}).Return(&abci.ListSnapshotsResponse{ Snapshots: tc.snapshots, }, nil) @@ -144,7 +146,7 @@ func TestReactor_Receive_SnapshotsRequest(t *testing.T) { peer := &p2pmocks.Peer{} if len(tc.expectResponses) > 0 { peer.On("ID").Return(p2p.ID("id")) - peer.On("Send", mock.MatchedBy(func(i interface{}) bool { + peer.On("Send", mock.MatchedBy(func(i any) bool { e, ok := i.(p2p.Envelope) return ok && e.ChannelID == SnapshotChannel })).Run(func(args mock.Arguments) { @@ -161,7 +163,7 @@ func TestReactor_Receive_SnapshotsRequest(t *testing.T) { // Start a reactor and send a SnapshotsRequestMessage, then wait for and check responses cfg := config.DefaultStateSyncConfig() - r := NewReactor(*cfg, conn, nil, "", NopMetrics()) + r := NewReactor(*cfg, conn, nil, NopMetrics()) err := r.Start() require.NoError(t, err) t.Cleanup(func() { diff --git a/statesync/snapshots.go b/internal/statesync/snapshots.go similarity index 99% rename from statesync/snapshots.go rename to internal/statesync/snapshots.go index 5d4f9fe4d34..28c3e7cad5a 100644 --- a/statesync/snapshots.go +++ b/internal/statesync/snapshots.go @@ -6,7 +6,7 @@ import ( "math/rand" "sort" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/p2p" ) @@ -55,7 +55,7 @@ type snapshotPool struct { snapshotBlacklist map[snapshotKey]bool } -// newSnapshotPool creates a new snapshot pool. The state source is used for +// newSnapshotPool creates a new snapshot pool. The state source is used for. func newSnapshotPool() *snapshotPool { return &snapshotPool{ snapshots: make(map[snapshotKey]*snapshot), diff --git a/statesync/snapshots_test.go b/internal/statesync/snapshots_test.go similarity index 100% rename from statesync/snapshots_test.go rename to internal/statesync/snapshots_test.go diff --git a/statesync/stateprovider.go b/internal/statesync/stateprovider.go similarity index 84% rename from statesync/stateprovider.go rename to internal/statesync/stateprovider.go index 25bfcb39bfa..8d843fb74fb 100644 --- a/statesync/stateprovider.go +++ b/internal/statesync/stateprovider.go @@ -2,27 +2,27 @@ package statesync import ( "context" + "errors" "fmt" "strings" - "time" dbm "github.com/cometbft/cometbft-db" - + cmtstate "github.com/cometbft/cometbft/api/cometbft/state/v1" + sm "github.com/cometbft/cometbft/internal/state" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/light" lightprovider "github.com/cometbft/cometbft/light/provider" lighthttp "github.com/cometbft/cometbft/light/provider/http" lightrpc "github.com/cometbft/cometbft/light/rpc" lightdb "github.com/cometbft/cometbft/light/store/db" - cmtstate "github.com/cometbft/cometbft/proto/tendermint/state" rpchttp "github.com/cometbft/cometbft/rpc/client/http" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) -//go:generate ../scripts/mockery_generate.sh StateProvider +//go:generate ../../scripts/mockery_generate.sh StateProvider // StateProvider is a provider of trusted state data for bootstrapping a node. This refers // to the state.State object, not the state machine. @@ -44,15 +44,14 @@ type lightClientStateProvider struct { providers map[lightprovider.Provider]string } -// NewLightClientStateProvider creates a new StateProvider using a light client and RPC clients. -func NewLightClientStateProvider( - ctx context.Context, +func NewLightClientStateProviderWithDBKeyVersion(ctx context.Context, chainID string, version cmtstate.Version, initialHeight int64, servers []string, trustOptions light.TrustOptions, logger log.Logger, + dbKeyLayoutVereson string, ) (StateProvider, error) { if len(servers) < 2 { return nil, fmt.Errorf("at least 2 RPC servers are required, got %v", len(servers)) @@ -73,7 +72,7 @@ func NewLightClientStateProvider( } lc, err := light.NewClient(ctx, chainID, trustOptions, providers[0], providers[1:], - lightdb.New(dbm.NewMemDB(), ""), light.Logger(logger), light.MaxRetryAttempts(5)) + lightdb.NewWithDBVersion(dbm.NewMemDB(), "", dbKeyLayoutVereson), light.Logger(logger), light.MaxRetryAttempts(5)) if err != nil { return nil, err } @@ -85,13 +84,28 @@ func NewLightClientStateProvider( }, nil } +// NewLightClientStateProvider creates a new StateProvider using a light client and RPC clients. +// DB Key layout will default to v1. +func NewLightClientStateProvider( + ctx context.Context, + chainID string, + version cmtstate.Version, + initialHeight int64, + servers []string, + trustOptions light.TrustOptions, + logger log.Logger, +) (StateProvider, error) { + return NewLightClientStateProviderWithDBKeyVersion(ctx, + chainID, version, initialHeight, servers, trustOptions, logger, "") +} + // AppHash implements StateProvider. func (s *lightClientStateProvider) AppHash(ctx context.Context, height uint64) ([]byte, error) { s.Lock() defer s.Unlock() // We have to fetch the next height, which contains the app hash for the previous height. - header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), time.Now()) + header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), cmttime.Now()) if err != nil { return nil, err } @@ -103,7 +117,7 @@ func (s *lightClientStateProvider) AppHash(ctx context.Context, height uint64) ( // breaking it. We should instead have a Has(ctx, height) method which checks // that the state provider has access to the necessary data for the height. // We piggyback on AppHash() since it's called when adding snapshots to the pool. - _, err = s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) + _, err = s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), cmttime.Now()) if err != nil { return nil, err } @@ -114,7 +128,7 @@ func (s *lightClientStateProvider) AppHash(ctx context.Context, height uint64) ( func (s *lightClientStateProvider) Commit(ctx context.Context, height uint64) (*types.Commit, error) { s.Lock() defer s.Unlock() - header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) + header, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), cmttime.Now()) if err != nil { return nil, err } @@ -143,22 +157,22 @@ func (s *lightClientStateProvider) State(ctx context.Context, height uint64) (sm // // We need to fetch the NextValidators from height+2 because if the application changed // the validator set at the snapshot height then this only takes effect at height+2. - lastLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now()) + lastLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height), cmttime.Now()) if err != nil { return sm.State{}, err } - currentLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), time.Now()) + currentLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+1), cmttime.Now()) if err != nil { return sm.State{}, err } - nextLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), time.Now()) + nextLightBlock, err := s.lc.VerifyLightBlockAtHeight(ctx, int64(height+2), cmttime.Now()) if err != nil { return sm.State{}, err } state.Version = cmtstate.Version{ Consensus: currentLightBlock.Version, - Software: version.TMCoreSemVer, + Software: version.CMTSemVer, } state.LastBlockHeight = lastLightBlock.Height state.LastBlockTime = lastLightBlock.Time @@ -173,7 +187,7 @@ func (s *lightClientStateProvider) State(ctx context.Context, height uint64) (sm // We'll also need to fetch consensus params via RPC, using light client verification. primaryURL, ok := s.providers[s.lc.Primary()] if !ok || primaryURL == "" { - return sm.State{}, fmt.Errorf("could not find address for primary light client provider") + return sm.State{}, errors.New("could not find address for primary light client provider") } primaryRPC, err := rpcClient(primaryURL) if err != nil { @@ -191,12 +205,12 @@ func (s *lightClientStateProvider) State(ctx context.Context, height uint64) (sm return state, nil } -// rpcClient sets up a new RPC client +// rpcClient sets up a new RPC client. func rpcClient(server string) (*rpchttp.HTTP, error) { if !strings.Contains(server, "://") { server = "http://" + server } - c, err := rpchttp.New(server, "/websocket") + c, err := rpchttp.New(server) if err != nil { return nil, err } diff --git a/statesync/syncer.go b/internal/statesync/syncer.go similarity index 93% rename from statesync/syncer.go rename to internal/statesync/syncer.go index 38bdedfd1b6..58256138737 100644 --- a/statesync/syncer.go +++ b/internal/statesync/syncer.go @@ -8,14 +8,14 @@ import ( "time" abci "github.com/cometbft/cometbft/abci/types" + ssproto "github.com/cometbft/cometbft/api/cometbft/statesync/v1" "github.com/cometbft/cometbft/config" + sm "github.com/cometbft/cometbft/internal/state" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/light" "github.com/cometbft/cometbft/p2p" - ssproto "github.com/cometbft/cometbft/proto/tendermint/statesync" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" ) @@ -73,7 +73,6 @@ func newSyncer( stateProvider StateProvider, tempDir string, ) *syncer { - return &syncer{ logger: logger, stateProvider: stateProvider, @@ -322,7 +321,7 @@ func (s *syncer) Sync(snapshot *snapshot, chunks *chunkQueue) (sm.State, *types. func (s *syncer) offerSnapshot(snapshot *snapshot) error { s.logger.Info("Offering snapshot to ABCI app", "height", snapshot.Height, "format", snapshot.Format, "hash", log.NewLazySprintf("%X", snapshot.Hash)) - resp, err := s.conn.OfferSnapshot(context.TODO(), &abci.RequestOfferSnapshot{ + resp, err := s.conn.OfferSnapshot(context.TODO(), &abci.OfferSnapshotRequest{ Snapshot: &abci.Snapshot{ Height: snapshot.Height, Format: snapshot.Format, @@ -336,17 +335,17 @@ func (s *syncer) offerSnapshot(snapshot *snapshot) error { return fmt.Errorf("failed to offer snapshot: %w", err) } switch resp.Result { - case abci.ResponseOfferSnapshot_ACCEPT: + case abci.OFFER_SNAPSHOT_RESULT_ACCEPT: s.logger.Info("Snapshot accepted, restoring", "height", snapshot.Height, "format", snapshot.Format, "hash", log.NewLazySprintf("%X", snapshot.Hash)) return nil - case abci.ResponseOfferSnapshot_ABORT: + case abci.OFFER_SNAPSHOT_RESULT_ABORT: return errAbort - case abci.ResponseOfferSnapshot_REJECT: + case abci.OFFER_SNAPSHOT_RESULT_REJECT: return errRejectSnapshot - case abci.ResponseOfferSnapshot_REJECT_FORMAT: + case abci.OFFER_SNAPSHOT_RESULT_REJECT_FORMAT: return errRejectFormat - case abci.ResponseOfferSnapshot_REJECT_SENDER: + case abci.OFFER_SNAPSHOT_RESULT_REJECT_SENDER: return errRejectSender default: return fmt.Errorf("unknown ResponseOfferSnapshot result %v", resp.Result) @@ -364,7 +363,7 @@ func (s *syncer) applyChunks(chunks *chunkQueue) error { return fmt.Errorf("failed to fetch chunk: %w", err) } - resp, err := s.conn.ApplySnapshotChunk(context.TODO(), &abci.RequestApplySnapshotChunk{ + resp, err := s.conn.ApplySnapshotChunk(context.TODO(), &abci.ApplySnapshotChunkRequest{ Index: chunk.Index, Chunk: chunk.Chunk, Sender: string(chunk.Sender), @@ -395,14 +394,14 @@ func (s *syncer) applyChunks(chunks *chunkQueue) error { } switch resp.Result { - case abci.ResponseApplySnapshotChunk_ACCEPT: - case abci.ResponseApplySnapshotChunk_ABORT: + case abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT: + case abci.APPLY_SNAPSHOT_CHUNK_RESULT_ABORT: return errAbort - case abci.ResponseApplySnapshotChunk_RETRY: + case abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY: chunks.Retry(chunk.Index) - case abci.ResponseApplySnapshotChunk_RETRY_SNAPSHOT: + case abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT: return errRetrySnapshot - case abci.ResponseApplySnapshotChunk_REJECT_SNAPSHOT: + case abci.APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT: return errRejectSnapshot default: return fmt.Errorf("unknown ResponseApplySnapshotChunk result %v", resp.Result) @@ -441,23 +440,18 @@ func (s *syncer) fetchChunks(ctx context.Context, snapshot *snapshot, chunks *ch s.logger.Info("Fetching snapshot chunk", "height", snapshot.Height, "format", snapshot.Format, "chunk", index, "total", chunks.Size()) - ticker := time.NewTicker(s.retryTimeout) - defer ticker.Stop() - s.requestChunk(snapshot, index) select { case <-chunks.WaitFor(index): next = true - case <-ticker.C: + case <-time.After(s.retryTimeout): next = false case <-ctx.Done(): return } - - ticker.Stop() } } @@ -481,9 +475,9 @@ func (s *syncer) requestChunk(snapshot *snapshot, chunk uint32) { }) } -// verifyApp verifies the sync, checking the app hash, last block height and app version +// verifyApp verifies the sync, checking the app hash, last block height and app version. func (s *syncer) verifyApp(snapshot *snapshot, appVersion uint64) error { - resp, err := s.connQuery.Info(context.TODO(), proxy.RequestInfo) + resp, err := s.connQuery.Info(context.TODO(), proxy.InfoRequest) if err != nil { return fmt.Errorf("failed to query ABCI app for appHash: %w", err) } @@ -491,7 +485,7 @@ func (s *syncer) verifyApp(snapshot *snapshot, appVersion uint64) error { // sanity check that the app version in the block matches the application's own record // of its version if resp.AppVersion != appVersion { - // An error here most likely means that the app hasn't inplemented state sync + // An error here most likely means that the app hasn't implemented state sync // or the Info call correctly return fmt.Errorf("app version mismatch. Expected: %d, got: %d", appVersion, resp.AppVersion) diff --git a/statesync/syncer_test.go b/internal/statesync/syncer_test.go similarity index 70% rename from statesync/syncer_test.go rename to internal/statesync/syncer_test.go index 7abef23fd36..b11054e376d 100644 --- a/statesync/syncer_test.go +++ b/internal/statesync/syncer_test.go @@ -10,26 +10,27 @@ import ( "github.com/stretchr/testify/require" abci "github.com/cometbft/cometbft/abci/types" + cmtstate "github.com/cometbft/cometbft/api/cometbft/state/v1" + ssproto "github.com/cometbft/cometbft/api/cometbft/statesync/v1" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/config" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/statesync/mocks" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/p2p" p2pmocks "github.com/cometbft/cometbft/p2p/mocks" - cmtstate "github.com/cometbft/cometbft/proto/tendermint/state" - ssproto "github.com/cometbft/cometbft/proto/tendermint/statesync" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" "github.com/cometbft/cometbft/proxy" proxymocks "github.com/cometbft/cometbft/proxy/mocks" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/statesync/mocks" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) const testAppVersion = 9 -// Sets up a basic syncer that can be used to test OfferSnapshot requests -func setupOfferSyncer(t *testing.T) (*syncer, *proxymocks.AppConnSnapshot) { +// Sets up a basic syncer that can be used to test OfferSnapshot requests. +func setupOfferSyncer() (*syncer, *proxymocks.AppConnSnapshot) { connQuery := &proxymocks.AppConnQuery{} connSnapshot := &proxymocks.AppConnSnapshot{} stateProvider := &mocks.StateProvider{} @@ -40,7 +41,7 @@ func setupOfferSyncer(t *testing.T) (*syncer, *proxymocks.AppConnSnapshot) { return syncer, connSnapshot } -// Sets up a simple peer mock with an ID +// Sets up a simple peer mock with an ID. func simplePeer(id string) *p2pmocks.Peer { peer := &p2pmocks.Peer{} peer.On("ID").Return(p2p.ID(id)) @@ -55,12 +56,12 @@ func TestSyncer_SyncAny(t *testing.T) { Block: version.BlockProtocol, App: testAppVersion, }, - Software: version.TMCoreSemVer, + Software: version.CMTSemVer, }, LastBlockHeight: 1, LastBlockID: types.BlockID{Hash: []byte("blockhash")}, - LastBlockTime: time.Now(), + LastBlockTime: cmttime.Now(), LastResultsHash: []byte("last_results_hash"), AppHash: []byte("app_hash"), @@ -98,7 +99,7 @@ func TestSyncer_SyncAny(t *testing.T) { // Adding a couple of peers should trigger snapshot discovery messages peerA := &p2pmocks.Peer{} peerA.On("ID").Return(p2p.ID("a")) - peerA.On("Send", mock.MatchedBy(func(i interface{}) bool { + peerA.On("Send", mock.MatchedBy(func(i any) bool { e, ok := i.(p2p.Envelope) if !ok { return false @@ -111,7 +112,7 @@ func TestSyncer_SyncAny(t *testing.T) { peerB := &p2pmocks.Peer{} peerB.On("ID").Return(p2p.ID("b")) - peerB.On("Send", mock.MatchedBy(func(i interface{}) bool { + peerB.On("Send", mock.MatchedBy(func(i any) bool { e, ok := i.(p2p.Envelope) if !ok { return false @@ -124,21 +125,21 @@ func TestSyncer_SyncAny(t *testing.T) { // Both peers report back with snapshots. One of them also returns a snapshot we don't want, in // format 2, which will be rejected by the ABCI application. - new, err := syncer.AddSnapshot(peerA, s) + isNew, err := syncer.AddSnapshot(peerA, s) require.NoError(t, err) - assert.True(t, new) + assert.True(t, isNew) - new, err = syncer.AddSnapshot(peerB, s) + isNew, err = syncer.AddSnapshot(peerB, s) require.NoError(t, err) - assert.False(t, new) + assert.False(t, isNew) - new, err = syncer.AddSnapshot(peerB, &snapshot{Height: 2, Format: 2, Chunks: 3, Hash: []byte{1}}) + isNew, err = syncer.AddSnapshot(peerB, &snapshot{Height: 2, Format: 2, Chunks: 3, Hash: []byte{1}}) require.NoError(t, err) - assert.True(t, new) + assert.True(t, isNew) // We start a sync, with peers sending back chunks when requested. We first reject the snapshot // with height 2 format 2, and accept the snapshot at height 1. - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: &abci.Snapshot{ Height: 2, Format: 2, @@ -146,8 +147,8 @@ func TestSyncer_SyncAny(t *testing.T) { Hash: []byte{1}, }, AppHash: []byte("app_hash_2"), - }).Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_REJECT_FORMAT}, nil) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + }).Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_REJECT_FORMAT}, nil) + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: &abci.Snapshot{ Height: s.Height, Format: s.Format, @@ -156,7 +157,7 @@ func TestSyncer_SyncAny(t *testing.T) { Metadata: s.Metadata, }, AppHash: []byte("app_hash"), - }).Times(2).Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT}, nil) + }).Times(2).Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_ACCEPT}, nil) chunkRequests := make(map[uint32]int) chunkRequestsMtx := cmtsync.Mutex{} @@ -176,11 +177,11 @@ func TestSyncer_SyncAny(t *testing.T) { chunkRequests[msg.Index]++ chunkRequestsMtx.Unlock() } - peerA.On("Send", mock.MatchedBy(func(i interface{}) bool { + peerA.On("Send", mock.MatchedBy(func(i any) bool { e, ok := i.(p2p.Envelope) return ok && e.ChannelID == ChunkChannel })).Maybe().Run(onChunkRequest).Return(true) - peerB.On("Send", mock.MatchedBy(func(i interface{}) bool { + peerB.On("Send", mock.MatchedBy(func(i any) bool { e, ok := i.(p2p.Envelope) return ok && e.ChannelID == ChunkChannel })).Maybe().Run(onChunkRequest).Return(true) @@ -188,24 +189,24 @@ func TestSyncer_SyncAny(t *testing.T) { // The first time we're applying chunk 2 we tell it to retry the snapshot and discard chunk 1, // which should cause it to keep the existing chunk 0 and 2, and restart restoration from // beginning. We also wait for a little while, to exercise the retry logic in fetchChunks(). - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 2, Chunk: []byte{1, 1, 2}, - }).Once().Run(func(args mock.Arguments) { time.Sleep(2 * time.Second) }).Return( - &abci.ResponseApplySnapshotChunk{ - Result: abci.ResponseApplySnapshotChunk_RETRY_SNAPSHOT, + }).Once().Run(func(_ mock.Arguments) { time.Sleep(2 * time.Second) }).Return( + &abci.ApplySnapshotChunkResponse{ + Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT, RefetchChunks: []uint32{1}, }, nil) - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 0, Chunk: []byte{1, 1, 0}, - }).Times(2).Return(&abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + }).Times(2).Return(&abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil) + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 1, Chunk: []byte{1, 1, 1}, - }).Times(2).Return(&abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + }).Times(2).Return(&abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil) + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 2, Chunk: []byte{1, 1, 2}, - }).Once().Return(&abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) - connQuery.On("Info", mock.Anything, proxy.RequestInfo).Return(&abci.ResponseInfo{ + }).Once().Return(&abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil) + connQuery.On("Info", mock.Anything, proxy.InfoRequest).Return(&abci.InfoResponse{ AppVersion: testAppVersion, LastBlockHeight: 1, LastBlockAppHash: []byte("app_hash"), @@ -232,20 +233,20 @@ func TestSyncer_SyncAny(t *testing.T) { } func TestSyncer_SyncAny_noSnapshots(t *testing.T) { - syncer, _ := setupOfferSyncer(t) + syncer, _ := setupOfferSyncer() _, _, err := syncer.SyncAny(0, func() {}) assert.Equal(t, errNoSnapshots, err) } func TestSyncer_SyncAny_abort(t *testing.T) { - syncer, connSnapshot := setupOfferSyncer(t) + syncer, connSnapshot := setupOfferSyncer() s := &snapshot{Height: 1, Format: 1, Chunks: 3, Hash: []byte{1, 2, 3}} _, err := syncer.AddSnapshot(simplePeer("id"), s) require.NoError(t, err) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(s), AppHash: []byte("app_hash"), - }).Once().Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ABORT}, nil) + }).Once().Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_ABORT}, nil) _, _, err = syncer.SyncAny(0, func() {}) assert.Equal(t, errAbort, err) @@ -253,7 +254,7 @@ func TestSyncer_SyncAny_abort(t *testing.T) { } func TestSyncer_SyncAny_reject(t *testing.T) { - syncer, connSnapshot := setupOfferSyncer(t) + syncer, connSnapshot := setupOfferSyncer() // s22 is tried first, then s12, then s11, then errNoSnapshots s22 := &snapshot{Height: 2, Format: 2, Chunks: 3, Hash: []byte{1, 2, 3}} @@ -266,17 +267,17 @@ func TestSyncer_SyncAny_reject(t *testing.T) { _, err = syncer.AddSnapshot(simplePeer("id"), s11) require.NoError(t, err) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(s22), AppHash: []byte("app_hash"), - }).Once().Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_REJECT}, nil) + }).Once().Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_REJECT}, nil) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(s12), AppHash: []byte("app_hash"), - }).Once().Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_REJECT}, nil) + }).Once().Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_REJECT}, nil) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(s11), AppHash: []byte("app_hash"), - }).Once().Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_REJECT}, nil) + }).Once().Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_REJECT}, nil) _, _, err = syncer.SyncAny(0, func() {}) assert.Equal(t, errNoSnapshots, err) @@ -284,7 +285,7 @@ func TestSyncer_SyncAny_reject(t *testing.T) { } func TestSyncer_SyncAny_reject_format(t *testing.T) { - syncer, connSnapshot := setupOfferSyncer(t) + syncer, connSnapshot := setupOfferSyncer() // s22 is tried first, which reject s22 and s12, then s11 will abort. s22 := &snapshot{Height: 2, Format: 2, Chunks: 3, Hash: []byte{1, 2, 3}} @@ -297,13 +298,13 @@ func TestSyncer_SyncAny_reject_format(t *testing.T) { _, err = syncer.AddSnapshot(simplePeer("id"), s11) require.NoError(t, err) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(s22), AppHash: []byte("app_hash"), - }).Once().Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_REJECT_FORMAT}, nil) + }).Once().Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_REJECT_FORMAT}, nil) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(s11), AppHash: []byte("app_hash"), - }).Once().Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ABORT}, nil) + }).Once().Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_ABORT}, nil) _, _, err = syncer.SyncAny(0, func() {}) assert.Equal(t, errAbort, err) @@ -311,7 +312,7 @@ func TestSyncer_SyncAny_reject_format(t *testing.T) { } func TestSyncer_SyncAny_reject_sender(t *testing.T) { - syncer, connSnapshot := setupOfferSyncer(t) + syncer, connSnapshot := setupOfferSyncer() peerA := simplePeer("a") peerB := simplePeer("b") @@ -335,13 +336,13 @@ func TestSyncer_SyncAny_reject_sender(t *testing.T) { _, err = syncer.AddSnapshot(peerC, sbc) require.NoError(t, err) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(sbc), AppHash: []byte("app_hash"), - }).Once().Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_REJECT_SENDER}, nil) + }).Once().Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_REJECT_SENDER}, nil) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(sa), AppHash: []byte("app_hash"), - }).Once().Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_REJECT}, nil) + }).Once().Return(&abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_REJECT}, nil) _, _, err = syncer.SyncAny(0, func() {}) assert.Equal(t, errNoSnapshots, err) @@ -349,18 +350,18 @@ func TestSyncer_SyncAny_reject_sender(t *testing.T) { } func TestSyncer_SyncAny_abciError(t *testing.T) { - syncer, connSnapshot := setupOfferSyncer(t) + syncer, connSnapshot := setupOfferSyncer() errBoom := errors.New("boom") s := &snapshot{Height: 1, Format: 1, Chunks: 3, Hash: []byte{1, 2, 3}} _, err := syncer.AddSnapshot(simplePeer("id"), s) require.NoError(t, err) - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(s), AppHash: []byte("app_hash"), }).Once().Return(nil, errBoom) _, _, err = syncer.SyncAny(0, func() {}) - assert.True(t, errors.Is(err, errBoom)) + require.ErrorIs(t, err, errBoom) connSnapshot.AssertExpectations(t) } @@ -369,28 +370,28 @@ func TestSyncer_offerSnapshot(t *testing.T) { boom := errors.New("boom") testcases := map[string]struct { - result abci.ResponseOfferSnapshot_Result + result abci.OfferSnapshotResult err error expectErr error }{ - "accept": {abci.ResponseOfferSnapshot_ACCEPT, nil, nil}, - "abort": {abci.ResponseOfferSnapshot_ABORT, nil, errAbort}, - "reject": {abci.ResponseOfferSnapshot_REJECT, nil, errRejectSnapshot}, - "reject_format": {abci.ResponseOfferSnapshot_REJECT_FORMAT, nil, errRejectFormat}, - "reject_sender": {abci.ResponseOfferSnapshot_REJECT_SENDER, nil, errRejectSender}, - "unknown": {abci.ResponseOfferSnapshot_UNKNOWN, nil, unknownErr}, + "accept": {abci.OFFER_SNAPSHOT_RESULT_ACCEPT, nil, nil}, + "abort": {abci.OFFER_SNAPSHOT_RESULT_ABORT, nil, errAbort}, + "reject": {abci.OFFER_SNAPSHOT_RESULT_REJECT, nil, errRejectSnapshot}, + "reject_format": {abci.OFFER_SNAPSHOT_RESULT_REJECT_FORMAT, nil, errRejectFormat}, + "reject_sender": {abci.OFFER_SNAPSHOT_RESULT_REJECT_SENDER, nil, errRejectSender}, + "unknown": {abci.OFFER_SNAPSHOT_RESULT_UNKNOWN, nil, unknownErr}, "error": {0, boom, boom}, "unknown non-zero": {9, nil, unknownErr}, } for name, tc := range testcases { tc := tc t.Run(name, func(t *testing.T) { - syncer, connSnapshot := setupOfferSyncer(t) + syncer, connSnapshot := setupOfferSyncer() s := &snapshot{Height: 1, Format: 1, Chunks: 3, Hash: []byte{1, 2, 3}, trustedAppHash: []byte("app_hash")} - connSnapshot.On("OfferSnapshot", mock.Anything, &abci.RequestOfferSnapshot{ + connSnapshot.On("OfferSnapshot", mock.Anything, &abci.OfferSnapshotRequest{ Snapshot: toABCI(s), AppHash: []byte("app_hash"), - }).Return(&abci.ResponseOfferSnapshot{Result: tc.result}, tc.err) + }).Return(&abci.OfferSnapshotResponse{Result: tc.result}, tc.err) err := syncer.offerSnapshot(s) if tc.expectErr == unknownErr { require.Error(t, err) @@ -410,16 +411,16 @@ func TestSyncer_applyChunks_Results(t *testing.T) { boom := errors.New("boom") testcases := map[string]struct { - result abci.ResponseApplySnapshotChunk_Result + result abci.ApplySnapshotChunkResult err error expectErr error }{ - "accept": {abci.ResponseApplySnapshotChunk_ACCEPT, nil, nil}, - "abort": {abci.ResponseApplySnapshotChunk_ABORT, nil, errAbort}, - "retry": {abci.ResponseApplySnapshotChunk_RETRY, nil, nil}, - "retry_snapshot": {abci.ResponseApplySnapshotChunk_RETRY_SNAPSHOT, nil, errRetrySnapshot}, - "reject_snapshot": {abci.ResponseApplySnapshotChunk_REJECT_SNAPSHOT, nil, errRejectSnapshot}, - "unknown": {abci.ResponseApplySnapshotChunk_UNKNOWN, nil, unknownErr}, + "accept": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT, nil, nil}, + "abort": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_ABORT, nil, errAbort}, + "retry": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY, nil, nil}, + "retry_snapshot": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT, nil, errRetrySnapshot}, + "reject_snapshot": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT, nil, errRejectSnapshot}, + "unknown": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN, nil, unknownErr}, "error": {0, boom, boom}, "unknown non-zero": {9, nil, unknownErr}, } @@ -440,14 +441,15 @@ func TestSyncer_applyChunks_Results(t *testing.T) { _, err = chunks.Add(&chunk{Height: 1, Format: 1, Index: 0, Chunk: body}) require.NoError(t, err) - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 0, Chunk: body, - }).Once().Return(&abci.ResponseApplySnapshotChunk{Result: tc.result}, tc.err) - if tc.result == abci.ResponseApplySnapshotChunk_RETRY { - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + }).Once().Return(&abci.ApplySnapshotChunkResponse{Result: tc.result}, tc.err) + if tc.result == abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY { + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 0, Chunk: body, - }).Once().Return(&abci.ResponseApplySnapshotChunk{ - Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) + }).Once().Return(&abci.ApplySnapshotChunkResponse{ + Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT, + }, nil) } err = syncer.applyChunks(chunks) @@ -468,13 +470,13 @@ func TestSyncer_applyChunks_Results(t *testing.T) { func TestSyncer_applyChunks_RefetchChunks(t *testing.T) { // Discarding chunks via refetch_chunks should work the same for all results testcases := map[string]struct { - result abci.ResponseApplySnapshotChunk_Result + result abci.ApplySnapshotChunkResult }{ - "accept": {abci.ResponseApplySnapshotChunk_ACCEPT}, - "abort": {abci.ResponseApplySnapshotChunk_ABORT}, - "retry": {abci.ResponseApplySnapshotChunk_RETRY}, - "retry_snapshot": {abci.ResponseApplySnapshotChunk_RETRY_SNAPSHOT}, - "reject_snapshot": {abci.ResponseApplySnapshotChunk_REJECT_SNAPSHOT}, + "accept": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, + "abort": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_ABORT}, + "retry": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY}, + "retry_snapshot": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT}, + "reject_snapshot": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT}, } for name, tc := range testcases { tc := tc @@ -500,15 +502,15 @@ func TestSyncer_applyChunks_RefetchChunks(t *testing.T) { require.NoError(t, err) // The first two chunks are accepted, before the last one asks for 1 to be refetched - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 0, Chunk: []byte{0}, - }).Once().Return(&abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + }).Once().Return(&abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil) + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 1, Chunk: []byte{1}, - }).Once().Return(&abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + }).Once().Return(&abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil) + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 2, Chunk: []byte{2}, - }).Once().Return(&abci.ResponseApplySnapshotChunk{ + }).Once().Return(&abci.ApplySnapshotChunkResponse{ Result: tc.result, RefetchChunks: []uint32{1}, }, nil) @@ -533,13 +535,13 @@ func TestSyncer_applyChunks_RefetchChunks(t *testing.T) { func TestSyncer_applyChunks_RejectSenders(t *testing.T) { // Banning chunks senders via ban_chunk_senders should work the same for all results testcases := map[string]struct { - result abci.ResponseApplySnapshotChunk_Result + result abci.ApplySnapshotChunkResult }{ - "accept": {abci.ResponseApplySnapshotChunk_ACCEPT}, - "abort": {abci.ResponseApplySnapshotChunk_ABORT}, - "retry": {abci.ResponseApplySnapshotChunk_RETRY}, - "retry_snapshot": {abci.ResponseApplySnapshotChunk_RETRY_SNAPSHOT}, - "reject_snapshot": {abci.ResponseApplySnapshotChunk_REJECT_SNAPSHOT}, + "accept": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, + "abort": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_ABORT}, + "retry": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY}, + "retry_snapshot": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT}, + "reject_snapshot": {abci.APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT}, } for name, tc := range testcases { tc := tc @@ -586,24 +588,24 @@ func TestSyncer_applyChunks_RejectSenders(t *testing.T) { require.NoError(t, err) // The first two chunks are accepted, before the last one asks for b sender to be rejected - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 0, Chunk: []byte{0}, Sender: "a", - }).Once().Return(&abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + }).Once().Return(&abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil) + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 1, Chunk: []byte{1}, Sender: "b", - }).Once().Return(&abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + }).Once().Return(&abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil) + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 2, Chunk: []byte{2}, Sender: "c", - }).Once().Return(&abci.ResponseApplySnapshotChunk{ + }).Once().Return(&abci.ApplySnapshotChunkResponse{ Result: tc.result, RejectSenders: []string{string(peerB.ID())}, }, nil) // On retry, the last chunk will be tried again, so we just accept it then. - if tc.result == abci.ResponseApplySnapshotChunk_RETRY { - connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.RequestApplySnapshotChunk{ + if tc.result == abci.APPLY_SNAPSHOT_CHUNK_RESULT_RETRY { + connSnapshot.On("ApplySnapshotChunk", mock.Anything, &abci.ApplySnapshotChunkRequest{ Index: 2, Chunk: []byte{2}, Sender: "c", - }).Once().Return(&abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil) + }).Once().Return(&abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil) } // We don't really care about the result of applyChunks, since it has separate test. @@ -638,26 +640,26 @@ func TestSyncer_verifyApp(t *testing.T) { s := &snapshot{Height: 3, Format: 1, Chunks: 5, Hash: []byte{1, 2, 3}, trustedAppHash: []byte("app_hash")} testcases := map[string]struct { - response *abci.ResponseInfo + response *abci.InfoResponse err error expectErr error }{ - "verified": {&abci.ResponseInfo{ + "verified": {&abci.InfoResponse{ LastBlockHeight: 3, LastBlockAppHash: []byte("app_hash"), AppVersion: appVersion, }, nil, nil}, - "invalid app version": {&abci.ResponseInfo{ + "invalid app version": {&abci.InfoResponse{ LastBlockHeight: 3, LastBlockAppHash: []byte("app_hash"), AppVersion: 2, }, nil, appVersionMismatchErr}, - "invalid height": {&abci.ResponseInfo{ + "invalid height": {&abci.InfoResponse{ LastBlockHeight: 5, LastBlockAppHash: []byte("app_hash"), AppVersion: appVersion, }, nil, errVerifyFailed}, - "invalid hash": {&abci.ResponseInfo{ + "invalid hash": {&abci.InfoResponse{ LastBlockHeight: 3, LastBlockAppHash: []byte("xxx"), AppVersion: appVersion, @@ -674,7 +676,7 @@ func TestSyncer_verifyApp(t *testing.T) { cfg := config.DefaultStateSyncConfig() syncer := newSyncer(*cfg, log.NewNopLogger(), connSnapshot, connQuery, stateProvider, "") - connQuery.On("Info", mock.Anything, proxy.RequestInfo).Return(tc.response, tc.err) + connQuery.On("Info", mock.Anything, proxy.InfoRequest).Return(tc.response, tc.err) err := syncer.verifyApp(s, appVersion) unwrapped := errors.Unwrap(err) if unwrapped != nil { diff --git a/internal/statesync/types.go b/internal/statesync/types.go new file mode 100644 index 00000000000..0d8ea10df68 --- /dev/null +++ b/internal/statesync/types.go @@ -0,0 +1,13 @@ +package statesync + +import ( + ssproto "github.com/cometbft/cometbft/api/cometbft/statesync/v1" + "github.com/cometbft/cometbft/types" +) + +var ( + _ types.Wrapper = &ssproto.ChunkRequest{} + _ types.Wrapper = &ssproto.ChunkResponse{} + _ types.Wrapper = &ssproto.SnapshotsRequest{} + _ types.Wrapper = &ssproto.SnapshotsResponse{} +) diff --git a/internal/store/db_key_layout.go b/internal/store/db_key_layout.go new file mode 100644 index 00000000000..b26c75f87dc --- /dev/null +++ b/internal/store/db_key_layout.go @@ -0,0 +1,124 @@ +package store + +import ( + "fmt" + + "github.com/google/orderedcode" +) + +type BlockKeyLayout interface { + CalcBlockMetaKey(height int64) []byte + + CalcBlockPartKey(height int64, partIndex int) []byte + + CalcBlockCommitKey(height int64) []byte + + CalcSeenCommitKey(height int64) []byte + + CalcExtCommitKey(height int64) []byte + + CalcBlockHashKey(hash []byte) []byte +} + +type v1LegacyLayout struct{} + +// CalcBlockCommitKey implements BlockKeyLayout. +func (*v1LegacyLayout) CalcBlockCommitKey(height int64) []byte { + return []byte(fmt.Sprintf("C:%v", height)) +} + +// CalcBlockHashKey implements BlockKeyLayout. +func (*v1LegacyLayout) CalcBlockHashKey(hash []byte) []byte { + return []byte(fmt.Sprintf("BH:%x", hash)) +} + +// CalcBlockMetaKey implements BlockKeyLayout. +func (*v1LegacyLayout) CalcBlockMetaKey(height int64) []byte { + return []byte(fmt.Sprintf("H:%v", height)) +} + +// CalcBlockPartKey implements BlockKeyLayout. +func (*v1LegacyLayout) CalcBlockPartKey(height int64, partIndex int) []byte { + return []byte(fmt.Sprintf("P:%v:%v", height, partIndex)) +} + +// CalcExtCommitKey implements BlockKeyLayout. +func (*v1LegacyLayout) CalcExtCommitKey(height int64) []byte { + return []byte(fmt.Sprintf("EC:%v", height)) +} + +// CalcSeenCommitKey implements BlockKeyLayout. +func (*v1LegacyLayout) CalcSeenCommitKey(height int64) []byte { + return []byte(fmt.Sprintf("SC:%v", height)) +} + +var _ BlockKeyLayout = (*v1LegacyLayout)(nil) + +type v2Layout struct{} + +// key prefixes. +const ( + // prefixes are unique across all tm db's. + prefixBlockMeta = int64(0) + prefixBlockPart = int64(1) + prefixBlockCommit = int64(2) + prefixSeenCommit = int64(3) + prefixExtCommit = int64(4) + prefixBlockHash = int64(5) +) + +// CalcBlockCommitKey implements BlockKeyLayout. +func (*v2Layout) CalcBlockCommitKey(height int64) []byte { + key, err := orderedcode.Append(nil, prefixBlockCommit, height) + if err != nil { + panic(err) + } + return key +} + +// CalcBlockHashKey implements BlockKeyLayout. +func (*v2Layout) CalcBlockHashKey(hash []byte) []byte { + key, err := orderedcode.Append(nil, prefixBlockHash, string(hash)) + if err != nil { + panic(err) + } + return key +} + +// CalcBlockMetaKey implements BlockKeyLayout. +func (*v2Layout) CalcBlockMetaKey(height int64) []byte { + key, err := orderedcode.Append(nil, prefixBlockMeta, height) + if err != nil { + panic(err) + } + return key +} + +// CalcBlockPartKey implements BlockKeyLayout. +func (*v2Layout) CalcBlockPartKey(height int64, partIndex int) []byte { + key, err := orderedcode.Append(nil, prefixBlockPart, height, int64(partIndex)) + if err != nil { + panic(err) + } + return key +} + +// CalcExtCommitKey implements BlockKeyLayout. +func (*v2Layout) CalcExtCommitKey(height int64) []byte { + key, err := orderedcode.Append(nil, prefixExtCommit, height) + if err != nil { + panic(err) + } + return key +} + +// CalcSeenCommitKey implements BlockKeyLayout. +func (*v2Layout) CalcSeenCommitKey(height int64) []byte { + key, err := orderedcode.Append(nil, prefixSeenCommit, height) + if err != nil { + panic(err) + } + return key +} + +var _ BlockKeyLayout = (*v2Layout)(nil) diff --git a/internal/store/metrics.gen.go b/internal/store/metrics.gen.go new file mode 100644 index 00000000000..9eb5e306d35 --- /dev/null +++ b/internal/store/metrics.gen.go @@ -0,0 +1,32 @@ +// Code generated by metricsgen. DO NOT EDIT. + +package store + +import ( + "github.com/go-kit/kit/metrics/discard" + prometheus "github.com/go-kit/kit/metrics/prometheus" + stdprometheus "github.com/prometheus/client_golang/prometheus" +) + +func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { + labels := []string{} + for i := 0; i < len(labelsAndValues); i += 2 { + labels = append(labels, labelsAndValues[i]) + } + return &Metrics{ + BlockStoreAccessDurationSeconds: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_store_access_duration_seconds", + Help: "The duration of accesses to the state store labeled by which method was called on the store.", + + Buckets: stdprometheus.ExponentialBuckets(0.0002, 10, 5), + }, append(labels, "method")).With(labelsAndValues...), + } +} + +func NopMetrics() *Metrics { + return &Metrics{ + BlockStoreAccessDurationSeconds: discard.NewHistogram(), + } +} diff --git a/internal/store/metrics.go b/internal/store/metrics.go new file mode 100644 index 00000000000..bac0b9e2aaa --- /dev/null +++ b/internal/store/metrics.go @@ -0,0 +1,20 @@ +package store + +import ( + "github.com/go-kit/kit/metrics" +) + +const ( + // MetricsSubsystem is a subsystem shared by all metrics exposed by this + // package. + MetricsSubsystem = "store" +) + +//go:generate go run ../../scripts/metricsgen -struct=Metrics + +// Metrics contains metrics exposed by this package. +type Metrics struct { + // The duration of accesses to the state store labeled by which method + // was called on the store. + BlockStoreAccessDurationSeconds metrics.Histogram `metrics_bucketsizes:"0.0002, 10, 5" metrics_buckettype:"exp" metrics_labels:"method"` +} diff --git a/store/store.go b/internal/store/store.go similarity index 55% rename from store/store.go rename to internal/store/store.go index a82f947609d..088074b0607 100644 --- a/store/store.go +++ b/internal/store/store.go @@ -4,19 +4,27 @@ import ( "errors" "fmt" "strconv" + "time" "github.com/cosmos/gogoproto/proto" + "github.com/go-kit/kit/metrics" dbm "github.com/cometbft/cometbft-db" - - "github.com/cometbft/cometbft/evidence" - cmtsync "github.com/cometbft/cometbft/libs/sync" - cmtstore "github.com/cometbft/cometbft/proto/tendermint/store" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - sm "github.com/cometbft/cometbft/state" + cmtstore "github.com/cometbft/cometbft/api/cometbft/store/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/internal/evidence" + sm "github.com/cometbft/cometbft/internal/state" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" ) +// Assuming the length of a block part is 64kB (`types.BlockPartSizeBytes`), +// the maximum size of a block, that will be batch saved, is 640kB. The +// benchmarks have shown that `goleveldb` still performs well with blocks of +// this size. However, if the block is larger than 1MB, the performance degrades. +const maxBlockPartsToBatch = 10 + /* BlockStore is a simple low level store for blocks. @@ -35,27 +43,116 @@ The store can be assumed to contain all contiguous blocks between base and heigh // deserializing loaded data, indicating probable corruption on disk. */ type BlockStore struct { - db dbm.DB - - // mtx guards access to the struct fields listed below it. We rely on the database to enforce - // fine-grained concurrency control for its data, and thus this mutex does not apply to - // database contents. The only reason for keeping these fields in the struct is that the data + db dbm.DB + metrics *Metrics + + // mtx guards access to the struct fields listed below it. Although we rely on the database + // to enforce fine-grained concurrency control for its data, we need to make sure that + // no external observer can get data from the database that is not in sync with the fields below, + // and vice-versa. Hence, when updating the fields below, we use the mutex to make sure + // that the database is also up to date. This prevents any concurrent external access from + // obtaining inconsistent data. + // The only reason for keeping these fields in the struct is that the data // can't efficiently be queried from the database since the key encoding we use is not // lexicographically ordered (see https://github.com/tendermint/tendermint/issues/4567). mtx cmtsync.RWMutex base int64 height int64 + + dbKeyLayout BlockKeyLayout + + blocksDeleted int64 + compact bool + compactionInterval int64 +} + +type BlockStoreOption func(*BlockStore) + +// WithCompaction sets the compaciton parameters. +func WithCompaction(compact bool, compactionInterval int64) BlockStoreOption { + return func(bs *BlockStore) { + bs.compact = compact + bs.compactionInterval = compactionInterval + } +} + +// WithMetrics sets the metrics. +func WithMetrics(metrics *Metrics) BlockStoreOption { + return func(bs *BlockStore) { bs.metrics = metrics } +} + +// WithDBKeyLayout the metrics. +func WithDBKeyLayout(dbKeyLayout string) BlockStoreOption { + return func(bs *BlockStore) { setDBLayout(bs, dbKeyLayout) } +} + +func setDBLayout(bStore *BlockStore, dbKeyLayoutVersion string) { + if !bStore.IsEmpty() { + var version []byte + var err error + if version, err = bStore.db.Get([]byte("version")); err != nil { + // WARN: This is because currently cometBFT DB does not return an error if the key does not exist + // If this behavior changes we need to account for that. + panic(err) + } + if len(version) != 0 { + dbKeyLayoutVersion = string(version) + } + } + switch dbKeyLayoutVersion { + case "v1", "": + bStore.dbKeyLayout = &v1LegacyLayout{} + dbKeyLayoutVersion = "v1" + case "v2": + bStore.dbKeyLayout = &v2Layout{} + default: + panic("unknown key layout version") + } + if err := bStore.db.SetSync([]byte("version"), []byte(dbKeyLayoutVersion)); err != nil { + panic(err) + } } // NewBlockStore returns a new BlockStore with the given DB, // initialized to the last height that was committed to the DB. -func NewBlockStore(db dbm.DB) *BlockStore { +func NewBlockStore(db dbm.DB, options ...BlockStoreOption) *BlockStore { + start := time.Now() + bs := LoadBlockStoreState(db) - return &BlockStore{ - base: bs.Base, - height: bs.Height, - db: db, + + bStore := &BlockStore{ + base: bs.Base, + height: bs.Height, + db: db, + metrics: NopMetrics(), + } + + for _, option := range options { + option(bStore) + } + + if bStore.dbKeyLayout == nil { + setDBLayout(bStore, "v1") } + + addTimeSample(bStore.metrics.BlockStoreAccessDurationSeconds.With("method", "new_block_store"), start)() + return bStore +} + +func (bs *BlockStore) GetVersion() string { + switch bs.dbKeyLayout.(type) { + case *v1LegacyLayout: + return "v1" + case *v2Layout: + return "v2" + } + return "no version set" +} + +func (bs *BlockStore) IsEmpty() bool { + bs.mtx.RLock() + defer bs.mtx.RUnlock() + return bs.base == 0 && bs.height == 0 } // Base returns the first known contiguous block height, or 0 for empty block stores. @@ -94,12 +191,12 @@ func (bs *BlockStore) LoadBaseMeta() *types.BlockMeta { // LoadBlock returns the block with the given height. // If no block is found for that height, it returns nil. -func (bs *BlockStore) LoadBlock(height int64) *types.Block { +func (bs *BlockStore) LoadBlock(height int64) (*types.Block, *types.BlockMeta) { + start := time.Now() blockMeta := bs.LoadBlockMeta(height) if blockMeta == nil { - return nil + return nil, nil } - pbb := new(cmtproto.Block) buf := []byte{} for i := 0; i < int(blockMeta.BlockID.PartSetHeader.Total); i++ { @@ -107,35 +204,39 @@ func (bs *BlockStore) LoadBlock(height int64) *types.Block { // If the part is missing (e.g. since it has been deleted after we // loaded the block meta) we consider the whole block to be missing. if part == nil { - return nil + return nil, nil } buf = append(buf, part.Bytes...) } + addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "load_block"), start)() + err := proto.Unmarshal(buf, pbb) if err != nil { // NOTE: The existence of meta should imply the existence of the // block. So, make sure meta is only saved after blocks are saved. panic(fmt.Sprintf("Error reading block: %v", err)) } - block, err := types.BlockFromProto(pbb) if err != nil { - panic(fmt.Errorf("error from proto block: %w", err)) + panic(cmterrors.ErrMsgFromProto{MessageName: "Block", Err: err}) } - return block + return block, blockMeta } // LoadBlockByHash returns the block with the given hash. // If no block is found for that hash, it returns nil. // Panics if it fails to parse height associated with the given hash. -func (bs *BlockStore) LoadBlockByHash(hash []byte) *types.Block { - bz, err := bs.db.Get(calcBlockHashKey(hash)) +func (bs *BlockStore) LoadBlockByHash(hash []byte) (*types.Block, *types.BlockMeta) { + // WARN this function includes the time for LoadBlock and will count the time it takes to load the entire block, block parts + // AND unmarshall + defer addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "load_block_by_hash"), time.Now())() + bz, err := bs.db.Get(bs.dbKeyLayout.CalcBlockHashKey(hash)) if err != nil { panic(err) } if len(bz) == 0 { - return nil + return nil, nil } s := string(bz) @@ -151,15 +252,17 @@ func (bs *BlockStore) LoadBlockByHash(hash []byte) *types.Block { // If no part is found for the given height and index, it returns nil. func (bs *BlockStore) LoadBlockPart(height int64, index int) *types.Part { pbpart := new(cmtproto.Part) - - bz, err := bs.db.Get(calcBlockPartKey(height, index)) + start := time.Now() + bz, err := bs.db.Get(bs.dbKeyLayout.CalcBlockPartKey(height, index)) if err != nil { panic(err) } + + addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "load_block_part"), start)() + if len(bz) == 0 { return nil } - err = proto.Unmarshal(bz, pbpart) if err != nil { panic(fmt.Errorf("unmarshal to cmtproto.Part failed: %w", err)) @@ -176,11 +279,14 @@ func (bs *BlockStore) LoadBlockPart(height int64, index int) *types.Part { // If no block is found for the given height, it returns nil. func (bs *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta { pbbm := new(cmtproto.BlockMeta) - bz, err := bs.db.Get(calcBlockMetaKey(height)) + start := time.Now() + bz, err := bs.db.Get(bs.dbKeyLayout.CalcBlockMetaKey(height)) if err != nil { panic(err) } + addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "load_block_meta"), start)() + if len(bz) == 0 { return nil } @@ -189,10 +295,9 @@ func (bs *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta { if err != nil { panic(fmt.Errorf("unmarshal to cmtproto.BlockMeta: %w", err)) } - blockMeta, err := types.BlockMetaFromProto(pbbm) if err != nil { - panic(fmt.Errorf("error from proto blockMeta: %w", err)) + panic(cmterrors.ErrMsgFromProto{MessageName: "BlockMetadata", Err: err}) } return blockMeta @@ -201,7 +306,9 @@ func (bs *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta { // LoadBlockMetaByHash returns the blockmeta who's header corresponds to the given // hash. If none is found, returns nil. func (bs *BlockStore) LoadBlockMetaByHash(hash []byte) *types.BlockMeta { - bz, err := bs.db.Get(calcBlockHashKey(hash)) + // WARN Same as for block by hash, this includes the time to get the block metadata and unmarshall it + defer addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "load_block_meta_by_hash"), time.Now())() + bz, err := bs.db.Get(bs.dbKeyLayout.CalcBlockHashKey(hash)) if err != nil { panic(err) } @@ -223,20 +330,26 @@ func (bs *BlockStore) LoadBlockMetaByHash(hash []byte) *types.BlockMeta { // If no commit is found for the given height, it returns nil. func (bs *BlockStore) LoadBlockCommit(height int64) *types.Commit { pbc := new(cmtproto.Commit) - bz, err := bs.db.Get(calcBlockCommitKey(height)) + + start := time.Now() + bz, err := bs.db.Get(bs.dbKeyLayout.CalcBlockCommitKey(height)) if err != nil { panic(err) } + + addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "load_block_commit"), start)() + if len(bz) == 0 { return nil } + err = proto.Unmarshal(bz, pbc) if err != nil { panic(fmt.Errorf("error reading block commit: %w", err)) } commit, err := types.CommitFromProto(pbc) if err != nil { - panic(fmt.Errorf("converting commit to proto: %w", err)) + panic(cmterrors.ErrMsgToProto{MessageName: "Commit", Err: err}) } return commit } @@ -246,13 +359,19 @@ func (bs *BlockStore) LoadBlockCommit(height int64) *types.Commit { // as the commit in the block. func (bs *BlockStore) LoadBlockExtendedCommit(height int64) *types.ExtendedCommit { pbec := new(cmtproto.ExtendedCommit) - bz, err := bs.db.Get(calcExtCommitKey(height)) + + start := time.Now() + bz, err := bs.db.Get(bs.dbKeyLayout.CalcExtCommitKey(height)) if err != nil { panic(fmt.Errorf("fetching extended commit: %w", err)) } + + addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "load_block_ext_commit"), start)() + if len(bz) == 0 { return nil } + err = proto.Unmarshal(bz, pbec) if err != nil { panic(fmt.Errorf("decoding extended commit: %w", err)) @@ -269,13 +388,18 @@ func (bs *BlockStore) LoadBlockExtendedCommit(height int64) *types.ExtendedCommi // a new block at `height + 1` that includes this commit in its block.LastCommit. func (bs *BlockStore) LoadSeenCommit(height int64) *types.Commit { pbc := new(cmtproto.Commit) - bz, err := bs.db.Get(calcSeenCommitKey(height)) + start := time.Now() + bz, err := bs.db.Get(bs.dbKeyLayout.CalcSeenCommitKey(height)) if err != nil { panic(err) } + + addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "load_seen_commit"), start)() + if len(bz) == 0 { return nil } + err = proto.Unmarshal(bz, pbc) if err != nil { panic(fmt.Sprintf("error reading block seen commit: %v", err)) @@ -288,10 +412,12 @@ func (bs *BlockStore) LoadSeenCommit(height int64) *types.Commit { return commit } -// PruneBlocks removes block up to (but not including) a height. It returns number of blocks pruned and the evidence retain height - the height at which data needed to prove evidence must not be removed. +// PruneBlocks removes block up to (but not including) a height. It returns the +// number of blocks pruned and the evidence retain height - the height at which +// data needed to prove evidence must not be removed. func (bs *BlockStore) PruneBlocks(height int64, state sm.State) (uint64, int64, error) { if height <= 0 { - return 0, -1, fmt.Errorf("height must be greater than 0") + return 0, -1, errors.New("height must be greater than 0") } bs.mtx.RLock() if height > bs.height { @@ -309,24 +435,19 @@ func (bs *BlockStore) PruneBlocks(height int64, state sm.State) (uint64, int64, batch := bs.db.NewBatch() defer batch.Close() flush := func(batch dbm.Batch, base int64) error { - // We can't trust batches to be atomic, so update base first to make sure noone + // We can't trust batches to be atomic, so update base first to make sure no one // tries to access missing blocks. bs.mtx.Lock() + defer batch.Close() + defer bs.mtx.Unlock() bs.base = base - bs.mtx.Unlock() - bs.saveState() - - err := batch.WriteSync() - if err != nil { - return fmt.Errorf("failed to prune up to height %v: %w", base, err) - } - batch.Close() - return nil + return bs.saveStateAndWriteDB(batch, "failed to prune") } + defer addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "prune_blocks"), time.Now())() + evidencePoint := height for h := base; h < height; h++ { - meta := bs.LoadBlockMeta(h) if meta == nil { // assume already deleted continue @@ -341,24 +462,24 @@ func (bs *BlockStore) PruneBlocks(height int64, state sm.State) (uint64, int64, // if height is beyond the evidence point we dont delete the header if h < evidencePoint { - if err := batch.Delete(calcBlockMetaKey(h)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcBlockMetaKey(h)); err != nil { return 0, -1, err } } - if err := batch.Delete(calcBlockHashKey(meta.BlockID.Hash)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcBlockHashKey(meta.BlockID.Hash)); err != nil { return 0, -1, err } // if height is beyond the evidence point we dont delete the commit data if h < evidencePoint { - if err := batch.Delete(calcBlockCommitKey(h)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcBlockCommitKey(h)); err != nil { return 0, -1, err } } - if err := batch.Delete(calcSeenCommitKey(h)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcSeenCommitKey(h)); err != nil { return 0, -1, err } for p := 0; p < int(meta.BlockID.PartSetHeader.Total); p++ { - if err := batch.Delete(calcBlockPartKey(h, p)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcBlockPartKey(h, p)); err != nil { return 0, -1, err } } @@ -379,7 +500,21 @@ func (bs *BlockStore) PruneBlocks(height int64, state sm.State) (uint64, int64, if err != nil { return 0, -1, err } - return pruned, evidencePoint, nil + bs.blocksDeleted += int64(pruned) + + if bs.compact && bs.blocksDeleted >= bs.compactionInterval { + // When the range is nil,nil, the database will try to compact + // ALL levels. Another option is to set a predefined range of + // specific keys. + err = bs.db.Compact(nil, nil) + if err == nil { + // If there was no error in compaction we reset the counter. + // Otherwise we preserve the number of blocks deleted so + // we can trigger compaction in the next pruning iteration + bs.blocksDeleted = 0 + } + } + return pruned, evidencePoint, err } // SaveBlock persists the given block, blockParts, and seenCommit to the underlying db. @@ -390,15 +525,30 @@ func (bs *BlockStore) PruneBlocks(height int64, state sm.State) (uint64, int64, // we need this to reload the precommits to catch-up nodes to the // most recent height. Otherwise they'd stall at H-1. func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenCommit *types.Commit) { + defer addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "save_block"), time.Now())() if block == nil { panic("BlockStore can only save a non-nil block") } - if err := bs.saveBlockToBatch(block, blockParts, seenCommit); err != nil { + + batch := bs.db.NewBatch() + defer batch.Close() + + if err := bs.saveBlockToBatch(block, blockParts, seenCommit, batch); err != nil { panic(err) } + bs.mtx.Lock() + defer bs.mtx.Unlock() + bs.height = block.Height + if bs.base == 0 { + bs.base = block.Height + } + // Save new BlockStoreState descriptor. This also flushes the database. - bs.saveState() + err := bs.saveStateAndWriteDB(batch, "failed to save block") + if err != nil { + panic(err) + } } // SaveBlockWithExtendedCommit persists the given block, blockParts, and @@ -407,28 +557,58 @@ func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, s // height. This allows the vote extension data to be persisted for all blocks // that are saved. func (bs *BlockStore) SaveBlockWithExtendedCommit(block *types.Block, blockParts *types.PartSet, seenExtendedCommit *types.ExtendedCommit) { + // WARN includes marshaling the blockstore state + start := time.Now() + if block == nil { panic("BlockStore can only save a non-nil block") } if err := seenExtendedCommit.EnsureExtensions(true); err != nil { panic(fmt.Errorf("problems saving block with extensions: %w", err)) } - if err := bs.saveBlockToBatch(block, blockParts, seenExtendedCommit.ToCommit()); err != nil { + + batch := bs.db.NewBatch() + defer batch.Close() + + if err := bs.saveBlockToBatch(block, blockParts, seenExtendedCommit.ToCommit(), batch); err != nil { panic(err) } height := block.Height + marshallingTime := time.Now() + pbec := seenExtendedCommit.ToProto() + extCommitBytes := mustEncode(pbec) - if err := bs.db.Set(calcExtCommitKey(height), extCommitBytes); err != nil { + + extCommitMarshallTDiff := time.Since(marshallingTime).Seconds() + + if err := batch.Set(bs.dbKeyLayout.CalcExtCommitKey(height), extCommitBytes); err != nil { panic(err) } + bs.mtx.Lock() + defer bs.mtx.Unlock() + bs.height = height + if bs.base == 0 { + bs.base = height + } + // Save new BlockStoreState descriptor. This also flushes the database. - bs.saveState() + err := bs.saveStateAndWriteDB(batch, "failed to save block with extended commit") + if err != nil { + panic(err) + } + + bs.metrics.BlockStoreAccessDurationSeconds.With("method", "save_block_ext_commit").Observe(time.Since(start).Seconds() - extCommitMarshallTDiff) } -func (bs *BlockStore) saveBlockToBatch(block *types.Block, blockParts *types.PartSet, seenCommit *types.Commit) error { +func (bs *BlockStore) saveBlockToBatch( + block *types.Block, + blockParts *types.PartSet, + seenCommit *types.Commit, + batch dbm.Batch, +) error { if block == nil { panic("BlockStore can only save a non-nil block") } @@ -446,15 +626,22 @@ func (bs *BlockStore) saveBlockToBatch(block *types.Block, blockParts *types.Par return fmt.Errorf("BlockStore cannot save seen commit of a different height (block: %d, commit: %d)", height, seenCommit.Height) } + // If the block is small, batch save the block parts. Otherwise, save the + // parts individually. + saveBlockPartsToBatch := blockParts.Count() <= maxBlockPartsToBatch + + start := time.Now() + // Save block parts. This must be done before the block meta, since callers // typically load the block meta first as an indication that the block exists // and then go on to load block parts - we must make sure the block is // complete as soon as the block meta is written. for i := 0; i < int(blockParts.Total()); i++ { part := blockParts.GetPart(i) - bs.saveBlockPart(height, i, part) + bs.saveBlockPart(height, i, part, batch, saveBlockPartsToBatch) } + marshallTime := time.Now() // Save block meta blockMeta := types.NewBlockMeta(block, blockParts) pbm := blockMeta.ToProto() @@ -462,111 +649,109 @@ func (bs *BlockStore) saveBlockToBatch(block *types.Block, blockParts *types.Par return errors.New("nil blockmeta") } metaBytes := mustEncode(pbm) - if err := bs.db.Set(calcBlockMetaKey(height), metaBytes); err != nil { + blockMetaMarshallDiff := time.Since(marshallTime).Seconds() + + if err := batch.Set(bs.dbKeyLayout.CalcBlockMetaKey(height), metaBytes); err != nil { return err } - if err := bs.db.Set(calcBlockHashKey(hash), []byte(fmt.Sprintf("%d", height))); err != nil { + if err := batch.Set(bs.dbKeyLayout.CalcBlockHashKey(hash), []byte(strconv.FormatInt(height, 10))); err != nil { return err } + marshallTime = time.Now() // Save block commit (duplicate and separate from the Block) pbc := block.LastCommit.ToProto() blockCommitBytes := mustEncode(pbc) - if err := bs.db.Set(calcBlockCommitKey(height-1), blockCommitBytes); err != nil { + + blockMetaMarshallDiff += time.Since(marshallTime).Seconds() + + if err := batch.Set(bs.dbKeyLayout.CalcBlockCommitKey(height-1), blockCommitBytes); err != nil { return err } + marshallTime = time.Now() + // Save seen commit (seen +2/3 precommits for block) // NOTE: we can delete this at a later height pbsc := seenCommit.ToProto() seenCommitBytes := mustEncode(pbsc) - if err := bs.db.Set(calcSeenCommitKey(height), seenCommitBytes); err != nil { - return err - } - // Done! - bs.mtx.Lock() - bs.height = height - if bs.base == 0 { - bs.base = height + blockMetaMarshallDiff += time.Since(marshallTime).Seconds() + if err := batch.Set(bs.dbKeyLayout.CalcSeenCommitKey(height), seenCommitBytes); err != nil { + return err } - bs.mtx.Unlock() + bs.metrics.BlockStoreAccessDurationSeconds.With("method", "save_block_to_batch").Observe(time.Since(start).Seconds() - blockMetaMarshallDiff) return nil } -func (bs *BlockStore) saveBlockPart(height int64, index int, part *types.Part) { +func (bs *BlockStore) saveBlockPart(height int64, index int, part *types.Part, batch dbm.Batch, saveBlockPartsToBatch bool) { + defer addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "save_block_part"), time.Now())() pbp, err := part.ToProto() if err != nil { - panic(fmt.Errorf("unable to make part into proto: %w", err)) + panic(cmterrors.ErrMsgToProto{MessageName: "Part", Err: err}) } + partBytes := mustEncode(pbp) - if err := bs.db.Set(calcBlockPartKey(height, index), partBytes); err != nil { + + if saveBlockPartsToBatch { + err = batch.Set(bs.dbKeyLayout.CalcBlockPartKey(height, index), partBytes) + } else { + err = bs.db.Set(bs.dbKeyLayout.CalcBlockPartKey(height, index), partBytes) + } + if err != nil { panic(err) } } -func (bs *BlockStore) saveState() { - bs.mtx.RLock() +// Contract: the caller MUST have, at least, a read lock on `bs`. +func (bs *BlockStore) saveStateAndWriteDB(batch dbm.Batch, errMsg string) error { bss := cmtstore.BlockStoreState{ Base: bs.base, Height: bs.height, } - bs.mtx.RUnlock() - SaveBlockStoreState(&bss, bs.db) + start := time.Now() + + SaveBlockStoreState(&bss, batch) + + err := batch.WriteSync() + if err != nil { + return fmt.Errorf("error writing batch to DB %q: (base %d, height %d): %w", + errMsg, bs.base, bs.height, err) + } + defer addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "save_bs_state"), start)() + + return nil } // SaveSeenCommit saves a seen commit, used by e.g. the state sync reactor when bootstrapping node. func (bs *BlockStore) SaveSeenCommit(height int64, seenCommit *types.Commit) error { pbc := seenCommit.ToProto() seenCommitBytes, err := proto.Marshal(pbc) + + defer addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "save_seen_commit"), time.Now())() + if err != nil { return fmt.Errorf("unable to marshal commit: %w", err) } - return bs.db.Set(calcSeenCommitKey(height), seenCommitBytes) + return bs.db.Set(bs.dbKeyLayout.CalcSeenCommitKey(height), seenCommitBytes) } func (bs *BlockStore) Close() error { return bs.db.Close() } -//----------------------------------------------------------------------------- - -func calcBlockMetaKey(height int64) []byte { - return []byte(fmt.Sprintf("H:%v", height)) -} - -func calcBlockPartKey(height int64, partIndex int) []byte { - return []byte(fmt.Sprintf("P:%v:%v", height, partIndex)) -} - -func calcBlockCommitKey(height int64) []byte { - return []byte(fmt.Sprintf("C:%v", height)) -} - -func calcSeenCommitKey(height int64) []byte { - return []byte(fmt.Sprintf("SC:%v", height)) -} - -func calcExtCommitKey(height int64) []byte { - return []byte(fmt.Sprintf("EC:%v", height)) -} - -func calcBlockHashKey(hash []byte) []byte { - return []byte(fmt.Sprintf("BH:%x", hash)) -} - -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- var blockStoreKey = []byte("blockStore") // SaveBlockStoreState persists the blockStore state to the database. -func SaveBlockStoreState(bsj *cmtstore.BlockStoreState, db dbm.DB) { +func SaveBlockStoreState(bsj *cmtstore.BlockStoreState, batch dbm.Batch) { bytes, err := proto.Marshal(bsj) if err != nil { panic(fmt.Sprintf("Could not marshal state bytes: %v", err)) } - if err := db.SetSync(blockStoreKey, bytes); err != nil { + if err := batch.Set(blockStoreKey, bytes); err != nil { panic(err) } } @@ -598,7 +783,7 @@ func LoadBlockStoreState(db dbm.DB) cmtstore.BlockStoreState { return bsj } -// mustEncode proto encodes a proto.message and panics if fails +// mustEncode proto encodes a proto.message and panics if fails. func mustEncode(pb proto.Message) []byte { bz, err := proto.Marshal(pb) if err != nil { @@ -607,11 +792,13 @@ func mustEncode(pb proto.Message) []byte { return bz } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // DeleteLatestBlock removes the block pointed to by height, // lowering height by one. func (bs *BlockStore) DeleteLatestBlock() error { + defer addTimeSample(bs.metrics.BlockStoreAccessDurationSeconds.With("method", "delete_latest_block"), time.Now())() + bs.mtx.RLock() targetHeight := bs.height bs.mtx.RUnlock() @@ -622,34 +809,38 @@ func (bs *BlockStore) DeleteLatestBlock() error { // delete what we can, skipping what's already missing, to ensure partial // blocks get deleted fully. if meta := bs.LoadBlockMeta(targetHeight); meta != nil { - if err := batch.Delete(calcBlockHashKey(meta.BlockID.Hash)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcBlockHashKey(meta.BlockID.Hash)); err != nil { return err } for p := 0; p < int(meta.BlockID.PartSetHeader.Total); p++ { - if err := batch.Delete(calcBlockPartKey(targetHeight, p)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcBlockPartKey(targetHeight, p)); err != nil { return err } } } - if err := batch.Delete(calcBlockCommitKey(targetHeight)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcBlockCommitKey(targetHeight)); err != nil { return err } - if err := batch.Delete(calcSeenCommitKey(targetHeight)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcSeenCommitKey(targetHeight)); err != nil { return err } // delete last, so as to not leave keys built on meta.BlockID dangling - if err := batch.Delete(calcBlockMetaKey(targetHeight)); err != nil { + if err := batch.Delete(bs.dbKeyLayout.CalcBlockMetaKey(targetHeight)); err != nil { return err } bs.mtx.Lock() + defer bs.mtx.Unlock() bs.height = targetHeight - 1 - bs.mtx.Unlock() - bs.saveState() + return bs.saveStateAndWriteDB(batch, "failed to delete the latest block") +} - err := batch.WriteSync() - if err != nil { - return fmt.Errorf("failed to delete height %v: %w", targetHeight, err) +// addTimeSample returns a function that, when called, adds an observation to m. +// The observation added to m is the number of seconds elapsed since addTimeSample +// was initially called. addTimeSample is meant to be called in a defer to calculate +// the amount of time a function takes to complete. +func addTimeSample(h metrics.Histogram, start time.Time) func() { + return func() { + h.Observe(time.Since(start).Seconds()) } - return nil } diff --git a/store/store_test.go b/internal/store/store_test.go similarity index 62% rename from store/store_test.go rename to internal/store/store_test.go index ca56a7bd036..ffb372e524d 100644 --- a/store/store_test.go +++ b/internal/store/store_test.go @@ -1,7 +1,7 @@ package store import ( - "bytes" + "encoding/json" "fmt" "os" "runtime/debug" @@ -14,25 +14,25 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - + cmtstore "github.com/cometbft/cometbft/api/cometbft/store/v1" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" + cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto" + "github.com/cometbft/cometbft/crypto/ed25519" + cmtrand "github.com/cometbft/cometbft/internal/rand" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/indexer/block" + "github.com/cometbft/cometbft/internal/state/txindex" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtstore "github.com/cometbft/cometbft/proto/tendermint/store" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" - sm "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) -// A cleanupFunc cleans up any config / test files created for a particular -// test. -type cleanupFunc func() - // make an extended commit with a single vote containing just the height and a -// timestamp +// timestamp. func makeTestExtCommit(height int64, timestamp time.Time) *types.ExtendedCommit { extCommitSigs := []types.ExtendedCommitSig{{ CommitSig: types.CommitSig{ @@ -53,20 +53,24 @@ func makeTestExtCommit(height int64, timestamp time.Time) *types.ExtendedCommit } } -func makeStateAndBlockStore(logger log.Logger) (sm.State, *BlockStore, cleanupFunc) { +func makeStateAndBlockStoreAndIndexers() (sm.State, *BlockStore, txindex.TxIndexer, indexer.BlockIndexer, func(), sm.Store) { config := test.ResetTestRoot("blockchain_reactor_test") - // blockDB := dbm.NewDebugDB("blockDB", dbm.NewMemDB()) - // stateDB := dbm.NewDebugDB("stateDB", dbm.NewMemDB()) blockDB := dbm.NewMemDB() stateDB := dbm.NewMemDB() stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) - state, err := stateStore.LoadFromDBOrGenesisFile(config.GenesisFile()) + state, err := sm.MakeGenesisStateFromFile(config.GenesisFile()) if err != nil { panic(fmt.Errorf("error constructing state from genesis file: %w", err)) } - return state, NewBlockStore(blockDB), func() { os.RemoveAll(config.RootDir) } + + txIndexer, blockIndexer, err := block.IndexerFromConfig(config, cfg.DefaultDBProvider, "test") + if err != nil { + panic(err) + } + + return state, NewBlockStore(blockDB), txIndexer, blockIndexer, func() { os.RemoveAll(config.RootDir) }, stateStore } func TestLoadBlockStoreState(t *testing.T) { @@ -87,9 +91,14 @@ func TestLoadBlockStoreState(t *testing.T) { for _, tc := range testCases { db := dbm.NewMemDB() - SaveBlockStoreState(tc.bss, db) + batch := db.NewBatch() + SaveBlockStoreState(tc.bss, batch) + err := batch.WriteSync() + require.NoError(t, err) retrBSJ := LoadBlockStoreState(db) assert.Equal(t, tc.want, retrBSJ, "expected the retrieved DBs to match: %s", tc.testName) + err = batch.Close() + require.NoError(t, err) } } @@ -114,20 +123,20 @@ func TestNewBlockStore(t *testing.T) { for i, tt := range panicCausers { tt := tt // Expecting a panic here on trying to parse an invalid blockStore - _, _, panicErr := doFn(func() (interface{}, error) { + _, _, panicErr := doFn(func() (any, error) { err := db.Set(blockStoreKey, tt.data) require.NoError(t, err) _ = NewBlockStore(db) return nil, nil }) - require.NotNil(t, panicErr, "#%d panicCauser: %q expected a panic", i, tt.data) + require.Error(t, panicErr, "#%d panicCauser: %q expected a panic", i, tt.data) assert.Contains(t, fmt.Sprintf("%#v", panicErr), tt.wantErr, "#%d data: %q", i, tt.data) } err = db.Set(blockStoreKey, []byte{}) require.NoError(t, err) bs = NewBlockStore(db) - assert.Equal(t, bs.Height(), int64(0), "expecting empty bytes to be unmarshaled alright") + assert.Equal(t, int64(0), bs.Height(), "expecting empty bytes to be unmarshaled alright") } func newInMemoryBlockStore() (*BlockStore, dbm.DB) { @@ -138,23 +147,25 @@ func newInMemoryBlockStore() (*BlockStore, dbm.DB) { // TODO: This test should be simplified ... func TestBlockStoreSaveLoadBlock(t *testing.T) { - state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) + state, bs, _, _, cleanup, _ := makeStateAndBlockStoreAndIndexers() defer cleanup() - require.Equal(t, bs.Base(), int64(0), "initially the base should be zero") - require.Equal(t, bs.Height(), int64(0), "initially the height should be zero") + require.Equal(t, int64(0), bs.Base(), "initially the base should be zero") + require.Equal(t, int64(0), bs.Height(), "initially the height should be zero") // check there are no blocks at various heights noBlockHeights := []int64{0, -1, 100, 1000, 2} for i, height := range noBlockHeights { - if g := bs.LoadBlock(height); g != nil { + if g, _ := bs.LoadBlock(height); g != nil { t.Errorf("#%d: height(%d) got a block; want nil", i, height) } } - // save a block - block := state.MakeBlock(bs.Height()+1, nil, new(types.Commit), nil, state.Validators.GetProposer().Address) - validPartSet, err := block.MakePartSet(2) + // save a block big enough to have two block parts + txs := []types.Tx{make([]byte, types.BlockPartSizeBytes)} // TX taking one block part alone + block := state.MakeBlock(bs.Height()+1, txs, new(types.Commit), nil, state.Validators.GetProposer().Address) + validPartSet, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) + require.GreaterOrEqual(t, validPartSet.Total(), uint32(2)) part2 := validPartSet.GetPart(1) seenCommit := makeTestExtCommit(block.Header.Height, cmttime.Now()) @@ -209,7 +220,8 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { Height: 5, ChainID: "block_test", Time: cmttime.Now(), - ProposerAddress: cmtrand.Bytes(crypto.AddressSize)}, + ProposerAddress: cmtrand.Bytes(crypto.AddressSize), + }, makeTestExtCommit(5, cmttime.Now()).ToCommit(), ), parts: validPartSet, @@ -279,36 +291,35 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { tuple := tuple bs, db := newInMemoryBlockStore() // SaveBlock - res, err, panicErr := doFn(func() (interface{}, error) { + res, err, panicErr := doFn(func() (any, error) { bs.SaveBlockWithExtendedCommit(tuple.block, tuple.parts, tuple.seenCommit) if tuple.block == nil { return nil, nil } if tuple.corruptBlockInDB { - err := db.Set(calcBlockMetaKey(tuple.block.Height), []byte("block-bogus")) + err := db.Set(bs.dbKeyLayout.CalcBlockMetaKey(tuple.block.Height), []byte("block-bogus")) require.NoError(t, err) } - bBlock := bs.LoadBlock(tuple.block.Height) - bBlockMeta := bs.LoadBlockMeta(tuple.block.Height) + bBlock, bBlockMeta := bs.LoadBlock(tuple.block.Height) if tuple.eraseSeenCommitInDB { - err := db.Delete(calcSeenCommitKey(tuple.block.Height)) + err := db.Delete(bs.dbKeyLayout.CalcSeenCommitKey(tuple.block.Height)) require.NoError(t, err) } if tuple.corruptSeenCommitInDB { - err := db.Set(calcSeenCommitKey(tuple.block.Height), []byte("bogus-seen-commit")) + err := db.Set(bs.dbKeyLayout.CalcSeenCommitKey(tuple.block.Height), []byte("bogus-seen-commit")) require.NoError(t, err) } bSeenCommit := bs.LoadSeenCommit(tuple.block.Height) commitHeight := tuple.block.Height - 1 if tuple.eraseCommitInDB { - err := db.Delete(calcBlockCommitKey(commitHeight)) + err := db.Delete(bs.dbKeyLayout.CalcBlockCommitKey(commitHeight)) require.NoError(t, err) } if tuple.corruptCommitInDB { - err := db.Set(calcBlockCommitKey(commitHeight), []byte("foo-bogus")) + err := db.Set(bs.dbKeyLayout.CalcBlockCommitKey(commitHeight), []byte("foo-bogus")) require.NoError(t, err) } bCommit := bs.LoadBlockCommit(commitHeight) @@ -334,8 +345,8 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { continue } - assert.Nil(t, panicErr, "#%d: unexpected panic", i) - assert.Nil(t, err, "#%d: expecting a non-nil error", i) + require.NoError(t, panicErr, "#%d: unexpected panic", i) + require.NoError(t, err, "#%d: expecting a non-nil error", i) qua, ok := res.(*quad) if !ok || qua == nil { t.Errorf("#%d: got nil quad back; gotType=%T", i, res) @@ -389,13 +400,13 @@ func TestSaveBlockWithExtendedCommitPanicOnAbsentExtension(t *testing.T) { }, } { t.Run(testCase.name, func(t *testing.T) { - state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) + state, bs, _, _, cleanup, _ := makeStateAndBlockStoreAndIndexers() defer cleanup() h := bs.Height() + 1 block := state.MakeBlock(h, test.MakeNTxs(h, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) seenCommit := makeTestExtCommit(block.Header.Height, cmttime.Now()) - ps, err := block.MakePartSet(2) + ps, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) testCase.malleateCommit(seenCommit) if testCase.shouldPanic { @@ -430,12 +441,12 @@ func TestLoadBlockExtendedCommit(t *testing.T) { }, } { t.Run(testCase.name, func(t *testing.T) { - state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) + state, bs, _, _, cleanup, _ := makeStateAndBlockStoreAndIndexers() defer cleanup() h := bs.Height() + 1 block := state.MakeBlock(h, test.MakeNTxs(h, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) seenCommit := makeTestExtCommit(block.Header.Height, cmttime.Now()) - ps, err := block.MakePartSet(2) + ps, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) if testCase.saveExtended { bs.SaveBlockWithExtendedCommit(block, ps, seenCommit) @@ -464,7 +475,7 @@ func TestLoadBaseMeta(t *testing.T) { for h := int64(1); h <= 10; h++ { block := state.MakeBlock(h, test.MakeNTxs(h, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) - partSet, err := block.MakePartSet(2) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) seenCommit := makeTestExtCommit(h, cmttime.Now()) bs.SaveBlockWithExtendedCommit(block, partSet, seenCommit) @@ -486,7 +497,7 @@ func TestLoadBlockPart(t *testing.T) { bs, db := newInMemoryBlockStore() const height, index = 10, 1 - loadPart := func() (interface{}, error) { + loadPart := func() (any, error) { part := bs.LoadBlockPart(height, index) return part, nil } @@ -497,33 +508,234 @@ func TestLoadBlockPart(t *testing.T) { // Initially no contents. // 1. Requesting for a non-existent block shouldn't fail res, _, panicErr := doFn(loadPart) - require.Nil(t, panicErr, "a non-existent block part shouldn't cause a panic") + require.NoError(t, panicErr, "a non-existent block part shouldn't cause a panic") require.Nil(t, res, "a non-existent block part should return nil") // 2. Next save a corrupted block then try to load it - err = db.Set(calcBlockPartKey(height, index), []byte("CometBFT")) + err = db.Set(bs.dbKeyLayout.CalcBlockPartKey(height, index), []byte("CometBFT")) require.NoError(t, err) res, _, panicErr = doFn(loadPart) - require.NotNil(t, panicErr, "expecting a non-nil panic") + require.Error(t, panicErr, "expecting a non-nil panic") require.Contains(t, panicErr.Error(), "unmarshal to cmtproto.Part failed") // 3. A good block serialized and saved to the DB should be retrievable block := state.MakeBlock(height, nil, new(types.Commit), nil, state.Validators.GetProposer().Address) - partSet, err := block.MakePartSet(2) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) part1 := partSet.GetPart(0) pb1, err := part1.ToProto() require.NoError(t, err) - err = db.Set(calcBlockPartKey(height, index), mustEncode(pb1)) + err = db.Set(bs.dbKeyLayout.CalcBlockPartKey(height, index), mustEncode(pb1)) require.NoError(t, err) gotPart, _, panicErr := doFn(loadPart) - require.Nil(t, panicErr, "an existent and proper block should not panic") + require.NoError(t, panicErr, "an existent and proper block should not panic") require.Nil(t, res, "a properly saved block should return a proper block") - require.Equal(t, gotPart.(*types.Part), part1, + + // Having to do this because of https://github.com/stretchr/testify/issues/1141 + gotPartJSON, err := json.Marshal(gotPart.(*types.Part)) + require.NoError(t, err) + part1JSON, err := json.Marshal(part1) + require.NoError(t, err) + require.JSONEq(t, string(gotPartJSON), string(part1JSON), "expecting successful retrieval of previously saved block") } +type prunerObserver struct { + sm.NoopPrunerObserver + prunedABCIResInfoCh chan *sm.ABCIResponsesPrunedInfo + prunedBlocksResInfoCh chan *sm.BlocksPrunedInfo +} + +func newPrunerObserver(infoChCap int) *prunerObserver { + return &prunerObserver{ + prunedABCIResInfoCh: make(chan *sm.ABCIResponsesPrunedInfo, infoChCap), + prunedBlocksResInfoCh: make(chan *sm.BlocksPrunedInfo, infoChCap), + } +} + +func (o *prunerObserver) PrunerPrunedABCIRes(info *sm.ABCIResponsesPrunedInfo) { + o.prunedABCIResInfoCh <- info +} + +func (o *prunerObserver) PrunerPrunedBlocks(info *sm.BlocksPrunedInfo) { + o.prunedBlocksResInfoCh <- info +} + +// This test tests the pruning service and its pruning of the blockstore +// The state store cannot be pruned here because we do not have proper +// state stored. The test is expected to pass even though the log should +// inform about the inability to prune the state store. +func TestPruningService(t *testing.T) { + config := test.ResetTestRoot("blockchain_reactor_pruning_test") + defer os.RemoveAll(config.RootDir) + state, bs, txIndexer, blockIndexer, cleanup, stateStore := makeStateAndBlockStoreAndIndexers() + defer cleanup() + assert.EqualValues(t, 0, bs.Base()) + assert.EqualValues(t, 0, bs.Height()) + assert.EqualValues(t, 0, bs.Size()) + + err := initStateStoreRetainHeights(stateStore, 0, 0, 0) + require.NoError(t, err) + + obs := newPrunerObserver(1) + + pruner := sm.NewPruner( + stateStore, + bs, + blockIndexer, + txIndexer, + log.TestingLogger(), + sm.WithPrunerInterval(time.Second*1), + sm.WithPrunerObserver(obs), + sm.WithPrunerCompanionEnabled(), + ) + + err = pruner.SetApplicationBlockRetainHeight(1) + require.Error(t, err) + err = pruner.SetApplicationBlockRetainHeight(0) + require.NoError(t, err) + + // make more than 1000 blocks, to test batch deletions + for h := int64(1); h <= 1500; h++ { + block := state.MakeBlock(h, test.MakeNTxs(h, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) + require.NoError(t, err) + seenCommit := makeTestExtCommit(h, cmttime.Now()) + bs.SaveBlockWithExtendedCommit(block, partSet, seenCommit) + } + + assert.EqualValues(t, 1, bs.Base()) + assert.EqualValues(t, 1500, bs.Height()) + assert.EqualValues(t, 1500, bs.Size()) + + state.LastBlockTime = cmttime.Now().Add(24 * time.Hour) + state.LastBlockHeight = 1500 + + state.ConsensusParams.Evidence.MaxAgeNumBlocks = 400 + state.ConsensusParams.Evidence.MaxAgeDuration = 1 * time.Minute + + pk := ed25519.GenPrivKey().PubKey() + + // Generate a bunch of state data. + // This is needed because the pruning is expecting to load the state from the database thus + // We have to have acceptable values for all fields of the state + validator := &types.Validator{Address: pk.Address(), VotingPower: 100, PubKey: pk} + validatorSet := &types.ValidatorSet{ + Validators: []*types.Validator{validator}, + Proposer: validator, + } + state.Validators = validatorSet + state.NextValidators = validatorSet + if state.LastBlockHeight >= 1 { + state.LastValidators = state.Validators + } + + err = stateStore.Save(state) + require.NoError(t, err) + // Check that basic pruning works + err = pruner.SetApplicationBlockRetainHeight(1200) + require.NoError(t, err) + err = pruner.SetCompanionBlockRetainHeight(1200) + require.NoError(t, err) + err = pruner.Start() + require.NoError(t, err) + + select { + case info := <-obs.prunedBlocksResInfoCh: + assert.EqualValues(t, 0, info.FromHeight) + assert.EqualValues(t, 1199, info.ToHeight) + assert.EqualValues(t, 1200, bs.Base()) + assert.EqualValues(t, 1500, bs.Height()) + assert.EqualValues(t, 301, bs.Size()) + block, meta := bs.LoadBlock(1200) + require.NotNil(t, block) + require.NotNil(t, meta) + block, meta = bs.LoadBlock(1199) + require.Nil(t, block) + require.Nil(t, meta) + // The header and commit for heights 1100 onwards + // need to remain to verify evidence + require.NotNil(t, bs.LoadBlockMeta(1100)) + require.Nil(t, bs.LoadBlockMeta(1099)) + require.NotNil(t, bs.LoadBlockCommit(1100)) + require.Nil(t, bs.LoadBlockCommit(1099)) + for i := int64(1); i < 1200; i++ { + block, meta = bs.LoadBlock(i) + require.Nil(t, block) + require.Nil(t, meta) + } + for i := int64(1200); i <= 1500; i++ { + block, meta = bs.LoadBlock(i) + require.NotNil(t, block) + require.NotNil(t, meta) + } + t.Log("Done pruning blocks until height 1200") + + case <-time.After(5 * time.Second): + require.Fail(t, "timed out waiting for pruning run to complete") + } + + // Pruning below the current base should error + err = pruner.SetApplicationBlockRetainHeight(1199) + require.Error(t, err) + + // Pruning to the current base should work + err = pruner.SetApplicationBlockRetainHeight(1200) + require.NoError(t, err) + + // Pruning again should work + err = pruner.SetApplicationBlockRetainHeight(1300) + require.NoError(t, err) + + err = pruner.SetCompanionBlockRetainHeight(1350) + require.NoError(t, err) + + select { + case <-obs.prunedBlocksResInfoCh: + assert.EqualValues(t, 1300, bs.Base()) + + // we should still have the header and the commit + // as they're needed for evidence + require.NotNil(t, bs.LoadBlockMeta(1100)) + require.Nil(t, bs.LoadBlockMeta(1099)) + require.NotNil(t, bs.LoadBlockCommit(1100)) + require.Nil(t, bs.LoadBlockCommit(1099)) + t.Log("Done pruning up until 1300") + case <-time.After(5 * time.Second): + require.Fail(t, "timed out waiting for pruning run to complete") + } + // Setting the pruning height beyond the current height should error + err = pruner.SetApplicationBlockRetainHeight(1501) + require.Error(t, err) + + // Pruning to the current height should work + err = pruner.SetApplicationBlockRetainHeight(1500) + require.NoError(t, err) + + select { + case <-obs.prunedBlocksResInfoCh: + // But we will prune only until 1350 because that was the Companions height + // and it is lower + block, meta := bs.LoadBlock(1349) + assert.Nil(t, block) + assert.Nil(t, meta) + block, meta = bs.LoadBlock(1350) + assert.NotNil(t, block, fmt.Sprintf("expected block at height 1350 to be there, but it was not; block store base height = %d", bs.Base())) + assert.NotNil(t, meta) + block, meta = bs.LoadBlock(1500) + assert.NotNil(t, block) + assert.NotNil(t, meta) + block, meta = bs.LoadBlock(1501) + assert.Nil(t, block) + assert.Nil(t, meta) + t.Log("Done pruning blocks until 1500") + + case <-time.After(5 * time.Second): + require.Fail(t, "timed out waiting for pruning run to complete") + } +} + func TestPruneBlocks(t *testing.T) { config := test.ResetTestRoot("blockchain_reactor_test") defer os.RemoveAll(config.RootDir) @@ -548,7 +760,7 @@ func TestPruneBlocks(t *testing.T) { // make more than 1000 blocks, to test batch deletions for h := int64(1); h <= 1500; h++ { block := state.MakeBlock(h, test.MakeNTxs(h, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) - partSet, err := block.MakePartSet(2) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) seenCommit := makeTestExtCommit(h, cmttime.Now()) bs.SaveBlockWithExtendedCommit(block, partSet, seenCommit) @@ -558,11 +770,11 @@ func TestPruneBlocks(t *testing.T) { assert.EqualValues(t, 1500, bs.Height()) assert.EqualValues(t, 1500, bs.Size()) - state.LastBlockTime = time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC) + state.LastBlockTime = cmttime.Now().Add(24 * time.Hour) state.LastBlockHeight = 1500 state.ConsensusParams.Evidence.MaxAgeNumBlocks = 400 - state.ConsensusParams.Evidence.MaxAgeDuration = 1 * time.Second + state.ConsensusParams.Evidence.MaxAgeDuration = 1 * time.Minute // Check that basic pruning works pruned, evidenceRetainHeight, err := bs.PruneBlocks(1200, state) @@ -573,8 +785,12 @@ func TestPruneBlocks(t *testing.T) { assert.EqualValues(t, 301, bs.Size()) assert.EqualValues(t, 1100, evidenceRetainHeight) - require.NotNil(t, bs.LoadBlock(1200)) - require.Nil(t, bs.LoadBlock(1199)) + block, meta := bs.LoadBlock(1200) + require.NotNil(t, block) + require.NotNil(t, meta) + block, meta = bs.LoadBlock(1199) + require.Nil(t, block) + require.Nil(t, meta) // The header and commit for heights 1100 onwards // need to remain to verify evidence @@ -584,10 +800,14 @@ func TestPruneBlocks(t *testing.T) { require.Nil(t, bs.LoadBlockCommit(1099)) for i := int64(1); i < 1200; i++ { - require.Nil(t, bs.LoadBlock(i)) + block, meta = bs.LoadBlock(i) + require.Nil(t, block) + require.Nil(t, meta) } for i := int64(1200); i <= 1500; i++ { - require.NotNil(t, bs.LoadBlock(i)) + block, meta = bs.LoadBlock(i) + require.NotNil(t, block) + require.NotNil(t, meta) } // Pruning below the current base should error @@ -620,15 +840,21 @@ func TestPruneBlocks(t *testing.T) { pruned, _, err = bs.PruneBlocks(1500, state) require.NoError(t, err) assert.EqualValues(t, 200, pruned) - assert.Nil(t, bs.LoadBlock(1499)) - assert.NotNil(t, bs.LoadBlock(1500)) - assert.Nil(t, bs.LoadBlock(1501)) + block, meta = bs.LoadBlock(1499) + assert.Nil(t, block) + assert.Nil(t, meta) + block, meta = bs.LoadBlock(1500) + assert.NotNil(t, block) + assert.NotNil(t, meta) + block, meta = bs.LoadBlock(1501) + assert.Nil(t, block) + assert.Nil(t, meta) } func TestLoadBlockMeta(t *testing.T) { bs, db := newInMemoryBlockStore() height := int64(10) - loadMeta := func() (interface{}, error) { + loadMeta := func() (any, error) { meta := bs.LoadBlockMeta(height) return meta, nil } @@ -636,14 +862,14 @@ func TestLoadBlockMeta(t *testing.T) { // Initially no contents. // 1. Requesting for a non-existent blockMeta shouldn't fail res, _, panicErr := doFn(loadMeta) - require.Nil(t, panicErr, "a non-existent blockMeta shouldn't cause a panic") + require.NoError(t, panicErr) require.Nil(t, res, "a non-existent blockMeta should return nil") // 2. Next save a corrupted blockMeta then try to load it - err := db.Set(calcBlockMetaKey(height), []byte("CometBFT-Meta")) + err := db.Set(bs.dbKeyLayout.CalcBlockMetaKey(height), []byte("CometBFT-Meta")) require.NoError(t, err) res, _, panicErr = doFn(loadMeta) - require.NotNil(t, panicErr, "expecting a non-nil panic") + require.Error(t, panicErr) require.Contains(t, panicErr.Error(), "unmarshal to cmtproto.BlockMeta") // 3. A good blockMeta serialized and saved to the DB should be retrievable @@ -653,10 +879,10 @@ func TestLoadBlockMeta(t *testing.T) { }, Height: 1, ProposerAddress: cmtrand.Bytes(crypto.AddressSize), }} pbm := meta.ToProto() - err = db.Set(calcBlockMetaKey(height), mustEncode(pbm)) + err = db.Set(bs.dbKeyLayout.CalcBlockMetaKey(height), mustEncode(pbm)) require.NoError(t, err) gotMeta, _, panicErr := doFn(loadMeta) - require.Nil(t, panicErr, "an existent and proper block should not panic") + require.NoError(t, panicErr, "an existent and proper block should not panic") require.Nil(t, res, "a properly saved blockMeta should return a proper blocMeta ") pbmeta := meta.ToProto() if gmeta, ok := gotMeta.(*types.BlockMeta); ok { @@ -677,7 +903,7 @@ func TestLoadBlockMetaByHash(t *testing.T) { bs := NewBlockStore(dbm.NewMemDB()) b1 := state.MakeBlock(state.LastBlockHeight+1, test.MakeNTxs(state.LastBlockHeight+1, 10), new(types.Commit), nil, state.Validators.GetProposer().Address) - partSet, err := b1.MakePartSet(2) + partSet, err := b1.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) seenCommit := makeTestExtCommit(1, cmttime.Now()) bs.SaveBlock(b1, partSet, seenCommit.ToCommit()) @@ -689,18 +915,18 @@ func TestLoadBlockMetaByHash(t *testing.T) { } func TestBlockFetchAtHeight(t *testing.T) { - state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) + state, bs, _, _, cleanup, _ := makeStateAndBlockStoreAndIndexers() defer cleanup() - require.Equal(t, bs.Height(), int64(0), "initially the height should be zero") + require.Equal(t, int64(0), bs.Height(), "initially the height should be zero") block := state.MakeBlock(bs.Height()+1, nil, new(types.Commit), nil, state.Validators.GetProposer().Address) - partSet, err := block.MakePartSet(2) + partSet, err := block.MakePartSet(types.BlockPartSizeBytes) require.NoError(t, err) seenCommit := makeTestExtCommit(block.Header.Height, cmttime.Now()) bs.SaveBlockWithExtendedCommit(block, partSet, seenCommit) require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed") - blockAtHeight := bs.LoadBlock(bs.Height()) + blockAtHeight, _ := bs.LoadBlock(bs.Height()) b1, err := block.ToProto() require.NoError(t, err) b2, err := blockAtHeight.ToProto() @@ -711,13 +937,13 @@ func TestBlockFetchAtHeight(t *testing.T) { require.Equal(t, block.Hash(), blockAtHeight.Hash(), "expecting a successful load of the last saved block") - blockAtHeightPlus1 := bs.LoadBlock(bs.Height() + 1) + blockAtHeightPlus1, _ := bs.LoadBlock(bs.Height() + 1) require.Nil(t, blockAtHeightPlus1, "expecting an unsuccessful load of Height()+1") - blockAtHeightPlus2 := bs.LoadBlock(bs.Height() + 2) + blockAtHeightPlus2, _ := bs.LoadBlock(bs.Height() + 2) require.Nil(t, blockAtHeightPlus2, "expecting an unsuccessful load of Height()+2") } -func doFn(fn func() (interface{}, error)) (res interface{}, err error, panicErr error) { +func doFn(fn func() (any, error)) (res any, err error, panicErr error) { defer func() { if r := recover(); r != nil { switch e := r.(type) { @@ -745,3 +971,16 @@ func newBlock(hdr types.Header, lastCommit *types.Commit) *types.Block { LastCommit: lastCommit, } } + +func initStateStoreRetainHeights(stateStore sm.Store, appBlockRH, dcBlockRH, dcBlockResultsRH int64) error { + if err := stateStore.SaveApplicationRetainHeight(appBlockRH); err != nil { + return fmt.Errorf("failed to set initial application block retain height: %w", err) + } + if err := stateStore.SaveCompanionBlockRetainHeight(dcBlockRH); err != nil { + return fmt.Errorf("failed to set initial companion block retain height: %w", err) + } + if err := stateStore.SaveABCIResRetainHeight(dcBlockResultsRH); err != nil { + return fmt.Errorf("failed to set initial ABCI results retain height: %w", err) + } + return nil +} diff --git a/libs/strings/string.go b/internal/strings/string.go similarity index 95% rename from libs/strings/string.go rename to internal/strings/string.go index 37026dcc208..9f93247cb9f 100644 --- a/libs/strings/string.go +++ b/internal/strings/string.go @@ -59,9 +59,7 @@ func IsASCIIText(s string) bool { return false } for _, b := range []byte(s) { - if 32 <= b && b <= 126 { - // good - } else { + if b < 32 || b > 126 { return false } } @@ -84,7 +82,7 @@ func ASCIITrim(s string) string { return string(r) } -// StringSliceEqual checks if string slices a and b are equal +// StringSliceEqual checks if string slices a and b are equal. func StringSliceEqual(a, b []string) bool { if len(a) != len(b) { return false diff --git a/libs/strings/string_test.go b/internal/strings/string_test.go similarity index 90% rename from libs/strings/string_test.go rename to internal/strings/string_test.go index 1ec7b0d56be..afd32c87bcb 100644 --- a/libs/strings/string_test.go +++ b/internal/strings/string_test.go @@ -3,9 +3,8 @@ package strings import ( "testing" - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestStringInSlice(t *testing.T) { @@ -31,10 +30,10 @@ func TestIsASCIIText(t *testing.T) { } func TestASCIITrim(t *testing.T) { - assert.Equal(t, ASCIITrim(" "), "") - assert.Equal(t, ASCIITrim(" a"), "a") - assert.Equal(t, ASCIITrim("a "), "a") - assert.Equal(t, ASCIITrim(" a "), "a") + assert.Equal(t, "", ASCIITrim(" ")) + assert.Equal(t, "a", ASCIITrim(" a")) + assert.Equal(t, "a", ASCIITrim("a ")) + assert.Equal(t, "a", ASCIITrim(" a ")) assert.Panics(t, func() { ASCIITrim("\xC2\xA2") }) } diff --git a/libs/sync/deadlock.go b/internal/sync/deadlock.go similarity index 100% rename from libs/sync/deadlock.go rename to internal/sync/deadlock.go diff --git a/libs/sync/sync.go b/internal/sync/sync.go similarity index 100% rename from libs/sync/sync.go rename to internal/sync/sync.go diff --git a/libs/tempfile/tempfile.go b/internal/tempfile/tempfile.go similarity index 95% rename from libs/tempfile/tempfile.go rename to internal/tempfile/tempfile.go index f79cd0e1632..4fd5ba14c51 100644 --- a/libs/tempfile/tempfile.go +++ b/internal/tempfile/tempfile.go @@ -9,24 +9,24 @@ import ( "strings" "time" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) const ( atomicWriteFilePrefix = "write-file-atomic-" // Maximum number of atomic write file conflicts before we start reseeding - // (reduced from golang's default 10 due to using an increased randomness space) + // (reduced from golang's default 10 due to using an increased randomness space). atomicWriteFileMaxNumConflicts = 5 // Maximum number of attempts to make at writing the write file before giving up - // (reduced from golang's default 10000 due to using an increased randomness space) + // (reduced from golang's default 10000 due to using an increased randomness space). atomicWriteFileMaxNumWriteAttempts = 1000 // LCG constants from Donald Knuth MMIX - // This LCG's has a period equal to 2**64 + // This LCG's has a period equal to 2**64. lcgA = 6364136223846793005 lcgC = 1442695040888963407 // Create in case it doesn't exist and force kernel // flush, which still leaves the potential of lingering disk cache. - // Never overwrites files + // Never overwrites files. atomicWriteFileFlag = os.O_WRONLY | os.O_CREATE | os.O_SYNC | os.O_TRUNC | os.O_EXCL ) @@ -65,7 +65,7 @@ func randWriteFileSuffix() string { suffix := strconv.Itoa(int(r)) if string(suffix[0]) == "-" { // Replace first "-" with "0". This is purely for UI clarity, - // as otherwhise there would be two `-` in a row. + // as otherwise there would be two `-` in a row. suffix = strings.Replace(suffix, "-", "0", 1) } return suffix diff --git a/libs/tempfile/tempfile_test.go b/internal/tempfile/tempfile_test.go similarity index 88% rename from libs/tempfile/tempfile_test.go rename to internal/tempfile/tempfile_test.go index 4ff18863f4a..e2f8fa5385a 100644 --- a/libs/tempfile/tempfile_test.go +++ b/internal/tempfile/tempfile_test.go @@ -6,18 +6,18 @@ import ( "bytes" "fmt" "os" - testing "testing" + "testing" "github.com/stretchr/testify/require" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) func TestWriteFileAtomic(t *testing.T) { var ( data = []byte(cmtrand.Str(cmtrand.Intn(2048))) old = cmtrand.Bytes(cmtrand.Intn(2048)) - perm os.FileMode = 0600 + perm os.FileMode = 0o600 ) f, err := os.CreateTemp("/tmp", "write-atomic-test-") @@ -26,7 +26,7 @@ func TestWriteFileAtomic(t *testing.T) { } defer os.Remove(f.Name()) - if err = os.WriteFile(f.Name(), old, 0600); err != nil { + if err = os.WriteFile(f.Name(), old, 0o600); err != nil { t.Fatal(err) } @@ -68,7 +68,7 @@ func TestWriteFileAtomicDuplicateFile(t *testing.T) { firstFileRand := randWriteFileSuffix() atomicWriteFileRand = defaultSeed fname := "/tmp/" + atomicWriteFilePrefix + firstFileRand - f, err := os.OpenFile(fname, atomicWriteFileFlag, 0777) + f, err := os.OpenFile(fname, atomicWriteFileFlag, 0o777) defer os.Remove(fname) // Defer here, in case there is a panic in WriteFileAtomic. defer os.Remove(fileToWrite) @@ -76,7 +76,7 @@ func TestWriteFileAtomicDuplicateFile(t *testing.T) { require.NoError(t, err) _, err = f.WriteString(testString) require.NoError(t, err) - err = WriteFileAtomic(fileToWrite, []byte(expectedString), 0777) + err = WriteFileAtomic(fileToWrite, []byte(expectedString), 0o777) require.NoError(t, err) // Check that the first atomic file was untouched firstAtomicFileBytes, err := os.ReadFile(fname) @@ -112,8 +112,8 @@ func TestWriteFileAtomicManyDuplicates(t *testing.T) { for i := 0; i < atomicWriteFileMaxNumConflicts+2; i++ { fileRand := randWriteFileSuffix() fname := "/tmp/" + atomicWriteFilePrefix + fileRand - f, err := os.OpenFile(fname, atomicWriteFileFlag, 0777) - require.Nil(t, err) + f, err := os.OpenFile(fname, atomicWriteFileFlag, 0o777) + require.NoError(t, err) _, err = f.WriteString(fmt.Sprintf(testString, i)) require.NoError(t, err) defer os.Remove(fname) @@ -123,7 +123,7 @@ func TestWriteFileAtomicManyDuplicates(t *testing.T) { // Defer here, in case there is a panic in WriteFileAtomic. defer os.Remove(fileToWrite) - err := WriteFileAtomic(fileToWrite, []byte(expectedString), 0777) + err := WriteFileAtomic(fileToWrite, []byte(expectedString), 0o777) require.NoError(t, err) // Check that all intermittent atomic file were untouched atomicWriteFileRand = defaultSeed @@ -131,13 +131,13 @@ func TestWriteFileAtomicManyDuplicates(t *testing.T) { fileRand := randWriteFileSuffix() fname := "/tmp/" + atomicWriteFilePrefix + fileRand firstAtomicFileBytes, err := os.ReadFile(fname) - require.Nil(t, err, "Error reading first atomic file") + require.NoError(t, err, "Error reading first atomic file") require.Equal(t, []byte(fmt.Sprintf(testString, i)), firstAtomicFileBytes, "atomic write file %d was overwritten", i) } // Check that the resultant file is correct resultantFileBytes, err := os.ReadFile(fileToWrite) - require.Nil(t, err, "Error reading resultant file") + require.NoError(t, err, "Error reading resultant file") require.Equal(t, []byte(expectedString), resultantFileBytes, "Written file had incorrect bytes") } diff --git a/internal/test/block.go b/internal/test/block.go index 5889ac3517d..16491a0e4cb 100644 --- a/internal/test/block.go +++ b/internal/test/block.go @@ -16,9 +16,7 @@ const ( DefaultTestChainID = "test-chain" ) -var ( - DefaultTestTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) -) +var DefaultTestTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) func RandomAddress() []byte { return crypto.CRandBytes(crypto.AddressSize) @@ -43,7 +41,7 @@ func MakeBlockIDWithHash(hash []byte) types.BlockID { } // MakeHeader fills the rest of the contents of the header such that it passes -// validate basic +// validate basic. func MakeHeader(t *testing.T, h *types.Header) *types.Header { t.Helper() if h.Version.Block == 0 { @@ -52,7 +50,7 @@ func MakeHeader(t *testing.T, h *types.Header) *types.Header { if h.Height == 0 { h.Height = 1 } - if h.LastBlockID.IsZero() { + if h.LastBlockID.IsNil() { h.LastBlockID = MakeBlockID() } if h.ChainID == "" { diff --git a/internal/test/commit.go b/internal/test/commit.go index 599d56d3012..c39339c3224 100644 --- a/internal/test/commit.go +++ b/internal/test/commit.go @@ -4,7 +4,6 @@ import ( "fmt" "time" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" ) @@ -20,14 +19,14 @@ func MakeCommitFromVoteSet(blockID types.BlockID, voteSet *types.VoteSet, valida ValidatorIndex: int32(i), Height: voteSet.GetHeight(), Round: voteSet.GetRound(), - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, BlockID: blockID, Timestamp: now, } v := vote.ToProto() - if err := validators[i].SignVote(voteSet.ChainID(), v); err != nil { + if err := validators[i].SignVote(voteSet.ChainID(), v, false); err != nil { return nil, err } vote.Signature = v.Signature @@ -36,7 +35,7 @@ func MakeCommitFromVoteSet(blockID types.BlockID, voteSet *types.VoteSet, valida } } - return voteSet.MakeExtendedCommit(types.ABCIParams{VoteExtensionsEnableHeight: 0}).ToCommit(), nil + return voteSet.MakeExtendedCommit(types.DefaultFeatureParams()).ToCommit(), nil } func MakeCommit(blockID types.BlockID, height int64, round int32, valSet *types.ValidatorSet, privVals []types.PrivValidator, chainID string, now time.Time) (*types.Commit, error) { @@ -62,14 +61,14 @@ func MakeCommit(blockID types.BlockID, height int64, round int32, valSet *types. ValidatorIndex: idx, Height: height, Round: round, - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, BlockID: blockID, Timestamp: now, } v := vote.ToProto() - if err := privVal.SignVote(chainID, v); err != nil { + if err := privVal.SignVote(chainID, v, false); err != nil { return nil, err } diff --git a/internal/test/config.go b/internal/test/config.go index 2685584e178..a47dc2a1d62 100644 --- a/internal/test/config.go +++ b/internal/test/config.go @@ -6,7 +6,7 @@ import ( "path/filepath" "github.com/cometbft/cometbft/config" - cmtos "github.com/cometbft/cometbft/libs/os" + cmtos "github.com/cometbft/cometbft/internal/os" ) func ResetTestRoot(testName string) *config.Config { @@ -32,11 +32,11 @@ func ResetTestRootWithChainID(testName string, chainID string) *config.Config { chainID = DefaultTestChainID } testGenesis := fmt.Sprintf(testGenesisFmt, chainID) - cmtos.MustWriteFile(genesisFilePath, []byte(testGenesis), 0644) + cmtos.MustWriteFile(genesisFilePath, []byte(testGenesis), 0o644) } // we always overwrite the priv val - cmtos.MustWriteFile(privKeyFilePath, []byte(testPrivValidatorKey), 0644) - cmtos.MustWriteFile(privStateFilePath, []byte(testPrivValidatorState), 0644) + cmtos.MustWriteFile(privKeyFilePath, []byte(testPrivValidatorKey), 0o644) + cmtos.MustWriteFile(privStateFilePath, []byte(testPrivValidatorState), 0o644) config := config.TestConfig().SetRoot(rootDir) return config @@ -46,12 +46,16 @@ var testGenesisFmt = `{ "genesis_time": "2018-10-10T08:20:13.695936996Z", "chain_id": "%s", "initial_height": "1", - "consensus_params": { + "consensus_params": { "block": { "max_bytes": "22020096", "max_gas": "-1", "time_iota_ms": "10" }, + "synchrony": { + "message_delay": "500000000", + "precision": "10000000" + }, "evidence": { "max_age_num_blocks": "100000", "max_age_duration": "172800000000000", @@ -65,8 +69,12 @@ var testGenesisFmt = `{ "abci": { "vote_extensions_enable_height": "0" }, - "version": {} - }, + "version": {}, + "feature": { + "vote_extensions_enable_height": "0", + "pbts_enable_height": "1" + } + }, "validators": [ { "pub_key": { diff --git a/internal/test/genesis.go b/internal/test/genesis.go index 22b8028b8e1..7e71f1d5207 100644 --- a/internal/test/genesis.go +++ b/internal/test/genesis.go @@ -12,7 +12,6 @@ func GenesisDoc( consensusParams *types.ConsensusParams, chainID string, ) *types.GenesisDoc { - genesisValidators := make([]types.GenesisValidator, len(validators)) for i := range validators { diff --git a/internal/test/params.go b/internal/test/params.go index c4421d53cc4..136267aa27b 100644 --- a/internal/test/params.go +++ b/internal/test/params.go @@ -5,10 +5,12 @@ import ( ) // ConsensusParams returns a default set of ConsensusParams that are suitable -// for use in testing +// for use in testing. func ConsensusParams() *types.ConsensusParams { c := types.DefaultConsensusParams() // enable vote extensions - c.ABCI.VoteExtensionsEnableHeight = 1 + c.Feature.VoteExtensionsEnableHeight = 1 + // enabled PBTS + c.Feature.PbtsEnableHeight = 1 return c } diff --git a/internal/test/validator.go b/internal/test/validator.go index 73733a018a9..4c436dce89e 100644 --- a/internal/test/validator.go +++ b/internal/test/validator.go @@ -2,15 +2,17 @@ package test import ( "context" + "fmt" "sort" "testing" "github.com/stretchr/testify/require" + "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/types" ) -func Validator(ctx context.Context, votingPower int64) (*types.Validator, types.PrivValidator, error) { +func Validator(_ context.Context, votingPower int64) (*types.Validator, types.PrivValidator, error) { privVal := types.NewMockPV() pubKey, err := privVal.GetPubKey() if err != nil { @@ -22,11 +24,12 @@ func Validator(ctx context.Context, votingPower int64) (*types.Validator, types. } func ValidatorSet(ctx context.Context, t *testing.T, numValidators int, votingPower int64) (*types.ValidatorSet, []types.PrivValidator) { + t.Helper() + var ( valz = make([]*types.Validator, numValidators) privValidators = make([]types.PrivValidator, numValidators) ) - t.Helper() for i := 0; i < numValidators; i++ { val, privValidator, err := Validator(ctx, votingPower) @@ -39,3 +42,22 @@ func ValidatorSet(ctx context.Context, t *testing.T, numValidators int, votingPo return types.NewValidatorSet(valz), privValidators } + +func GenesisValidatorSet(nVals int) ([]types.GenesisValidator, map[string]types.PrivValidator) { + vals := make([]types.GenesisValidator, nVals) + privVals := make(map[string]types.PrivValidator, nVals) + for i := 0; i < nVals; i++ { + secret := []byte(fmt.Sprintf("test%d", i)) + pk := ed25519.GenPrivKeyFromSecret(secret) + valAddr := pk.PubKey().Address() + vals[i] = types.GenesisValidator{ + Address: valAddr, + PubKey: pk.PubKey(), + Power: 1000, + Name: fmt.Sprintf("test%d", i), + } + privVals[valAddr.String()] = types.NewMockPVWithParams(pk, false, false) + } + + return vals, privVals +} diff --git a/libs/timer/throttle_timer.go b/internal/timer/throttle_timer.go similarity index 84% rename from libs/timer/throttle_timer.go rename to internal/timer/throttle_timer.go index d27269f4e53..4a5c340ad44 100644 --- a/libs/timer/throttle_timer.go +++ b/internal/timer/throttle_timer.go @@ -3,7 +3,7 @@ package timer import ( "time" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) /* @@ -24,9 +24,9 @@ type ThrottleTimer struct { } func NewThrottleTimer(name string, dur time.Duration) *ThrottleTimer { - var ch = make(chan struct{}) - var quit = make(chan struct{}) - var t = &ThrottleTimer{Name: name, Ch: ch, dur: dur, quit: quit} + ch := make(chan struct{}) + quit := make(chan struct{}) + t := &ThrottleTimer{Name: name, Ch: ch, dur: dur, quit: quit} t.mtx.Lock() t.timer = time.AfterFunc(dur, t.fireRoutine) t.mtx.Unlock() @@ -64,7 +64,7 @@ func (t *ThrottleTimer) Unset() { } // For ease of .Stop()'ing services before .Start()'ing them, -// we ignore .Stop()'s on nil ThrottleTimers +// we ignore .Stop()'s on nil ThrottleTimers. func (t *ThrottleTimer) Stop() bool { if t == nil { return false diff --git a/libs/timer/throttle_timer_test.go b/internal/timer/throttle_timer_test.go similarity index 90% rename from libs/timer/throttle_timer_test.go rename to internal/timer/throttle_timer_test.go index 527c89ecea8..14df4bebced 100644 --- a/libs/timer/throttle_timer_test.go +++ b/internal/timer/throttle_timer_test.go @@ -4,11 +4,9 @@ import ( "testing" "time" - // make govet noshadow happy... - asrt "github.com/stretchr/testify/assert" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) type thCounter struct { @@ -31,7 +29,7 @@ func (c *thCounter) Count() int { } // Read should run in a go-routine and -// updates count by one every time a packet comes in +// updates count by one every time a packet comes in. func (c *thCounter) Read() { for range c.input { c.Increment() diff --git a/libs/bytes/bytes.go b/libs/bytes/bytes.go index 95b4cc35fca..85ea79b4bd2 100644 --- a/libs/bytes/bytes.go +++ b/libs/bytes/bytes.go @@ -9,12 +9,12 @@ import ( // HexBytes enables HEX-encoding for json/encoding. type HexBytes []byte -// Marshal needed for protobuf compatibility +// Marshal needed for protobuf compatibility. func (bz HexBytes) Marshal() ([]byte, error) { return bz, nil } -// Unmarshal needed for protobuf compatibility +// Unmarshal needed for protobuf compatibility. func (bz *HexBytes) Unmarshal(data []byte) error { *bz = data return nil diff --git a/libs/bytes/bytes_test.go b/libs/bytes/bytes_test.go index db882f1c1a5..b4e2c8b647b 100644 --- a/libs/bytes/bytes_test.go +++ b/libs/bytes/bytes_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // This is a trivial test for protobuf compatibility. @@ -14,20 +15,20 @@ func TestMarshal(t *testing.T) { bz := []byte("hello world") dataB := HexBytes(bz) bz2, err := dataB.Marshal() - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, bz, bz2) var dataB2 HexBytes err = (&dataB2).Unmarshal(bz) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, dataB, dataB2) } // Test that the hex encoding works. func TestJSONMarshal(t *testing.T) { type TestStruct struct { - B1 []byte - B2 HexBytes + B1 []byte `json:"B1" yaml:"B1"` // normal bytes + B2 HexBytes `json:"B2" yaml:"B2"` // hex bytes } cases := []struct { @@ -49,7 +50,7 @@ func TestJSONMarshal(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Equal(t, string(jsonBytes), tc.expected) + assert.Equal(t, tc.expected, string(jsonBytes)) // TODO do fuzz testing to ensure that unmarshal fails @@ -65,6 +66,7 @@ func TestJSONMarshal(t *testing.T) { } } +// Test that the hex encoding works. func TestHexBytes_String(t *testing.T) { hs := HexBytes([]byte("test me")) if _, err := strconv.ParseInt(hs.String(), 16, 64); err != nil { diff --git a/libs/cli/flags/log_level.go b/libs/cli/flags/log_level.go index 13879e71a74..2abfee5d735 100644 --- a/libs/cli/flags/log_level.go +++ b/libs/cli/flags/log_level.go @@ -1,11 +1,11 @@ package flags import ( - "errors" "fmt" "strings" "github.com/cometbft/cometbft/libs/log" + cmterrors "github.com/cometbft/cometbft/types/errors" ) const ( @@ -21,7 +21,7 @@ const ( // ParseLogLevel("consensus:debug,mempool:debug,*:error", log.NewTMLogger(os.Stdout), "info") func ParseLogLevel(lvl string, logger log.Logger, defaultLogLevelValue string) (log.Logger, error) { if lvl == "" { - return nil, errors.New("empty log level") + return nil, cmterrors.ErrRequiredField{Field: "LogLevel"} } l := lvl @@ -73,7 +73,6 @@ func ParseLogLevel(lvl string, logger log.Logger, defaultLogLevelValue string) ( list) } options = append(options, option) - } } diff --git a/libs/cli/flags/log_level_test.go b/libs/cli/flags/log_level_test.go index 17af292e7cd..14be860b177 100644 --- a/libs/cli/flags/log_level_test.go +++ b/libs/cli/flags/log_level_test.go @@ -26,21 +26,24 @@ func TestParseLogLevel(t *testing.T) { ``, `{"_msg":"Mesmero","level":"error","module":"mempool"}`, `{"_msg":"Mind","level":"info","module":"state"}`, // if no default is given, assume info - ``}}, + ``, + }}, {"mempool:error,*:debug", []string{ `{"_msg":"Kingpin","level":"debug","module":"wire"}`, ``, `{"_msg":"Mesmero","level":"error","module":"mempool"}`, `{"_msg":"Mind","level":"info","module":"state"}`, - `{"_msg":"Gideon","level":"debug"}`}}, + `{"_msg":"Gideon","level":"debug"}`, + }}, {"*:debug,wire:none", []string{ ``, `{"_msg":"Kitty Pryde","level":"info","module":"mempool"}`, `{"_msg":"Mesmero","level":"error","module":"mempool"}`, `{"_msg":"Mind","level":"info","module":"state"}`, - `{"_msg":"Gideon","level":"debug"}`}}, + `{"_msg":"Gideon","level":"debug"}`, + }}, } for _, c := range correctLogLevels { diff --git a/libs/cli/helper.go b/libs/cli/helper.go index 37fe34fc9ff..0bd0b4be668 100644 --- a/libs/cli/helper.go +++ b/libs/cli/helper.go @@ -18,11 +18,11 @@ func WriteConfigVals(dir string, vals map[string]string) error { data += fmt.Sprintf("%s = \"%s\"\n", k, v) } cfile := filepath.Join(dir, "config.toml") - return os.WriteFile(cfile, []byte(data), 0600) + return os.WriteFile(cfile, []byte(data), 0o600) } // RunWithArgs executes the given command with the specified command line args -// and environmental variables set. It returns any error returned from cmd.Execute() +// and environmental variables set. It returns any error returned from cmd.Execute(). func RunWithArgs(cmd Executable, args []string, env map[string]string) error { oargs := os.Args oenv := map[string]string{} @@ -52,7 +52,7 @@ func RunWithArgs(cmd Executable, args []string, env map[string]string) error { // RunCaptureWithArgs executes the given command with the specified command // line args and environmental variables set. It returns string fields // representing output written to stdout and stderr, additionally any error -// from cmd.Execute() is also returned +// from cmd.Execute() is also returned. func RunCaptureWithArgs(cmd Executable, args []string, env map[string]string) (stdout, stderr string, err error) { oldout, olderr := os.Stdout, os.Stderr // keep backup of the real stdout rOut, wOut, _ := os.Pipe() diff --git a/libs/cli/setup.go b/libs/cli/setup.go index 521695bdbd4..125bcacbff7 100644 --- a/libs/cli/setup.go +++ b/libs/cli/setup.go @@ -19,12 +19,12 @@ const ( ) // Executable is the minimal interface to *corba.Command, so we can -// wrap if desired before the test +// wrap if desired before the test. type Executable interface { Execute() error } -// PrepareBaseCmd is meant for CometBFT and other servers +// PrepareBaseCmd is meant for CometBFT and other servers. func PrepareBaseCmd(cmd *cobra.Command, envPrefix, defaultHome string) Executor { cobra.OnInitialize(func() { initEnv(envPrefix) }) cmd.PersistentFlags().StringP(HomeFlag, "", defaultHome, "directory for config and data") @@ -55,7 +55,7 @@ func initEnv(prefix string) { } // This copies all variables like TMROOT to TM_ROOT, -// so we can support both formats for the user +// so we can support both formats for the user. func copyEnvVars(prefix string) { prefix = strings.ToUpper(prefix) ps := prefix + "_" @@ -71,7 +71,7 @@ func copyEnvVars(prefix string) { } } -// Executor wraps the cobra Command with a nicer Execute method +// Executor wraps the cobra Command with a nicer Execute method. type Executor struct { *cobra.Command Exit func(int) // this is os.Exit by default, override in tests @@ -110,7 +110,7 @@ func (e Executor) Execute() error { type cobraCmdFunc func(cmd *cobra.Command, args []string) error // Returns a single function that calls each argument function in sequence -// RunE, PreRunE, PersistentPreRunE, etc. all have this same signature +// RunE, PreRunE, PersistentPreRunE, etc. all have this same signature. func concatCobraCmdFuncs(fs ...cobraCmdFunc) cobraCmdFunc { return func(cmd *cobra.Command, args []string) error { for _, f := range fs { @@ -124,8 +124,8 @@ func concatCobraCmdFuncs(fs ...cobraCmdFunc) cobraCmdFunc { } } -// Bind all flags and read the config into viper -func bindFlagsLoadViper(cmd *cobra.Command, args []string) error { +// Bind all flags and read the config into viper. +func bindFlagsLoadViper(cmd *cobra.Command, _ []string) error { // cmd.Flags() includes flags from this command and all persistent flags from the parent if err := viper.BindPFlags(cmd.Flags()); err != nil { return err @@ -138,17 +138,15 @@ func bindFlagsLoadViper(cmd *cobra.Command, args []string) error { viper.AddConfigPath(filepath.Join(homeDir, "config")) // search root directory /config // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - // stderr, so if we redirect output to json file, this doesn't appear - // fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) - } else if _, ok := err.(viper.ConfigFileNotFoundError); !ok { + err := viper.ReadInConfig() + if _, ok := err.(viper.ConfigFileNotFoundError); !ok { // ignore not found error, return other errors return err } return nil } -func validateOutput(cmd *cobra.Command, args []string) error { +func validateOutput(_ *cobra.Command, _ []string) error { // validate output format output := viper.GetString(OutputFlag) switch output { diff --git a/libs/cli/setup_test.go b/libs/cli/setup_test.go index fec49e5c1ed..3303fd6ab93 100644 --- a/libs/cli/setup_test.go +++ b/libs/cli/setup_test.go @@ -27,8 +27,11 @@ func TestSetupEnv(t *testing.T) { {nil, map[string]string{"DEMO_FOOBAR": "good"}, "good"}, {nil, map[string]string{"DEMOFOOBAR": "silly"}, "silly"}, // and that cli overrides env... - {[]string{"--foobar", "important"}, - map[string]string{"DEMO_FOOBAR": "ignored"}, "important"}, + { + []string{"--foobar", "important"}, + map[string]string{"DEMO_FOOBAR": "ignored"}, + "important", + }, } for idx, tc := range cases { @@ -37,7 +40,7 @@ func TestSetupEnv(t *testing.T) { var foo string demo := &cobra.Command{ Use: "demo", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { foo = viper.GetString("foobar") return nil }, @@ -49,7 +52,7 @@ func TestSetupEnv(t *testing.T) { viper.Reset() args := append([]string{cmd.Use}, tc.args...) err := RunWithArgs(cmd, args, tc.env) - require.Nil(t, err, i) + require.NoError(t, err, i) assert.Equal(t, tc.expected, foo, i) } } @@ -68,7 +71,7 @@ func TestSetupConfig(t *testing.T) { cval1 := "fubble" conf1 := tempDir() err := WriteConfigVals(conf1, map[string]string{"boo": cval1}) - require.Nil(t, err) + require.NoError(t, err) cases := []struct { args []string @@ -95,7 +98,7 @@ func TestSetupConfig(t *testing.T) { var foo, two string boo := &cobra.Command{ Use: "reader", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { foo = viper.GetString("boo") two = viper.GetString("two-words") return nil @@ -109,7 +112,7 @@ func TestSetupConfig(t *testing.T) { viper.Reset() args := append([]string{cmd.Use}, tc.args...) err := RunWithArgs(cmd, args, tc.env) - require.Nil(t, err, i) + require.NoError(t, err, i) assert.Equal(t, tc.expected, foo, i) assert.Equal(t, tc.expectedTwo, two, i) } @@ -127,11 +130,11 @@ func TestSetupUnmarshal(t *testing.T) { cval1, cval2 := "someone", "else" conf1 := tempDir() err := WriteConfigVals(conf1, map[string]string{"name": cval1}) - require.Nil(t, err) + require.NoError(t, err) // even with some ignored fields, should be no problem conf2 := tempDir() err = WriteConfigVals(conf2, map[string]string{"name": cval2, "foo": "bar"}) - require.Nil(t, err) + require.NoError(t, err) // unused is not declared on a flag and remains from base base := DemoConfig{ @@ -174,7 +177,7 @@ func TestSetupUnmarshal(t *testing.T) { cfg := base marsh := &cobra.Command{ Use: "marsh", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return viper.Unmarshal(&cfg) }, } @@ -188,7 +191,7 @@ func TestSetupUnmarshal(t *testing.T) { viper.Reset() args := append([]string{cmd.Use}, tc.args...) err := RunWithArgs(cmd, args, tc.env) - require.Nil(t, err, i) + require.NoError(t, err, i) assert.Equal(t, tc.expected, cfg, i) } } @@ -211,7 +214,7 @@ func TestSetupTrace(t *testing.T) { // test command that store value of foobar in local variable trace := &cobra.Command{ Use: "trace", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return fmt.Errorf("trace flag = %t", viper.GetBool(TraceFlag)) }, } @@ -221,14 +224,14 @@ func TestSetupTrace(t *testing.T) { viper.Reset() args := append([]string{cmd.Use}, tc.args...) stdout, stderr, err := RunCaptureWithArgs(cmd, args, tc.env) - require.NotNil(t, err, i) + require.Error(t, err, i) require.Equal(t, "", stdout, i) require.NotEqual(t, "", stderr, i) msg := strings.Split(stderr, "\n") - desired := fmt.Sprintf("ERROR: %s", tc.expected) + desired := "ERROR: " + tc.expected assert.Equal(t, desired, msg[0], i) t.Log(msg) - if tc.long && assert.True(t, len(msg) > 2, i) { + if tc.long && assert.Greater(t, len(msg), 2, i) { // the next line starts the stack trace... assert.Contains(t, stderr, "TestSetupTrace", i) assert.Contains(t, stderr, "setup_test.go", i) diff --git a/libs/json/decoder.go b/libs/json/decoder.go index 86ff27d3935..1aca2ca223b 100644 --- a/libs/json/decoder.go +++ b/libs/json/decoder.go @@ -10,11 +10,11 @@ import ( // Unmarshal unmarshals JSON into the given value, using Amino-compatible JSON encoding (strings // for 64-bit numbers, and type wrappers for registered types). -func Unmarshal(bz []byte, v interface{}) error { +func Unmarshal(bz []byte, v any) error { return decode(bz, v) } -func decode(bz []byte, v interface{}) error { +func decode(bz []byte, v any) error { if len(bz) == 0 { return errors.New("cannot decode empty bytes") } @@ -115,7 +115,6 @@ func decodeReflectList(bz []byte, rv reflect.Value) error { return fmt.Errorf("got %v bytes, expected %v", len(buf), rv.Len()) } reflect.Copy(rv, reflect.ValueOf(buf)) - } else if err := decodeStdlib(bz, rv); err != nil { return err } diff --git a/libs/json/decoder_test.go b/libs/json/decoder_test.go index 9a33bf0e2ad..9d19b26a41a 100644 --- a/libs/json/decoder_test.go +++ b/libs/json/decoder_test.go @@ -21,7 +21,7 @@ func TestUnmarshal(t *testing.T) { testcases := map[string]struct { json string - value interface{} + value any err bool }{ "bool true": {"true", true, false}, diff --git a/libs/json/doc.go b/libs/json/doc.go index a4fb461db5f..18a4c97cee9 100644 --- a/libs/json/doc.go +++ b/libs/json/doc.go @@ -90,7 +90,7 @@ // // type Struct struct { // Car *Car -// Vehicle Vehicle +// Vehicle // } // // Struct{Car: &Car{Wheels: 4}, Vehicle: &Car{Wheels: 4}} diff --git a/libs/json/encoder.go b/libs/json/encoder.go index 11990e2af6c..cd404d9bfda 100644 --- a/libs/json/encoder.go +++ b/libs/json/encoder.go @@ -19,7 +19,7 @@ var ( // Marshal marshals the value as JSON, using Amino-compatible JSON encoding (strings for // 64-bit numbers, and type wrappers for registered types). -func Marshal(v interface{}) ([]byte, error) { +func Marshal(v any) ([]byte, error) { buf := new(bytes.Buffer) err := encode(buf, v) if err != nil { @@ -29,7 +29,7 @@ func Marshal(v interface{}) ([]byte, error) { } // MarshalIndent marshals the value as JSON, using the given prefix and indentation. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { +func MarshalIndent(v any, prefix, indent string) ([]byte, error) { bz, err := Marshal(v) if err != nil { return nil, err @@ -42,7 +42,7 @@ func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { return buf.Bytes(), nil } -func encode(w io.Writer, v interface{}) error { +func encode(w io.Writer, v any) error { // Bare nil values can't be reflected, so we must handle them here. if v == nil { return writeStr(w, "null") @@ -237,7 +237,7 @@ func encodeReflectInterface(w io.Writer, rv reflect.Value) error { return writeStr(w, "}") } -func encodeStdlib(w io.Writer, v interface{}) error { +func encodeStdlib(w io.Writer, v any) error { // Doesn't stream the output because that adds a newline, as per: // https://golang.org/pkg/encoding/json/#Encoder.Encode blob, err := json.Marshal(v) diff --git a/libs/json/encoder_test.go b/libs/json/encoder_test.go index e6eb18a1225..70576b4fde3 100644 --- a/libs/json/encoder_test.go +++ b/libs/json/encoder_test.go @@ -19,7 +19,7 @@ func TestMarshal(t *testing.T) { boat := Boat{Sail: true} testcases := map[string]struct { - value interface{} + value any output string }{ "nil": {nil, `null`}, diff --git a/libs/json/helpers_test.go b/libs/json/helpers_test.go index 46d5b471b45..4f6666557da 100644 --- a/libs/json/helpers_test.go +++ b/libs/json/helpers_test.go @@ -23,29 +23,31 @@ type Car struct { Wheels int32 } -func (c *Car) Drive() error { return nil } +func (*Car) Drive() error { return nil } // Boat is a value implementation of Vehicle. type Boat struct { Sail bool } -func (b Boat) Drive() error { return nil } +func (Boat) Drive() error { return nil } // These are public and private encryption keys. -type PublicKey [8]byte -type PrivateKey [8]byte +type ( + PublicKey [8]byte + PrivateKey [8]byte +) // Custom has custom marshalers and unmarshalers, taking pointer receivers. type CustomPtr struct { Value string } -func (c *CustomPtr) MarshalJSON() ([]byte, error) { +func (*CustomPtr) MarshalJSON() ([]byte, error) { return []byte("\"custom\""), nil } -func (c *CustomPtr) UnmarshalJSON(bz []byte) error { +func (c *CustomPtr) UnmarshalJSON(_ []byte) error { c.Value = "custom" return nil } @@ -56,11 +58,11 @@ type CustomValue struct { Value string } -func (c CustomValue) MarshalJSON() ([]byte, error) { +func (CustomValue) MarshalJSON() ([]byte, error) { return []byte("\"custom\""), nil } -func (c CustomValue) UnmarshalJSON(bz []byte) error { +func (CustomValue) UnmarshalJSON(_ []byte) error { return nil } diff --git a/libs/json/structs.go b/libs/json/structs.go index 8c717e3c83b..a80be91b73d 100644 --- a/libs/json/structs.go +++ b/libs/json/structs.go @@ -6,13 +6,11 @@ import ( "strings" "unicode" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) -var ( - // cache caches struct info. - cache = newStructInfoCache() -) +// cache caches struct info. +var cache = newStructInfoCache() // structCache is a cache of struct info. type structInfoCache struct { diff --git a/libs/json/types.go b/libs/json/types.go index 4d9a0e229c8..7e71ecf8d8c 100644 --- a/libs/json/types.go +++ b/libs/json/types.go @@ -5,13 +5,11 @@ import ( "fmt" "reflect" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) -var ( - // typeRegistry contains globally registered types for JSON encoding/decoding. - typeRegistry = newTypes() -) +// typeRegistry contains globally registered types for JSON encoding/decoding. +var typeRegistry = newTypes() // RegisterType registers a type for Amino-compatible interface encoding in the global type // registry. These types will be encoded with a type wrapper `{"type":"","value":}` @@ -20,7 +18,7 @@ var ( // the a value or pointer based on the registered type. // // Should only be called in init() functions, as it panics on error. -func RegisterType(_type interface{}, name string) { +func RegisterType(_type any, name string) { if _type == nil { panic("cannot register nil type") } diff --git a/libs/log/tmfmt_logger.go b/libs/log/cmtfmt_logger.go similarity index 93% rename from libs/log/tmfmt_logger.go rename to libs/log/cmtfmt_logger.go index 1d8cb80aac9..fab9277fe43 100644 --- a/libs/log/tmfmt_logger.go +++ b/libs/log/cmtfmt_logger.go @@ -7,11 +7,12 @@ import ( "io" "strings" "sync" - "time" kitlog "github.com/go-kit/log" kitlevel "github.com/go-kit/log/level" "github.com/go-logfmt/logfmt" + + cmttime "github.com/cometbft/cometbft/types/time" ) type tmfmtEncoder struct { @@ -25,7 +26,7 @@ func (l *tmfmtEncoder) Reset() { } var tmfmtEncoderPool = sync.Pool{ - New: func() interface{} { + New: func() any { var enc tmfmtEncoder enc.Encoder = logfmt.NewEncoder(&enc.buf) return &enc @@ -47,7 +48,7 @@ func NewTMFmtLogger(w io.Writer) kitlog.Logger { return &tmfmtLogger{w} } -func (l tmfmtLogger) Log(keyvals ...interface{}) error { +func (l tmfmtLogger) Log(keyvals ...any) error { enc := tmfmtEncoderPool.Get().(*tmfmtEncoder) enc.Reset() defer tmfmtEncoderPool.Put(enc) @@ -92,7 +93,6 @@ func (l tmfmtLogger) Log(keyvals ...interface{}) error { if s, ok := keyvals[i+1].(fmt.Stringer); ok { keyvals[i+1] = s.String() } - } // Form a custom CometBFT line @@ -104,7 +104,7 @@ func (l tmfmtLogger) Log(keyvals ...interface{}) error { // D - first character of the level, uppercase (ASCII only) // [2016-05-02|11:06:44.322] - our time format (see https://golang.org/src/time/format.go) // Stopping ... - message - enc.buf.WriteString(fmt.Sprintf("%c[%s] %-44s ", lvl[0]-32, time.Now().Format("2006-01-02|15:04:05.000"), msg)) + enc.buf.WriteString(fmt.Sprintf("%c[%s] %-44s ", lvl[0]-32, cmttime.Now().Format("2006-01-02|15:04:05.000"), msg)) if module != unknown { enc.buf.WriteString("module=" + module + " ") diff --git a/libs/log/tmfmt_logger_test.go b/libs/log/cmtfmt_logger_test.go similarity index 97% rename from libs/log/tmfmt_logger_test.go rename to libs/log/cmtfmt_logger_test.go index d4e8f8bfec2..f1294e579b2 100644 --- a/libs/log/tmfmt_logger_test.go +++ b/libs/log/cmtfmt_logger_test.go @@ -15,7 +15,6 @@ import ( ) func TestTMFmtLogger(t *testing.T) { - t.Parallel() buf := &bytes.Buffer{} logger := log.NewTMFmtLogger(buf) @@ -70,11 +69,11 @@ func BenchmarkTMFmtLoggerContextual(b *testing.B) { } func TestTMFmtLoggerConcurrency(t *testing.T) { - t.Parallel() testConcurrency(t, log.NewTMFmtLogger(io.Discard), 10000) } func benchmarkRunnerKitlog(b *testing.B, logger kitlog.Logger, f func(kitlog.Logger)) { + b.Helper() lc := kitlog.With(logger, "common_key", "common_value") b.ReportAllocs() b.ResetTimer() @@ -91,6 +90,7 @@ var ( // These test are designed to be run with the race detector. func testConcurrency(t *testing.T, logger kitlog.Logger, total int) { + t.Helper() n := int(math.Sqrt(float64(total))) share := total / n @@ -122,4 +122,4 @@ func spam(logger kitlog.Logger, count int) error { type mymap map[int]int -func (m mymap) String() string { return "special_behavior" } +func (mymap) String() string { return "special_behavior" } diff --git a/libs/log/filter.go b/libs/log/filter.go index 4b7ed981cd8..bc13513934a 100644 --- a/libs/log/filter.go +++ b/libs/log/filter.go @@ -18,8 +18,8 @@ type filter struct { } type keyval struct { - key interface{} - value interface{} + key any + value any } // NewFilter wraps next and implements filtering. See the commentary on the @@ -38,7 +38,7 @@ func NewFilter(next Logger, options ...Option) Logger { return l } -func (l *filter) Info(msg string, keyvals ...interface{}) { +func (l *filter) Info(msg string, keyvals ...any) { levelAllowed := l.allowed&levelInfo != 0 if !levelAllowed { return @@ -46,7 +46,7 @@ func (l *filter) Info(msg string, keyvals ...interface{}) { l.next.Info(msg, keyvals...) } -func (l *filter) Debug(msg string, keyvals ...interface{}) { +func (l *filter) Debug(msg string, keyvals ...any) { levelAllowed := l.allowed&levelDebug != 0 if !levelAllowed { return @@ -54,7 +54,7 @@ func (l *filter) Debug(msg string, keyvals ...interface{}) { l.next.Debug(msg, keyvals...) } -func (l *filter) Error(msg string, keyvals ...interface{}) { +func (l *filter) Error(msg string, keyvals ...any) { levelAllowed := l.allowed&levelError != 0 if !levelAllowed { return @@ -82,7 +82,7 @@ func (l *filter) Error(msg string, keyvals ...interface{}) { // log.AllowError(), // log.AllowInfoWith("module", "crypto"), log.AllowNoneWith("user", "Sam")) // logger.With("user", "Sam").With("module", "crypto").Info("Hello") # produces "I... Hello module=crypto user=Sam" -func (l *filter) With(keyvals ...interface{}) Logger { +func (l *filter) With(keyvals ...any) Logger { keyInAllowedKeyvals := false for i := len(keyvals) - 2; i >= 0; i -= 2 { @@ -124,7 +124,7 @@ func (l *filter) With(keyvals ...interface{}) Logger { } } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- // Option sets a parameter for the filter. type Option func(*filter) @@ -176,21 +176,21 @@ func allowed(allowed level) Option { } // AllowDebugWith allows error, info and debug level log events to pass for a specific key value pair. -func AllowDebugWith(key interface{}, value interface{}) Option { +func AllowDebugWith(key any, value any) Option { return func(l *filter) { l.allowedKeyvals[keyval{key, value}] = levelError | levelInfo | levelDebug } } // AllowInfoWith allows error and info level log events to pass for a specific key value pair. -func AllowInfoWith(key interface{}, value interface{}) Option { +func AllowInfoWith(key any, value any) Option { return func(l *filter) { l.allowedKeyvals[keyval{key, value}] = levelError | levelInfo } } // AllowErrorWith allows only error level log events to pass for a specific key value pair. -func AllowErrorWith(key interface{}, value interface{}) Option { +func AllowErrorWith(key any, value any) Option { return func(l *filter) { l.allowedKeyvals[keyval{key, value}] = levelError } } // AllowNoneWith allows no leveled log events to pass for a specific key value pair. -func AllowNoneWith(key interface{}, value interface{}) Option { +func AllowNoneWith(key any, value any) Option { return func(l *filter) { l.allowedKeyvals[keyval{key, value}] = 0 } } diff --git a/libs/log/lazy.go b/libs/log/lazy.go index a8fb74f03aa..6183edb4713 100644 --- a/libs/log/lazy.go +++ b/libs/log/lazy.go @@ -8,13 +8,13 @@ import ( type LazySprintf struct { format string - args []interface{} + args []any } // NewLazySprintf defers fmt.Sprintf until the Stringer interface is invoked. // This is particularly useful for avoiding calling Sprintf when debugging is not // active. -func NewLazySprintf(format string, args ...interface{}) *LazySprintf { +func NewLazySprintf(format string, args ...any) *LazySprintf { return &LazySprintf{format, args} } diff --git a/libs/log/logger.go b/libs/log/logger.go index 22ed68f1a1a..a3765522fd8 100644 --- a/libs/log/logger.go +++ b/libs/log/logger.go @@ -8,11 +8,11 @@ import ( // Logger is what any CometBFT library should take. type Logger interface { - Debug(msg string, keyvals ...interface{}) - Info(msg string, keyvals ...interface{}) - Error(msg string, keyvals ...interface{}) + Debug(msg string, keyvals ...any) + Info(msg string, keyvals ...any) + Error(msg string, keyvals ...any) - With(keyvals ...interface{}) Logger + With(keyvals ...any) Logger } // NewSyncWriter returns a new writer that is safe for concurrent use by diff --git a/libs/log/nop_logger.go b/libs/log/nop_logger.go index 12d75abe6b7..94d2aeb898d 100644 --- a/libs/log/nop_logger.go +++ b/libs/log/nop_logger.go @@ -2,16 +2,16 @@ package log type nopLogger struct{} -// Interface assertions +// Interface assertions. var _ Logger = (*nopLogger)(nil) // NewNopLogger returns a logger that doesn't do anything. func NewNopLogger() Logger { return &nopLogger{} } -func (nopLogger) Info(string, ...interface{}) {} -func (nopLogger) Debug(string, ...interface{}) {} -func (nopLogger) Error(string, ...interface{}) {} +func (nopLogger) Info(string, ...any) {} +func (nopLogger) Debug(string, ...any) {} +func (nopLogger) Error(string, ...any) {} -func (l *nopLogger) With(...interface{}) Logger { +func (l *nopLogger) With(...any) Logger { return l } diff --git a/libs/log/testing_logger.go b/libs/log/testing_logger.go index 7c6f661a745..f9c86946c0c 100644 --- a/libs/log/testing_logger.go +++ b/libs/log/testing_logger.go @@ -8,10 +8,8 @@ import ( "github.com/go-kit/log/term" ) -var ( - // reuse the same logger across all tests - _testingLogger Logger -) +// reuse the same logger across all tests. +var _testingLogger Logger // TestingLogger returns a TMLogger which writes to STDOUT if testing being run // with the verbose (-v) flag, NopLogger otherwise. @@ -45,7 +43,7 @@ func TestingLoggerWithOutput(w io.Writer) Logger { // TestingLoggerWithColorFn allow you to provide your own color function. See // TestingLogger for documentation. -func TestingLoggerWithColorFn(colorFn func(keyvals ...interface{}) term.FgBgColor) Logger { +func TestingLoggerWithColorFn(colorFn func(keyvals ...any) term.FgBgColor) Logger { if _testingLogger != nil { return _testingLogger } diff --git a/libs/log/tm_logger.go b/libs/log/tm_logger.go index ac0d08adb00..13b022faea8 100644 --- a/libs/log/tm_logger.go +++ b/libs/log/tm_logger.go @@ -18,7 +18,7 @@ type tmLogger struct { srcLogger kitlog.Logger } -// Interface assertions +// Interface assertions. var _ Logger = (*tmLogger)(nil) // NewTMLogger returns a logger that encodes msg and keyvals to the Writer @@ -26,7 +26,7 @@ var _ Logger = (*tmLogger)(nil) // that underlying logger could be swapped with something else. func NewTMLogger(w io.Writer) Logger { // Color by level value - colorFn := func(keyvals ...interface{}) term.FgBgColor { + colorFn := func(keyvals ...any) term.FgBgColor { if keyvals[0] != kitlevel.Key() { panic(fmt.Sprintf("expected level key to be first, got %v", keyvals[0])) } @@ -45,12 +45,12 @@ func NewTMLogger(w io.Writer) Logger { // NewTMLoggerWithColorFn allows you to provide your own color function. See // NewTMLogger for documentation. -func NewTMLoggerWithColorFn(w io.Writer, colorFn func(keyvals ...interface{}) term.FgBgColor) Logger { +func NewTMLoggerWithColorFn(w io.Writer, colorFn func(keyvals ...any) term.FgBgColor) Logger { return &tmLogger{term.NewLogger(w, NewTMFmtLogger, colorFn)} } // Info logs a message at level Info. -func (l *tmLogger) Info(msg string, keyvals ...interface{}) { +func (l *tmLogger) Info(msg string, keyvals ...any) { lWithLevel := kitlevel.Info(l.srcLogger) if err := kitlog.With(lWithLevel, msgKey, msg).Log(keyvals...); err != nil { @@ -60,7 +60,7 @@ func (l *tmLogger) Info(msg string, keyvals ...interface{}) { } // Debug logs a message at level Debug. -func (l *tmLogger) Debug(msg string, keyvals ...interface{}) { +func (l *tmLogger) Debug(msg string, keyvals ...any) { lWithLevel := kitlevel.Debug(l.srcLogger) if err := kitlog.With(lWithLevel, msgKey, msg).Log(keyvals...); err != nil { @@ -70,7 +70,7 @@ func (l *tmLogger) Debug(msg string, keyvals ...interface{}) { } // Error logs a message at level Error. -func (l *tmLogger) Error(msg string, keyvals ...interface{}) { +func (l *tmLogger) Error(msg string, keyvals ...any) { lWithLevel := kitlevel.Error(l.srcLogger) lWithMsg := kitlog.With(lWithLevel, msgKey, msg) @@ -81,6 +81,6 @@ func (l *tmLogger) Error(msg string, keyvals ...interface{}) { // With returns a new contextual logger with keyvals prepended to those passed // to calls to Info, Debug or Error. -func (l *tmLogger) With(keyvals ...interface{}) Logger { +func (l *tmLogger) With(keyvals ...any) Logger { return &tmLogger{kitlog.With(l.srcLogger, keyvals...)} } diff --git a/libs/log/tm_logger_test.go b/libs/log/tm_logger_test.go index 95b4fd5379d..30d69e40383 100644 --- a/libs/log/tm_logger_test.go +++ b/libs/log/tm_logger_test.go @@ -98,6 +98,7 @@ func BenchmarkTMLoggerContextual(b *testing.B) { } func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) { + b.Helper() lc := logger.With("common_key", "common_value") b.ReportAllocs() b.ResetTimer() diff --git a/libs/log/tracing_logger.go b/libs/log/tracing_logger.go index d2a6ff44e5e..2ecfccf1a39 100644 --- a/libs/log/tracing_logger.go +++ b/libs/log/tracing_logger.go @@ -28,24 +28,24 @@ type tracingLogger struct { next Logger } -func (l *tracingLogger) Info(msg string, keyvals ...interface{}) { +func (l *tracingLogger) Info(msg string, keyvals ...any) { l.next.Info(msg, formatErrors(keyvals)...) } -func (l *tracingLogger) Debug(msg string, keyvals ...interface{}) { +func (l *tracingLogger) Debug(msg string, keyvals ...any) { l.next.Debug(msg, formatErrors(keyvals)...) } -func (l *tracingLogger) Error(msg string, keyvals ...interface{}) { +func (l *tracingLogger) Error(msg string, keyvals ...any) { l.next.Error(msg, formatErrors(keyvals)...) } -func (l *tracingLogger) With(keyvals ...interface{}) Logger { +func (l *tracingLogger) With(keyvals ...any) Logger { return &tracingLogger{next: l.next.With(formatErrors(keyvals)...)} } -func formatErrors(keyvals []interface{}) []interface{} { - newKeyvals := make([]interface{}, len(keyvals)) +func formatErrors(keyvals []any) []any { + newKeyvals := make([]any, len(keyvals)) copy(newKeyvals, keyvals) for i := 0; i < len(newKeyvals)-1; i += 2 { if err, ok := newKeyvals[i+1].(stackTracer); ok { diff --git a/libs/math/fraction.go b/libs/math/fraction.go index a8d28559243..ca4f9468734 100644 --- a/libs/math/fraction.go +++ b/libs/math/fraction.go @@ -27,7 +27,7 @@ func (fr Fraction) String() string { func ParseFraction(f string) (Fraction, error) { o := strings.Split(f, "/") if len(o) != 2 { - return Fraction{}, errors.New("incorrect formating: should have a single slash i.e. \"1/3\"") + return Fraction{}, errors.New("incorrect formatting: should have a single slash i.e. \"1/3\"") } numerator, err := strconv.ParseUint(o[0], 10, 64) if err != nil { diff --git a/libs/math/fraction_test.go b/libs/math/fraction_test.go index 73ca0f6c83f..550cf9162c8 100644 --- a/libs/math/fraction_test.go +++ b/libs/math/fraction_test.go @@ -4,10 +4,10 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParseFraction(t *testing.T) { - testCases := []struct { f string exp Fraction @@ -76,11 +76,10 @@ func TestParseFraction(t *testing.T) { for idx, tc := range testCases { output, err := ParseFraction(tc.f) if tc.err { - assert.Error(t, err, idx) + require.Error(t, err, idx) } else { - assert.NoError(t, err, idx) + require.NoError(t, err, idx) } assert.Equal(t, tc.exp, output, idx) } - } diff --git a/libs/math/math.go b/libs/math/math.go index cf567a97a59..fa33d63e14b 100644 --- a/libs/math/math.go +++ b/libs/math/math.go @@ -14,7 +14,7 @@ func MaxInt(a, b int) int { return b } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- func MinInt64(a, b int64) int64 { if a < b { diff --git a/libs/math/safemath.go b/libs/math/safemath.go index ff7f0908f94..0464c35b254 100644 --- a/libs/math/safemath.go +++ b/libs/math/safemath.go @@ -5,12 +5,14 @@ import ( "math" ) -var ErrOverflowInt32 = errors.New("int32 overflow") -var ErrOverflowUint8 = errors.New("uint8 overflow") -var ErrOverflowInt8 = errors.New("int8 overflow") +var ( + ErrOverflowInt32 = errors.New("int32 overflow") + ErrOverflowUint8 = errors.New("uint8 overflow") + ErrOverflowInt8 = errors.New("int8 overflow") +) // SafeAddInt32 adds two int32 integers -// If there is an overflow this will panic +// If there is an overflow this will panic. func SafeAddInt32(a, b int32) int32 { if b > 0 && (a > math.MaxInt32-b) { panic(ErrOverflowInt32) @@ -21,7 +23,7 @@ func SafeAddInt32(a, b int32) int32 { } // SafeSubInt32 subtracts two int32 integers -// If there is an overflow this will panic +// If there is an overflow this will panic. func SafeSubInt32(a, b int32) int32 { if b > 0 && (a < math.MinInt32+b) { panic(ErrOverflowInt32) @@ -32,7 +34,7 @@ func SafeSubInt32(a, b int32) int32 { } // SafeConvertInt32 takes a int and checks if it overflows -// If there is an overflow this will panic +// If there is an overflow this will panic. func SafeConvertInt32(a int64) int32 { if a > math.MaxInt32 { panic(ErrOverflowInt32) @@ -43,7 +45,7 @@ func SafeConvertInt32(a int64) int32 { } // SafeConvertUint8 takes an int64 and checks if it overflows -// If there is an overflow it returns an error +// If there is an overflow it returns an error. func SafeConvertUint8(a int64) (uint8, error) { if a > math.MaxUint8 { return 0, ErrOverflowUint8 @@ -54,7 +56,7 @@ func SafeConvertUint8(a int64) (uint8, error) { } // SafeConvertInt8 takes an int64 and checks if it overflows -// If there is an overflow it returns an error +// If there is an overflow it returns an error. func SafeConvertInt8(a int64) (int8, error) { if a > math.MaxInt8 { return 0, ErrOverflowInt8 diff --git a/libs/test/mutate.go b/libs/test/mutate.go index 3a0d58301be..4e2e6a1a397 100644 --- a/libs/test/mutate.go +++ b/libs/test/mutate.go @@ -1,10 +1,10 @@ package test import ( - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) -// Contract: !bytes.Equal(input, output) && len(input) >= len(output) +// Contract: !bytes.Equal(input, output) && len(input) >= len(output). func MutateByteSlice(bytez []byte) []byte { // If bytez is empty, panic if len(bytez) == 0 { diff --git a/libs/time/mocks/source.go b/libs/time/mocks/source.go new file mode 100644 index 00000000000..a8e49b314ed --- /dev/null +++ b/libs/time/mocks/source.go @@ -0,0 +1,28 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + time "time" + + mock "github.com/stretchr/testify/mock" +) + +// Source is an autogenerated mock type for the Source type +type Source struct { + mock.Mock +} + +// Now provides a mock function with given fields: +func (_m *Source) Now() time.Time { + ret := _m.Called() + + var r0 time.Time + if rf, ok := ret.Get(0).(func() time.Time); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Time) + } + + return r0 +} diff --git a/light/client.go b/light/client.go index d155c993f1e..f960db298c1 100644 --- a/light/client.go +++ b/light/client.go @@ -9,9 +9,9 @@ import ( "sync" "time" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/light/provider" "github.com/cometbft/cometbft/light/store" "github.com/cometbft/cometbft/types" @@ -118,7 +118,7 @@ func MaxClockDrift(d time.Duration) Option { // As an example, say the light client received block B at a time // 12:05 (this is the real time) and the time on the block // was 12:00. Then the lag here is 5 minutes. -// Default: 10s +// Default: 10s. func MaxBlockLag(d time.Duration) Option { return func(c *Client) { c.maxBlockLag = d @@ -129,7 +129,7 @@ func MaxBlockLag(d time.Duration) Option { // light blocks from a primary provider, verifies them either sequentially or by // skipping some and stores them in a trusted store (usually, a local FS). // -// Default verification: SkippingVerification(DefaultTrustLevel) +// Default verification: SkippingVerification(DefaultTrustLevel). type Client struct { chainID string trustingPeriod time.Duration // see TrustOptions.Period @@ -178,10 +178,10 @@ func NewClient( primary provider.Provider, witnesses []provider.Provider, trustedStore store.Store, - options ...Option) (*Client, error) { - + options ...Option, +) (*Client, error) { if err := trustOptions.ValidateBasic(); err != nil { - return nil, fmt.Errorf("invalid TrustOptions: %w", err) + return nil, ErrInvalidTrustOptions{Err: err} } c, err := NewClientFromTrustedStore(chainID, trustOptions.Period, primary, witnesses, trustedStore, options...) @@ -208,15 +208,15 @@ func NewClient( // NewClientFromTrustedStore initializes existing client from the trusted store. // -// See NewClient +// See NewClient. func NewClientFromTrustedStore( chainID string, trustingPeriod time.Duration, primary provider.Provider, witnesses []provider.Provider, trustedStore store.Store, - options ...Option) (*Client, error) { - + options ...Option, +) (*Client, error) { c := &Client{ chainID: chainID, trustingPeriod: trustingPeriod, @@ -229,7 +229,7 @@ func NewClientFromTrustedStore( witnesses: witnesses, trustedStore: trustedStore, pruningSize: defaultPruningSize, - confirmationFn: func(action string) bool { return true }, + confirmationFn: func(_ string) bool { return true }, quit: make(chan struct{}), logger: log.NewNopLogger(), } @@ -246,8 +246,7 @@ func NewClientFromTrustedStore( // Verify witnesses are all on the same chain. for i, w := range witnesses { if w.ChainID() != chainID { - return nil, fmt.Errorf("witness #%d: %v is on another chain %s, expected %s", - i, w, w.ChainID(), chainID) + return nil, ErrUnexpectedChainID{Index: i, Witness: w, Actual: w.ChainID(), Expected: chainID} } } @@ -263,17 +262,17 @@ func NewClientFromTrustedStore( return c, nil } -// restoreTrustedLightBlock loads the latest trusted light block from the store +// restoreTrustedLightBlock loads the latest trusted light block from the store. func (c *Client) restoreTrustedLightBlock() error { lastHeight, err := c.trustedStore.LastLightBlockHeight() if err != nil { - return fmt.Errorf("can't get last trusted light block height: %w", err) + return ErrGetTrustedBlockHeight{Err: err} } if lastHeight > 0 { trustedBlock, err := c.trustedStore.LightBlock(lastHeight) if err != nil { - return fmt.Errorf("can't get last trusted light block: %w", err) + return ErrGetTrustedBlock{Err: err} } c.latestTrustedBlock = trustedBlock c.logger.Info("Restored trusted light block", "height", lastHeight) @@ -325,7 +324,7 @@ func (c *Client) checkTrustedHeaderUsingOptions(ctx context.Context, options Tru // remove all the headers (options.Height, trustedHeader.Height] err := c.cleanupAfter(options.Height) if err != nil { - return fmt.Errorf("cleanupAfter(%d): %w", options.Height, err) + return ErrCleanupAfter{Height: options.Height, Err: err} } c.logger.Info("Rolled back to older header (newer headers were removed)", @@ -344,13 +343,13 @@ func (c *Client) checkTrustedHeaderUsingOptions(ctx context.Context, options Tru action := fmt.Sprintf( "Prev. trusted header's hash %X doesn't match hash %X from primary provider. Remove all the stored light blocks?", c.latestTrustedBlock.Hash(), primaryHash) - if c.confirmationFn(action) { - err := c.Cleanup() - if err != nil { - return fmt.Errorf("failed to cleanup: %w", err) - } - } else { - return errors.New("refused to remove the stored light blocks despite hashes mismatch") + if !c.confirmationFn(action) { + return ErrRemoveStoredBlocksRefused + } + + err := c.Cleanup() + if err != nil { + return ErrCleanup{Err: err} } } @@ -374,13 +373,13 @@ func (c *Client) initializeWithTrustOptions(ctx context.Context, options TrustOp } if !bytes.Equal(l.Hash(), options.Hash) { - return fmt.Errorf("expected header's hash %X, but got %X", options.Hash, l.Hash()) + return ErrHeaderHashMismatch{Expected: options.Hash, Actual: l.Hash()} } // 2) Ensure that +2/3 of validators signed correctly. err = l.ValidatorSet.VerifyCommitLight(c.chainID, l.Commit.BlockID, l.Height, l.Commit) if err != nil { - return fmt.Errorf("invalid commit: %w", err) + return ErrInvalidCommit{Err: err} } // 3) Cross-verify with witnesses to ensure everybody has the same state. @@ -412,19 +411,19 @@ func (c *Client) TrustedLightBlock(height int64) (*types.LightBlock, error) { func (c *Client) compareWithLatestHeight(height int64) (int64, error) { latestHeight, err := c.LastTrustedHeight() if err != nil { - return 0, fmt.Errorf("can't get last trusted height: %w", err) + return 0, ErrGetLastTrustedHeight{Err: err} } if latestHeight == -1 { - return 0, errors.New("no headers exist") + return 0, ErrNoHeadersExist } switch { case height > latestHeight: - return 0, fmt.Errorf("unverified header/valset requested (latest: %d)", latestHeight) + return 0, ErrUnverifiedHeight{Height: latestHeight} case height == 0: return latestHeight, nil case height < 0: - return 0, errors.New("negative height") + return 0, ErrNegativeHeight } return height, nil @@ -436,7 +435,7 @@ func (c *Client) compareWithLatestHeight(height int64) (int64, error) { func (c *Client) Update(ctx context.Context, now time.Time) (*types.LightBlock, error) { lastTrustedHeight, err := c.LastTrustedHeight() if err != nil { - return nil, fmt.Errorf("can't get last trusted height: %w", err) + return nil, ErrGetLastTrustedHeight{Err: err} } if lastTrustedHeight == -1 { @@ -470,10 +469,10 @@ func (c *Client) Update(ctx context.Context, now time.Time) (*types.LightBlock, // It returns provider.ErrlightBlockNotFound if light block is not found by // primary. // -// It will replace the primary provider if an error from a request to the provider occurs +// It will replace the primary provider if an error from a request to the provider occurs. func (c *Client) VerifyLightBlockAtHeight(ctx context.Context, height int64, now time.Time) (*types.LightBlock, error) { if height <= 0 { - return nil, errors.New("negative or zero height") + return nil, ErrNegativeOrZeroHeight } // Check if the light block already verified. @@ -524,10 +523,10 @@ func (c *Client) VerifyLightBlockAtHeight(ctx context.Context, height int64, now // restart. func (c *Client) VerifyHeader(ctx context.Context, newHeader *types.Header, now time.Time) error { if newHeader == nil { - return errors.New("nil header") + return ErrNilHeader } if newHeader.Height <= 0 { - return errors.New("negative or zero height") + return ErrNegativeOrZeroHeight } // Check if newHeader already verified. @@ -535,7 +534,7 @@ func (c *Client) VerifyHeader(ctx context.Context, newHeader *types.Header, now if err == nil { // Make sure it's the same header. if !bytes.Equal(l.Hash(), newHeader.Hash()) { - return fmt.Errorf("existing trusted header %X does not match newHeader %X", l.Hash(), newHeader.Hash()) + return ErrExistingHeaderHashMismatch{Existing: l.Hash(), New: newHeader.Hash()} } c.logger.Info("Header has already been verified", "height", newHeader.Height, "hash", newHeader.Hash()) @@ -545,11 +544,11 @@ func (c *Client) VerifyHeader(ctx context.Context, newHeader *types.Header, now // Request the header and the vals. l, err = c.lightBlockFromPrimary(ctx, newHeader.Height) if err != nil { - return fmt.Errorf("failed to retrieve light block from primary to verify against: %w", err) + return ErrGetBlock{Err: err} } if !bytes.Equal(l.Hash(), newHeader.Hash()) { - return fmt.Errorf("light block header %X does not match newHeader %X", l.Hash(), newHeader.Hash()) + return ErrLightHeaderHashMismatch{Existing: l.Hash(), New: newHeader.Hash()} } return c.verifyLightBlock(ctx, l, now) @@ -574,7 +573,7 @@ func (c *Client) verifyLightBlock(ctx context.Context, newLightBlock *types.Ligh firstBlockHeight, err := c.FirstTrustedHeight() if err != nil { - return fmt.Errorf("can't get first light block height: %w", err) + return ErrGetFirstBlockHeight{Err: err} } switch { @@ -587,7 +586,7 @@ func (c *Client) verifyLightBlock(ctx context.Context, newLightBlock *types.Ligh var firstBlock *types.LightBlock firstBlock, err = c.trustedStore.LightBlock(firstBlockHeight) if err != nil { - return fmt.Errorf("can't get first light block: %w", err) + return ErrGetFirstBlock{Err: err} } err = c.backwards(ctx, firstBlock.Header, newLightBlock.Header) @@ -596,7 +595,7 @@ func (c *Client) verifyLightBlock(ctx context.Context, newLightBlock *types.Ligh var closestBlock *types.LightBlock closestBlock, err = c.trustedStore.LightBlockBefore(newLightBlock.Height) if err != nil { - return fmt.Errorf("can't get signed header before height %d: %w", newLightBlock.Height, err) + return ErrGetSignedHeaderBeforeHeight{Height: newLightBlock.Height, Err: err} } err = verifyFunc(ctx, closestBlock, newLightBlock, now) } @@ -609,13 +608,13 @@ func (c *Client) verifyLightBlock(ctx context.Context, newLightBlock *types.Ligh return c.updateTrustedLightBlock(newLightBlock) } -// see VerifyHeader +// see VerifyHeader. func (c *Client) verifySequential( ctx context.Context, trustedBlock *types.LightBlock, newLightBlock *types.LightBlock, - now time.Time) error { - + now time.Time, +) error { var ( verifiedBlock = trustedBlock interimBlock *types.LightBlock @@ -708,8 +707,8 @@ func (c *Client) verifySkipping( source provider.Provider, trustedBlock *types.LightBlock, newLightBlock *types.LightBlock, - now time.Time) ([]*types.LightBlock, error) { - + now time.Time, +) ([]*types.LightBlock, error) { var ( blockCache = []*types.LightBlock{newLightBlock} depth = 0 @@ -773,13 +772,13 @@ func (c *Client) verifySkipping( } // verifySkippingAgainstPrimary does verifySkipping plus it compares new header with -// witnesses and replaces primary if it sends the light client an invalid header +// witnesses and replaces primary if it sends the light client an invalid header. func (c *Client) verifySkippingAgainstPrimary( ctx context.Context, trustedBlock *types.LightBlock, newLightBlock *types.LightBlock, - now time.Time) error { - + now time.Time, +) error { trace, err := c.verifySkipping(ctx, c.primary, trustedBlock, newLightBlock, now) switch errors.Unwrap(err).(type) { @@ -886,7 +885,7 @@ func (c *Client) cleanupAfter(height int64) error { if err == store.ErrLightBlockNotFound || (h != nil && h.Height <= height) { break } else if err != nil { - return fmt.Errorf("failed to get header before %d: %w", prevHeight, err) + return ErrGetHeaderBeforeHeight{Height: prevHeight, Err: err} } err = c.trustedStore.DeleteLightBlock(h.Height) @@ -911,12 +910,12 @@ func (c *Client) updateTrustedLightBlock(l *types.LightBlock) error { c.logger.Debug("updating trusted light block", "light_block", l) if err := c.trustedStore.SaveLightBlock(l); err != nil { - return fmt.Errorf("failed to save trusted header: %w", err) + return ErrSaveTrustedHeader{Err: err} } if c.pruningSize > 0 { if err := c.trustedStore.Prune(c.pruningSize); err != nil { - return fmt.Errorf("prune: %w", err) + return ErrPrune{Err: err} } } @@ -933,8 +932,8 @@ func (c *Client) updateTrustedLightBlock(l *types.LightBlock) error { func (c *Client) backwards( ctx context.Context, trustedHeader *types.Header, - newHeader *types.Header) error { - + newHeader *types.Header, +) error { var ( verifiedHeader = trustedHeader interimHeader *types.Header @@ -943,7 +942,7 @@ func (c *Client) backwards( for verifiedHeader.Height > newHeader.Height { interimBlock, err := c.lightBlockFromPrimary(ctx, verifiedHeader.Height-1) if err != nil { - return fmt.Errorf("failed to obtain the header at height #%d: %w", verifiedHeader.Height-1, err) + return ErrGetHeaderAtHeight{Height: verifiedHeader.Height - 1, Err: err} } interimHeader = interimBlock.Header c.logger.Debug("Verify newHeader against verifiedHeader", @@ -1015,7 +1014,7 @@ func (c *Client) lightBlockFromPrimary(ctx context.Context, height int64) (*type } } -// NOTE: requires a providerMutex lock +// NOTE: requires a providerMutex lock. func (c *Client) removeWitnesses(indexes []int) error { // check that we will still have witnesses remaining if len(c.witnesses) <= len(indexes) { @@ -1172,7 +1171,6 @@ and remove witness. Otherwise, use the different primary`, e.WitnessIndex), "wit c.logger.Info("error comparing first header with witness. You may want to consider removing the witness", "err", err) } - } // remove witnesses that have misbehaved diff --git a/light/client_benchmark_test.go b/light/client_benchmark_test.go index e9d11c952f3..fb206110d29 100644 --- a/light/client_benchmark_test.go +++ b/light/client_benchmark_test.go @@ -6,7 +6,6 @@ import ( "time" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/light" "github.com/cometbft/cometbft/light/provider" @@ -22,7 +21,7 @@ import ( // // Remember that none of these benchmarks account for network latency. var ( - benchmarkFullNode = mockp.New(genMockNode(chainID, 1000, 100, 1, bTime)) + benchmarkFullNode = mockp.New(genMockNode(1000, 100, 1, bTime)) genesisBlock, _ = benchmarkFullNode.LightBlock(context.Background(), 1) ) diff --git a/light/client_test.go b/light/client_test.go index 6e975212d62..ddfe7996402 100644 --- a/light/client_test.go +++ b/light/client_test.go @@ -2,7 +2,6 @@ package light_test import ( "context" - "errors" "sync" "testing" "time" @@ -11,7 +10,6 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/light" @@ -32,10 +30,10 @@ var ( bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") h1 = keys.GenSignedHeader(chainID, 1, bTime, nil, vals, vals, hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)) - // 3/3 signed + // 3/3 signed. h2 = keys.GenSignedHeaderLastBlockID(chainID, 2, bTime.Add(30*time.Minute), nil, vals, vals, hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys), types.BlockID{Hash: h1.Hash()}) - // 3/3 signed + // 3/3 signed. h3 = keys.GenSignedHeaderLastBlockID(chainID, 3, bTime.Add(1*time.Hour), nil, vals, vals, hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys), types.BlockID{Hash: h2.Hash()}) trustPeriod = 4 * time.Hour @@ -65,20 +63,20 @@ var ( valSet, ) deadNode = mockp.NewDeadMock(chainID) - largeFullNode = mockp.New(genMockNode(chainID, 10, 3, 0, bTime)) + largeFullNode = mockp.New(genMockNode(10, 3, 0, bTime)) ) func TestValidateTrustOptions(t *testing.T) { testCases := []struct { - err bool - to light.TrustOptions + expErr error + to light.TrustOptions }{ { - false, + nil, trustOptions, }, { - true, + light.ErrNegativeOrZeroPeriod, light.TrustOptions{ Period: -1 * time.Hour, Height: 1, @@ -86,7 +84,7 @@ func TestValidateTrustOptions(t *testing.T) { }, }, { - true, + light.ErrNegativeOrZeroHeight, light.TrustOptions{ Period: 1 * time.Hour, Height: 0, @@ -94,7 +92,7 @@ func TestValidateTrustOptions(t *testing.T) { }, }, { - true, + light.ErrInvalidHashSize{32, 14}, light.TrustOptions{ Period: 1 * time.Hour, Height: 1, @@ -105,10 +103,11 @@ func TestValidateTrustOptions(t *testing.T) { for _, tc := range testCases { err := tc.to.ValidateBasic() - if tc.err { - assert.Error(t, err) - } else { - assert.NoError(t, err) + switch { + case tc.expErr != nil && assert.Error(t, err): //nolint:testifylint // require.Error doesn't work with the logic here + assert.Equal(t, tc.expErr, err) + default: + require.NoError(t, err) } } } @@ -246,9 +245,9 @@ func TestClient_SequentialVerification(t *testing.T) { _, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(3*time.Hour)) if tc.verifyErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -370,18 +369,18 @@ func TestClient_SkippingVerification(t *testing.T) { _, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(3*time.Hour)) if tc.verifyErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } } // start from a large light block to make sure that the pivot height doesn't select a height outside -// the appropriate range +// the appropriate range. func TestClientLargeBisectionVerification(t *testing.T) { - veryLargeFullNode := mockp.New(genMockNode(chainID, 100, 3, 0, bTime)) + veryLargeFullNode := mockp.New(genMockNode(100, 3, 0, bTime)) trustedLightBlock, err := veryLargeFullNode.LightBlock(ctx, 5) require.NoError(t, err) c, err := light.NewClient( @@ -399,7 +398,7 @@ func TestClientLargeBisectionVerification(t *testing.T) { ) require.NoError(t, err) h, err := c.Update(ctx, bTime.Add(100*time.Minute)) - assert.NoError(t, err) + require.NoError(t, err) h2, err := veryLargeFullNode.LightBlock(ctx, 100) require.NoError(t, err) assert.Equal(t, h, h2) @@ -430,7 +429,7 @@ func TestClientBisectionBetweenTrustedHeaders(t *testing.T) { // verify using bisection the light block between the two trusted light blocks _, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(1*time.Hour)) - assert.NoError(t, err) + require.NoError(t, err) } func TestClient_Cleanup(t *testing.T) { @@ -452,11 +451,11 @@ func TestClient_Cleanup(t *testing.T) { // Check no light blocks exist after Cleanup. l, err := c.TrustedLightBlock(1) - assert.Error(t, err) - assert.Nil(t, l) + require.Error(t, err) + require.Nil(t, l) } -// trustedHeader.Height == options.Height +// trustedHeader.Height == options.Height. func TestClientRestoresTrustedHeaderAfterStartup1(t *testing.T) { // 1. options.Hash == trustedHeader.Hash { @@ -476,7 +475,7 @@ func TestClientRestoresTrustedHeaderAfterStartup1(t *testing.T) { require.NoError(t, err) l, err := c.TrustedLightBlock(1) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, l) assert.Equal(t, l.Hash(), h1.Hash()) assert.Equal(t, l.ValidatorSet.Hash(), h1.ValidatorsHash.Bytes()) @@ -517,15 +516,15 @@ func TestClientRestoresTrustedHeaderAfterStartup1(t *testing.T) { require.NoError(t, err) l, err := c.TrustedLightBlock(1) - assert.NoError(t, err) + require.NoError(t, err) if assert.NotNil(t, l) { assert.Equal(t, l.Hash(), header1.Hash()) - assert.NoError(t, l.ValidateBasic(chainID)) + require.NoError(t, l.ValidateBasic(chainID)) } } } -// trustedHeader.Height < options.Height +// trustedHeader.Height < options.Height. func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) { // 1. options.Hash == trustedHeader.Hash { @@ -550,10 +549,10 @@ func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) { // Check we still have the 1st header (+header+). l, err := c.TrustedLightBlock(1) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, l) assert.Equal(t, l.Hash(), h1.Hash()) - assert.NoError(t, l.ValidateBasic(chainID)) + require.NoError(t, l.ValidateBasic(chainID)) } // 2. options.Hash != trustedHeader.Hash @@ -596,12 +595,12 @@ func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) { // Check we no longer have the invalid 1st header (+header+). l, err := c.TrustedLightBlock(1) - assert.Error(t, err) - assert.Nil(t, l) + require.Error(t, err) + require.Nil(t, l) } } -// trustedHeader.Height > options.Height +// trustedHeader.Height > options.Height. func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) { // 1. options.Hash == trustedHeader.Hash { @@ -626,19 +625,19 @@ func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) { // Check we still have the 1st light block. l, err := c.TrustedLightBlock(1) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, l) assert.Equal(t, l.Hash(), h1.Hash()) - assert.NoError(t, l.ValidateBasic(chainID)) + require.NoError(t, l.ValidateBasic(chainID)) // Check we no longer have 2nd light block. l, err = c.TrustedLightBlock(2) - assert.Error(t, err) - assert.Nil(t, l) + require.Error(t, err) + require.Nil(t, l) l, err = c.TrustedLightBlock(3) - assert.Error(t, err) - assert.Nil(t, l) + require.Error(t, err) + require.Nil(t, l) } // 2. options.Hash != trustedHeader.Hash @@ -685,15 +684,15 @@ func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) { // Check we have swapped invalid 1st light block (+lightblock+) with correct one (+lightblock2+). l, err := c.TrustedLightBlock(1) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, l) assert.Equal(t, l.Hash(), header1.Hash()) - assert.NoError(t, l.ValidateBasic(chainID)) + require.NoError(t, l.ValidateBasic(chainID)) // Check we no longer have invalid 2nd light block (+lightblock2+). l, err = c.TrustedLightBlock(2) - assert.Error(t, err) - assert.Nil(t, l) + require.Error(t, err) + require.Nil(t, l) } } @@ -711,10 +710,10 @@ func TestClient_Update(t *testing.T) { // should result in downloading & verifying header #3 l, err := c.Update(ctx, bTime.Add(2*time.Hour)) - assert.NoError(t, err) + require.NoError(t, err) if assert.NotNil(t, l) { assert.EqualValues(t, 3, l.Height) - assert.NoError(t, l.ValidateBasic(chainID)) + require.NoError(t, l.ValidateBasic(chainID)) } } @@ -745,13 +744,13 @@ func TestClient_Concurrency(t *testing.T) { assert.Equal(t, chainID, c.ChainID()) _, err := c.LastTrustedHeight() - assert.NoError(t, err) + require.NoError(t, err) _, err = c.FirstTrustedHeight() - assert.NoError(t, err) + require.NoError(t, err) l, err := c.TrustedLightBlock(1) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, l) }() } @@ -776,7 +775,7 @@ func TestClientReplacesPrimaryWithWitnessIfPrimaryIsUnavailable(t *testing.T) { require.NoError(t, err) assert.NotEqual(t, c.Primary(), deadNode) - assert.Equal(t, 2, len(c.Witnesses())) + assert.Len(t, c.Witnesses(), 2) } func TestClient_BackwardsVerification(t *testing.T) { @@ -806,12 +805,12 @@ func TestClient_BackwardsVerification(t *testing.T) { // 2) untrusted header is expired but trusted header is not => expect no error h, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(8*time.Minute)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, h) // 3) already stored headers should return the header without error h, err = c.VerifyLightBlockAtHeight(ctx, 5, bTime.Add(6*time.Minute)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, h) // 4a) First verify latest header @@ -820,16 +819,15 @@ func TestClient_BackwardsVerification(t *testing.T) { // 4b) Verify backwards using bisection => expect no error _, err = c.VerifyLightBlockAtHeight(ctx, 7, bTime.Add(9*time.Minute)) - assert.NoError(t, err) + require.NoError(t, err) // shouldn't have verified this header in the process _, err = c.TrustedLightBlock(8) - assert.Error(t, err) + require.Error(t, err) // 5) Try bisection method, but closest header (at 7) has expired // so expect error _, err = c.VerifyLightBlockAtHeight(ctx, 8, bTime.Add(12*time.Minute)) - assert.Error(t, err) - + require.Error(t, err) } { testCases := []struct { @@ -880,7 +878,7 @@ func TestClient_BackwardsVerification(t *testing.T) { require.NoError(t, err, idx) _, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(1*time.Hour).Add(1*time.Second)) - assert.Error(t, err, idx) + require.Error(t, err, idx) } } } @@ -903,7 +901,7 @@ func TestClient_NewClientFromTrustedStore(t *testing.T) { // 2) Check light block exists (deadNode is being used to ensure we're not getting // it from primary) h, err := c.TrustedLightBlock(1) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualValues(t, l1.Height, h.Height) } @@ -954,14 +952,14 @@ func TestClientRemovesWitnessIfItSendsUsIncorrectHeader(t *testing.T) { // witness behaves incorrectly -> removed from list, no error l, err := c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(2*time.Hour)) - assert.NoError(t, err) + require.NoError(t, err) assert.EqualValues(t, 1, len(c.Witnesses())) // light block should still be verified assert.EqualValues(t, 2, l.Height) // remaining witnesses don't have light block -> error _, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(2*time.Hour)) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, light.ErrFailedHeaderCrossReferencing, err) } // witness does not have a light block -> left in the list @@ -998,11 +996,11 @@ func TestClient_TrustedValidatorSet(t *testing.T) { light.Logger(log.TestingLogger()), ) require.NoError(t, err) - assert.Equal(t, 2, len(c.Witnesses())) + assert.Len(t, c.Witnesses(), 2) _, err = c.VerifyLightBlockAtHeight(ctx, 2, bTime.Add(2*time.Hour).Add(1*time.Second)) - assert.NoError(t, err) - assert.Equal(t, 1, len(c.Witnesses())) + require.NoError(t, err) + assert.Len(t, c.Witnesses(), 1) } func TestClientPrunesHeadersAndValidatorSets(t *testing.T) { @@ -1025,7 +1023,7 @@ func TestClientPrunesHeadersAndValidatorSets(t *testing.T) { require.Equal(t, int64(3), h.Height) _, err = c.TrustedLightBlock(1) - assert.Error(t, err) + require.Error(t, err) } func TestClientEnsureValidHeadersAndValSets(t *testing.T) { @@ -1092,15 +1090,15 @@ func TestClientEnsureValidHeadersAndValSets(t *testing.T) { _, err = c.VerifyLightBlockAtHeight(ctx, 3, bTime.Add(2*time.Hour)) if tc.err { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } } } func TestClientHandlesContexts(t *testing.T) { - p := mockp.New(genMockNode(chainID, 100, 10, 1, bTime)) + p := mockp.New(genMockNode(100, 10, 1, bTime)) genBlock, err := p.LightBlock(ctx, 1) require.NoError(t, err) @@ -1121,7 +1119,7 @@ func TestClientHandlesContexts(t *testing.T) { ) require.Error(t, ctxTimeOut.Err()) require.Error(t, err) - require.True(t, errors.Is(err, context.DeadlineExceeded)) + require.ErrorIs(t, err, context.DeadlineExceeded) // instantiate the client for real c, err := light.NewClient( @@ -1144,7 +1142,7 @@ func TestClientHandlesContexts(t *testing.T) { _, err = c.VerifyLightBlockAtHeight(ctxTimeOutBlock, 100, bTime.Add(100*time.Minute)) require.Error(t, ctxTimeOutBlock.Err()) require.Error(t, err) - require.True(t, errors.Is(err, context.DeadlineExceeded)) + require.ErrorIs(t, err, context.DeadlineExceeded) // verify a block with a cancel ctxCancel, cancel := context.WithCancel(ctx) @@ -1153,5 +1151,5 @@ func TestClientHandlesContexts(t *testing.T) { _, err = c.VerifyLightBlockAtHeight(ctxCancel, 100, bTime.Add(100*time.Minute)) require.Error(t, ctxCancel.Err()) require.Error(t, err) - require.True(t, errors.Is(err, context.Canceled)) + require.ErrorIs(t, err, context.Canceled) } diff --git a/light/detector.go b/light/detector.go index 228dec61a6c..82a622c8866 100644 --- a/light/detector.go +++ b/light/detector.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "errors" - "fmt" "time" "github.com/cometbft/cometbft/light/provider" @@ -27,7 +26,7 @@ import ( // trusted and saves it to the trusted store. func (c *Client) detectDivergence(ctx context.Context, primaryTrace []*types.LightBlock, now time.Time) error { if primaryTrace == nil || len(primaryTrace) < 2 { - return errors.New("nil or single block primary trace") + return ErrNilOrSinglePrimaryTrace } var ( headerMatched bool @@ -114,13 +113,12 @@ func (c *Client) detectDivergence(ctx context.Context, primaryTrace []*types.Lig // // 3: nil -> the hashes of the two headers match func (c *Client) compareNewHeaderWithWitness(ctx context.Context, errc chan error, h *types.SignedHeader, - witness provider.Provider, witnessIndex int) { - + witness provider.Provider, witnessIndex int, +) { lightBlock, err := witness.LightBlock(ctx, h.Height) switch err { // no error means we move on to checking the hash of the two headers case nil: - break // the witness hasn't been helpful in comparing headers, we mark the response and continue // comparing with the rest of the witnesses @@ -213,7 +211,7 @@ func (c *Client) sendEvidence(ctx context.Context, ev *types.LightClientAttackEv } // handleConflictingHeaders handles the primary style of attack, which is where a primary and witness have -// two headers of the same height but with different hashes +// two headers of the same height but with different hashes. func (c *Client) handleConflictingHeaders( ctx context.Context, primaryTrace []*types.LightBlock, @@ -238,7 +236,7 @@ func (c *Client) handleConflictingHeaders( // and generate evidence against the primary that we can send to the witness commonBlock, trustedBlock := witnessTrace[0], witnessTrace[len(witnessTrace)-1] evidenceAgainstPrimary := newLightClientAttackEvidence(primaryBlock, trustedBlock, commonBlock) - c.logger.Error("ATTEMPTED ATTACK DETECTED. Sending evidence againt primary by witness", "ev", evidenceAgainstPrimary, + c.logger.Error("ATTEMPTED ATTACK DETECTED. Sending evidence against primary by witness", "ev", evidenceAgainstPrimary, "primary", c.primary, "witness", supportingWitness) c.sendEvidence(ctx, evidenceAgainstPrimary, supportingWitness) @@ -274,7 +272,7 @@ func (c *Client) handleConflictingHeaders( } // examineConflictingHeaderAgainstTrace takes a trace from one provider and a divergent header that -// it has received from another and preforms verifySkipping at the heights of each of the intermediate +// it has received from another and performs verifySkipping at the heights of each of the intermediate // headers in the trace until it reaches the divergentHeader. 1 of 2 things can happen. // // 1. The light client verifies a header that is different to the intermediate header in the trace. This @@ -293,7 +291,6 @@ func (c *Client) examineConflictingHeaderAgainstTrace( targetBlock *types.LightBlock, source provider.Provider, now time.Time, ) ([]*types.LightBlock, *types.LightBlock, error) { - var ( previouslyVerifiedBlock, sourceBlock *types.LightBlock sourceTrace []*types.LightBlock @@ -301,8 +298,7 @@ func (c *Client) examineConflictingHeaderAgainstTrace( ) if targetBlock.Height < trace[0].Height { - return nil, nil, fmt.Errorf("target block has a height lower than the trusted height (%d < %d)", - targetBlock.Height, trace[0].Height) + return nil, nil, ErrTargetBlockHeightLessThanTrusted{Target: targetBlock.Height, Trusted: trace[0].Height} } for idx, traceBlock := range trace { @@ -314,8 +310,7 @@ func (c *Client) examineConflictingHeaderAgainstTrace( // the end of the trace has a lesser time than the target block then all blocks in the trace should have a // lesser time if traceBlock.Time.After(targetBlock.Time) { - return nil, nil, - errors.New("sanity check failed: expected traceblock to have a lesser time than the target block") + return nil, nil, ErrInvalidBlockTime } // before sending back the divergent block and trace we need to ensure we have verified @@ -323,7 +318,7 @@ func (c *Client) examineConflictingHeaderAgainstTrace( if previouslyVerifiedBlock.Height != targetBlock.Height { sourceTrace, err = c.verifySkipping(ctx, source, previouslyVerifiedBlock, targetBlock, now) if err != nil { - return nil, nil, fmt.Errorf("verifySkipping of conflicting header failed: %w", err) + return nil, nil, ErrVerifySkipping{Err: err} } } return sourceTrace, traceBlock, nil @@ -335,7 +330,7 @@ func (c *Client) examineConflictingHeaderAgainstTrace( } else { sourceBlock, err = source.LightBlock(ctx, traceBlock.Height) if err != nil { - return nil, nil, fmt.Errorf("failed to examine trace: %w", err) + return nil, nil, ErrExamineTrace{Err: err} } } @@ -343,8 +338,7 @@ func (c *Client) examineConflictingHeaderAgainstTrace( // else we cannot continue with verification. if idx == 0 { if shash, thash := sourceBlock.Hash(), traceBlock.Hash(); !bytes.Equal(shash, thash) { - return nil, nil, fmt.Errorf("trusted block is different to the source's first block (%X = %X)", - thash, shash) + return nil, nil, ErrBlockHashMismatch{TraceBlockHash: thash, SourceBlockHash: shash} } previouslyVerifiedBlock = sourceBlock continue @@ -354,7 +348,7 @@ func (c *Client) examineConflictingHeaderAgainstTrace( // intermediate height sourceTrace, err = c.verifySkipping(ctx, source, previouslyVerifiedBlock, sourceBlock, now) if err != nil { - return nil, nil, fmt.Errorf("verifySkipping of conflicting header failed: %w", err) + return nil, nil, ErrVerifySkipping{Err: err} } // check if the headers verified by the source has diverged from the trace if shash, thash := sourceBlock.Hash(), traceBlock.Hash(); !bytes.Equal(shash, thash) { @@ -370,13 +364,12 @@ func (c *Client) examineConflictingHeaderAgainstTrace( // prerequisites to this function were not met. Namely that either trace[len(trace)-1].Height < targetBlock.Height // or that trace[i].Hash() != targetBlock.Hash() return nil, nil, errNoDivergence - } // getTargetBlockOrLatest gets the latest height, if it is greater than the target height then it queries // the target height else it returns the latest. returns true if it successfully managed to acquire the target // height. -func (c *Client) getTargetBlockOrLatest( +func (*Client) getTargetBlockOrLatest( ctx context.Context, height int64, witness provider.Provider, diff --git a/light/detector_test.go b/light/detector_test.go index d8afacefd89..bc31d181ddc 100644 --- a/light/detector_test.go +++ b/light/detector_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/light" "github.com/cometbft/cometbft/light/provider" @@ -27,7 +26,7 @@ func TestLightClientAttackEvidence_Lunatic(t *testing.T) { primaryValidators = make(map[int64]*types.ValidatorSet, latestHeight) ) - witnessHeaders, witnessValidators, chainKeys := genMockNodeWithKeys(chainID, latestHeight, valSize, 2, bTime) + witnessHeaders, witnessValidators, chainKeys := genMockNodeWithKeys(latestHeight, valSize, 2, bTime) witness := mockp.New(chainID, witnessHeaders, witnessValidators) forgedKeys := chainKeys[divergenceHeight-1].ChangeKeys(3) // we change 3 out of the 5 validators (still 2/5 remain) forgedVals := forgedKeys.ToValidators(2, 0) @@ -62,7 +61,7 @@ func TestLightClientAttackEvidence_Lunatic(t *testing.T) { // Check verification returns an error. _, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour)) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, light.ErrLightClientAttack, err) } @@ -107,7 +106,7 @@ func TestLightClientAttackEvidence_Equivocation(t *testing.T) { primaryValidators = make(map[int64]*types.ValidatorSet, latestHeight) ) // validators don't change in this network (however we still use a map just for convenience) - witnessHeaders, witnessValidators, chainKeys := genMockNodeWithKeys(chainID, latestHeight+2, valSize, 2, bTime) + witnessHeaders, witnessValidators, chainKeys := genMockNodeWithKeys(latestHeight+2, valSize, 2, bTime) witness := mockp.New(chainID, witnessHeaders, witnessValidators) for height := int64(1); height <= latestHeight; height++ { @@ -145,7 +144,7 @@ func TestLightClientAttackEvidence_Equivocation(t *testing.T) { // Check verification returns an error. _, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour)) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, light.ErrLightClientAttack, err) } @@ -184,7 +183,7 @@ func TestLightClientAttackEvidence_ForwardLunatic(t *testing.T) { primaryValidators = make(map[int64]*types.ValidatorSet, forgedHeight) ) - witnessHeaders, witnessValidators, chainKeys := genMockNodeWithKeys(chainID, latestHeight, valSize, 2, bTime) + witnessHeaders, witnessValidators, chainKeys := genMockNodeWithKeys(latestHeight, valSize, 2, bTime) // primary has the exact same headers except it forges one extra header in the future using keys from 2/5ths of // the validators @@ -259,7 +258,7 @@ func TestLightClientAttackEvidence_ForwardLunatic(t *testing.T) { // Now assert that verification returns an error. We craft the light clients time to be a little ahead of the chain // to allow a window for the attack to manifest itself. _, err = c.Update(ctx, bTime.Add(time.Duration(forgedHeight)*time.Minute)) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, light.ErrLightClientAttack, err) } @@ -276,7 +275,7 @@ func TestLightClientAttackEvidence_ForwardLunatic(t *testing.T) { // We attempt the same call but now the supporting witness has a block which should // immediately conflict in time with the primary _, err = c.VerifyLightBlockAtHeight(ctx, forgedHeight, bTime.Add(time.Duration(forgedHeight)*time.Minute)) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, light.ErrLightClientAttack, err) } assert.True(t, witness.HasEvidence(evAgainstPrimary)) @@ -301,17 +300,17 @@ func TestLightClientAttackEvidence_ForwardLunatic(t *testing.T) { require.NoError(t, err) _, err = c.Update(ctx, bTime.Add(time.Duration(forgedHeight)*time.Minute)) - assert.NoError(t, err) + require.NoError(t, err) } // 1. Different nodes therefore a divergent header is produced. // => light client returns an error upon creation because primary and witness // have a different view. func TestClientDivergentTraces1(t *testing.T) { - primary := mockp.New(genMockNode(chainID, 10, 5, 2, bTime)) + primary := mockp.New(genMockNode(10, 5, 2, bTime)) firstBlock, err := primary.LightBlock(ctx, 1) require.NoError(t, err) - witness := mockp.New(genMockNode(chainID, 10, 5, 2, bTime)) + witness := mockp.New(genMockNode(10, 5, 2, bTime)) _, err = light.NewClient( ctx, @@ -332,9 +331,9 @@ func TestClientDivergentTraces1(t *testing.T) { } // 2. Two out of three nodes don't respond but the third has a header that matches -// => verification should be successful and all the witnesses should remain +// => verification should be successful and all the witnesses should remain. func TestClientDivergentTraces2(t *testing.T) { - primary := mockp.New(genMockNode(chainID, 10, 5, 2, bTime)) + primary := mockp.New(genMockNode(10, 5, 2, bTime)) firstBlock, err := primary.LightBlock(ctx, 1) require.NoError(t, err) c, err := light.NewClient( @@ -354,20 +353,20 @@ func TestClientDivergentTraces2(t *testing.T) { require.NoError(t, err) _, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour)) - assert.NoError(t, err) - assert.Equal(t, 3, len(c.Witnesses())) + require.NoError(t, err) + assert.Len(t, c.Witnesses(), 3) } // 3. witness has the same first header, but different second header -// => creation should succeed, but the verification should fail +// => creation should succeed, but the verification should fail. func TestClientDivergentTraces3(t *testing.T) { - _, primaryHeaders, primaryVals := genMockNode(chainID, 10, 5, 2, bTime) + _, primaryHeaders, primaryVals := genMockNode(10, 5, 2, bTime) primary := mockp.New(chainID, primaryHeaders, primaryVals) firstBlock, err := primary.LightBlock(ctx, 1) require.NoError(t, err) - _, mockHeaders, mockVals := genMockNode(chainID, 10, 5, 2, bTime) + _, mockHeaders, mockVals := genMockNode(10, 5, 2, bTime) mockHeaders[1] = primaryHeaders[1] mockVals[1] = primaryVals[1] witness := mockp.New(chainID, mockHeaders, mockVals) @@ -389,20 +388,20 @@ func TestClientDivergentTraces3(t *testing.T) { require.NoError(t, err) _, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour)) - assert.Error(t, err) - assert.Equal(t, 1, len(c.Witnesses())) + require.Error(t, err) + assert.Len(t, c.Witnesses(), 1) } // 4. Witness has a divergent header but can not produce a valid trace to back it up. -// It should be ignored +// It should be ignored. func TestClientDivergentTraces4(t *testing.T) { - _, primaryHeaders, primaryVals := genMockNode(chainID, 10, 5, 2, bTime) + _, primaryHeaders, primaryVals := genMockNode(10, 5, 2, bTime) primary := mockp.New(chainID, primaryHeaders, primaryVals) firstBlock, err := primary.LightBlock(ctx, 1) require.NoError(t, err) - _, mockHeaders, mockVals := genMockNode(chainID, 10, 5, 2, bTime) + _, mockHeaders, mockVals := genMockNode(10, 5, 2, bTime) witness := primary.Copy(chainID) witness.AddLightBlock(&types.LightBlock{ SignedHeader: mockHeaders[10], @@ -425,6 +424,6 @@ func TestClientDivergentTraces4(t *testing.T) { require.NoError(t, err) _, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour)) - assert.Error(t, err) - assert.Equal(t, 1, len(c.Witnesses())) + require.Error(t, err) + assert.Len(t, c.Witnesses(), 1) } diff --git a/light/doc.go b/light/doc.go index 3cc2741bf05..35f69d84281 100644 --- a/light/doc.go +++ b/light/doc.go @@ -121,7 +121,7 @@ See https://docs.cometbft.com/main/core/light-client.html for usage example. Or see -https://github.com/cometbft/cometbft/tree/main/spec/consensus/light-client +https://github.com/cometbft/cometbft/blob/main/spec/light-client/README.md for the full spec */ package light diff --git a/light/errors.go b/light/errors.go index bc6357def66..fef7b7026d7 100644 --- a/light/errors.go +++ b/light/errors.go @@ -5,9 +5,41 @@ import ( "fmt" "time" + cmtbytes "github.com/cometbft/cometbft/libs/bytes" + cmtmath "github.com/cometbft/cometbft/libs/math" + "github.com/cometbft/cometbft/light/provider" "github.com/cometbft/cometbft/types" ) +var ( + + // ErrFailedHeaderCrossReferencing is returned when the detector was not able to cross reference the header + // with any of the connected witnesses. + ErrFailedHeaderCrossReferencing = errors.New("all witnesses have either not responded, don't have the " + + "blocks or sent invalid blocks. You should look to change your witnesses " + + "or review the light client's logs for more information") + // ErrLightClientAttack is returned when the light client has detected an attempt + // to verify a false header and has sent the evidence to either a witness or primary. + ErrLightClientAttack = errors.New(`attempted attack detected. +Light client received valid conflicting header from witness. +Unable to verify header. Evidence has been sent to both providers. +Check logs for full evidence and trace`) + + // ErrNoWitnesses means that there are not enough witnesses connected to + // continue running the light client. + ErrNoWitnesses = errors.New("no witnesses connected. please reset light client") + ErrNilOrSinglePrimaryTrace = errors.New("nil or single block primary trace") + ErrHeaderHeightAdjacent = errors.New("headers must be non adjacent in height") + ErrHeaderHeightNotAdjacent = errors.New("headers must be adjacent in height") + ErrNegativeOrZeroPeriod = errors.New("negative or zero period") + ErrNegativeHeight = errors.New("negative height") + ErrNegativeOrZeroHeight = errors.New("negative or zero height") + ErrInvalidBlockTime = errors.New("expected traceblock to have a lesser time than the target block") + ErrRemoveStoredBlocksRefused = errors.New("refused to remove the stored light blocks despite hashes mismatch") + ErrNoHeadersExist = errors.New("no headers exist") + ErrNilHeader = errors.New("nil header") +) + // ErrOldHeaderExpired means the old (trusted) header has expired according to // the given trustingPeriod and current time. If so, the light client must be // reset subjectively. @@ -20,6 +52,134 @@ func (e ErrOldHeaderExpired) Error() string { return fmt.Sprintf("old header has expired at %v (now: %v)", e.At, e.Now) } +type ErrTargetBlockHeightLessThanTrusted struct { + Target int64 + Trusted int64 +} + +func (e ErrTargetBlockHeightLessThanTrusted) Error() string { + return fmt.Sprintf("target block has a height lower than the trusted height (%d < %d)", e.Target, e.Trusted) +} + +type ErrHeaderHeightNotMonotonic struct { + GotHeight int64 + OldHeight int64 +} + +func (e ErrHeaderHeightNotMonotonic) Error() string { + return fmt.Sprintf("expected new header height %d to be greater than one of old header %d", e.GotHeight, e.OldHeight) +} + +type ErrHeaderTimeNotMonotonic struct { + GotTime time.Time + OldTime time.Time +} + +func (e ErrHeaderTimeNotMonotonic) Error() string { + return fmt.Sprintf("expected new header time %v to be after old header time %v", e.GotTime, e.OldTime) +} + +type ErrHeaderTimeExceedMaxClockDrift struct { + Ti time.Time + Now time.Time + Drift time.Duration +} + +func (e ErrHeaderTimeExceedMaxClockDrift) Error() string { + return fmt.Sprintf("new header has a time from the future %v (now: %v; max clock drift: %v)", e.Ti, e.Now, e.Drift) +} + +type ErrUnverifiedHeight struct { + Height int64 +} + +func (e ErrUnverifiedHeight) Error() string { + return fmt.Sprintf("unverified header/valset requested (latest: %d)", e.Height) +} + +type ErrInvalidTrustLevel struct { + Level cmtmath.Fraction +} + +func (e ErrInvalidTrustLevel) Error() string { + return fmt.Sprintf("trustLevel must be within [1/3, 1], given %v", e.Level) +} + +type ErrValidatorsMismatch struct { + HeaderHash cmtbytes.HexBytes + ValidatorsHash cmtbytes.HexBytes + Height int64 +} + +func (e ErrValidatorsMismatch) Error() string { + return fmt.Sprintf("expected new header validators (%X) to match those that were supplied (%X) at height %d", e.HeaderHash, e.ValidatorsHash, e.Height) +} + +type ErrValidatorHashMismatch struct { + TrustedHash cmtbytes.HexBytes + ValidatorHash cmtbytes.HexBytes +} + +func (e ErrValidatorHashMismatch) Error() string { + return fmt.Sprintf("expected old header next validators (%X) to match those from new header (%X)", e.TrustedHash, e.ValidatorHash) +} + +type ErrBlockHashMismatch struct { + TraceBlockHash cmtbytes.HexBytes + SourceBlockHash cmtbytes.HexBytes +} + +func (e ErrBlockHashMismatch) Error() string { + return fmt.Sprintf("trusted block is different to the source's first block (%X = %X)", e.TraceBlockHash, e.SourceBlockHash) +} + +type ErrHeaderHashMismatch struct { + Expected cmtbytes.HexBytes + Actual cmtbytes.HexBytes +} + +func (e ErrHeaderHashMismatch) Error() string { + return fmt.Sprintf("expected header's hash %X, but got %X", e.Expected, e.Actual) +} + +type ErrExistingHeaderHashMismatch struct { + Existing cmtbytes.HexBytes + New cmtbytes.HexBytes +} + +func (e ErrExistingHeaderHashMismatch) Error() string { + return fmt.Sprintf("existing trusted header %X does not match newHeader %X", e.Existing, e.New) +} + +type ErrLightHeaderHashMismatch struct { + Existing cmtbytes.HexBytes + New cmtbytes.HexBytes +} + +func (e ErrLightHeaderHashMismatch) Error() string { + return fmt.Sprintf("light block header %X does not match newHeader %X", e.Existing, e.New) +} + +type ErrInvalidHashSize struct { + Expected int + Actual int +} + +func (e ErrInvalidHashSize) Error() string { + return fmt.Sprintf("expected hash size to be %d bytes, got %d bytes", e.Expected, e.Actual) +} + +type ErrUnexpectedChainID struct { + Index int + Witness provider.Provider + Actual string + Expected string +} + +func (e ErrUnexpectedChainID) Error() string { + return fmt.Sprintf("witness #%d: %v is on another chain %s, expected %s", e.Index, e.Witness, e.Actual, e.Expected) +} + // ErrNewValSetCantBeTrusted means the new validator set cannot be trusted // because < 1/3rd (+trustLevel+) of the old validator set has signed. type ErrNewValSetCantBeTrusted struct { @@ -27,7 +187,7 @@ type ErrNewValSetCantBeTrusted struct { } func (e ErrNewValSetCantBeTrusted) Error() string { - return fmt.Sprintf("cant trust new val set: %v", e.Reason) + return fmt.Sprintf("can't trust new val set: %v", e.Reason) } // ErrInvalidHeader means the header either failed the basic validation or @@ -40,11 +200,229 @@ func (e ErrInvalidHeader) Error() string { return fmt.Sprintf("invalid header: %v", e.Reason) } -// ErrFailedHeaderCrossReferencing is returned when the detector was not able to cross reference the header -// with any of the connected witnesses. -var ErrFailedHeaderCrossReferencing = errors.New("all witnesses have either not responded, don't have the " + - " blocks or sent invalid blocks. You should look to change your witnesses" + - " or review the light client's logs for more information") +func (e ErrInvalidHeader) Unwrap() error { + return e.Reason +} + +type ErrVerifySkipping struct { + Err error +} + +func (e ErrVerifySkipping) Error() string { + return fmt.Sprintf("verifySkipping of conflicting header failed: %v", e.Err) +} + +func (e ErrVerifySkipping) Unwrap() error { + return e.Err +} + +type ErrExamineTrace struct { + Err error +} + +func (e ErrExamineTrace) Error() string { + return fmt.Sprintf("failed to examine trace: %v", e.Err) +} + +func (e ErrExamineTrace) Unwrap() error { + return e.Err +} + +type ErrHeaderValidateBasic struct { + Err error +} + +func (e ErrHeaderValidateBasic) Error() string { + return fmt.Sprintf("untrustedHeader.ValidateBasic failed: %v", e.Err) +} + +func (e ErrHeaderValidateBasic) Unwrap() error { + return e.Err +} + +type ErrInvalidTrustOptions struct { + Err error +} + +func (e ErrInvalidTrustOptions) Error() string { + return fmt.Sprintf("invalid TrustOptions: %v", e.Err) +} + +func (e ErrInvalidTrustOptions) Unwrap() error { + return e.Err +} + +type ErrGetTrustedBlock struct { + Err error +} + +func (e ErrGetTrustedBlock) Error() string { + return fmt.Sprintf("can't get last trusted light block: %v", e.Err) +} + +func (e ErrGetTrustedBlock) Unwrap() error { + return e.Err +} + +type ErrGetTrustedBlockHeight struct { + Err error +} + +func (e ErrGetTrustedBlockHeight) Error() string { + return fmt.Sprintf("can't get last trusted light block height: %v", e.Err) +} + +func (e ErrGetTrustedBlockHeight) Unwrap() error { + return e.Err +} + +type ErrCleanup struct { + Err error +} + +func (e ErrCleanup) Error() string { + return fmt.Sprintf("failed to cleanup: %v", e.Err) +} + +func (e ErrCleanup) Unwrap() error { + return e.Err +} + +type ErrGetBlock struct { + Err error +} + +func (e ErrGetBlock) Error() string { + return fmt.Sprintf("failed to retrieve light block from primary to verify against: %v", e.Err) +} + +func (e ErrGetBlock) Unwrap() error { + return e.Err +} + +type ErrGetFirstBlock struct { + Err error +} + +func (e ErrGetFirstBlock) Error() string { + return fmt.Sprintf("can't get first light block: %v", e.Err) +} + +func (e ErrGetFirstBlock) Unwrap() error { + return e.Err +} + +type ErrGetFirstBlockHeight struct { + Err error +} + +func (e ErrGetFirstBlockHeight) Error() string { + return fmt.Sprintf("can't get first light block height: %v", e.Err) +} + +func (e ErrGetFirstBlockHeight) Unwrap() error { + return e.Err +} + +type ErrInvalidCommit struct { + Err error +} + +func (e ErrInvalidCommit) Error() string { + return fmt.Sprintf("invalid commit: %v", e.Err) +} + +func (e ErrInvalidCommit) Unwrap() error { + return e.Err +} + +type ErrGetLastTrustedHeight struct { + Err error +} + +func (e ErrGetLastTrustedHeight) Error() string { + return fmt.Sprintf("can't get last trusted height: %v", e.Err) +} + +func (e ErrGetLastTrustedHeight) Unwrap() error { + return e.Err +} + +type ErrPrune struct { + Err error +} + +func (e ErrPrune) Error() string { + return fmt.Sprintf("prune: %v", e.Err) +} + +func (e ErrPrune) Unwrap() error { + return e.Err +} + +type ErrSaveTrustedHeader struct { + Err error +} + +func (e ErrSaveTrustedHeader) Error() string { + return fmt.Sprintf("failed to save trusted header: %v", e.Err) +} + +func (e ErrSaveTrustedHeader) Unwrap() error { + return e.Err +} + +type ErrCleanupAfter struct { + Height int64 + Err error +} + +func (e ErrCleanupAfter) Error() string { + return fmt.Sprintf("cleanup after height %d failed: %v", e.Height, e.Err) +} + +func (e ErrCleanupAfter) Unwrap() error { + return e.Err +} + +type ErrGetSignedHeaderBeforeHeight struct { + Height int64 + Err error +} + +func (e ErrGetSignedHeaderBeforeHeight) Error() string { + return fmt.Sprintf("can't get signed header before height %d: %v", e.Height, e.Err) +} + +func (e ErrGetSignedHeaderBeforeHeight) Unwrap() error { + return e.Err +} + +type ErrGetHeaderBeforeHeight struct { + Height int64 + Err error +} + +func (e ErrGetHeaderBeforeHeight) Error() string { + return fmt.Sprintf("failed to get header before %d: %v", e.Height, e.Err) +} + +func (e ErrGetHeaderBeforeHeight) Unwrap() error { + return e.Err +} + +type ErrGetHeaderAtHeight struct { + Height int64 + Err error +} + +func (e ErrGetHeaderAtHeight) Error() string { + return fmt.Sprintf("failed to obtain the header at height #%d: %v", e.Height, e.Err) +} + +func (e ErrGetHeaderAtHeight) Unwrap() error { + return e.Err +} // ErrVerificationFailed means either sequential or skipping verification has // failed to verify from header #1 to header #2 due to some reason. @@ -63,18 +441,6 @@ func (e ErrVerificationFailed) Error() string { return fmt.Sprintf("verify from #%d to #%d failed: %v", e.From, e.To, e.Reason) } -// ErrLightClientAttack is returned when the light client has detected an attempt -// to verify a false header and has sent the evidence to either a witness or primary. -var ErrLightClientAttack = errors.New(`attempted attack detected. - Light client received valid conflicting header from witness. - Unable to verify header. Evidence has been sent to both providers. - Check logs for full evidence and trace`, -) - -// ErrNoWitnesses means that there are not enough witnesses connected to -// continue running the light client. -var ErrNoWitnesses = errors.New("no witnesses connected. please reset light client") - // ----------------------------- INTERNAL ERRORS --------------------------------- // ErrConflictingHeaders is thrown when two conflicting headers are discovered. @@ -100,6 +466,10 @@ func (e errBadWitness) Error() string { return fmt.Sprintf("Witness %d returned error: %s", e.WitnessIndex, e.Reason.Error()) } +func (e errBadWitness) Unwrap() error { + return e.Reason +} + var errNoDivergence = errors.New( "sanity check failed: no divergence between the original trace and the provider's new trace", ) diff --git a/light/example_test.go b/light/example_test.go index 45304de9a44..11506ed531f 100644 --- a/light/example_test.go +++ b/light/example_test.go @@ -9,7 +9,6 @@ import ( "time" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/abci/example/kvstore" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/light" @@ -17,6 +16,7 @@ import ( httpp "github.com/cometbft/cometbft/light/provider/http" dbs "github.com/cometbft/cometbft/light/store/db" rpctest "github.com/cometbft/cometbft/rpc/test" + cmttime "github.com/cometbft/cometbft/types/time" ) // Automatically getting new headers and verifying them. @@ -71,7 +71,7 @@ func ExampleClient_Update() { time.Sleep(2 * time.Second) - h, err := c.Update(context.Background(), time.Now()) + h, err := c.Update(context.Background(), cmttime.Now()) if err != nil { stdlog.Fatal(err) } @@ -134,7 +134,7 @@ func ExampleClient_VerifyLightBlockAtHeight() { } }() - _, err = c.VerifyLightBlockAtHeight(context.Background(), 3, time.Now()) + _, err = c.VerifyLightBlockAtHeight(context.Background(), 3, cmttime.Now()) if err != nil { stdlog.Fatal(err) } @@ -151,11 +151,11 @@ func ExampleClient_VerifyLightBlockAtHeight() { func TestMain(m *testing.M) { // start a CometBFT node (and kvstore) in the background to test against app := kvstore.NewInMemoryApplication() - node := rpctest.StartTendermint(app, rpctest.SuppressStdout) + node := rpctest.StartCometBFT(app, rpctest.SuppressStdout) code := m.Run() // and shut down proper at the end - rpctest.StopTendermint(node) + rpctest.StopCometBFT(node) os.Exit(code) } diff --git a/light/helpers_test.go b/light/helpers_test.go index e88335c4cf4..ce06eeb6d89 100644 --- a/light/helpers_test.go +++ b/light/helpers_test.go @@ -3,11 +3,10 @@ package light_test import ( "time" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/crypto/tmhash" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" @@ -99,8 +98,8 @@ func (pkz privKeys) signHeader(header *types.Header, valSet *types.ValidatorSet, } func makeVote(header *types.Header, valset *types.ValidatorSet, - key crypto.PrivKey, blockID types.BlockID) *types.Vote { - + key crypto.PrivKey, blockID types.BlockID, +) *types.Vote { addr := key.PubKey().Address() idx, _ := valset.GetByAddress(addr) vote := &types.Vote{ @@ -109,7 +108,7 @@ func makeVote(header *types.Header, valset *types.ValidatorSet, Height: header.Height, Round: 1, Timestamp: cmttime.Now(), - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, BlockID: blockID, } @@ -133,8 +132,8 @@ func makeVote(header *types.Header, valset *types.ValidatorSet, } func genHeader(chainID string, height int64, bTime time.Time, txs types.Txs, - valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte) *types.Header { - + valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, +) *types.Header { return &types.Header{ Version: cmtversion.Consensus{Block: version.BlockProtocol, App: 0}, ChainID: chainID, @@ -154,8 +153,8 @@ func genHeader(chainID string, height int64, bTime time.Time, txs types.Txs, // GenSignedHeader calls genHeader and signHeader and combines them into a SignedHeader. func (pkz privKeys) GenSignedHeader(chainID string, height int64, bTime time.Time, txs types.Txs, - valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, first, last int) *types.SignedHeader { - + valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, first, last int, +) *types.SignedHeader { header := genHeader(chainID, height, bTime, txs, valset, nextValset, appHash, consHash, resHash) return &types.SignedHeader{ Header: header, @@ -166,8 +165,8 @@ func (pkz privKeys) GenSignedHeader(chainID string, height int64, bTime time.Tim // GenSignedHeaderLastBlockID calls genHeader and signHeader and combines them into a SignedHeader. func (pkz privKeys) GenSignedHeaderLastBlockID(chainID string, height int64, bTime time.Time, txs types.Txs, valset, nextValset *types.ValidatorSet, appHash, consHash, resHash []byte, first, last int, - lastBlockID types.BlockID) *types.SignedHeader { - + lastBlockID types.BlockID, +) *types.SignedHeader { header := genHeader(chainID, height, bTime, txs, valset, nextValset, appHash, consHash, resHash) header.LastBlockID = lastBlockID return &types.SignedHeader{ @@ -185,16 +184,16 @@ func (pkz privKeys) ChangeKeys(delta int) privKeys { // blockSize) and with variation in validator sets. BlockIntervals are in per minute. // NOTE: Expected to have a large validator set size ~ 100 validators. func genMockNodeWithKeys( - chainID string, blockSize int64, valSize int, valVariation float32, bTime time.Time) ( map[int64]*types.SignedHeader, map[int64]*types.ValidatorSet, - map[int64]privKeys) { - + map[int64]privKeys, +) { var ( + chainID = "test-chain" headers = make(map[int64]*types.SignedHeader, blockSize) valset = make(map[int64]*types.ValidatorSet, blockSize+1) keymap = make(map[int64]privKeys, blockSize+1) @@ -239,15 +238,16 @@ func genMockNodeWithKeys( } func genMockNode( - chainID string, blockSize int64, valSize int, valVariation float32, bTime time.Time) ( string, map[int64]*types.SignedHeader, - map[int64]*types.ValidatorSet) { - headers, valset, _ := genMockNodeWithKeys(chainID, blockSize, valSize, valVariation, bTime) + map[int64]*types.ValidatorSet, +) { + chainID := "test-chain" + headers, valset, _ := genMockNodeWithKeys(blockSize, valSize, valVariation, bTime) return chainID, headers, valset } diff --git a/light/provider/errors.go b/light/provider/errors.go index 398647b3e17..b3ef342008f 100644 --- a/light/provider/errors.go +++ b/light/provider/errors.go @@ -7,14 +7,14 @@ import ( var ( // ErrHeightTooHigh is returned when the height is higher than the last - // block that the provider has. The light client will not remove the provider + // block that the provider has. The light client will not remove the provider. ErrHeightTooHigh = errors.New("height requested is too high") // ErrLightBlockNotFound is returned when a provider can't find the // requested header (i.e. it has been pruned). - // The light client will not remove the provider + // The light client will not remove the provider. ErrLightBlockNotFound = errors.New("light block not found") // ErrNoResponse is returned if the provider doesn't respond to the - // request in a gieven time + // request in a gieven time. ErrNoResponse = errors.New("client failed to respond") ) @@ -25,5 +25,17 @@ type ErrBadLightBlock struct { } func (e ErrBadLightBlock) Error() string { - return fmt.Sprintf("client provided bad signed header: %s", e.Reason.Error()) + return "client provided bad signed header: " + e.Reason.Error() +} + +func (e ErrBadLightBlock) Unwrap() error { + return e.Reason +} + +type ErrNegativeHeight struct { + Height int64 +} + +func (e ErrNegativeHeight) Error() string { + return fmt.Sprintf("expected height >= 0, got height %d", e.Height) } diff --git a/light/provider/http/http.go b/light/provider/http/http.go index 9fb01dd96c1..0478ea01938 100644 --- a/light/provider/http/http.go +++ b/light/provider/http/http.go @@ -39,7 +39,7 @@ func New(chainID, remote string) (provider.Provider, error) { remote = "http://" + remote } - httpClient, err := rpchttp.NewWithTimeout(remote, "/websocket", timeout) + httpClient, err := rpchttp.NewWithTimeout(remote, timeout) if err != nil { return nil, err } @@ -164,7 +164,6 @@ OUTER_LOOP: default: return nil, err } - } } @@ -180,6 +179,15 @@ func (p *http) signedHeader(ctx context.Context, height *int64) (*types.SignedHe commit, err := p.client.Commit(ctx, height) switch { case err == nil: + // See https://github.com/cometbft/cometbft/issues/575 + // If the node is starting at a non-zero height, but does not yet + // have any blocks, it can return an empty signed header without + // returning an error. + if commit.SignedHeader.IsEmpty() { + // Technically this means that the provider still needs to + // catch up. + return nil, provider.ErrHeightTooHigh + } return &commit.SignedHeader, nil case regexpTooHigh.MatchString(err.Error()): @@ -203,7 +211,7 @@ func (p *http) signedHeader(ctx context.Context, height *int64) (*types.SignedHe func validateHeight(height int64) (*int64, error) { if height < 0 { - return nil, fmt.Errorf("expected height >= 0, got height %d", height) + return nil, provider.ErrNegativeHeight{Height: height} } h := &height @@ -214,7 +222,7 @@ func validateHeight(height int64) (*int64, error) { } // exponential backoff (with jitter) -// 0.5s -> 2s -> 4.5s -> 8s -> 12.5 with 1s variation +// 0.5s -> 2s -> 4.5s -> 8s -> 12.5 with 1s variation. func backoffTimeout(attempt uint16) time.Duration { //nolint:gosec // G404: Use of weak random number generator return time.Duration(500*attempt*attempt)*time.Millisecond + time.Duration(rand.Intn(1000))*time.Millisecond diff --git a/light/provider/http/http_test.go b/light/provider/http/http_test.go index 3ef7dbb1795..f6b4565d9a0 100644 --- a/light/provider/http/http_test.go +++ b/light/provider/http/http_test.go @@ -22,72 +22,80 @@ import ( func TestNewProvider(t *testing.T) { c, err := lighthttp.New("chain-test", "192.168.0.1:26657") require.NoError(t, err) - require.Equal(t, fmt.Sprintf("%s", c), "http{http://192.168.0.1:26657}") + require.Equal(t, "http{http://192.168.0.1:26657}", fmt.Sprintf("%s", c)) c, err = lighthttp.New("chain-test", "http://153.200.0.1:26657") require.NoError(t, err) - require.Equal(t, fmt.Sprintf("%s", c), "http{http://153.200.0.1:26657}") + require.Equal(t, "http{http://153.200.0.1:26657}", fmt.Sprintf("%s", c)) c, err = lighthttp.New("chain-test", "153.200.0.1") require.NoError(t, err) - require.Equal(t, fmt.Sprintf("%s", c), "http{http://153.200.0.1}") + require.Equal(t, "http{http://153.200.0.1}", fmt.Sprintf("%s", c)) } func TestProvider(t *testing.T) { - app := kvstore.NewInMemoryApplication() - app.RetainBlocks = 10 - node := rpctest.StartTendermint(app) - - cfg := rpctest.GetConfig() - defer os.RemoveAll(cfg.RootDir) - rpcAddr := cfg.RPC.ListenAddress - genDoc, err := types.GenesisDocFromFile(cfg.GenesisFile()) - require.NoError(t, err) - chainID := genDoc.ChainID - - c, err := rpchttp.New(rpcAddr, "/websocket") - require.Nil(t, err) - - p := lighthttp.NewWithClient(chainID, c) - require.NoError(t, err) - require.NotNil(t, p) - - // let it produce some blocks - err = rpcclient.WaitForHeight(c, 10, nil) - require.NoError(t, err) - - // let's get the highest block - lb, err := p.LightBlock(context.Background(), 0) - require.NoError(t, err) - require.NotNil(t, lb) - assert.True(t, lb.Height < 1000) - - // let's check this is valid somehow - assert.Nil(t, lb.ValidateBasic(chainID)) - - // historical queries now work :) - lower := lb.Height - 3 - lb, err = p.LightBlock(context.Background(), lower) - require.NoError(t, err) - assert.Equal(t, lower, lb.Height) - - // fetching missing heights (both future and pruned) should return appropriate errors - lb, err = p.LightBlock(context.Background(), 1000) - require.Error(t, err) - require.Nil(t, lb) - assert.Equal(t, provider.ErrHeightTooHigh, err) - - _, err = p.LightBlock(context.Background(), 1) - require.Error(t, err) - require.Nil(t, lb) - assert.Equal(t, provider.ErrLightBlockNotFound, err) - - // stop the full node and check that a no response error is returned - rpctest.StopTendermint(node) - time.Sleep(10 * time.Second) - lb, err = p.LightBlock(context.Background(), lower+2) - // we should see a connection refused - require.Error(t, err) - require.Contains(t, err.Error(), "connection refused") - require.Nil(t, lb) + for _, path := range []string{"", "/", "/v1", "/v1/"} { + app := kvstore.NewInMemoryApplication() + app.RetainBlocks = 10 + node := rpctest.StartCometBFT(app, rpctest.RecreateConfig) + + cfg := rpctest.GetConfig() + defer os.RemoveAll(cfg.RootDir) + rpcAddr := cfg.RPC.ListenAddress + genDoc, err := types.GenesisDocFromFile(cfg.GenesisFile()) + require.NoError(t, err) + chainID := genDoc.ChainID + + c, err := rpchttp.New(rpcAddr + path) + require.NoError(t, err) + + p := lighthttp.NewWithClient(chainID, c) + require.NoError(t, err) + require.NotNil(t, p) + + // let it produce some blocks + err = rpcclient.WaitForHeight(c, 10, nil) + require.NoError(t, err) + + // let's get the highest block + lb, err := p.LightBlock(context.Background(), 0) + require.NoError(t, err) + require.NotNil(t, lb) + assert.GreaterOrEqual(t, lb.Height, int64(10)) + + // let's check this is valid somehow + require.NoError(t, lb.ValidateBasic(chainID)) + + // historical queries now work :) + lb, err = p.LightBlock(context.Background(), 0) + require.NoError(t, err) + require.NotNil(t, lb) + lower := lb.Height - 3 + lb, err = p.LightBlock(context.Background(), lower) + require.NoError(t, err) + assert.Equal(t, lower, lb.Height) + + // fetching missing heights (both future and pruned) should return appropriate errors + lb, err = p.LightBlock(context.Background(), 0) + require.NoError(t, err) + require.NotNil(t, lb) + lb, err = p.LightBlock(context.Background(), lb.Height+100000) + require.Error(t, err) + require.Nil(t, lb) + assert.Equal(t, provider.ErrHeightTooHigh, err) + + _, err = p.LightBlock(context.Background(), 1) + require.Error(t, err) + require.Nil(t, lb) + assert.Equal(t, provider.ErrLightBlockNotFound, err) + + // stop the full node and check that a no response error is returned + rpctest.StopCometBFT(node) + time.Sleep(10 * time.Second) + lb, err = p.LightBlock(context.Background(), lower+2) + // we should see a connection refused + require.Error(t, err) + require.Contains(t, err.Error(), "connection refused") + require.Nil(t, lb) + } } diff --git a/light/provider/mock/deadmock.go b/light/provider/mock/deadmock.go index 8e388107380..1d12838026f 100644 --- a/light/provider/mock/deadmock.go +++ b/light/provider/mock/deadmock.go @@ -18,12 +18,12 @@ func NewDeadMock(chainID string) provider.Provider { func (p *deadMock) ChainID() string { return p.chainID } -func (p *deadMock) String() string { return "deadMock" } +func (*deadMock) String() string { return "deadMock" } -func (p *deadMock) LightBlock(_ context.Context, height int64) (*types.LightBlock, error) { +func (*deadMock) LightBlock(context.Context, int64) (*types.LightBlock, error) { return nil, provider.ErrNoResponse } -func (p *deadMock) ReportEvidence(_ context.Context, ev types.Evidence) error { +func (*deadMock) ReportEvidence(context.Context, types.Evidence) error { return provider.ErrNoResponse } diff --git a/light/provider/provider.go b/light/provider/provider.go index 333d8c1e891..7a20e26ede5 100644 --- a/light/provider/provider.go +++ b/light/provider/provider.go @@ -25,5 +25,5 @@ type Provider interface { LightBlock(ctx context.Context, height int64) (*types.LightBlock, error) // ReportEvidence reports an evidence of misbehavior. - ReportEvidence(context.Context, types.Evidence) error + ReportEvidence(ctx context.Context, ev types.Evidence) error } diff --git a/light/proxy/errors.go b/light/proxy/errors.go new file mode 100644 index 00000000000..0c92dd6faf6 --- /dev/null +++ b/light/proxy/errors.go @@ -0,0 +1,28 @@ +package proxy + +import "fmt" + +type ErrCreateHTTPClient struct { + Addr string + Err error +} + +func (e ErrCreateHTTPClient) Error() string { + return fmt.Sprintf("failed to create http client for %s: %v", e.Addr, e.Err) +} + +func (e ErrCreateHTTPClient) Unwrap() error { + return e.Err +} + +type ErrStartHTTPClient struct { + Err error +} + +func (e ErrStartHTTPClient) Error() string { + return fmt.Sprintf("can't start client: %v", e.Err) +} + +func (e ErrStartHTTPClient) Unwrap() error { + return e.Err +} diff --git a/light/proxy/proxy.go b/light/proxy/proxy.go index 450169a56b5..74bd7675b49 100644 --- a/light/proxy/proxy.go +++ b/light/proxy/proxy.go @@ -2,12 +2,11 @@ package proxy import ( "context" - "fmt" "net" "net/http" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" "github.com/cometbft/cometbft/libs/log" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" "github.com/cometbft/cometbft/light" lrpc "github.com/cometbft/cometbft/light/rpc" rpchttp "github.com/cometbft/cometbft/rpc/client/http" @@ -32,9 +31,9 @@ func NewProxy( logger log.Logger, opts ...lrpc.Option, ) (*Proxy, error) { - rpcClient, err := rpchttp.NewWithTimeout(providerAddr, "/websocket", uint(config.WriteTimeout.Seconds())) + rpcClient, err := rpchttp.NewWithTimeout(providerAddr, uint(config.WriteTimeout.Seconds())) if err != nil { - return nil, fmt.Errorf("failed to create http client for %s: %w", providerAddr, err) + return nil, ErrCreateHTTPClient{Addr: providerAddr, Err: err} } return &Proxy{ @@ -104,11 +103,12 @@ func (p *Proxy) listen() (net.Listener, *http.ServeMux, error) { ) wm.SetLogger(wmLogger) mux.HandleFunc("/websocket", wm.WebsocketHandler) + mux.HandleFunc("/v1/websocket", wm.WebsocketHandler) // 3) Start a client. if !p.Client.IsRunning() { if err := p.Client.Start(); err != nil { - return nil, mux, fmt.Errorf("can't start client: %w", err) + return nil, mux, ErrStartHTTPClient{Err: err} } } diff --git a/light/proxy/routes.go b/light/proxy/routes.go index 62e20712706..e779f3c384f 100644 --- a/light/proxy/routes.go +++ b/light/proxy/routes.go @@ -73,7 +73,7 @@ func makeStatusFunc(c *lrpc.Client) rpcStatusFunc { type rpcNetInfoFunc func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultNetInfo, error) func makeNetInfoFunc(c *lrpc.Client) rpcNetInfoFunc { - return func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultNetInfo, error) { + return func(ctx *rpctypes.Context, _, _ int64) (*ctypes.ResultNetInfo, error) { return c.NetInfo(ctx.Context()) } } @@ -190,7 +190,7 @@ func makeBlockSearchFunc(c *lrpc.Client) rpcBlockSearchFunc { return func( ctx *rpctypes.Context, query string, - prove bool, + _ bool, page, perPage *int, orderBy string, ) (*ctypes.ResultBlockSearch, error) { diff --git a/light/rpc/client.go b/light/rpc/client.go index b26c51a9d23..e3b5a32ce34 100644 --- a/light/rpc/client.go +++ b/light/rpc/client.go @@ -3,24 +3,23 @@ package rpc import ( "bytes" "context" - "errors" "fmt" "regexp" "time" "github.com/cometbft/cometbft/crypto/merkle" + "github.com/cometbft/cometbft/internal/service" + "github.com/cometbft/cometbft/internal/state" cmtbytes "github.com/cometbft/cometbft/libs/bytes" cmtmath "github.com/cometbft/cometbft/libs/math" - service "github.com/cometbft/cometbft/libs/service" rpcclient "github.com/cometbft/cometbft/rpc/client" ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" - "github.com/cometbft/cometbft/state" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" + cmttime "github.com/cometbft/cometbft/types/time" ) -var errNegOrZeroHeight = errors.New("negative or zero height") - // KeyPathFunc builds a merkle path out of the given path and key. type KeyPathFunc func(path string, key []byte) (merkle.KeyPath, error) @@ -66,7 +65,7 @@ func KeyPathFn(fn KeyPathFunc) Option { // DefaultMerkleKeyPathFn creates a function used to generate merkle key paths // from a path string and a key. This is the default used by the cosmos SDK. -// This merkle key paths are required when verifying /abci_query calls +// This merkle key paths are required when verifying /abci_query calls. func DefaultMerkleKeyPathFn() KeyPathFunc { // regexp for extracting store name from /abci_query path storeNameRegexp := regexp.MustCompile(`\/store\/(.+)\/key`) @@ -74,7 +73,7 @@ func DefaultMerkleKeyPathFn() KeyPathFunc { return func(path string, key []byte) (merkle.KeyPath, error) { matches := storeNameRegexp.FindStringSubmatch(path) if len(matches) != 2 { - return nil, fmt.Errorf("can't find store name in %s using %s", path, storeNameRegexp) + return nil, ErrMissingStoreName{Path: path, Rex: storeNameRegexp} } storeName := matches[1] @@ -129,8 +128,8 @@ func (c *Client) ABCIQuery(ctx context.Context, path string, data cmtbytes.HexBy // ABCIQueryWithOptions returns an error if opts.Prove is false. func (c *Client) ABCIQueryWithOptions(ctx context.Context, path string, data cmtbytes.HexBytes, - opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { - + opts rpcclient.ABCIQueryOptions, +) (*ctypes.ResultABCIQuery, error) { // always request the proof opts.Prove = true @@ -142,16 +141,16 @@ func (c *Client) ABCIQueryWithOptions(ctx context.Context, path string, data cmt // Validate the response. if resp.IsErr() { - return nil, fmt.Errorf("err response code: %v", resp.Code) + return nil, ErrResponseCode{Code: resp.Code} } if len(resp.Key) == 0 { - return nil, errors.New("empty key") + return nil, cmterrors.ErrRequiredField{Field: "key"} } if resp.ProofOps == nil || len(resp.ProofOps.Ops) == 0 { - return nil, errors.New("no proof ops") + return nil, ErrNoProofOps } if resp.Height <= 0 { - return nil, errNegOrZeroHeight + return nil, ErrNegOrZeroHeight } // Update the light client if we're behind. @@ -166,23 +165,23 @@ func (c *Client) ABCIQueryWithOptions(ctx context.Context, path string, data cmt if resp.Value != nil { // 1) build a Merkle key path from path and resp.Key if c.keyPathFn == nil { - return nil, errors.New("please configure Client with KeyPathFn option") + return nil, ErrNilKeyPathFn } kp, err := c.keyPathFn(path, resp.Key) if err != nil { - return nil, fmt.Errorf("can't build merkle key path: %w", err) + return nil, ErrBuildMerkleKeyPath{Err: err} } // 2) verify value err = c.prt.VerifyValue(resp.ProofOps, l.AppHash, kp.String(), resp.Value) if err != nil { - return nil, fmt.Errorf("verify value proof: %w", err) + return nil, ErrVerifyValueProof{Err: err} } } else { // OR validate the absence proof against the trusted header. err = c.prt.VerifyAbsence(resp.ProofOps, l.AppHash, string(resp.Key)) if err != nil { - return nil, fmt.Errorf("verify absence proof: %w", err) + return nil, ErrVerifyAbsenceProof{Err: err} } } @@ -236,7 +235,7 @@ func (c *Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.Re return nil, err } if res.BlockHeight <= 0 { - return nil, errNegOrZeroHeight + return nil, ErrNegOrZeroHeight } // Update the light client if we're behind. @@ -247,8 +246,7 @@ func (c *Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.Re // Verify hash. if cH, tH := res.ConsensusParams.Hash(), l.ConsensusHash; !bytes.Equal(cH, tH) { - return nil, fmt.Errorf("params hash %X does not match trusted hash %X", - cH, tH) + return nil, ErrParamHashMismatch{ConsensusParamsHash: cH, ConsensusHash: tH} } return res, nil @@ -269,10 +267,10 @@ func (c *Client) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) // Validate res. for i, meta := range res.BlockMetas { if meta == nil { - return nil, fmt.Errorf("nil block meta %d", i) + return nil, ErrNilBlockMeta{Index: i} } if err := meta.ValidateBasic(); err != nil { - return nil, fmt.Errorf("invalid block meta %d: %w", i, err) + return nil, ErrInvalidBlockMeta{I: i, Err: err} } } @@ -288,11 +286,10 @@ func (c *Client) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) for _, meta := range res.BlockMetas { h, err := c.lc.TrustedLightBlock(meta.Header.Height) if err != nil { - return nil, fmt.Errorf("trusted header %d: %w", meta.Header.Height, err) + return nil, ErrTrustedHeader{Height: meta.Header.Height, Err: err} } if bmH, tH := meta.Header.Hash(), h.Hash(); !bytes.Equal(bmH, tH) { - return nil, fmt.Errorf("block meta header %X does not match with trusted header %X", - bmH, tH) + return nil, ErrBlockMetaHeaderMismatch{BlockMetaHeader: bmH, TrustedHeader: tH} } } @@ -322,8 +319,7 @@ func (c *Client) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, return nil, err } if bmH, bH := res.BlockID.Hash, res.Block.Hash(); !bytes.Equal(bmH, bH) { - return nil, fmt.Errorf("blockID %X does not match with block %X", - bmH, bH) + return nil, ErrBlockIDMismatch{BlockID: bmH, Block: bH} } // Update the light client if we're behind. @@ -334,8 +330,7 @@ func (c *Client) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, // Verify block. if bH, tH := res.Block.Hash(), l.Hash(); !bytes.Equal(bH, tH) { - return nil, fmt.Errorf("block header %X does not match with trusted header %X", - bH, tH) + return nil, ErrBlockHeaderMismatch{BlockHeader: bH, TrustedHeader: tH} } return res, nil @@ -356,8 +351,7 @@ func (c *Client) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBl return nil, err } if bmH, bH := res.BlockID.Hash, res.Block.Hash(); !bytes.Equal(bmH, bH) { - return nil, fmt.Errorf("blockID %X does not match with block %X", - bmH, bH) + return nil, ErrBlockIDMismatch{BlockID: bmH, Block: bH} } // Update the light client if we're behind. @@ -368,8 +362,7 @@ func (c *Client) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBl // Verify block. if bH, tH := res.Block.Hash(), l.Hash(); !bytes.Equal(bH, tH) { - return nil, fmt.Errorf("block header %X does not match with trusted header %X", - bH, tH) + return nil, ErrBlockHeaderMismatch{BlockHeader: bH, TrustedHeader: tH} } return res, nil @@ -377,13 +370,13 @@ func (c *Client) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBl // BlockResults returns the block results for the given height. If no height is // provided, the results of the block preceding the latest are returned. -// NOTE: Light client only verifies the tx results +// NOTE: Light client only verifies the tx results. func (c *Client) BlockResults(ctx context.Context, height *int64) (*ctypes.ResultBlockResults, error) { var h int64 if height == nil { res, err := c.next.Status(ctx) if err != nil { - return nil, fmt.Errorf("can't get latest height: %w", err) + return nil, ErrGetLatestHeight{Err: err} } // Can't return the latest block results here because we won't be able to // prove them. Return the results for the previous block instead. @@ -399,7 +392,7 @@ func (c *Client) BlockResults(ctx context.Context, height *int64) (*ctypes.Resul // Validate res. if res.Height <= 0 { - return nil, errNegOrZeroHeight + return nil, ErrNegOrZeroHeight } // Update the light client if we're behind. @@ -410,18 +403,17 @@ func (c *Client) BlockResults(ctx context.Context, height *int64) (*ctypes.Resul } // Build a Merkle tree out of the above 3 binary slices. - rH := state.TxResultsHash(res.TxsResults) + rH := state.TxResultsHash(res.TxResults) // Verify block results. if !bytes.Equal(rH, trustedBlock.LastResultsHash) { - return nil, fmt.Errorf("last results %X does not match with trusted last results %X", - rH, trustedBlock.LastResultsHash) + return nil, ErrLastResultMismatch{ResultHash: rH, LastResultHash: trustedBlock.LastResultsHash} } return res, nil } -// Header fetches and verifies the header directly via the light client +// Header fetches and verifies the header directly via the light client. func (c *Client) Header(ctx context.Context, height *int64) (*ctypes.ResultHeader, error) { lb, err := c.updateLightClientIfNeededTo(ctx, height) if err != nil { @@ -448,8 +440,7 @@ func (c *Client) HeaderByHash(ctx context.Context, hash cmtbytes.HexBytes) (*cty } if !bytes.Equal(lb.Header.Hash(), res.Header.Hash()) { - return nil, fmt.Errorf("primary header hash does not match trusted header hash. (%X != %X)", - lb.Header.Hash(), res.Header.Hash()) + return nil, ErrPrimaryHeaderMismatch{PrimaryHeaderHash: lb.Header.Hash(), TrustedHeaderHash: res.Header.Hash()} } return res, nil @@ -479,7 +470,7 @@ func (c *Client) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.Resul // Validate res. if res.Height <= 0 { - return nil, errNegOrZeroHeight + return nil, ErrNegOrZeroHeight } // Update the light client if we're behind. @@ -517,7 +508,6 @@ func (c *Client) Validators( height *int64, pagePtr, perPagePtr *int, ) (*ctypes.ResultValidators, error) { - // Update the light client if we're behind and retrieve the light block at the // requested height or at the latest height if no height is provided. l, err := c.updateLightClientIfNeededTo(ctx, height) @@ -539,7 +529,8 @@ func (c *Client) Validators( BlockHeight: l.Height, Validators: v, Count: len(v), - Total: totalCount}, nil + Total: totalCount, + }, nil } func (c *Client) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { @@ -547,7 +538,8 @@ func (c *Client) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*cty } func (c *Client) Subscribe(ctx context.Context, subscriber, query string, - outCapacity ...int) (out <-chan ctypes.ResultEvent, err error) { + outCapacity ...int, +) (out <-chan ctypes.ResultEvent, err error) { return c.next.Subscribe(ctx, subscriber, query, outCapacity...) } @@ -565,12 +557,12 @@ func (c *Client) updateLightClientIfNeededTo(ctx context.Context, height *int64) err error ) if height == nil { - l, err = c.lc.Update(ctx, time.Now()) + l, err = c.lc.Update(ctx, cmttime.Now()) } else { - l, err = c.lc.VerifyLightBlockAtHeight(ctx, *height, time.Now()) + l, err = c.lc.VerifyLightBlockAtHeight(ctx, *height, cmttime.Now()) } if err != nil { - return nil, fmt.Errorf("failed to update light client to %d: %w", *height, err) + return nil, ErrUpdateClient{Height: *height, Err: err} } return l, nil } @@ -581,7 +573,7 @@ func (c *Client) RegisterOpDecoder(typ string, dec merkle.OpDecoder) { // SubscribeWS subscribes for events using the given query and remote address as // a subscriber, but does not verify responses (UNSAFE)! -// TODO: verify data +// TODO: verify data. func (c *Client) SubscribeWS(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, error) { out, err := c.next.Subscribe(context.Background(), ctx.RemoteAddr(), query) if err != nil { @@ -628,9 +620,9 @@ func (c *Client) UnsubscribeAllWS(ctx *rpctypes.Context) (*ctypes.ResultUnsubscr return &ctypes.ResultUnsubscribe{}, nil } -// XXX: Copied from rpc/core/env.go +// XXX: Copied from rpc/core/env.go. const ( - // see README + // see README. defaultPerPage = 30 maxPerPage = 100 ) @@ -650,7 +642,7 @@ func validatePage(pagePtr *int, perPage, totalCount int) (int, error) { } page := *pagePtr if page <= 0 || page > pages { - return 1, fmt.Errorf("page should be within [1, %d] range, given %d", pages, page) + return 1, ErrPageRange{Pages: pages, Page: page} } return page, nil diff --git a/light/rpc/errors.go b/light/rpc/errors.go new file mode 100644 index 00000000000..bfd1989a805 --- /dev/null +++ b/light/rpc/errors.go @@ -0,0 +1,190 @@ +package rpc + +import ( + "errors" + "fmt" + "regexp" + + cmtbytes "github.com/cometbft/cometbft/libs/bytes" +) + +var ( + ErrNegOrZeroHeight = errors.New("negative or zero height") + ErrNoProofOps = errors.New("no proof ops") + ErrNilKeyPathFn = errors.New("please configure Client with KeyPathFn option") +) + +type ErrMissingStoreName struct { + Path string + Rex *regexp.Regexp +} + +func (e ErrMissingStoreName) Error() string { + return fmt.Sprintf("can't find store name in %s using %s", e.Path, e.Rex) +} + +type ErrResponseCode struct { + Code uint32 +} + +func (e ErrResponseCode) Error() string { + return fmt.Sprintf("err response code: %v", e.Code) +} + +type ErrPageRange struct { + Pages int + Page int +} + +func (e ErrPageRange) Error() string { + return fmt.Sprintf("page should be within [1, %d] range, given %d", e.Pages, e.Page) +} + +type ErrNilBlockMeta struct { + Index int +} + +func (e ErrNilBlockMeta) Error() string { + return fmt.Sprintf("nil block meta %d", e.Index) +} + +type ErrParamHashMismatch struct { + ConsensusParamsHash []byte + ConsensusHash cmtbytes.HexBytes +} + +func (e ErrParamHashMismatch) Error() string { + return fmt.Sprintf("params hash %X does not match trusted hash %X", e.ConsensusParamsHash, e.ConsensusHash) +} + +type ErrLastResultMismatch struct { + ResultHash []byte + LastResultHash cmtbytes.HexBytes +} + +func (e ErrLastResultMismatch) Error() string { + return fmt.Sprintf("last results %X does not match with trusted last results %X", e.ResultHash, e.LastResultHash) +} + +type ErrPrimaryHeaderMismatch struct { + PrimaryHeaderHash cmtbytes.HexBytes + TrustedHeaderHash cmtbytes.HexBytes +} + +func (e ErrPrimaryHeaderMismatch) Error() string { + return fmt.Sprintf("primary header hash does not match trusted header hash. (%X != %X)", e.PrimaryHeaderHash, e.TrustedHeaderHash) +} + +type ErrBlockHeaderMismatch struct { + BlockHeader cmtbytes.HexBytes + TrustedHeader cmtbytes.HexBytes +} + +func (e ErrBlockHeaderMismatch) Error() string { + return fmt.Sprintf("block header %X does not match with trusted header %X", e.BlockHeader, e.TrustedHeader) +} + +type ErrBlockMetaHeaderMismatch struct { + BlockMetaHeader cmtbytes.HexBytes + TrustedHeader cmtbytes.HexBytes +} + +func (e ErrBlockMetaHeaderMismatch) Error() string { + return fmt.Sprintf("block meta header %X does not match with trusted header %X", e.BlockMetaHeader, e.TrustedHeader) +} + +type ErrBlockIDMismatch struct { + BlockID cmtbytes.HexBytes + Block cmtbytes.HexBytes +} + +func (e ErrBlockIDMismatch) Error() string { + return fmt.Sprintf("blockID %X does not match with block %X", e.BlockID, e.Block) +} + +type ErrBuildMerkleKeyPath struct { + Err error +} + +func (e ErrBuildMerkleKeyPath) Error() string { + return fmt.Sprintf("can't build merkle key path: %v", e.Err) +} + +func (e ErrBuildMerkleKeyPath) Unwrap() error { + return e.Err +} + +type ErrVerifyValueProof struct { + Err error +} + +func (e ErrVerifyValueProof) Error() string { + return fmt.Sprintf("verify value proof: %v", e.Err) +} + +func (e ErrVerifyValueProof) Unwrap() error { + return e.Err +} + +type ErrVerifyAbsenceProof struct { + Err error +} + +func (e ErrVerifyAbsenceProof) Error() string { + return fmt.Sprintf("verify absence proof: %v", e.Err) +} + +func (e ErrVerifyAbsenceProof) Unwrap() error { + return e.Err +} + +type ErrGetLatestHeight struct { + Err error +} + +func (e ErrGetLatestHeight) Error() string { + return fmt.Sprintf("can't get latest height: %v", e.Err) +} + +func (e ErrGetLatestHeight) Unwrap() error { + return e.Err +} + +type ErrInvalidBlockMeta struct { + I int + Err error +} + +func (e ErrInvalidBlockMeta) Error() string { + return fmt.Sprintf("invalid block meta %d: %v", e.I, e.Err) +} + +func (e ErrInvalidBlockMeta) Unwrap() error { + return e.Err +} + +type ErrTrustedHeader struct { + Height int64 + Err error +} + +func (e ErrTrustedHeader) Error() string { + return fmt.Sprintf("trusted header %d: %v", e.Height, e.Err) +} + +func (e ErrTrustedHeader) Unwrap() error { + return e.Err +} + +type ErrUpdateClient struct { + Height int64 + Err error +} + +func (e ErrUpdateClient) Error() string { + return fmt.Sprintf("failed to update light client to %d: %v", e.Height, e.Err) +} + +func (e ErrUpdateClient) Unwrap() error { + return e.Err +} diff --git a/light/rpc/mocks/light_client.go b/light/rpc/mocks/light_client.go index 5699dfe4395..dc3792941c2 100644 --- a/light/rpc/mocks/light_client.go +++ b/light/rpc/mocks/light_client.go @@ -21,6 +21,10 @@ type LightClient struct { func (_m *LightClient) ChainID() string { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for ChainID") + } + var r0 string if rf, ok := ret.Get(0).(func() string); ok { r0 = rf() @@ -35,6 +39,10 @@ func (_m *LightClient) ChainID() string { func (_m *LightClient) TrustedLightBlock(height int64) (*types.LightBlock, error) { ret := _m.Called(height) + if len(ret) == 0 { + panic("no return value specified for TrustedLightBlock") + } + var r0 *types.LightBlock var r1 error if rf, ok := ret.Get(0).(func(int64) (*types.LightBlock, error)); ok { @@ -61,6 +69,10 @@ func (_m *LightClient) TrustedLightBlock(height int64) (*types.LightBlock, error func (_m *LightClient) Update(ctx context.Context, now time.Time) (*types.LightBlock, error) { ret := _m.Called(ctx, now) + if len(ret) == 0 { + panic("no return value specified for Update") + } + var r0 *types.LightBlock var r1 error if rf, ok := ret.Get(0).(func(context.Context, time.Time) (*types.LightBlock, error)); ok { @@ -87,6 +99,10 @@ func (_m *LightClient) Update(ctx context.Context, now time.Time) (*types.LightB func (_m *LightClient) VerifyLightBlockAtHeight(ctx context.Context, height int64, now time.Time) (*types.LightBlock, error) { ret := _m.Called(ctx, height, now) + if len(ret) == 0 { + panic("no return value specified for VerifyLightBlockAtHeight") + } + var r0 *types.LightBlock var r1 error if rf, ok := ret.Get(0).(func(context.Context, int64, time.Time) (*types.LightBlock, error)); ok { @@ -109,13 +125,12 @@ func (_m *LightClient) VerifyLightBlockAtHeight(ctx context.Context, height int6 return r0, r1 } -type mockConstructorTestingTNewLightClient interface { +// NewLightClient creates a new instance of LightClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewLightClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewLightClient creates a new instance of LightClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewLightClient(t mockConstructorTestingTNewLightClient) *LightClient { +}) *LightClient { mock := &LightClient{} mock.Mock.Test(t) diff --git a/light/setup.go b/light/setup.go index 66ae15d6aa8..7482c850676 100644 --- a/light/setup.go +++ b/light/setup.go @@ -22,8 +22,8 @@ func NewHTTPClient( primaryAddress string, witnessesAddresses []string, trustedStore store.Store, - options ...Option) (*Client, error) { - + options ...Option, +) (*Client, error) { providers, err := providersFromAddresses(append(witnessesAddresses, primaryAddress), chainID) if err != nil { return nil, err @@ -51,8 +51,8 @@ func NewHTTPClientFromTrustedStore( primaryAddress string, witnessesAddresses []string, trustedStore store.Store, - options ...Option) (*Client, error) { - + options ...Option, +) (*Client, error) { providers, err := providersFromAddresses(append(witnessesAddresses, primaryAddress), chainID) if err != nil { return nil, err diff --git a/light/store/db/db.go b/light/store/db/db.go index 83d1f1abdfd..ffbc45123d2 100644 --- a/light/store/db/db.go +++ b/light/store/db/db.go @@ -2,38 +2,85 @@ package db import ( "encoding/binary" - "fmt" - "regexp" - "strconv" dbm "github.com/cometbft/cometbft-db" - - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/light/store" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" ) -var sizeKey = []byte("size") - type dbs struct { db dbm.DB prefix string mtx cmtsync.RWMutex size uint16 + + dbKeyLayout LightStoreKeyLayout +} + +func isEmpty(db dbm.DB) bool { + iter, err := db.Iterator(nil, nil) + if err != nil { + panic(err) + } + + defer iter.Close() + for ; iter.Valid(); iter.Next() { + return false + } + return true +} + +func setDBKeyLayout(db dbm.DB, lightStore *dbs, dbKeyLayoutVersion string) { + if !isEmpty(db) { + var version []byte + var err error + if version, err = lightStore.db.Get([]byte("version")); err != nil { + // WARN: This is because currently cometBFT DB does not return an error if the key does not exist + // If this behavior changes we need to account for that. + panic(err) + } + if len(version) != 0 { + dbKeyLayoutVersion = string(version) + } + } + + switch dbKeyLayoutVersion { + case "v1", "": + lightStore.dbKeyLayout = &v1LegacyLayout{} + dbKeyLayoutVersion = "v1" + case "v2": + lightStore.dbKeyLayout = &v2Layout{} + default: + panic("unknown key layout version") + } + + if err := lightStore.db.SetSync([]byte("version"), []byte(dbKeyLayoutVersion)); err != nil { + panic(err) + } } // New returns a Store that wraps any DB (with an optional prefix in case you // want to use one DB with many light clients). func New(db dbm.DB, prefix string) store.Store { + return NewWithDBVersion(db, prefix, "") +} + +func NewWithDBVersion(db dbm.DB, prefix string, dbKeyVersion string) store.Store { + dbStore := &dbs{db: db, prefix: prefix} + + setDBKeyLayout(db, dbStore, dbKeyVersion) + size := uint16(0) - bz, err := db.Get(sizeKey) + bz, err := db.Get(dbStore.dbKeyLayout.SizeKey(prefix)) if err == nil && len(bz) > 0 { size = unmarshalSize(bz) } - - return &dbs{db: db, prefix: prefix, size: size} + dbStore.size = size + return dbStore } // SaveLightBlock persists LightBlock to the db. @@ -46,12 +93,12 @@ func (s *dbs) SaveLightBlock(lb *types.LightBlock) error { lbpb, err := lb.ToProto() if err != nil { - return fmt.Errorf("unable to convert light block to protobuf: %w", err) + return cmterrors.ErrMsgToProto{MessageName: "LightBlock", Err: err} } lbBz, err := lbpb.Marshal() if err != nil { - return fmt.Errorf("marshaling LightBlock: %w", err) + return store.ErrMarshalBlock{Err: err} } s.mtx.Lock() @@ -60,13 +107,13 @@ func (s *dbs) SaveLightBlock(lb *types.LightBlock) error { b := s.db.NewBatch() defer b.Close() if err = b.Set(s.lbKey(lb.Height), lbBz); err != nil { - return err + return store.ErrStore{Err: err} } - if err = b.Set(sizeKey, marshalSize(s.size+1)); err != nil { - return err + if err = b.Set(s.dbKeyLayout.SizeKey(s.prefix), marshalSize(s.size+1)); err != nil { + return store.ErrStore{Err: err} } if err = b.WriteSync(); err != nil { - return err + return store.ErrStore{Err: err} } s.size++ @@ -88,13 +135,13 @@ func (s *dbs) DeleteLightBlock(height int64) error { b := s.db.NewBatch() defer b.Close() if err := b.Delete(s.lbKey(height)); err != nil { - return err + return store.ErrStore{Err: err} } - if err := b.Set(sizeKey, marshalSize(s.size-1)); err != nil { - return err + if err := b.Set(s.dbKeyLayout.SizeKey(s.prefix), marshalSize(s.size-1)); err != nil { + return store.ErrStore{Err: err} } if err := b.WriteSync(); err != nil { - return err + return store.ErrStore{Err: err} } s.size-- @@ -120,12 +167,12 @@ func (s *dbs) LightBlock(height int64) (*types.LightBlock, error) { var lbpb cmtproto.LightBlock err = lbpb.Unmarshal(bz) if err != nil { - return nil, fmt.Errorf("unmarshal error: %w", err) + return nil, store.ErrUnmarshal{Err: err} } lightBlock, err := types.LightBlockFromProto(&lbpb) if err != nil { - return nil, fmt.Errorf("proto conversion error: %w", err) + return nil, store.ErrProtoConversion{Err: err} } return lightBlock, err @@ -134,7 +181,7 @@ func (s *dbs) LightBlock(height int64) (*types.LightBlock, error) { // LastLightBlockHeight returns the last LightBlock height stored. // // Safe for concurrent use by multiple goroutines. -func (s *dbs) LastLightBlockHeight() (int64, error) { +func (s *dbs) LastLightBlockHeight() (height int64, err error) { itr, err := s.db.ReverseIterator( s.lbKey(1), append(s.lbKey(1<<63-1), byte(0x00)), @@ -146,20 +193,24 @@ func (s *dbs) LastLightBlockHeight() (int64, error) { for itr.Valid() { key := itr.Key() - _, height, ok := parseLbKey(key) - if ok { + height, err = s.dbKeyLayout.ParseLBKey(key, s.prefix) + if err == nil { return height, nil } itr.Next() } - return -1, itr.Error() + if itr.Error() != nil { + err = itr.Error() + } + + return -1, err } // FirstLightBlockHeight returns the first LightBlock height stored. // // Safe for concurrent use by multiple goroutines. -func (s *dbs) FirstLightBlockHeight() (int64, error) { +func (s *dbs) FirstLightBlockHeight() (height int64, err error) { itr, err := s.db.Iterator( s.lbKey(1), append(s.lbKey(1<<63-1), byte(0x00)), @@ -171,14 +222,16 @@ func (s *dbs) FirstLightBlockHeight() (int64, error) { for itr.Valid() { key := itr.Key() - _, height, ok := parseLbKey(key) - if ok { + height, err = s.dbKeyLayout.ParseLBKey(key, s.prefix) + if err == nil { return height, nil } itr.Next() } - - return -1, itr.Error() + if itr.Error() != nil { + err = itr.Error() + } + return -1, err } // LightBlockBefore iterates over light blocks until it finds a block before @@ -201,14 +254,14 @@ func (s *dbs) LightBlockBefore(height int64) (*types.LightBlock, error) { for itr.Valid() { key := itr.Key() - _, existingHeight, ok := parseLbKey(key) - if ok { + existingHeight, err := s.dbKeyLayout.ParseLBKey(key, s.prefix) + if err == nil { return s.LightBlock(existingHeight) } itr.Next() } if err = itr.Error(); err != nil { - return nil, err + return nil, store.ErrStore{Err: err} } return nil, store.ErrLightBlockNotFound @@ -235,7 +288,7 @@ func (s *dbs) Prune(size uint16) error { append(s.lbKey(1<<63-1), byte(0x00)), ) if err != nil { - return err + return store.ErrStore{Err: err} } defer itr.Close() @@ -245,10 +298,10 @@ func (s *dbs) Prune(size uint16) error { pruned := 0 for itr.Valid() && numToPrune > 0 { key := itr.Key() - _, height, ok := parseLbKey(key) - if ok { + height, err := s.dbKeyLayout.ParseLBKey(key, s.prefix) + if err == nil { if err = b.Delete(s.lbKey(height)); err != nil { - return err + return store.ErrStore{Err: err} } } itr.Next() @@ -256,12 +309,12 @@ func (s *dbs) Prune(size uint16) error { pruned++ } if err = itr.Error(); err != nil { - return err + return store.ErrStore{Err: err} } err = b.WriteSync() if err != nil { - return err + return store.ErrStore{Err: err} } // 3) Update size. @@ -270,8 +323,8 @@ func (s *dbs) Prune(size uint16) error { s.size -= uint16(pruned) - if wErr := s.db.SetSync(sizeKey, marshalSize(s.size)); wErr != nil { - return fmt.Errorf("failed to persist size: %w", wErr) + if wErr := s.db.SetSync(s.dbKeyLayout.SizeKey(s.prefix), marshalSize(s.size)); wErr != nil { + return store.ErrStore{Err: wErr} } return nil @@ -287,33 +340,7 @@ func (s *dbs) Size() uint16 { } func (s *dbs) lbKey(height int64) []byte { - return []byte(fmt.Sprintf("lb/%s/%020d", s.prefix, height)) -} - -var keyPattern = regexp.MustCompile(`^(lb)/([^/]*)/([0-9]+)$`) - -func parseKey(key []byte) (part string, prefix string, height int64, ok bool) { - submatch := keyPattern.FindSubmatch(key) - if submatch == nil { - return "", "", 0, false - } - part = string(submatch[1]) - prefix = string(submatch[2]) - height, err := strconv.ParseInt(string(submatch[3]), 10, 64) - if err != nil { - return "", "", 0, false - } - ok = true // good! - return -} - -func parseLbKey(key []byte) (prefix string, height int64, ok bool) { - var part string - part, prefix, height, ok = parseKey(key) - if part != "lb" { - return "", 0, false - } - return + return s.dbKeyLayout.LBKey(height, s.prefix) } func marshalSize(size uint16) []byte { diff --git a/light/store/db/db_key_layout.go b/light/store/db/db_key_layout.go new file mode 100644 index 00000000000..dee4274b0ef --- /dev/null +++ b/light/store/db/db_key_layout.go @@ -0,0 +1,106 @@ +package db + +import ( + "errors" + "fmt" + "regexp" + "strconv" + + "github.com/google/orderedcode" +) + +type LightStoreKeyLayout interface { + ParseLBKey(key []byte, storePrefix string) (height int64, err error) + LBKey(height int64, prefix string) []byte + SizeKey(prefix string) []byte +} + +type v1LegacyLayout struct{} + +// LBKey implements LightStoreKeyLayout. +func (v1LegacyLayout) LBKey(height int64, prefix string) []byte { + return []byte(fmt.Sprintf("lb/%s/%020d", prefix, height)) +} + +// ParseLBKey implements LightStoreKeyLayout. +func (v1LegacyLayout) ParseLBKey(key []byte, _ string) (height int64, err error) { + var part string + part, _, height, err = parseKey(key) + if part != "lb" { + return 0, err + } + return height, nil +} + +// SizeKey implements LightStoreKeyLayout. +func (v1LegacyLayout) SizeKey(_ string) []byte { + return []byte("size") +} + +var _ LightStoreKeyLayout = v1LegacyLayout{} + +var keyPattern = regexp.MustCompile(`^(lb)/([^/]*)/([0-9]+)$`) + +func parseKey(key []byte) (part string, prefix string, height int64, err error) { + submatch := keyPattern.FindSubmatch(key) + if submatch == nil { + return "", "", 0, errors.New("not a light block key") + } + part = string(submatch[1]) + prefix = string(submatch[2]) + height, err = strconv.ParseInt(string(submatch[3]), 10, 64) + if err != nil { + return "", "", 0, err + } + return part, prefix, height, nil +} + +const ( + // prefixes must be unique across all db's. + prefixLightBlock = int64(11) + prefixSize = int64(12) +) + +type v2Layout struct{} + +// LBKey implements LightStoreKeyLayout. +func (v2Layout) LBKey(height int64, prefix string) []byte { + key, err := orderedcode.Append(nil, prefix, prefixLightBlock, height) + if err != nil { + panic(err) + } + return key +} + +// ParseLBKey implements LightStoreKeyLayout. +func (v2Layout) ParseLBKey(key []byte, storePrefix string) (height int64, err error) { + var ( + dbPrefix string + lightBlockPrefix int64 + ) + remaining, err := orderedcode.Parse(string(key), &dbPrefix, &lightBlockPrefix, &height) + if err != nil { + err = fmt.Errorf("failed to parse light block key: %w", err) + } + if len(remaining) != 0 { + err = fmt.Errorf("expected no remainder when parsing light block key but got: %s", remaining) + } + if lightBlockPrefix != prefixLightBlock { + err = fmt.Errorf("expected light block prefix but got: %d", lightBlockPrefix) + } + if dbPrefix != storePrefix { + err = fmt.Errorf("parsed key has a different prefix. Expected: %s, got: %s", storePrefix, dbPrefix) + } + return height, err +} + +// SizeKey implements LightStoreKeyLayout. +func (v2Layout) SizeKey(prefix string) []byte { + key, err := orderedcode.Append(nil, prefix, prefixSize) + if err != nil { + panic(err) + } + return key +} + +var _ LightStoreKeyLayout = v2Layout{} diff --git a/light/store/db/db_test.go b/light/store/db/db_test.go index a2caffa81f4..5afbaeee2c8 100644 --- a/light/store/db/db_test.go +++ b/light/store/db/db_test.go @@ -3,21 +3,94 @@ package db import ( "sync" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/tmhash" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) +func TestDBKeyLayoutVersioning(t *testing.T) { + prefix := "TestDBKeyLayoutVersioning" + db := dbm.NewMemDB() + dbStore := New(db, prefix) + + // Empty store + height, err := dbStore.LastLightBlockHeight() + require.NoError(t, err) + assert.EqualValues(t, -1, height) + + lb := randLightBlock(int64(1)) + // 1 key + err = dbStore.SaveLightBlock(lb) + require.NoError(t, err) + + lbKey := v1LegacyLayout{}.LBKey(int64(1), prefix) + + lbRetrieved, err := db.Get(lbKey) + require.NoError(t, err) + + var lbpb cmtproto.LightBlock + err = lbpb.Unmarshal(lbRetrieved) + require.NoError(t, err) + + lightBlock, err := types.LightBlockFromProto(&lbpb) + require.NoError(t, err) + + require.Equal(t, lightBlock.AppHash, lb.AppHash) + require.Equal(t, lightBlock.ConsensusHash, lb.ConsensusHash) + + lbKeyV2 := v2Layout{}.LBKey(1, prefix) + + lbv2, err := db.Get(lbKeyV2) + require.NoError(t, err) + require.Equal(t, len(lbv2), 0) + + // test on v2 + + prefix = "TestDBKeyLayoutVersioningV2" + db2 := dbm.NewMemDB() + dbStore2 := NewWithDBVersion(db2, prefix, "v2") + + // Empty store + height, err = dbStore2.LastLightBlockHeight() + require.NoError(t, err) + assert.EqualValues(t, -1, height) + + // 1 key + err = dbStore2.SaveLightBlock(lb) + require.NoError(t, err) + + lbKey = v1LegacyLayout{}.LBKey(int64(1), prefix) + // No block is found if we look for a key parsed with v1 + lbRetrieved, err = db2.Get(lbKey) + require.NoError(t, err) + require.Equal(t, len(lbRetrieved), 0) + + // Key parsed with v2 should find the light block + lbKeyV2 = v2Layout{}.LBKey(1, prefix) + lbv2, err = db2.Get(lbKeyV2) + require.NoError(t, err) + + // Unmarshall the light block bytes + err = lbpb.Unmarshal(lbv2) + require.NoError(t, err) + + lightBlock, err = types.LightBlockFromProto(&lbpb) + require.NoError(t, err) + + require.Equal(t, lightBlock.AppHash, lb.AppHash) + require.Equal(t, lightBlock.ConsensusHash, lb.ConsensusHash) +} + func TestLast_FirstLightBlockHeight(t *testing.T) { dbStore := New(dbm.NewMemDB(), "TestLast_FirstLightBlockHeight") @@ -43,8 +116,8 @@ func TestLast_FirstLightBlockHeight(t *testing.T) { assert.EqualValues(t, 1, height) } -func Test_SaveLightBlock(t *testing.T) { - dbStore := New(dbm.NewMemDB(), "Test_SaveLightBlockAndValidatorSet") +func Test_SaveLightBlockCustomConfig(t *testing.T) { + dbStore := NewWithDBVersion(dbm.NewMemDB(), "Test_SaveLightBlockAndValidatorSet", "v2") // Empty store h, err := dbStore.LightBlock(1) @@ -177,7 +250,7 @@ func randLightBlock(height int64) *types.LightBlock { Version: cmtversion.Consensus{Block: version.BlockProtocol, App: 0}, ChainID: cmtrand.Str(12), Height: height, - Time: time.Now(), + Time: cmttime.Now(), LastBlockID: types.BlockID{}, LastCommitHash: crypto.CRandBytes(tmhash.Size), DataHash: crypto.CRandBytes(tmhash.Size), diff --git a/light/store/errors.go b/light/store/errors.go index 099b5964d36..d5ec086b971 100644 --- a/light/store/errors.go +++ b/light/store/errors.go @@ -1,9 +1,58 @@ package store -import "errors" - -var ( - // ErrLightBlockNotFound is returned when a store does not have the - // requested header. - ErrLightBlockNotFound = errors.New("light block not found") +import ( + "errors" + "fmt" ) + +// ErrLightBlockNotFound is returned when a store does not have the +// requested header. +var ErrLightBlockNotFound = errors.New("light block not found") + +type ErrMarshalBlock struct { + Err error +} + +func (e ErrMarshalBlock) Error() string { + return fmt.Sprintf("marshaling LightBlock: %v", e.Err) +} + +func (e ErrMarshalBlock) Unwrap() error { + return e.Err +} + +type ErrUnmarshal struct { + Err error +} + +func (e ErrUnmarshal) Error() string { + return fmt.Sprintf("unmarshal error: %v", e.Err) +} + +func (e ErrUnmarshal) Unwrap() error { + return e.Err +} + +type ErrProtoConversion struct { + Err error +} + +func (e ErrProtoConversion) Error() string { + return fmt.Sprintf("proto conversion error: %v", e.Err) +} + +func (e ErrProtoConversion) Unwrap() error { + return e.Err +} + +type ErrStore struct { + Err error +} + +func (e ErrStore) Error() string { + return e.Err.Error() +} + +func (e ErrStore) Unwrap() error { + return e.Err +} diff --git a/light/trust_options.go b/light/trust_options.go index b2fd1d48dc2..85aef328ae5 100644 --- a/light/trust_options.go +++ b/light/trust_options.go @@ -1,8 +1,6 @@ package light import ( - "errors" - "fmt" "time" "github.com/cometbft/cometbft/crypto/tmhash" @@ -38,16 +36,13 @@ type TrustOptions struct { // ValidateBasic performs basic validation. func (opts TrustOptions) ValidateBasic() error { if opts.Period <= 0 { - return errors.New("negative or zero period") + return ErrNegativeOrZeroPeriod } if opts.Height <= 0 { - return errors.New("zero or negative height") + return ErrNegativeOrZeroHeight } if len(opts.Hash) != tmhash.Size { - return fmt.Errorf("expected hash size to be %d bytes, got %d bytes", - tmhash.Size, - len(opts.Hash), - ) + return ErrInvalidHashSize{Expected: tmhash.Size, Actual: len(opts.Hash)} } return nil } diff --git a/light/verifier.go b/light/verifier.go index 8905db56b05..dd81563c8f2 100644 --- a/light/verifier.go +++ b/light/verifier.go @@ -10,11 +10,9 @@ import ( "github.com/cometbft/cometbft/types" ) -var ( - // DefaultTrustLevel - new header can be trusted if at least one correct - // validator signed it. - DefaultTrustLevel = cmtmath.Fraction{Numerator: 1, Denominator: 3} -) +// DefaultTrustLevel - new header can be trusted if at least one correct +// validator signed it. +var DefaultTrustLevel = cmtmath.Fraction{Numerator: 1, Denominator: 3} // VerifyNonAdjacent verifies non-adjacent untrustedHeader against // trustedHeader. It ensures that: @@ -37,10 +35,10 @@ func VerifyNonAdjacent( trustingPeriod time.Duration, now time.Time, maxClockDrift time.Duration, - trustLevel cmtmath.Fraction) error { - + trustLevel cmtmath.Fraction, +) error { if untrustedHeader.Height == trustedHeader.Height+1 { - return errors.New("headers must be non adjacent in height") + return ErrHeaderHeightAdjacent } if HeaderExpired(trustedHeader, trustingPeriod, now) { @@ -96,10 +94,10 @@ func VerifyAdjacent( untrustedVals *types.ValidatorSet, // height=X+1 trustingPeriod time.Duration, now time.Time, - maxClockDrift time.Duration) error { - + maxClockDrift time.Duration, +) error { if untrustedHeader.Height != trustedHeader.Height+1 { - return errors.New("headers must be adjacent in height") + return ErrHeaderHeightNotAdjacent } if HeaderExpired(trustedHeader, trustingPeriod, now) { @@ -115,11 +113,7 @@ func VerifyAdjacent( // Check the validator hashes are the same if !bytes.Equal(untrustedHeader.ValidatorsHash, trustedHeader.NextValidatorsHash) { - err := fmt.Errorf("expected old header next validators (%X) to match those from new header (%X)", - trustedHeader.NextValidatorsHash, - untrustedHeader.ValidatorsHash, - ) - return err + return ErrValidatorHashMismatch{TrustedHash: trustedHeader.NextValidatorsHash, ValidatorHash: untrustedHeader.ValidatorsHash} } // Ensure that +2/3 of new validators signed correctly. @@ -140,8 +134,8 @@ func Verify( trustingPeriod time.Duration, now time.Time, maxClockDrift time.Duration, - trustLevel cmtmath.Fraction) error { - + trustLevel cmtmath.Fraction, +) error { if untrustedHeader.Height != trustedHeader.Height+1 { return VerifyNonAdjacent(trustedHeader, trustedVals, untrustedHeader, untrustedVals, trustingPeriod, now, maxClockDrift, trustLevel) @@ -155,37 +149,26 @@ func verifyNewHeaderAndVals( untrustedVals *types.ValidatorSet, trustedHeader *types.SignedHeader, now time.Time, - maxClockDrift time.Duration) error { - + maxClockDrift time.Duration, +) error { if err := untrustedHeader.ValidateBasic(trustedHeader.ChainID); err != nil { - return fmt.Errorf("untrustedHeader.ValidateBasic failed: %w", err) + return ErrHeaderValidateBasic{Err: err} } if untrustedHeader.Height <= trustedHeader.Height { - return fmt.Errorf("expected new header height %d to be greater than one of old header %d", - untrustedHeader.Height, - trustedHeader.Height) + return ErrHeaderHeightNotMonotonic{GotHeight: untrustedHeader.Height, OldHeight: trustedHeader.Height} } if !untrustedHeader.Time.After(trustedHeader.Time) { - return fmt.Errorf("expected new header time %v to be after old header time %v", - untrustedHeader.Time, - trustedHeader.Time) + return ErrHeaderTimeNotMonotonic{GotTime: untrustedHeader.Time, OldTime: trustedHeader.Time} } if !untrustedHeader.Time.Before(now.Add(maxClockDrift)) { - return fmt.Errorf("new header has a time from the future %v (now: %v; max clock drift: %v)", - untrustedHeader.Time, - now, - maxClockDrift) + return ErrHeaderTimeExceedMaxClockDrift{Ti: untrustedHeader.Time, Now: now, Drift: maxClockDrift} } if !bytes.Equal(untrustedHeader.ValidatorsHash, untrustedVals.Hash()) { - return fmt.Errorf("expected new header validators (%X) to match those that were supplied (%X) at height %d", - untrustedHeader.ValidatorsHash, - untrustedVals.Hash(), - untrustedHeader.Height, - ) + return ErrValidatorsMismatch{HeaderHash: untrustedHeader.ValidatorsHash, ValidatorsHash: untrustedVals.Hash(), Height: untrustedHeader.Height} } return nil @@ -198,7 +181,7 @@ func ValidateTrustLevel(lvl cmtmath.Fraction) error { if lvl.Numerator*3 < lvl.Denominator || // < 1/3 lvl.Numerator > lvl.Denominator || // > 1 lvl.Denominator == 0 { - return fmt.Errorf("trustLevel must be within [1/3, 1], given %v", lvl) + return ErrInvalidTrustLevel{Level: lvl} } return nil } @@ -231,14 +214,16 @@ func VerifyBackwards(untrustedHeader, trustedHeader *types.Header) error { return ErrInvalidHeader{ fmt.Errorf("expected older header time %v to be before new header time %v", untrustedHeader.Time, - trustedHeader.Time)} + trustedHeader.Time), + } } if !bytes.Equal(untrustedHeader.Hash(), trustedHeader.LastBlockID.Hash) { return ErrInvalidHeader{ fmt.Errorf("older header hash %X does not match trusted header's last block %X", untrustedHeader.Hash(), - trustedHeader.LastBlockID.Hash)} + trustedHeader.LastBlockID.Hash), + } } return nil diff --git a/light/verifier_test.go b/light/verifier_test.go index 5758bc46d94..36d6beeaaf0 100644 --- a/light/verifier_test.go +++ b/light/verifier_test.go @@ -6,10 +6,12 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" cmtmath "github.com/cometbft/cometbft/libs/math" "github.com/cometbft/cometbft/light" "github.com/cometbft/cometbft/types" + cmttime "github.com/cometbft/cometbft/types/time" ) const ( @@ -46,8 +48,8 @@ func TestVerifyAdjacentHeaders(t *testing.T) { vals, 3 * time.Hour, bTime.Add(2 * time.Hour), - nil, - "headers must be adjacent in height", + light.ErrHeaderHeightNotAdjacent, + "", }, // different chainID -> error 1: { @@ -56,8 +58,8 @@ func TestVerifyAdjacentHeaders(t *testing.T) { vals, 3 * time.Hour, bTime.Add(2 * time.Hour), - nil, - "header belongs to another chain", + light.ErrInvalidHeader{light.ErrHeaderValidateBasic{fmt.Errorf("header belongs to another chain %q, not %q", "different-chainID", chainID)}}, + "", }, // new header's time is before old header's time -> error 2: { @@ -66,8 +68,8 @@ func TestVerifyAdjacentHeaders(t *testing.T) { vals, 3 * time.Hour, bTime.Add(2 * time.Hour), - nil, - "to be after old header time", + light.ErrInvalidHeader{light.ErrHeaderTimeNotMonotonic{bTime.Add(-1 * time.Hour), bTime}}, + "", }, // new header's time is from the future -> error 3: { @@ -76,8 +78,8 @@ func TestVerifyAdjacentHeaders(t *testing.T) { vals, 3 * time.Hour, bTime.Add(2 * time.Hour), - nil, - "new header has a time from the future", + light.ErrInvalidHeader{light.ErrHeaderTimeExceedMaxClockDrift{bTime.Add(3 * time.Hour), bTime.Add(2 * time.Hour), 10 * time.Second}}, + "", }, // new header's time is from the future, but it's acceptable (< maxClockDrift) -> no error 4: { @@ -127,8 +129,9 @@ func TestVerifyAdjacentHeaders(t *testing.T) { keys.ToValidators(10, 1), 3 * time.Hour, bTime.Add(2 * time.Hour), - nil, - "to match those from new header", + light.ErrValidatorHashMismatch{header.NextValidatorsHash, keys.GenSignedHeader(chainID, nextHeight, bTime.Add(1*time.Hour), nil, keys.ToValidators(10, 1), vals, + hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)).ValidatorsHash}, + "", }, // vals are inconsistent with newHeader -> error 9: { @@ -137,8 +140,10 @@ func TestVerifyAdjacentHeaders(t *testing.T) { keys.ToValidators(10, 1), 3 * time.Hour, bTime.Add(2 * time.Hour), - nil, - "to match those that were supplied", + light.ErrInvalidHeader{light.ErrValidatorsMismatch{keys.GenSignedHeader(chainID, nextHeight, bTime.Add(1*time.Hour), nil, vals, vals, + hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)).ValidatorsHash, keys.ToValidators(10, 1).Hash(), keys.GenSignedHeader(chainID, nextHeight, bTime.Add(1*time.Hour), nil, vals, vals, + hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)).Height}}, + "", }, // old header has expired -> error 10: { @@ -147,8 +152,8 @@ func TestVerifyAdjacentHeaders(t *testing.T) { keys.ToValidators(10, 1), 1 * time.Hour, bTime.Add(1 * time.Hour), - nil, - "old header has expired", + light.ErrOldHeaderExpired{bTime.Add(1 * time.Hour), bTime.Add(1 * time.Hour)}, + "", }, } @@ -157,16 +162,15 @@ func TestVerifyAdjacentHeaders(t *testing.T) { t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { err := light.VerifyAdjacent(header, tc.newHeader, tc.newVals, tc.trustingPeriod, tc.now, maxClockDrift) switch { - case tc.expErr != nil && assert.Error(t, err): + case tc.expErr != nil && assert.Error(t, err): //nolint:testifylint // require.Error doesn't work with the logic here assert.Equal(t, tc.expErr, err) case tc.expErrText != "": assert.Contains(t, err.Error(), tc.expErrText) default: - assert.NoError(t, err) + require.NoError(t, err) } }) } - } func TestVerifyNonAdjacentHeaders(t *testing.T) { @@ -274,12 +278,12 @@ func TestVerifyNonAdjacentHeaders(t *testing.T) { light.DefaultTrustLevel) switch { - case tc.expErr != nil && assert.Error(t, err): + case tc.expErr != nil && assert.Error(t, err): //nolint:testifylint // require.Error doesn't work with the logic here assert.Equal(t, tc.expErr, err) case tc.expErrText != "": assert.Contains(t, err.Error(), tc.expErrText) default: - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -298,11 +302,14 @@ func TestVerifyReturnsErrorIfTrustLevelIsInvalid(t *testing.T) { bTime, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") header = keys.GenSignedHeader(chainID, lastHeight, bTime, nil, vals, vals, hash("app_hash"), hash("cons_hash"), hash("results_hash"), 0, len(keys)) + trustingPeriod = 2 * time.Hour + now = cmttime.Now() ) - err := light.Verify(header, vals, header, vals, 2*time.Hour, time.Now(), maxClockDrift, + err := light.Verify(header, vals, header, vals, trustingPeriod, now, maxClockDrift, cmtmath.Fraction{Numerator: 2, Denominator: 1}) - assert.Error(t, err) + expectedErr := light.ErrOldHeaderExpired{At: bTime.Add(trustingPeriod), Now: now} + require.EqualError(t, err, expectedErr.Error()) } func TestValidateTrustLevel(t *testing.T) { @@ -327,9 +334,9 @@ func TestValidateTrustLevel(t *testing.T) { for _, tc := range testCases { err := light.ValidateTrustLevel(tc.lvl) if !tc.valid { - assert.Error(t, err) + require.EqualError(t, err, light.ErrInvalidTrustLevel{Level: tc.lvl}.Error()) } else { - assert.NoError(t, err) + require.NoError(t, err) } } } diff --git a/mempool/bench_test.go b/mempool/bench_test.go index 1ddd59209e9..035528188b7 100644 --- a/mempool/bench_test.go +++ b/mempool/bench_test.go @@ -1,11 +1,18 @@ package mempool import ( - "encoding/binary" + "fmt" "sync/atomic" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/cometbft/cometbft/abci/example/kvstore" + abciserver "github.com/cometbft/cometbft/abci/server" + cmtrand "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/internal/test" + "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/proxy" ) @@ -15,13 +22,12 @@ func BenchmarkReap(b *testing.B) { mp, cleanup := newMempoolWithApp(cc) defer cleanup() - mp.config.Size = 100000 + mp.config.Size = 100_000_000 // so that the nmempool never saturates size := 10000 for i := 0; i < size; i++ { - tx := make([]byte, 8) - binary.BigEndian.PutUint64(tx, uint64(i)) - if err := mp.CheckTx(tx, nil, TxInfo{}); err != nil { + tx := kvstore.NewTxFromID(i) + if _, err := mp.CheckTx(tx); err != nil { b.Fatal(err) } } @@ -37,17 +43,15 @@ func BenchmarkCheckTx(b *testing.B) { mp, cleanup := newMempoolWithApp(cc) defer cleanup() - mp.config.Size = 1000000 + mp.config.Size = 100_000_000 b.ResetTimer() - for i := 0; i < b.N; i++ { b.StopTimer() - tx := make([]byte, 8) - binary.BigEndian.PutUint64(tx, uint64(i)) + tx := kvstore.NewTxFromID(i) b.StartTimer() - if err := mp.CheckTx(tx, nil, TxInfo{}); err != nil { + if _, err := mp.CheckTx(tx); err != nil { b.Fatal(err) } } @@ -59,19 +63,18 @@ func BenchmarkParallelCheckTx(b *testing.B) { mp, cleanup := newMempoolWithApp(cc) defer cleanup() - mp.config.Size = 100000000 + mp.config.Size = 100_000_000 var txcnt uint64 next := func() uint64 { - return atomic.AddUint64(&txcnt, 1) - 1 + return atomic.AddUint64(&txcnt, 1) } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { - tx := make([]byte, 8) - binary.BigEndian.PutUint64(tx, next()) - if err := mp.CheckTx(tx, nil, TxInfo{}); err != nil { + tx := kvstore.NewTxFromID(int(next())) + if _, err := mp.CheckTx(tx); err != nil { b.Fatal(err) } } @@ -84,17 +87,57 @@ func BenchmarkCheckDuplicateTx(b *testing.B) { mp, cleanup := newMempoolWithApp(cc) defer cleanup() - mp.config.Size = 1000000 + mp.config.Size = 2 + + tx := kvstore.NewTxFromID(1) + if _, err := mp.CheckTx(tx); err != nil { + b.Fatal(err) + } + e := mp.FlushAppConn() + require.NotErrorIs(b, nil, e) + b.ResetTimer() for i := 0; i < b.N; i++ { - tx := make([]byte, 8) - binary.BigEndian.PutUint64(tx, uint64(i)) - if err := mp.CheckTx(tx, nil, TxInfo{}); err != nil { - b.Fatal(err) + if _, err := mp.CheckTx(tx); err == nil { + b.Fatal("tx should be duplicate") } + } +} - if err := mp.CheckTx(tx, nil, TxInfo{}); err == nil { - b.Fatal("tx should be duplicate") +func BenchmarkUpdateRemoteClient(b *testing.B) { + sockPath := fmt.Sprintf("unix:///tmp/echo_%v.sock", cmtrand.Str(6)) + app := kvstore.NewInMemoryApplication() + + // Start server + server := abciserver.NewSocketServer(sockPath, app) + server.SetLogger(log.TestingLogger().With("module", "abci-server")) + if err := server.Start(); err != nil { + b.Fatalf("Error starting socket server: %v", err.Error()) + } + + b.Cleanup(func() { + if err := server.Stop(); err != nil { + b.Error(err) } + }) + cfg := test.ResetTestRoot("mempool_test") + mp, cleanup := newMempoolWithAppAndConfig(proxy.NewRemoteClientCreator(sockPath, "socket", true), cfg) + defer cleanup() + + b.ResetTimer() + for i := 1; i <= b.N; i++ { + tx := kvstore.NewTxFromID(i) + + _, e := mp.CheckTx(tx) + require.NoError(b, e) + + e = mp.FlushAppConn() + require.NoError(b, e) + + require.Equal(b, 1, mp.Size()) + + txs := mp.ReapMaxTxs(mp.Size()) + doCommit(b, mp, app, txs, int64(i)) + assert.True(b, true) } } diff --git a/mempool/cache.go b/mempool/cache.go index 37977e8fc5e..9e8833b9bf3 100644 --- a/mempool/cache.go +++ b/mempool/cache.go @@ -3,7 +3,7 @@ package mempool import ( "container/list" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/types" ) @@ -53,11 +53,12 @@ func (c *LRUTxCache) GetList() *list.List { return c.list } +// Reset resets the cache to an empty state. func (c *LRUTxCache) Reset() { c.mtx.Lock() defer c.mtx.Unlock() - c.cacheMap = make(map[types.TxKey]*list.Element, c.size) + clear(c.cacheMap) c.list.Init() } diff --git a/mempool/cache_test.go b/mempool/cache_test.go index bb659f20924..35089ba4790 100644 --- a/mempool/cache_test.go +++ b/mempool/cache_test.go @@ -3,14 +3,15 @@ package mempool import ( "crypto/rand" "crypto/sha256" - "fmt" + "strconv" "testing" + "github.com/stretchr/testify/require" + "github.com/cometbft/cometbft/abci/example/kvstore" abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/proxy" "github.com/cometbft/cometbft/types" - "github.com/stretchr/testify/require" ) func TestCacheRemove(t *testing.T) { @@ -28,14 +29,14 @@ func TestCacheRemove(t *testing.T) { cache.Push(txBytes) // make sure its added to both the linked list and the map - require.Equal(t, i+1, len(cache.cacheMap)) + require.Len(t, cache.cacheMap, i+1) require.Equal(t, i+1, cache.list.Len()) } for i := 0; i < numTxs; i++ { cache.Remove(txs[i]) // make sure its removed from both the map and the linked list - require.Equal(t, numTxs-(i+1), len(cache.cacheMap)) + require.Len(t, cache.cacheMap, numTxs-(i+1)) require.Equal(t, numTxs-(i+1), cache.list.Len()) } } @@ -62,26 +63,26 @@ func TestCacheAfterUpdate(t *testing.T) { } for tcIndex, tc := range tests { for i := 0; i < tc.numTxsToCreate; i++ { - tx := kvstore.NewTx(fmt.Sprintf("%d", i), "value") - err := mp.CheckTx(tx, func(resp *abci.ResponseCheckTx) { - require.False(t, resp.IsErr()) - }, TxInfo{}) + tx := kvstore.NewTx(strconv.Itoa(i), "value") + reqRes, err := mp.CheckTx(tx) require.NoError(t, err) + require.False(t, reqRes.Response.GetCheckTx().IsErr()) } updateTxs := []types.Tx{} for _, v := range tc.updateIndices { - tx := kvstore.NewTx(fmt.Sprintf("%d", v), "value") + tx := kvstore.NewTx(strconv.Itoa(v), "value") updateTxs = append(updateTxs, tx) } err := mp.Update(int64(tcIndex), updateTxs, abciResponses(len(updateTxs), abci.CodeTypeOK), nil, nil) require.NoError(t, err) for _, v := range tc.reAddIndices { - tx := kvstore.NewTx(fmt.Sprintf("%d", v), "value") - _ = mp.CheckTx(tx, func(resp *abci.ResponseCheckTx) { - require.False(t, resp.IsErr()) - }, TxInfo{}) + tx := kvstore.NewTx(strconv.Itoa(v), "value") + reqRes, err := mp.CheckTx(tx) + if err == nil { + require.False(t, reqRes.Response.GetCheckTx().IsErr()) + } } cache := mp.cache.(*LRUTxCache) @@ -92,7 +93,7 @@ func TestCacheAfterUpdate(t *testing.T) { "cache larger than expected on testcase %d", tcIndex) nodeVal := node.Value.(types.TxKey) - expTx := kvstore.NewTx(fmt.Sprintf("%d", tc.txsInCache[len(tc.txsInCache)-counter-1]), "value") + expTx := kvstore.NewTx(strconv.Itoa(tc.txsInCache[len(tc.txsInCache)-counter-1]), "value") expectedBz := sha256.Sum256(expTx) // Reference for reading the errors: // >>> sha256('\x00').hexdigest() @@ -106,7 +107,7 @@ func TestCacheAfterUpdate(t *testing.T) { counter++ node = node.Next() } - require.Equal(t, len(tc.txsInCache), counter, + require.Len(t, tc.txsInCache, counter, "cache smaller than expected on testcase %d", tcIndex) mp.Flush() } diff --git a/mempool/clist_mempool.go b/mempool/clist_mempool.go index e0501cebb2a..4263edf43a3 100644 --- a/mempool/clist_mempool.go +++ b/mempool/clist_mempool.go @@ -3,17 +3,17 @@ package mempool import ( "bytes" "context" - "errors" + "fmt" "sync" "sync/atomic" + abcicli "github.com/cometbft/cometbft/abci/client" abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/libs/clist" + "github.com/cometbft/cometbft/internal/clist" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtsync "github.com/cometbft/cometbft/libs/sync" - "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/proxy" "github.com/cometbft/cometbft/types" ) @@ -24,14 +24,17 @@ import ( // mempool uses a concurrent list structure for storing transactions that can // be efficiently accessed by multiple concurrent readers. type CListMempool struct { - // Atomic integers - height int64 // the last block Update()'d to - txsBytes int64 // total size of mempool, in bytes + height atomic.Int64 // the last block Update()'d to + txsBytes atomic.Int64 // total size of mempool, in bytes // notify listeners (ie. consensus) when txs are available - notifiedTxsAvailable bool + notifiedTxsAvailable atomic.Bool txsAvailable chan struct{} // fires once for each height, when the mempool is not empty + // Function set by the reactor to be called when a transaction is removed + // from the mempool. + removeTxOnReactorCb func(txKey types.TxKey) + config *config.MempoolConfig // Exclusive mutex for Update method to prevent concurrent execution of @@ -40,7 +43,6 @@ type CListMempool struct { preCheck PreCheckFunc postCheck PostCheckFunc - txs *clist.CList // concurrent linked-list of good txs proxyAppConn proxy.AppConnMempool // Track whether we're rechecking txs. @@ -49,8 +51,10 @@ type CListMempool struct { recheckCursor *clist.CElement // next expected response recheckEnd *clist.CElement // re-checking stops here - // Map for quick access to txs to record sender in CheckTx. - // txsMap: txKey -> CElement + // Concurrent linked-list of valid txs. + // `txsMap`: txKey -> CElement is for quick access to txs. + // Transactions in both `txs` and `txsMap` must to be kept in sync. + txs *clist.CList txsMap sync.Map // Keep a cache of already-seen txs. @@ -74,17 +78,16 @@ func NewCListMempool( height int64, options ...CListMempoolOption, ) *CListMempool { - mp := &CListMempool{ config: cfg, proxyAppConn: proxyAppConn, txs: clist.New(), - height: height, recheckCursor: nil, recheckEnd: nil, logger: log.NewNopLogger(), metrics: NopMetrics(), } + mp.height.Store(height) if cfg.CacheSize > 0 { mp.cache = NewLRUTxCache(cfg.CacheSize) @@ -101,11 +104,65 @@ func NewCListMempool( return mp } -// NOTE: not thread safe - should only be called once, on startup +func (mem *CListMempool) getCElement(txKey types.TxKey) (*clist.CElement, bool) { + if e, ok := mem.txsMap.Load(txKey); ok { + return e.(*clist.CElement), true + } + return nil, false +} + +func (mem *CListMempool) InMempool(txKey types.TxKey) bool { + _, ok := mem.getCElement(txKey) + return ok +} + +func (mem *CListMempool) addToCache(tx types.Tx) bool { + return mem.cache.Push(tx) +} + +func (mem *CListMempool) forceRemoveFromCache(tx types.Tx) { + mem.cache.Remove(tx) +} + +// tryRemoveFromCache removes a transaction from the cache in case it can be +// added to the mempool at a later stage (probably when the transaction becomes +// valid). +func (mem *CListMempool) tryRemoveFromCache(tx types.Tx) { + if !mem.config.KeepInvalidTxsInCache { + mem.forceRemoveFromCache(tx) + } +} + +func (mem *CListMempool) removeAllTxs() { + for e := mem.txs.Front(); e != nil; e = e.Next() { + mem.txs.Remove(e) + e.DetachPrev() + } + + mem.txsMap.Range(func(key, _ any) bool { + mem.txsMap.Delete(key) + mem.invokeRemoveTxOnReactor(key.(types.TxKey)) + return true + }) +} + +// NOTE: not thread safe - should only be called once, on startup. func (mem *CListMempool) EnableTxsAvailable() { mem.txsAvailable = make(chan struct{}, 1) } +func (mem *CListMempool) SetTxRemovedCallback(cb func(txKey types.TxKey)) { + mem.removeTxOnReactorCb = cb +} + +func (mem *CListMempool) invokeRemoveTxOnReactor(txKey types.TxKey) { + // Note that the callback is nil in the unit tests, where there are no + // reactors. + if mem.removeTxOnReactorCb != nil { + mem.removeTxOnReactorCb(txKey) + } +} + // SetLogger sets the Logger. func (mem *CListMempool) SetLogger(l log.Logger) { mem.logger = l @@ -147,12 +204,17 @@ func (mem *CListMempool) Size() int { // Safe for concurrent use by multiple goroutines. func (mem *CListMempool) SizeBytes() int64 { - return atomic.LoadInt64(&mem.txsBytes) + return mem.txsBytes.Load() } // Lock() must be help by the caller during execution. func (mem *CListMempool) FlushAppConn() error { - return mem.proxyAppConn.Flush(context.TODO()) + err := mem.proxyAppConn.Flush(context.TODO()) + if err != nil { + return ErrFlushAppConn{Err: err} + } + + return nil } // XXX: Unsafe! Calling Flush may leave mempool in inconsistent state. @@ -160,18 +222,10 @@ func (mem *CListMempool) Flush() { mem.updateMtx.RLock() defer mem.updateMtx.RUnlock() - _ = atomic.SwapInt64(&mem.txsBytes, 0) + mem.txsBytes.Store(0) mem.cache.Reset() - for e := mem.txs.Front(); e != nil; e = e.Next() { - mem.txs.Remove(e) - e.DetachPrev() - } - - mem.txsMap.Range(func(key, _ interface{}) bool { - mem.txsMap.Delete(key) - return true - }) + mem.removeAllTxs() } // TxsFront returns the first transaction in the ordered list for peer @@ -193,19 +247,8 @@ func (mem *CListMempool) TxsWaitChan() <-chan struct{} { } // It blocks if we're waiting on Update() or Reap(). -// cb: A callback from the CheckTx command. -// -// It gets called from another goroutine. -// -// CONTRACT: Either cb will get called, or err returned. -// // Safe for concurrent use by multiple goroutines. -func (mem *CListMempool) CheckTx( - tx types.Tx, - cb func(*abci.ResponseCheckTx), - txInfo TxInfo, -) error { - +func (mem *CListMempool) CheckTx(tx types.Tx) (*abcicli.ReqRes, error) { mem.updateMtx.RLock() // use defer to unlock mutex because application (*local client*) might panic defer mem.updateMtx.RUnlock() @@ -213,11 +256,11 @@ func (mem *CListMempool) CheckTx( txSize := len(tx) if err := mem.isFull(txSize); err != nil { - return err + return nil, err } if txSize > mem.config.MaxTxBytes { - return ErrTxTooLarge{ + return nil, ErrTxTooLarge{ Max: mem.config.MaxTxBytes, Actual: txSize, } @@ -225,125 +268,120 @@ func (mem *CListMempool) CheckTx( if mem.preCheck != nil { if err := mem.preCheck(tx); err != nil { - return ErrPreCheck{ - Reason: err, - } + return nil, ErrPreCheck{Err: err} } } // NOTE: proxyAppConn may error if tx buffer is full if err := mem.proxyAppConn.Error(); err != nil { - return err - } - - if !mem.cache.Push(tx) { // if the transaction already exists in the cache - // Record a new sender for a tx we've already seen. - // Note it's possible a tx is still in the cache but no longer in the mempool - // (eg. after committing a block, txs are removed from mempool but not cache), - // so we only record the sender for txs still in the mempool. - if e, ok := mem.txsMap.Load(tx.Key()); ok { - memTx := e.(*clist.CElement).Value.(*mempoolTx) - memTx.senders.LoadOrStore(txInfo.SenderID, true) - // TODO: consider punishing peer for dups, - // its non-trivial since invalid txs can become valid, - // but they can spam the same tx with little cost to them atm. - } - return ErrTxInCache + return nil, ErrAppConnMempool{Err: err} } - reqRes, err := mem.proxyAppConn.CheckTxAsync(context.TODO(), &abci.RequestCheckTx{Tx: tx}) + if added := mem.addToCache(tx); !added { + mem.logger.Debug("Not cached", "tx", tx.Hash()) + mem.metrics.AlreadyReceivedTxs.Add(1) + // TODO: consider punishing peer for dups, + // its non-trivial since invalid txs can become valid, + // but they can spam the same tx with little cost to them atm. + return nil, ErrTxInCache + } + mem.logger.Debug("Cached", "tx", tx.Hash()) + + reqRes, err := mem.proxyAppConn.CheckTxAsync(context.TODO(), &abci.CheckTxRequest{ + Tx: tx, + Type: abci.CHECK_TX_TYPE_CHECK, + }) if err != nil { - return err + mem.logger.Error("RequestCheckTx", "err", err) + return nil, ErrCheckTxAsync{Err: err} } - reqRes.SetCallback(mem.reqResCb(tx, txInfo.SenderID, txInfo.SenderP2PID, cb)) - return nil + return reqRes, nil } // Global callback that will be called after every ABCI response. -// Having a single global callback avoids needing to set a callback for each request. -// However, processing the checkTx response requires the peerID (so we can track which txs we heard from who), -// and peerID is not included in the ABCI request, so we have to set request-specific callbacks that -// include this information. If we're not in the midst of a recheck, this function will just return, -// so the request specific callback can do the work. -// -// When rechecking, we don't need the peerID, so the recheck callback happens -// here. func (mem *CListMempool) globalCb(req *abci.Request, res *abci.Response) { - if mem.recheckCursor == nil { - return - } - - mem.metrics.RecheckTimes.Add(1) - mem.resCbRecheck(req, res) + switch res.Value.(type) { + case *abci.Response_CheckTx: + checkType := req.GetCheckTx().GetType() + switch checkType { + case abci.CHECK_TX_TYPE_CHECK: + if mem.recheckCursor != nil { + // this should never happen + panic("recheck cursor is not nil before resCbFirstTime") + } + mem.resCbFirstTime(req.GetCheckTx().Tx, res.GetCheckTx()) - // update metrics - mem.metrics.Size.Set(float64(mem.Size())) -} + case abci.CHECK_TX_TYPE_RECHECK: + if mem.recheckCursor == nil { + return + } + mem.metrics.RecheckTimes.Add(1) + mem.resCbRecheck(req.GetCheckTx().Tx, res.GetCheckTx()) -// Request specific callback that should be set on individual reqRes objects -// to incorporate local information when processing the response. -// This allows us to track the peer that sent us this tx, so we can avoid sending it back to them. -// NOTE: alternatively, we could include this information in the ABCI request itself. -// -// External callers of CheckTx, like the RPC, can also pass an externalCb through here that is called -// when all other response processing is complete. -// -// Used in CheckTx to record PeerID who sent us the tx. -func (mem *CListMempool) reqResCb( - tx []byte, - peerID uint16, - peerP2PID p2p.ID, - externalCb func(*abci.ResponseCheckTx), -) func(res *abci.Response) { - return func(res *abci.Response) { - if mem.recheckCursor != nil { - // this should never happen - panic("recheck cursor is not nil in reqResCb") + default: + panic(fmt.Sprintf("unexpected value %d of RequestCheckTx.type", checkType)) } - mem.resCbFirstTime(tx, peerID, peerP2PID, res) - // update metrics mem.metrics.Size.Set(float64(mem.Size())) + mem.metrics.SizeBytes.Set(float64(mem.SizeBytes())) - // passed in by the caller of CheckTx, eg. the RPC - if externalCb != nil { - externalCb(res.GetCheckTx()) - } + default: + // ignore other messages } } // Called from: // - resCbFirstTime (lock not held) if tx is valid -func (mem *CListMempool) addTx(memTx *mempoolTx) { +func (mem *CListMempool) addTx(memTx *mempoolTx) bool { + tx := memTx.tx + + if mem.InMempool(tx.Key()) { + mem.logger.Debug( + "transaction already in mempool, not adding it again", + "tx", tx.Hash(), + "height", mem.height.Load(), + "total", mem.Size(), + ) + return false + } + e := mem.txs.PushBack(memTx) - mem.txsMap.Store(memTx.tx.Key(), e) - atomic.AddInt64(&mem.txsBytes, int64(len(memTx.tx))) - mem.metrics.TxSizeBytes.Observe(float64(len(memTx.tx))) + mem.txsMap.Store(tx.Key(), e) + mem.txsBytes.Add(int64(len(tx))) + mem.metrics.TxSizeBytes.Observe(float64(len(tx))) + + mem.logger.Debug( + "added valid transaction", + "tx", tx.Hash(), + "height", mem.height.Load(), + "total", mem.Size(), + ) + return true } +// RemoveTxByKey removes a transaction from the mempool by its TxKey index. // 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) { - mem.txs.Remove(elem) - elem.DetachPrev() - mem.txsMap.Delete(tx.Key()) - atomic.AddInt64(&mem.txsBytes, int64(-len(tx))) -} - -// RemoveTxByKey removes a transaction from the mempool by its TxKey index. 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)) - return nil - } - return errors.New("found empty transaction") + // The transaction should be removed from the reactor, even if it cannot be + // found in the mempool. + mem.invokeRemoveTxOnReactor(txKey) + + elem, ok := mem.getCElement(txKey) + if !ok { + return ErrTxNotFound } - return errors.New("transaction not found") + + mem.txs.Remove(elem) + elem.DetachPrev() + mem.txsMap.Delete(txKey) + tx := elem.Value.(*mempoolTx).tx + mem.txsBytes.Add(int64(-len(tx))) + mem.logger.Debug("removed transaction", "tx", tx.Hash(), "height", mem.height.Load(), "total", mem.Size()) + return nil } func (mem *CListMempool) isFull(txSize int) error { @@ -352,7 +390,7 @@ func (mem *CListMempool) isFull(txSize int) error { txsBytes = mem.SizeBytes() ) - if memSize >= mem.config.Size || int64(txSize)+txsBytes > mem.config.MaxTxsBytes { + if memSize >= mem.config.Size || uint64(txSize)+uint64(txsBytes) > uint64(mem.config.MaxTxsBytes) { return ErrMempoolIsFull{ NumTxs: memSize, MaxTxs: mem.config.Size, @@ -368,62 +406,38 @@ func (mem *CListMempool) isFull(txSize int) error { // // The case where the app checks the tx for the second and subsequent times is // handled by the resCbRecheck callback. -func (mem *CListMempool) resCbFirstTime( - tx []byte, - peerID uint16, - peerP2PID p2p.ID, - res *abci.Response, -) { - switch r := res.Value.(type) { - case *abci.Response_CheckTx: - var postCheckErr error - if mem.postCheck != nil { - postCheckErr = mem.postCheck(tx, r.CheckTx) - } - if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { - // Check mempool isn't full again to reduce the chance of exceeding the - // limits. - if err := mem.isFull(len(tx)); err != nil { - // remove from cache (mempool might have a space later) - mem.cache.Remove(tx) - mem.logger.Error(err.Error()) - return - } +func (mem *CListMempool) resCbFirstTime(tx types.Tx, res *abci.CheckTxResponse) { + var postCheckErr error + if mem.postCheck != nil { + postCheckErr = mem.postCheck(tx, res) + } - memTx := &mempoolTx{ - height: mem.height, - gasWanted: r.CheckTx.GasWanted, - tx: tx, - } - memTx.senders.Store(peerID, true) - mem.addTx(memTx) - mem.logger.Debug( - "added good transaction", - "tx", types.Tx(tx).Hash(), - "res", r, - "height", memTx.height, - "total", mem.Size(), - ) - mem.notifyTxsAvailable() - } else { - // ignore bad transaction - mem.logger.Debug( - "rejected bad transaction", - "tx", types.Tx(tx).Hash(), - "peerID", peerP2PID, - "res", r, - "err", postCheckErr, - ) - mem.metrics.FailedTxs.Add(1) - - if !mem.config.KeepInvalidTxsInCache { - // remove from cache (it might be good later) - mem.cache.Remove(tx) - } - } + if res.Code != abci.CodeTypeOK || postCheckErr != nil { + mem.tryRemoveFromCache(tx) + mem.logger.Debug( + "rejected invalid transaction", + "tx", tx.Hash(), + "res", res, + "err", postCheckErr, + ) + mem.metrics.FailedTxs.Add(1) + return + } - default: - // ignore other messages + // Check mempool isn't full again to reduce the chance of exceeding the + // limits. + if err := mem.isFull(len(tx)); err != nil { + mem.forceRemoveFromCache(tx) // mempool might have space later + mem.logger.Error(err.Error()) + return + } + + if mem.addTx(&mempoolTx{ + height: mem.height.Load(), + gasWanted: res.GasWanted, + tx: tx, + }) { + mem.notifyTxsAvailable() } } @@ -431,72 +445,65 @@ func (mem *CListMempool) resCbFirstTime( // // The case where the app checks the tx for the first time is handled by the // resCbFirstTime callback. -func (mem *CListMempool) resCbRecheck(req *abci.Request, res *abci.Response) { - switch r := res.Value.(type) { - case *abci.Response_CheckTx: - tx := req.GetCheckTx().Tx - memTx := mem.recheckCursor.Value.(*mempoolTx) - - // Search through the remaining list of tx to recheck for a transaction that matches - // the one we received from the ABCI application. - for { - if bytes.Equal(tx, memTx.tx) { - // We've found a tx in the recheck list that matches the tx that we - // received from the ABCI application. - // Break, and use this transaction for further checks. - break - } - - mem.logger.Error( - "re-CheckTx transaction mismatch", - "got", types.Tx(tx), - "expected", memTx.tx, - ) - - if mem.recheckCursor == mem.recheckEnd { - // we reached the end of the recheckTx list without finding a tx - // matching the one we received from the ABCI application. - // Return without processing any tx. - mem.recheckCursor = nil - return - } - - mem.recheckCursor = mem.recheckCursor.Next() - memTx = mem.recheckCursor.Value.(*mempoolTx) +func (mem *CListMempool) resCbRecheck(tx types.Tx, res *abci.CheckTxResponse) { + memTx := mem.recheckCursor.Value.(*mempoolTx) + + // Search through the remaining list of tx to recheck for a transaction that matches + // the one we received from the ABCI application. + for { + if bytes.Equal(tx, memTx.tx) { + // We've found a tx in the recheck list that matches the tx that we + // received from the ABCI application. + // Break, and use this transaction for further checks. + break } - var postCheckErr error - if mem.postCheck != nil { - postCheckErr = mem.postCheck(tx, r.CheckTx) - } + mem.logger.Error( + "re-CheckTx transaction mismatch", + "got", tx.Hash(), + "expected", memTx.tx.Hash(), + ) - if (r.CheckTx.Code == abci.CodeTypeOK) && postCheckErr == nil { - // Good, nothing to do. - } 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) - 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 { + // we reached the end of the recheckTx list without finding a tx + // matching the one we received from the ABCI application. + // Return without processing any tx. mem.recheckCursor = nil - } else { - mem.recheckCursor = mem.recheckCursor.Next() + return } - if mem.recheckCursor == nil { - // Done! - mem.logger.Debug("done rechecking txs") - // incase the recheck removed all txs - if mem.Size() > 0 { - mem.notifyTxsAvailable() - } + mem.recheckCursor = mem.recheckCursor.Next() + memTx = mem.recheckCursor.Value.(*mempoolTx) + } + + var postCheckErr error + if mem.postCheck != nil { + postCheckErr = mem.postCheck(tx, res) + } + + if (res.Code != abci.CodeTypeOK) || postCheckErr != nil { + // Tx became invalidated due to newly committed block. + mem.logger.Debug("tx is no longer valid", "tx", tx.Hash(), "res", res, "postCheckErr", postCheckErr) + if err := mem.RemoveTxByKey(memTx.tx.Key()); err != nil { + mem.logger.Debug("Transaction could not be removed from mempool", "err", err) + } + mem.tryRemoveFromCache(tx) + } + + if mem.recheckCursor == mem.recheckEnd { + mem.recheckCursor = nil + } else { + mem.recheckCursor = mem.recheckCursor.Next() + } + + if mem.recheckCursor == nil { + // Done! + mem.logger.Debug("done rechecking txs") + + // in case the recheck removed all txs + if mem.Size() > 0 { + mem.notifyTxsAvailable() } - default: - // ignore other messages } } @@ -509,9 +516,8 @@ func (mem *CListMempool) notifyTxsAvailable() { if mem.Size() == 0 { panic("notified txs available but mempool is empty!") } - if mem.txsAvailable != nil && !mem.notifiedTxsAvailable { + if mem.txsAvailable != nil && mem.notifiedTxsAvailable.CompareAndSwap(false, true) { // channel cap is 1, so this will send once - mem.notifiedTxsAvailable = true select { case mem.txsAvailable <- struct{}{}: default: @@ -578,6 +584,7 @@ func (mem *CListMempool) ReapMaxTxs(max int) types.Txs { } // Lock() must be help by the caller during execution. +// TODO: this function always returns nil; remove the return value. func (mem *CListMempool) Update( height int64, txs types.Txs, @@ -586,8 +593,8 @@ func (mem *CListMempool) Update( postCheck PostCheckFunc, ) error { // Set height - mem.height = height - mem.notifiedTxsAvailable = false + mem.height.Store(height) + mem.notifiedTxsAvailable.Store(false) if preCheck != nil { mem.preCheck = preCheck @@ -599,10 +606,9 @@ func (mem *CListMempool) Update( for i, tx := range txs { if txResults[i].Code == abci.CodeTypeOK { // Add valid committed tx to the cache (if missing). - _ = mem.cache.Push(tx) - } else if !mem.config.KeepInvalidTxsInCache { - // Allow invalid transactions to be resubmitted. - mem.cache.Remove(tx) + _ = mem.addToCache(tx) + } else { + mem.tryRemoveFromCache(tx) } // Remove committed tx from the mempool. @@ -616,7 +622,9 @@ func (mem *CListMempool) Update( // 100 // https://github.com/tendermint/tendermint/issues/3322. if err := mem.RemoveTxByKey(tx.Key()); err != nil { - mem.logger.Error("Committed transaction could not be removed from mempool", "key", tx.Key(), err.Error()) + mem.logger.Debug("Committed transaction not in local mempool (not an error)", + "key", tx.Key(), + "error", err.Error()) } } @@ -636,6 +644,7 @@ func (mem *CListMempool) Update( // Update metrics mem.metrics.Size.Set(float64(mem.Size())) + mem.metrics.SizeBytes.Set(float64(mem.SizeBytes())) return nil } @@ -652,12 +661,12 @@ func (mem *CListMempool) recheckTxs() { // NOTE: globalCb may be called concurrently. for e := mem.txs.Front(); e != nil; e = e.Next() { memTx := e.Value.(*mempoolTx) - _, err := mem.proxyAppConn.CheckTxAsync(context.TODO(), &abci.RequestCheckTx{ + _, err := mem.proxyAppConn.CheckTxAsync(context.TODO(), &abci.CheckTxRequest{ Tx: memTx.tx, - Type: abci.CheckTxType_Recheck, + Type: abci.CHECK_TX_TYPE_RECHECK, }) if err != nil { - mem.logger.Error("recheckTx", err, "err") + mem.logger.Error("recheckTx", "err", err) return } } @@ -666,21 +675,3 @@ func (mem *CListMempool) recheckTxs() { // all pending messages to the app. There doesn't seem to be any need here as the buffer // will get flushed regularly or when filled. } - -//-------------------------------------------------------------------------------- - -// mempoolTx is a transaction that successfully ran -type mempoolTx struct { - height int64 // height that this tx had been validated in - gasWanted int64 // amount of gas this tx states it will require - tx types.Tx // - - // ids of peers who've sent us this tx (as a map for quick lookups). - // senders: PeerID -> bool - senders sync.Map -} - -// Height returns the height for this transaction -func (memTx *mempoolTx) Height() int64 { - return atomic.LoadInt64(&memTx.height) -} diff --git a/mempool/clist_mempool_test.go b/mempool/clist_mempool_test.go index 061975ecf91..8e15271781a 100644 --- a/mempool/clist_mempool_test.go +++ b/mempool/clist_mempool_test.go @@ -6,6 +6,8 @@ import ( "fmt" mrand "math/rand" "os" + "strconv" + "sync" "testing" "time" @@ -21,10 +23,10 @@ import ( abciserver "github.com/cometbft/cometbft/abci/server" abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/config" + cmtrand "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" - cmtrand "github.com/cometbft/cometbft/libs/rand" - "github.com/cometbft/cometbft/libs/service" "github.com/cometbft/cometbft/proxy" "github.com/cometbft/cometbft/types" ) @@ -33,16 +35,17 @@ import ( // test. type cleanupFunc func() -func newMempoolWithAppMock(cc proxy.ClientCreator, client abciclient.Client) (*CListMempool, cleanupFunc, error) { +func newMempoolWithAppMock(client abciclient.Client) (*CListMempool, cleanupFunc) { conf := test.ResetTestRoot("mempool_test") - mp, cu := newMempoolWithAppAndConfigMock(cc, conf, client) - return mp, cu, nil + mp, cu := newMempoolWithAppAndConfigMock(conf, client) + return mp, cu } -func newMempoolWithAppAndConfigMock(cc proxy.ClientCreator, +func newMempoolWithAppAndConfigMock( cfg *config.Config, - client abciclient.Client) (*CListMempool, cleanupFunc) { + client abciclient.Client, +) (*CListMempool, cleanupFunc) { appConnMem := client appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool")) err := appConnMem.Start() @@ -64,7 +67,7 @@ func newMempoolWithApp(cc proxy.ClientCreator) (*CListMempool, cleanupFunc) { } func newMempoolWithAppAndConfig(cc proxy.ClientCreator, cfg *config.Config) (*CListMempool, cleanupFunc) { - appConnMem, _ := cc.NewABCIClient() + appConnMem, _ := cc.NewABCIMempoolClient() appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool")) err := appConnMem.Start() if err != nil { @@ -77,8 +80,9 @@ func newMempoolWithAppAndConfig(cc proxy.ClientCreator, cfg *config.Config) (*CL return mp, func() { os.RemoveAll(cfg.RootDir) } } -func ensureNoFire(t *testing.T, ch <-chan struct{}, timeoutMS int) { - timer := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond) +func ensureNoFire(t *testing.T, ch <-chan struct{}) { + t.Helper() + timer := time.NewTimer(100 * time.Millisecond) select { case <-ch: t.Fatal("Expected not to fire") @@ -87,6 +91,7 @@ func ensureNoFire(t *testing.T, ch <-chan struct{}, timeoutMS int) { } func ensureFire(t *testing.T, ch <-chan struct{}, timeoutMS int) { + t.Helper() timer := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond) select { case <-ch: @@ -95,13 +100,11 @@ func ensureFire(t *testing.T, ch <-chan struct{}, timeoutMS int) { } } -func checkTxs(t *testing.T, mp Mempool, count int, peerID uint16) types.Txs { - txs := make(types.Txs, count) - txInfo := TxInfo{SenderID: peerID} - for i := 0; i < count; i++ { - txBytes := kvstore.NewRandomTx(20) - txs[i] = txBytes - if err := mp.CheckTx(txBytes, nil, txInfo); err != nil { +// Call CheckTx on a given mempool on each transaction in the list. +func callCheckTx(t *testing.T, mp Mempool, txs types.Txs) { + t.Helper() + for i, tx := range txs { + if _, err := mp.CheckTx(tx); err != nil { // Skip invalid txs. // TestMempoolFilters will fail otherwise. It asserts a number of txs // returned. @@ -111,6 +114,24 @@ func checkTxs(t *testing.T, mp Mempool, count int, peerID uint16) types.Txs { t.Fatalf("CheckTx failed: %v while checking #%d tx", err, i) } } +} + +// Generate a list of random transactions. +func NewRandomTxs(numTxs int, txLen int) types.Txs { + txs := make(types.Txs, numTxs) + for i := 0; i < numTxs; i++ { + txBytes := kvstore.NewRandomTx(txLen) + txs[i] = txBytes + } + return txs +} + +// Generate a list of random transactions of a given size and call CheckTx on +// each of them. +func checkTxs(t *testing.T, mp Mempool, count int) types.Txs { + t.Helper() + txs := NewRandomTxs(count, 20) + callCheckTx(t, mp, txs) return txs } @@ -121,11 +142,11 @@ func TestReapMaxBytesMaxGas(t *testing.T) { defer cleanup() // Ensure gas calculation behaves as expected - checkTxs(t, mp, 1, UnknownPeerID) + checkTxs(t, mp, 1) tx0 := mp.TxsFront().Value.(*mempoolTx) require.Equal(t, tx0.gasWanted, int64(1), "transactions gas was set incorrectly") // ensure each tx is 20 bytes long - require.Equal(t, len(tx0.tx), 20, "Tx is longer than 20 bytes") + require.Len(t, tx0.tx, 20, "Tx is longer than 20 bytes") mp.Flush() // each table driven test creates numTxsToCreate txs with checkTx, and at the end clears all remaining txs. @@ -153,9 +174,9 @@ func TestReapMaxBytesMaxGas(t *testing.T) { {20, 20000, 30, 20}, } for tcIndex, tt := range tests { - checkTxs(t, mp, tt.numTxsToCreate, UnknownPeerID) + checkTxs(t, mp, tt.numTxsToCreate) got := mp.ReapMaxBytesMaxGas(tt.maxBytes, tt.maxGas) - assert.Equal(t, tt.expectedNumTxs, len(got), "Got %d txs, expected %d, tc #%d", + require.Len(t, got, tt.expectedNumTxs, "Got %d txs, expected %d, tc #%d", len(got), tt.expectedNumTxs, tcIndex) mp.Flush() } @@ -168,8 +189,8 @@ func TestMempoolFilters(t *testing.T) { defer cleanup() emptyTxArr := []types.Tx{[]byte{}} - nopPreFilter := func(tx types.Tx) error { return nil } - nopPostFilter := func(tx types.Tx, res *abci.ResponseCheckTx) error { return nil } + nopPreFilter := func(_ types.Tx) error { return nil } + nopPostFilter := func(_ types.Tx, _ *abci.CheckTxResponse) error { return nil } // each table driven test creates numTxsToCreate txs with checkTx, and at the end clears all remaining txs. // each tx has 20 bytes @@ -194,7 +215,7 @@ func TestMempoolFilters(t *testing.T) { for tcIndex, tt := range tests { err := mp.Update(1, emptyTxArr, abciResponses(len(emptyTxArr), abci.CodeTypeOK), tt.preFilter, tt.postFilter) require.NoError(t, err) - checkTxs(t, mp, tt.numTxsToCreate, UnknownPeerID) + checkTxs(t, mp, tt.numTxsToCreate) require.Equal(t, tt.expectedNumTxs, mp.Size(), "mempool had the incorrect size, on test case %d", tcIndex) mp.Flush() } @@ -211,8 +232,8 @@ func TestMempoolUpdate(t *testing.T) { tx1 := kvstore.NewTxFromID(1) err := mp.Update(1, []types.Tx{tx1}, abciResponses(1, abci.CodeTypeOK), nil, nil) require.NoError(t, err) - err = mp.CheckTx(tx1, nil, TxInfo{}) - if assert.Error(t, err) { + _, err = mp.CheckTx(tx1) + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, ErrTxInCache, err) } } @@ -220,7 +241,7 @@ func TestMempoolUpdate(t *testing.T) { // 2. Removes valid txs from the mempool { tx2 := kvstore.NewTxFromID(2) - err := mp.CheckTx(tx2, nil, TxInfo{}) + _, err := mp.CheckTx(tx2) require.NoError(t, err) err = mp.Update(1, []types.Tx{tx2}, abciResponses(1, abci.CodeTypeOK), nil, nil) require.NoError(t, err) @@ -230,50 +251,52 @@ func TestMempoolUpdate(t *testing.T) { // 3. Removes invalid transactions from the cache and the mempool (if present) { tx3 := kvstore.NewTxFromID(3) - err := mp.CheckTx(tx3, nil, TxInfo{}) + _, err := mp.CheckTx(tx3) require.NoError(t, err) err = mp.Update(1, []types.Tx{tx3}, abciResponses(1, 1), nil, nil) require.NoError(t, err) assert.Zero(t, mp.Size()) - err = mp.CheckTx(tx3, nil, TxInfo{}) + _, err = mp.CheckTx(tx3) require.NoError(t, err) } } +// Test dropping CheckTx requests when rechecking transactions. It mocks an asynchronous connection +// to the app. func TestMempoolUpdateDoesNotPanicWhenApplicationMissedTx(t *testing.T) { var callback abciclient.Callback mockClient := new(abciclimocks.Client) mockClient.On("Start").Return(nil) mockClient.On("SetLogger", mock.Anything) - mockClient.On("Error").Return(nil).Times(4) mockClient.On("SetResponseCallback", mock.MatchedBy(func(cb abciclient.Callback) bool { callback = cb; return true })) - app := kvstore.NewInMemoryApplication() - cc := proxy.NewLocalClientCreator(app) - mp, cleanup, err := newMempoolWithAppMock(cc, mockClient) - require.NoError(t, err) + mp, cleanup := newMempoolWithAppMock(mockClient) defer cleanup() // Add 4 transactions to the mempool by calling the mempool's `CheckTx` on each of them. txs := []types.Tx{[]byte{0x01}, []byte{0x02}, []byte{0x03}, []byte{0x04}} for _, tx := range txs { - reqRes := abciclient.NewReqRes(abci.ToRequestCheckTx(&abci.RequestCheckTx{Tx: tx})) - reqRes.Response = abci.ToResponseCheckTx(&abci.ResponseCheckTx{Code: abci.CodeTypeOK}) - - mockClient.On("CheckTxAsync", mock.Anything, mock.Anything).Return(reqRes, nil) - err := mp.CheckTx(tx, nil, TxInfo{}) + mockClient.On("CheckTxAsync", mock.Anything, mock.Anything).Return(nil, nil).Once() + _, err := mp.CheckTx(tx) require.NoError(t, err) + } + require.Zero(t, mp.Size()) - // ensure that the callback that the mempool sets on the ReqRes is run. - reqRes.InvokeCallback() + // Invoke CheckTx callbacks asynchronously. + for _, tx := range txs { + reqRes := newReqRes(tx, abci.CodeTypeOK, abci.CHECK_TX_TYPE_CHECK) + callback(reqRes.Request, reqRes.Response) } + require.Len(t, txs, mp.Size()) + require.Nil(t, mp.recheckCursor) // Calling update to remove the first transaction from the mempool. // This call also triggers the mempool to recheck its remaining transactions. - err = mp.Update(0, []types.Tx{txs[0]}, abciResponses(1, abci.CodeTypeOK), nil, nil) - require.Nil(t, err) + mockClient.On("CheckTxAsync", mock.Anything, mock.Anything).Return(nil, nil) + err := mp.Update(0, []types.Tx{txs[0]}, abciResponses(1, abci.CodeTypeOK), nil, nil) + require.NoError(t, err) // The mempool has now sent its requests off to the client to be rechecked // and is waiting for the corresponding callbacks to be called. @@ -281,12 +304,12 @@ func TestMempoolUpdateDoesNotPanicWhenApplicationMissedTx(t *testing.T) { // This simulates the client dropping the second request. // Previous versions of this code panicked when the ABCI application missed // a recheck-tx request. - resp := &abci.ResponseCheckTx{Code: abci.CodeTypeOK} - req := &abci.RequestCheckTx{Tx: txs[1]} - callback(abci.ToRequestCheckTx(req), abci.ToResponseCheckTx(resp)) + reqRes := newReqRes(txs[1], abci.CodeTypeOK, abci.CHECK_TX_TYPE_RECHECK) + callback(reqRes.Request, reqRes.Response) + + reqRes = newReqRes(txs[3], abci.CodeTypeOK, abci.CHECK_TX_TYPE_RECHECK) + callback(reqRes.Request, reqRes.Response) - req = &abci.RequestCheckTx{Tx: txs[3]} - callback(abci.ToRequestCheckTx(req), abci.ToResponseCheckTx(resp)) mockClient.AssertExpectations(t) } @@ -306,11 +329,11 @@ func TestMempool_KeepInvalidTxsInCache(t *testing.T) { b := make([]byte, 8) binary.BigEndian.PutUint64(b, 1) - err := mp.CheckTx(b, nil, TxInfo{}) + _, err := mp.CheckTx(b) require.NoError(t, err) // simulate new block - _, err = app.FinalizeBlock(context.Background(), &abci.RequestFinalizeBlock{ + _, err = app.FinalizeBlock(context.Background(), &abci.FinalizeBlockRequest{ Txs: [][]byte{a, b}, }) require.NoError(t, err) @@ -319,14 +342,14 @@ func TestMempool_KeepInvalidTxsInCache(t *testing.T) { require.NoError(t, err) // a must be added to the cache - err = mp.CheckTx(a, nil, TxInfo{}) - if assert.Error(t, err) { + _, err = mp.CheckTx(a) + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, ErrTxInCache, err) } // b must remain in the cache - err = mp.CheckTx(b, nil, TxInfo{}) - if assert.Error(t, err) { + _, err = mp.CheckTx(b) + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, ErrTxInCache, err) } } @@ -339,7 +362,7 @@ func TestMempool_KeepInvalidTxsInCache(t *testing.T) { // remove a from the cache to test (2) mp.cache.Remove(a) - err := mp.CheckTx(a, nil, TxInfo{}) + _, err := mp.CheckTx(a) require.NoError(t, err) } } @@ -351,15 +374,15 @@ func TestTxsAvailable(t *testing.T) { defer cleanup() mp.EnableTxsAvailable() - timeoutMS := 500 + timeoutMS := 100 - // with no txs, it shouldnt fire - ensureNoFire(t, mp.TxsAvailable(), timeoutMS) + // with no txs, it shouldn't fire + ensureNoFire(t, mp.TxsAvailable()) // send a bunch of txs, it should only fire once - txs := checkTxs(t, mp, 100, UnknownPeerID) + txs := checkTxs(t, mp, 100) ensureFire(t, mp.TxsAvailable(), timeoutMS) - ensureNoFire(t, mp.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable()) // call update with half the txs. // it should fire once now for the new height @@ -369,23 +392,23 @@ func TestTxsAvailable(t *testing.T) { t.Error(err) } ensureFire(t, mp.TxsAvailable(), timeoutMS) - ensureNoFire(t, mp.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable()) - // send a bunch more txs. we already fired for this height so it shouldnt fire again - moreTxs := checkTxs(t, mp, 50, UnknownPeerID) - ensureNoFire(t, mp.TxsAvailable(), timeoutMS) + // send a bunch more txs. we already fired for this height so it shouldn't fire again + moreTxs := checkTxs(t, mp, 50) + ensureNoFire(t, mp.TxsAvailable()) // now call update with all the txs. it should not fire as there are no txs left committedTxs = append(remainingTxs, moreTxs...) if err := mp.Update(2, committedTxs, abciResponses(len(committedTxs), abci.CodeTypeOK), nil, nil); err != nil { t.Error(err) } - ensureNoFire(t, mp.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable()) // send a bunch more txs, it should only fire once - checkTxs(t, mp, 100, UnknownPeerID) + checkTxs(t, mp, 100) ensureFire(t, mp.TxsAvailable(), timeoutMS) - ensureNoFire(t, mp.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable()) } func TestSerialReap(t *testing.T) { @@ -395,40 +418,40 @@ func TestSerialReap(t *testing.T) { mp, cleanup := newMempoolWithApp(cc) defer cleanup() - appConnCon, _ := cc.NewABCIClient() + appConnCon, _ := cc.NewABCIConsensusClient() appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus")) err := appConnCon.Start() - require.Nil(t, err) + require.NoError(t, err) cacheMap := make(map[string]struct{}) deliverTxsRange := func(start, end int) { // Deliver some txs. for i := start; i < end; i++ { - txBytes := kvstore.NewTx(fmt.Sprintf("%d", i), "true") - err := mp.CheckTx(txBytes, nil, TxInfo{}) + txBytes := kvstore.NewTx(strconv.Itoa(i), "true") + _, err := mp.CheckTx(txBytes) _, cached := cacheMap[string(txBytes)] if cached { - require.NotNil(t, err, "expected error for cached tx") + require.Error(t, err, "expected error for cached tx") } else { - require.Nil(t, err, "expected no err for uncached tx") + require.NoError(t, err, "expected no err for uncached tx") } cacheMap[string(txBytes)] = struct{}{} // Duplicates are cached and should return error - err = mp.CheckTx(txBytes, nil, TxInfo{}) - require.NotNil(t, err, "Expected error after CheckTx on duplicated tx") + _, err = mp.CheckTx(txBytes) + require.Error(t, err, "Expected error after CheckTx on duplicated tx") } } reapCheck := func(exp int) { txs := mp.ReapMaxBytesMaxGas(-1, -1) - require.Equal(t, len(txs), exp, fmt.Sprintf("Expected to reap %v txs but got %v", exp, len(txs))) + require.Len(t, txs, exp) } updateRange := func(start, end int) { txs := make(types.Txs, end-start) for i := start; i < end; i++ { - txs[i-start] = kvstore.NewTx(fmt.Sprintf("%d", i), "true") + txs[i-start] = kvstore.NewTx(strconv.Itoa(i), "true") } if err := mp.Update(0, txs, abciResponses(len(txs), abci.CodeTypeOK), nil, nil); err != nil { t.Error(err) @@ -439,10 +462,10 @@ func TestSerialReap(t *testing.T) { // Deliver some txs in a block txs := make([][]byte, end-start) for i := start; i < end; i++ { - txs[i-start] = kvstore.NewTx(fmt.Sprintf("%d", i), "true") + txs[i-start] = kvstore.NewTx(strconv.Itoa(i), "true") } - res, err := appConnCon.FinalizeBlock(context.Background(), &abci.RequestFinalizeBlock{Txs: txs}) + res, err := appConnCon.FinalizeBlock(context.Background(), &abci.FinalizeBlockRequest{Txs: txs}) if err != nil { t.Errorf("client error committing tx: %v", err) } @@ -456,13 +479,13 @@ func TestSerialReap(t *testing.T) { t.Errorf("error committing. Hash:%X", res.AppHash) } - _, err = appConnCon.Commit(context.Background(), &abci.RequestCommit{}) + _, err = appConnCon.Commit(context.Background(), &abci.CommitRequest{}) if err != nil { t.Errorf("client error committing: %v", err) } } - //---------------------------------------- + // ---------------------------------------- // Deliver some txs. deliverTxsRange(0, 100) @@ -483,7 +506,7 @@ func TestSerialReap(t *testing.T) { // Reap again. We should get the same amount reapCheck(1000) - // Commit from the conensus AppConn + // Commit from the consensus AppConn commitRange(0, 500) updateRange(0, 500) @@ -526,19 +549,19 @@ func TestMempool_CheckTxChecksTxSize(t *testing.T) { tx := cmtrand.Bytes(testCase.len) - err := mempl.CheckTx(tx, nil, TxInfo{}) + _, err := mempl.CheckTx(tx) bv := gogotypes.BytesValue{Value: tx} bz, err2 := bv.Marshal() require.NoError(t, err2) - require.Equal(t, len(bz), proto.Size(&bv), caseString) + require.Len(t, bz, proto.Size(&bv), caseString) if !testCase.err { require.NoError(t, err, caseString) } else { - require.Equal(t, err, ErrTxTooLarge{ + require.Equal(t, ErrTxTooLarge{ Max: maxTxSize, Actual: testCase.len, - }, caseString) + }, err, caseString) } } } @@ -558,7 +581,7 @@ func TestMempoolTxsBytes(t *testing.T) { // 2. len(tx) after CheckTx tx1 := kvstore.NewRandomTx(10) - err := mp.CheckTx(tx1, nil, TxInfo{}) + _, err := mp.CheckTx(tx1) require.NoError(t, err) assert.EqualValues(t, 10, mp.SizeBytes()) @@ -569,7 +592,7 @@ func TestMempoolTxsBytes(t *testing.T) { // 4. zero after Flush tx2 := kvstore.NewRandomTx(20) - err = mp.CheckTx(tx2, nil, TxInfo{}) + _, err = mp.CheckTx(tx2) require.NoError(t, err) assert.EqualValues(t, 20, mp.SizeBytes()) @@ -578,12 +601,12 @@ func TestMempoolTxsBytes(t *testing.T) { // 5. ErrMempoolIsFull is returned when/if MaxTxsBytes limit is reached. tx3 := kvstore.NewRandomTx(100) - err = mp.CheckTx(tx3, nil, TxInfo{}) + _, err = mp.CheckTx(tx3) require.NoError(t, err) tx4 := kvstore.NewRandomTx(10) - err = mp.CheckTx(tx4, nil, TxInfo{}) - if assert.Error(t, err) { + _, err = mp.CheckTx(tx4) + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.IsType(t, ErrMempoolIsFull{}, err) } @@ -596,26 +619,26 @@ func TestMempoolTxsBytes(t *testing.T) { txBytes := kvstore.NewRandomTx(10) - err = mp.CheckTx(txBytes, nil, TxInfo{}) + _, err = mp.CheckTx(txBytes) require.NoError(t, err) assert.EqualValues(t, 10, mp.SizeBytes()) - appConnCon, _ := cc.NewABCIClient() + appConnCon, _ := cc.NewABCIConsensusClient() appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus")) err = appConnCon.Start() - require.Nil(t, err) + require.NoError(t, err) t.Cleanup(func() { if err := appConnCon.Stop(); err != nil { t.Error(err) } }) - res, err := appConnCon.FinalizeBlock(context.Background(), &abci.RequestFinalizeBlock{Txs: [][]byte{txBytes}}) + res, err := appConnCon.FinalizeBlock(context.Background(), &abci.FinalizeBlockRequest{Txs: [][]byte{txBytes}}) require.NoError(t, err) require.EqualValues(t, 0, res.TxResults[0].Code) require.NotEmpty(t, res.AppHash) - _, err = appConnCon.Commit(context.Background(), &abci.RequestCommit{}) + _, err = appConnCon.Commit(context.Background(), &abci.CommitRequest{}) require.NoError(t, err) // Pretend like we committed nothing so txBytes gets rechecked and removed. @@ -624,14 +647,58 @@ func TestMempoolTxsBytes(t *testing.T) { assert.EqualValues(t, 10, mp.SizeBytes()) // 7. Test RemoveTxByKey function - err = mp.CheckTx(tx1, nil, TxInfo{}) + _, err = mp.CheckTx(tx1) require.NoError(t, err) assert.EqualValues(t, 20, mp.SizeBytes()) - assert.Error(t, mp.RemoveTxByKey(types.Tx([]byte{0x07}).Key())) + require.Error(t, mp.RemoveTxByKey(types.Tx([]byte{0x07}).Key())) assert.EqualValues(t, 20, mp.SizeBytes()) - assert.NoError(t, mp.RemoveTxByKey(types.Tx(tx1).Key())) + require.NoError(t, mp.RemoveTxByKey(types.Tx(tx1).Key())) assert.EqualValues(t, 10, mp.SizeBytes()) +} + +func TestMempoolNoCacheOverflow(t *testing.T) { + sockPath := fmt.Sprintf("unix:///tmp/echo_%v.sock", cmtrand.Str(6)) + app := kvstore.NewInMemoryApplication() + server := newRemoteApp(t, sockPath, app) + t.Cleanup(func() { + if err := server.Stop(); err != nil { + t.Error(err) + } + }) + cfg := test.ResetTestRoot("mempool_test") + mp, cleanup := newMempoolWithAppAndConfig(proxy.NewRemoteClientCreator(sockPath, "socket", true), cfg) + defer cleanup() + + // add tx0 + tx0 := kvstore.NewTxFromID(0) + _, err := mp.CheckTx(tx0) + require.NoError(t, err) + err = mp.FlushAppConn() + require.NoError(t, err) + + // saturate the cache to remove tx0 + for i := 1; i <= mp.config.CacheSize; i++ { + _, err = mp.CheckTx(kvstore.NewTxFromID(i)) + require.NoError(t, err) + } + err = mp.FlushAppConn() + require.NoError(t, err) + assert.False(t, mp.cache.Has(kvstore.NewTxFromID(0))) + // add again tx0 + _, err = mp.CheckTx(tx0) + require.NoError(t, err) + err = mp.FlushAppConn() + require.NoError(t, err) + + // tx0 should appear only once in mp.txs + found := 0 + for e := mp.txs.Front(); e != nil; e = e.Next() { + if types.Tx.Key(e.Value.(*mempoolTx).tx) == types.Tx.Key(tx0) { + found++ + } + } + assert.Equal(t, 1, found) } // This will non-deterministically catch some concurrency failures like @@ -641,7 +708,7 @@ func TestMempoolTxsBytes(t *testing.T) { func TestMempoolRemoteAppConcurrency(t *testing.T) { sockPath := fmt.Sprintf("unix:///tmp/echo_%v.sock", cmtrand.Str(6)) app := kvstore.NewInMemoryApplication() - _, server := newRemoteApp(t, sockPath, app) + server := newRemoteApp(t, sockPath, app) t.Cleanup(func() { if err := server.Stop(); err != nil { t.Error(err) @@ -656,29 +723,92 @@ func TestMempoolRemoteAppConcurrency(t *testing.T) { // generate small number of txs nTxs := 10 txLen := 200 - txs := make([]types.Tx, nTxs) - for i := 0; i < nTxs; i++ { - txs[i] = kvstore.NewRandomTx(txLen) - } + txs := NewRandomTxs(nTxs, txLen) // simulate a group of peers sending them over and over - N := cfg.Mempool.Size - maxPeers := 5 - for i := 0; i < N; i++ { - peerID := mrand.Intn(maxPeers) + n := cfg.Mempool.Size + for i := 0; i < n; i++ { txNum := mrand.Intn(nTxs) tx := txs[txNum] // this will err with ErrTxInCache many times ... - mp.CheckTx(tx, nil, TxInfo{SenderID: uint16(peerID)}) //nolint: errcheck // will error + mp.CheckTx(tx) //nolint: errcheck // will error } require.NoError(t, mp.FlushAppConn()) } -// caller must close server -func newRemoteApp(t *testing.T, addr string, app abci.Application) (abciclient.Client, service.Service) { - clientCreator, err := abciclient.NewClient(addr, "socket", true) +func TestMempoolConcurrentUpdateAndReceiveCheckTxResponse(t *testing.T) { + app := kvstore.NewInMemoryApplication() + cc := proxy.NewLocalClientCreator(app) + + cfg := test.ResetTestRoot("mempool_test") + mp, cleanup := newMempoolWithAppAndConfig(cc, cfg) + defer cleanup() + + for h := 1; h <= 100; h++ { + // Two concurrent threads for each height. One updates the mempool with one valid tx, + // writing the pool's height; the other, receives a CheckTx response, reading the height. + var wg sync.WaitGroup + wg.Add(2) + + go func(h int) { + defer wg.Done() + + err := mp.Update(int64(h), []types.Tx{tx}, abciResponses(1, abci.CodeTypeOK), nil, nil) + require.NoError(t, err) + require.Equal(t, int64(h), mp.height.Load(), "height mismatch") + }(h) + + go func(h int) { + defer wg.Done() + + tx := kvstore.NewTxFromID(h) + mp.resCbFirstTime(tx, &abci.CheckTxResponse{Code: abci.CodeTypeOK}) + require.Equal(t, h, mp.Size(), "pool size mismatch") + }(h) + + wg.Wait() + } +} + +func TestMempoolNotifyTxsAvailable(t *testing.T) { + app := kvstore.NewInMemoryApplication() + cc := proxy.NewLocalClientCreator(app) + + cfg := test.ResetTestRoot("mempool_test") + mp, cleanup := newMempoolWithAppAndConfig(cc, cfg) + defer cleanup() + + mp.EnableTxsAvailable() + assert.NotNil(t, mp.txsAvailable) + require.False(t, mp.notifiedTxsAvailable.Load()) + + // Adding a new valid tx to the pool will notify a tx is available + tx := kvstore.NewTxFromID(1) + mp.resCbFirstTime(tx, &abci.CheckTxResponse{Code: abci.CodeTypeOK}) + require.Equal(t, 1, mp.Size(), "pool size mismatch") + require.True(t, mp.notifiedTxsAvailable.Load()) + require.Len(t, mp.TxsAvailable(), 1) + <-mp.TxsAvailable() + + // Receiving CheckTx response for a tx already in the pool should not notify of available txs + mp.resCbFirstTime(tx, &abci.CheckTxResponse{Code: abci.CodeTypeOK}) + require.Equal(t, 1, mp.Size()) + require.True(t, mp.notifiedTxsAvailable.Load()) + require.Empty(t, mp.TxsAvailable()) + + // Updating the pool will remove the tx and set the variable to false + err := mp.Update(1, []types.Tx{tx}, abciResponses(1, abci.CodeTypeOK), nil, nil) + require.NoError(t, err) + require.Zero(t, mp.Size()) + require.False(t, mp.notifiedTxsAvailable.Load()) +} + +// caller must close server. +func newRemoteApp(t *testing.T, addr string, app abci.Application) service.Service { + t.Helper() + _, err := abciclient.NewClient(addr, "socket", true) require.NoError(t, err) // Start server @@ -688,7 +818,13 @@ func newRemoteApp(t *testing.T, addr string, app abci.Application) (abciclient.C t.Fatalf("Error starting socket server: %v", err.Error()) } - return clientCreator, server + return server +} + +func newReqRes(tx types.Tx, code uint32, requestType abci.CheckTxType) *abciclient.ReqRes { + reqRes := abciclient.NewReqRes(abci.ToCheckTxRequest(&abci.CheckTxRequest{Tx: tx, Type: requestType})) + reqRes.Response = abci.ToCheckTxResponse(&abci.CheckTxResponse{Code: code}) + return reqRes } func abciResponses(n int, code uint32) []*abci.ExecTxResult { @@ -698,3 +834,20 @@ func abciResponses(n int, code uint32) []*abci.ExecTxResult { } return responses } + +func doCommit(t require.TestingT, mp Mempool, app abci.Application, txs types.Txs, height int64) { + rfb := &abci.FinalizeBlockRequest{Txs: make([][]byte, len(txs))} + for i, tx := range txs { + rfb.Txs[i] = tx + } + _, e := app.FinalizeBlock(context.Background(), rfb) + require.NoError(t, e) + mp.Lock() + e = mp.FlushAppConn() + require.NoError(t, e) + _, e = app.Commit(context.Background(), &abci.CommitRequest{}) + require.NoError(t, e) + e = mp.Update(height, txs, abciResponses(txs.Len(), abci.CodeTypeOK), nil, nil) + require.NoError(t, e) + mp.Unlock() +} diff --git a/mempool/errors.go b/mempool/errors.go new file mode 100644 index 00000000000..714a4529800 --- /dev/null +++ b/mempool/errors.go @@ -0,0 +1,96 @@ +package mempool + +import ( + "errors" + "fmt" +) + +// ErrTxNotFound is returned to the client if tx is not found in mempool. +var ErrTxNotFound = errors.New("transaction not found in mempool") + +// ErrTxInCache is returned to the client if we saw tx earlier. +var ErrTxInCache = errors.New("tx already exists in cache") + +// ErrTxTooLarge defines an error when a transaction is too big to be sent in a +// message to other peers. +type ErrTxTooLarge struct { + Max int + Actual int +} + +func (e ErrTxTooLarge) Error() string { + return fmt.Sprintf("Tx too large. Max size is %d, but got %d", e.Max, e.Actual) +} + +// ErrMempoolIsFull defines an error where CometBFT and the application cannot +// handle that much load. +type ErrMempoolIsFull struct { + NumTxs int + MaxTxs int + TxsBytes int64 + MaxTxsBytes int64 +} + +func (e ErrMempoolIsFull) Error() string { + return fmt.Sprintf( + "mempool is full: number of txs %d (max: %d), total txs bytes %d (max: %d)", + e.NumTxs, + e.MaxTxs, + e.TxsBytes, + e.MaxTxsBytes, + ) +} + +// ErrPreCheck defines an error where a transaction fails a pre-check. +type ErrPreCheck struct { + Err error +} + +func (e ErrPreCheck) Error() string { + return fmt.Sprintf("tx pre check: %v", e.Err) +} + +func (e ErrPreCheck) Unwrap() error { + return e.Err +} + +// IsPreCheckError returns true if err is due to pre check failure. +func IsPreCheckError(err error) bool { + return errors.As(err, &ErrPreCheck{}) +} + +type ErrCheckTxAsync struct { + Err error +} + +func (e ErrCheckTxAsync) Error() string { + return fmt.Sprintf("check tx async: %v", e.Err) +} + +func (e ErrCheckTxAsync) Unwrap() error { + return e.Err +} + +type ErrAppConnMempool struct { + Err error +} + +func (e ErrAppConnMempool) Error() string { + return fmt.Sprintf("appConn mempool: %v", e.Err) +} + +func (e ErrAppConnMempool) Unwrap() error { + return e.Err +} + +type ErrFlushAppConn struct { + Err error +} + +func (e ErrFlushAppConn) Error() string { + return fmt.Sprintf("flush appConn mempool: %v", e.Err) +} + +func (e ErrFlushAppConn) Unwrap() error { + return e.Err +} diff --git a/mempool/ids.go b/mempool/ids.go deleted file mode 100644 index aad98b7a7d1..00000000000 --- a/mempool/ids.go +++ /dev/null @@ -1,71 +0,0 @@ -package mempool - -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 deleted file mode 100644 index c822dd84191..00000000000 --- a/mempool/ids_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package mempool - -import ( - "net" - "testing" - - "github.com/cometbft/cometbft/p2p/mock" - "github.com/stretchr/testify/assert" -) - -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) - }) -} diff --git a/mempool/mempool.go b/mempool/mempool.go index 812fee2d7cd..db73da0f094 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -2,10 +2,9 @@ package mempool import ( "crypto/sha256" - "errors" "fmt" - "math" + abcicli "github.com/cometbft/cometbft/abci/client" abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/types" ) @@ -13,14 +12,8 @@ import ( const ( MempoolChannel = byte(0x30) - // PeerCatchupSleepIntervalMS defines how much time to sleep if a peer is behind + // PeerCatchupSleepIntervalMS defines how much time to sleep if a peer is behind. PeerCatchupSleepIntervalMS = 100 - - // UnknownPeerID is the peer ID to use when running CheckTx when there is - // no peer (e.g. RPC) - UnknownPeerID uint16 = 0 - - MaxActiveIDs = math.MaxUint16 ) //go:generate ../scripts/mockery_generate.sh Mempool @@ -32,7 +25,7 @@ const ( type Mempool interface { // CheckTx executes a new transaction against the application to determine // its validity and whether it should be added to the mempool. - CheckTx(tx types.Tx, callback func(*abci.ResponseCheckTx), txInfo TxInfo) error + CheckTx(tx types.Tx) (*abcicli.ReqRes, error) // RemoveTxByKey removes a transaction, identified by its key, // from the mempool. @@ -93,6 +86,10 @@ type Mempool interface { // trigger once every height when transactions are available. EnableTxsAvailable() + // Set a callback function to be called when a transaction is removed from + // the mempool. + SetTxRemovedCallback(cb func(types.TxKey)) + // Size returns the number of transactions in the mempool. Size() int @@ -108,7 +105,7 @@ type PreCheckFunc func(types.Tx) error // PostCheckFunc is an optional filter executed after CheckTx and rejects // transaction if false is returned. An example would be to ensure a // transaction doesn't require more gas than available for the block. -type PostCheckFunc func(types.Tx, *abci.ResponseCheckTx) error +type PostCheckFunc func(types.Tx, *abci.CheckTxResponse) error // PreCheckMaxBytes checks that the size of the transaction is smaller or equal // to the expected maxBytes. @@ -127,7 +124,7 @@ func PreCheckMaxBytes(maxBytes int64) PreCheckFunc { // PostCheckMaxGas checks that the wanted gas is smaller or equal to the passed // maxGas. Returns nil if maxGas is -1. func PostCheckMaxGas(maxGas int64) PostCheckFunc { - return func(tx types.Tx, res *abci.ResponseCheckTx) error { + return func(_ types.Tx, res *abci.CheckTxResponse) error { if maxGas == -1 { return nil } @@ -144,52 +141,5 @@ func PostCheckMaxGas(maxGas int64) PostCheckFunc { } } -// ErrTxInCache is returned to the client if we saw tx earlier -var ErrTxInCache = errors.New("tx already exists in cache") - // TxKey is the fixed length array key used as an index. type TxKey [sha256.Size]byte - -// ErrTxTooLarge defines an error when a transaction is too big to be sent in a -// message to other peers. -type ErrTxTooLarge struct { - Max int - Actual int -} - -func (e ErrTxTooLarge) Error() string { - return fmt.Sprintf("Tx too large. Max size is %d, but got %d", e.Max, e.Actual) -} - -// ErrMempoolIsFull defines an error where CometBFT and the application cannot -// handle that much load. -type ErrMempoolIsFull struct { - NumTxs int - MaxTxs int - TxsBytes int64 - MaxTxsBytes int64 -} - -func (e ErrMempoolIsFull) Error() string { - return fmt.Sprintf( - "mempool is full: number of txs %d (max: %d), total txs bytes %d (max: %d)", - e.NumTxs, - e.MaxTxs, - e.TxsBytes, - e.MaxTxsBytes, - ) -} - -// ErrPreCheck defines an error where a transaction fails a pre-check. -type ErrPreCheck struct { - Reason error -} - -func (e ErrPreCheck) Error() string { - return e.Reason.Error() -} - -// IsPreCheckError returns true if err is due to pre check failure. -func IsPreCheckError(err error) bool { - return errors.As(err, &ErrPreCheck{}) -} diff --git a/mempool/mempoolTx.go b/mempool/mempoolTx.go new file mode 100644 index 00000000000..48313461a96 --- /dev/null +++ b/mempool/mempoolTx.go @@ -0,0 +1,19 @@ +package mempool + +import ( + "sync/atomic" + + "github.com/cometbft/cometbft/types" +) + +// mempoolTx is an entry in the mempool. +type mempoolTx struct { + height int64 // height that this tx had been validated in + gasWanted int64 // amount of gas this tx states it will require + tx types.Tx // validated by the application +} + +// Height returns the height for this transaction. +func (memTx *mempoolTx) Height() int64 { + return atomic.LoadInt64(&memTx.height) +} diff --git a/mempool/metrics.gen.go b/mempool/metrics.gen.go index 100c5e71cb6..6714c739711 100644 --- a/mempool/metrics.gen.go +++ b/mempool/metrics.gen.go @@ -20,6 +20,12 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "size", Help: "Number of uncommitted transactions in the mempool.", }, labels).With(labelsAndValues...), + SizeBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "size_bytes", + Help: "Total size of the mempool in bytes.", + }, labels).With(labelsAndValues...), TxSizeBytes: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, @@ -40,28 +46,36 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "rejected_txs", Help: "Number of rejected transactions.", }, labels).With(labelsAndValues...), - EvictedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "evicted_txs", - Help: "Number of evicted transactions.", - }, labels).With(labelsAndValues...), RecheckTimes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, Name: "recheck_times", Help: "Number of times transactions are rechecked in the mempool.", }, labels).With(labelsAndValues...), + AlreadyReceivedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "already_received_txs", + Help: "Number of duplicate transaction reception.", + }, labels).With(labelsAndValues...), + ActiveOutboundConnections: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "active_outbound_connections", + Help: "Number of connections being actively used for gossiping transactions (experimental feature).", + }, labels).With(labelsAndValues...), } } func NopMetrics() *Metrics { return &Metrics{ - Size: discard.NewGauge(), - TxSizeBytes: discard.NewHistogram(), - FailedTxs: discard.NewCounter(), - RejectedTxs: discard.NewCounter(), - EvictedTxs: discard.NewCounter(), - RecheckTimes: discard.NewCounter(), + Size: discard.NewGauge(), + SizeBytes: discard.NewGauge(), + TxSizeBytes: discard.NewHistogram(), + FailedTxs: discard.NewCounter(), + RejectedTxs: discard.NewCounter(), + RecheckTimes: discard.NewCounter(), + AlreadyReceivedTxs: discard.NewCounter(), + ActiveOutboundConnections: discard.NewGauge(), } } diff --git a/mempool/metrics.go b/mempool/metrics.go index 85ca8c0cfbd..e8148c9fb06 100644 --- a/mempool/metrics.go +++ b/mempool/metrics.go @@ -18,8 +18,11 @@ type Metrics struct { // Number of uncommitted transactions in the mempool. Size metrics.Gauge + // Total size of the mempool in bytes. + SizeBytes metrics.Gauge + // Histogram of transaction sizes in bytes. - TxSizeBytes metrics.Histogram `metrics_buckettype:"exp" metrics_bucketsizes:"1,3,7"` + TxSizeBytes metrics.Histogram `metrics_bucketsizes:"1,3,7" metrics_buckettype:"exp"` // Number of failed transactions. FailedTxs metrics.Counter @@ -28,16 +31,17 @@ type Metrics struct { // transactions that passed CheckTx but failed to make it into the mempool // due to resource limits, e.g. mempool is full and no lower priority // transactions exist in the mempool. - //metrics:Number of rejected transactions. + // metrics:Number of rejected transactions. RejectedTxs metrics.Counter - // EvictedTxs defines the number of evicted transactions. These are valid - // transactions that passed CheckTx and existed in the mempool but were later - // evicted to make room for higher priority valid transactions that passed - // CheckTx. - //metrics:Number of evicted transactions. - EvictedTxs metrics.Counter - // Number of times transactions are rechecked in the mempool. RecheckTimes metrics.Counter + + // Number of times transactions were received more than once. + // metrics:Number of duplicate transaction reception. + AlreadyReceivedTxs metrics.Counter + + // Number of connections being actively used for gossiping transactions + // (experimental feature). + ActiveOutboundConnections metrics.Gauge } diff --git a/mempool/mocks/mempool.go b/mempool/mocks/mempool.go index 7573c58e978..4a2aba0a218 100644 --- a/mempool/mocks/mempool.go +++ b/mempool/mocks/mempool.go @@ -3,12 +3,14 @@ package mocks import ( - abcitypes "github.com/cometbft/cometbft/abci/types" + abcicli "github.com/cometbft/cometbft/abci/client" mempool "github.com/cometbft/cometbft/mempool" mock "github.com/stretchr/testify/mock" types "github.com/cometbft/cometbft/types" + + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" ) // Mempool is an autogenerated mock type for the Mempool type @@ -16,18 +18,34 @@ type Mempool struct { mock.Mock } -// CheckTx provides a mock function with given fields: tx, callback, txInfo -func (_m *Mempool) CheckTx(tx types.Tx, callback func(*abcitypes.ResponseCheckTx), txInfo mempool.TxInfo) error { - ret := _m.Called(tx, callback, txInfo) +// CheckTx provides a mock function with given fields: tx +func (_m *Mempool) CheckTx(tx types.Tx) (*abcicli.ReqRes, error) { + ret := _m.Called(tx) - var r0 error - if rf, ok := ret.Get(0).(func(types.Tx, func(*abcitypes.ResponseCheckTx), mempool.TxInfo) error); ok { - r0 = rf(tx, callback, txInfo) + if len(ret) == 0 { + panic("no return value specified for CheckTx") + } + + var r0 *abcicli.ReqRes + var r1 error + if rf, ok := ret.Get(0).(func(types.Tx) (*abcicli.ReqRes, error)); ok { + return rf(tx) + } + if rf, ok := ret.Get(0).(func(types.Tx) *abcicli.ReqRes); ok { + r0 = rf(tx) } else { - r0 = ret.Error(0) + if ret.Get(0) != nil { + r0 = ret.Get(0).(*abcicli.ReqRes) + } } - return r0 + if rf, ok := ret.Get(1).(func(types.Tx) error); ok { + r1 = rf(tx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // EnableTxsAvailable provides a mock function with given fields: @@ -44,6 +62,10 @@ func (_m *Mempool) Flush() { func (_m *Mempool) FlushAppConn() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for FlushAppConn") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -63,6 +85,10 @@ func (_m *Mempool) Lock() { func (_m *Mempool) ReapMaxBytesMaxGas(maxBytes int64, maxGas int64) types.Txs { ret := _m.Called(maxBytes, maxGas) + if len(ret) == 0 { + panic("no return value specified for ReapMaxBytesMaxGas") + } + var r0 types.Txs if rf, ok := ret.Get(0).(func(int64, int64) types.Txs); ok { r0 = rf(maxBytes, maxGas) @@ -79,6 +105,10 @@ func (_m *Mempool) ReapMaxBytesMaxGas(maxBytes int64, maxGas int64) types.Txs { func (_m *Mempool) ReapMaxTxs(max int) types.Txs { ret := _m.Called(max) + if len(ret) == 0 { + panic("no return value specified for ReapMaxTxs") + } + var r0 types.Txs if rf, ok := ret.Get(0).(func(int) types.Txs); ok { r0 = rf(max) @@ -95,6 +125,10 @@ func (_m *Mempool) ReapMaxTxs(max int) types.Txs { func (_m *Mempool) RemoveTxByKey(txKey types.TxKey) error { ret := _m.Called(txKey) + if len(ret) == 0 { + panic("no return value specified for RemoveTxByKey") + } + var r0 error if rf, ok := ret.Get(0).(func(types.TxKey) error); ok { r0 = rf(txKey) @@ -105,10 +139,19 @@ func (_m *Mempool) RemoveTxByKey(txKey types.TxKey) error { return r0 } +// SetTxRemovedCallback provides a mock function with given fields: cb +func (_m *Mempool) SetTxRemovedCallback(cb func(types.TxKey)) { + _m.Called(cb) +} + // Size provides a mock function with given fields: func (_m *Mempool) Size() int { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Size") + } + var r0 int if rf, ok := ret.Get(0).(func() int); ok { r0 = rf() @@ -123,6 +166,10 @@ func (_m *Mempool) Size() int { func (_m *Mempool) SizeBytes() int64 { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for SizeBytes") + } + var r0 int64 if rf, ok := ret.Get(0).(func() int64); ok { r0 = rf() @@ -137,6 +184,10 @@ func (_m *Mempool) SizeBytes() int64 { func (_m *Mempool) TxsAvailable() <-chan struct{} { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for TxsAvailable") + } + var r0 <-chan struct{} if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { r0 = rf() @@ -155,11 +206,15 @@ func (_m *Mempool) Unlock() { } // Update provides a mock function with given fields: blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn -func (_m *Mempool) Update(blockHeight int64, blockTxs types.Txs, deliverTxResponses []*abcitypes.ExecTxResult, newPreFn mempool.PreCheckFunc, newPostFn mempool.PostCheckFunc) error { +func (_m *Mempool) Update(blockHeight int64, blockTxs types.Txs, deliverTxResponses []*v1.ExecTxResult, newPreFn mempool.PreCheckFunc, newPostFn mempool.PostCheckFunc) error { ret := _m.Called(blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn) + if len(ret) == 0 { + panic("no return value specified for Update") + } + var r0 error - if rf, ok := ret.Get(0).(func(int64, types.Txs, []*abcitypes.ExecTxResult, mempool.PreCheckFunc, mempool.PostCheckFunc) error); ok { + if rf, ok := ret.Get(0).(func(int64, types.Txs, []*v1.ExecTxResult, mempool.PreCheckFunc, mempool.PostCheckFunc) error); ok { r0 = rf(blockHeight, blockTxs, deliverTxResponses, newPreFn, newPostFn) } else { r0 = ret.Error(0) @@ -168,13 +223,12 @@ func (_m *Mempool) Update(blockHeight int64, blockTxs types.Txs, deliverTxRespon return r0 } -type mockConstructorTestingTNewMempool interface { +// NewMempool creates a new instance of Mempool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMempool(t interface { mock.TestingT Cleanup(func()) -} - -// NewMempool creates a new instance of Mempool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewMempool(t mockConstructorTestingTNewMempool) *Mempool { +}) *Mempool { mock := &Mempool{} mock.Mock.Test(t) diff --git a/mempool/nop_mempool.go b/mempool/nop_mempool.go new file mode 100644 index 00000000000..413c85ed069 --- /dev/null +++ b/mempool/nop_mempool.go @@ -0,0 +1,111 @@ +package mempool + +import ( + "errors" + + abcicli "github.com/cometbft/cometbft/abci/client" + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/internal/service" + "github.com/cometbft/cometbft/p2p" + "github.com/cometbft/cometbft/types" +) + +// NopMempool is a mempool that does nothing. +// +// The ABCI app is responsible for storing, disseminating, and proposing transactions. +// See [ADR-111](../docs/architecture/adr-111-nop-mempool.md). +type NopMempool struct{} + +// errNotAllowed indicates that the operation is not allowed with `nop` mempool. +var errNotAllowed = errors.New("not allowed with `nop` mempool") + +var _ Mempool = &NopMempool{} + +// CheckTx always returns an error. +func (*NopMempool) CheckTx(types.Tx) (*abcicli.ReqRes, error) { + return nil, errNotAllowed +} + +// RemoveTxByKey always returns an error. +func (*NopMempool) RemoveTxByKey(types.TxKey) error { return errNotAllowed } + +// ReapMaxBytesMaxGas always returns nil. +func (*NopMempool) ReapMaxBytesMaxGas(int64, int64) types.Txs { return nil } + +// ReapMaxTxs always returns nil. +func (*NopMempool) ReapMaxTxs(int) types.Txs { return nil } + +// Lock does nothing. +func (*NopMempool) Lock() {} + +// Unlock does nothing. +func (*NopMempool) Unlock() {} + +// Update does nothing. +func (*NopMempool) Update( + int64, + types.Txs, + []*abci.ExecTxResult, + PreCheckFunc, + PostCheckFunc, +) error { + return nil +} + +// FlushAppConn does nothing. +func (*NopMempool) FlushAppConn() error { return nil } + +// Flush does nothing. +func (*NopMempool) Flush() {} + +// TxsAvailable always returns nil. +func (*NopMempool) TxsAvailable() <-chan struct{} { + return nil +} + +// EnableTxsAvailable does nothing. +func (*NopMempool) EnableTxsAvailable() {} + +// SetTxRemovedCallback does nothing. +func (*NopMempool) SetTxRemovedCallback(func(txKey types.TxKey)) {} + +// Size always returns 0. +func (*NopMempool) Size() int { return 0 } + +// SizeBytes always returns 0. +func (*NopMempool) SizeBytes() int64 { return 0 } + +// NopMempoolReactor is a mempool reactor that does nothing. +type NopMempoolReactor struct { + service.BaseService +} + +// NewNopMempoolReactor returns a new `nop` reactor. +// +// To be used only in RPC. +func NewNopMempoolReactor() *NopMempoolReactor { + return &NopMempoolReactor{*service.NewBaseService(nil, "NopMempoolReactor", nil)} +} + +var _ p2p.Reactor = &NopMempoolReactor{} + +// WaitSync always returns false. +func (*NopMempoolReactor) WaitSync() bool { return false } + +// GetChannels always returns nil. +func (*NopMempoolReactor) GetChannels() []*p2p.ChannelDescriptor { return nil } + +// AddPeer does nothing. +func (*NopMempoolReactor) AddPeer(p2p.Peer) {} + +// InitPeer always returns nil. +func (*NopMempoolReactor) InitPeer(p2p.Peer) p2p.Peer { return nil } + +// RemovePeer does nothing. +func (*NopMempoolReactor) RemovePeer(p2p.Peer, any) {} + +// Receive does nothing. +func (*NopMempoolReactor) Receive(p2p.Envelope) {} + +// SetSwitch does nothing. +func (*NopMempoolReactor) SetSwitch(*p2p.Switch) {} diff --git a/mempool/nop_mempool_test.go b/mempool/nop_mempool_test.go new file mode 100644 index 00000000000..a89ccf61aa9 --- /dev/null +++ b/mempool/nop_mempool_test.go @@ -0,0 +1,40 @@ +package mempool + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cometbft/cometbft/types" +) + +var tx = types.Tx([]byte{0x01}) + +func TestNopMempool_Basic(t *testing.T) { + mem := &NopMempool{} + + assert.Equal(t, 0, mem.Size()) + assert.Equal(t, int64(0), mem.SizeBytes()) + + _, err := mem.CheckTx(tx) + assert.Equal(t, errNotAllowed, err) + + err = mem.RemoveTxByKey(tx.Key()) + assert.Equal(t, errNotAllowed, err) + + txs := mem.ReapMaxBytesMaxGas(0, 0) + assert.Nil(t, txs) + + txs = mem.ReapMaxTxs(0) + assert.Nil(t, txs) + + err = mem.FlushAppConn() + require.NoError(t, err) + + err = mem.Update(0, nil, nil, nil, nil) + require.NoError(t, err) + + txsAvailable := mem.TxsAvailable() + assert.Nil(t, txsAvailable) +} diff --git a/mempool/reactor.go b/mempool/reactor.go index 9306e1d0f1d..4dd03d1fbbe 100644 --- a/mempool/reactor.go +++ b/mempool/reactor.go @@ -1,15 +1,21 @@ package mempool import ( + "context" "errors" "fmt" + "sync/atomic" "time" + "golang.org/x/sync/semaphore" + + abci "github.com/cometbft/cometbft/abci/types" + protomem "github.com/cometbft/cometbft/api/cometbft/mempool/v1" cfg "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/libs/clist" + "github.com/cometbft/cometbft/internal/clist" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/p2p" - protomem "github.com/cometbft/cometbft/proto/tendermint/mempool" "github.com/cometbft/cometbft/types" ) @@ -20,24 +26,42 @@ type Reactor struct { p2p.BaseReactor config *cfg.MempoolConfig mempool *CListMempool - ids *mempoolIDs + + waitSync atomic.Bool + waitSyncCh chan struct{} // for signaling when to start receiving and sending txs + + // `txSenders` maps every received transaction to the set of peer IDs that + // have sent the transaction to this node. Sender IDs are used during + // transaction propagation to avoid sending a transaction to a peer that + // already has it. + txSenders map[types.TxKey]map[p2p.ID]bool + txSendersMtx cmtsync.Mutex + + // Semaphores to keep track of how many connections to peers are active for broadcasting + // transactions. Each semaphore has a capacity that puts an upper bound on the number of + // connections for different groups of peers. + activePersistentPeersSemaphore *semaphore.Weighted + activeNonPersistentPeersSemaphore *semaphore.Weighted } // NewReactor returns a new Reactor with the given config and mempool. -func NewReactor(config *cfg.MempoolConfig, mempool *CListMempool) *Reactor { +func NewReactor(config *cfg.MempoolConfig, mempool *CListMempool, waitSync bool) *Reactor { memR := &Reactor{ - config: config, - mempool: mempool, - ids: newMempoolIDs(), + config: config, + mempool: mempool, + waitSync: atomic.Bool{}, + txSenders: make(map[types.TxKey]map[p2p.ID]bool), } memR.BaseReactor = *p2p.NewBaseReactor("Mempool", memR) - return memR -} + if waitSync { + memR.waitSync.Store(true) + memR.waitSyncCh = make(chan struct{}) + } + memR.mempool.SetTxRemovedCallback(func(txKey types.TxKey) { memR.removeSenders(txKey) }) + memR.activePersistentPeersSemaphore = semaphore.NewWeighted(int64(memR.config.ExperimentalMaxGossipConnectionsToPersistentPeers)) + memR.activeNonPersistentPeersSemaphore = semaphore.NewWeighted(int64(memR.config.ExperimentalMaxGossipConnectionsToNonPersistentPeers)) -// InitPeer implements Reactor by creating a state for the peer. -func (memR *Reactor) InitPeer(peer p2p.Peer) p2p.Peer { - memR.ids.ReserveForPeer(peer) - return peer + return memR } // SetLogger sets the Logger on the reactor and the underlying mempool. @@ -48,6 +72,9 @@ func (memR *Reactor) SetLogger(l log.Logger) { // OnStart implements p2p.BaseReactor. func (memR *Reactor) OnStart() error { + if memR.WaitSync() { + memR.Logger.Info("Starting reactor in sync mode: tx propagation will start once sync completes") + } if !memR.config.Broadcast { memR.Logger.Info("Tx broadcasting is disabled") } @@ -78,14 +105,43 @@ func (memR *Reactor) GetChannels() []*p2p.ChannelDescriptor { // It starts a broadcast routine ensuring all txs are forwarded to the given peer. func (memR *Reactor) AddPeer(peer p2p.Peer) { if memR.config.Broadcast { - go memR.broadcastTxRoutine(peer) - } -} + go func() { + // Always forward transactions to unconditional peers. + if !memR.Switch.IsPeerUnconditional(peer.ID()) { + // Depending on the type of peer, we choose a semaphore to limit the gossiping peers. + var peerSemaphore *semaphore.Weighted + if peer.IsPersistent() && memR.config.ExperimentalMaxGossipConnectionsToPersistentPeers > 0 { + peerSemaphore = memR.activePersistentPeersSemaphore + } else if !peer.IsPersistent() && memR.config.ExperimentalMaxGossipConnectionsToNonPersistentPeers > 0 { + peerSemaphore = memR.activeNonPersistentPeersSemaphore + } -// RemovePeer implements Reactor. -func (memR *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) { - memR.ids.Reclaim(peer) - // broadcast routine checks if peer is gone and returns + if peerSemaphore != nil { + for peer.IsRunning() { + // Block on the semaphore until a slot is available to start gossiping with this peer. + // Do not block indefinitely, in case the peer is disconnected before gossiping starts. + ctxTimeout, cancel := context.WithTimeout(context.TODO(), 30*time.Second) + // Block sending transactions to peer until one of the connections become + // available in the semaphore. + err := peerSemaphore.Acquire(ctxTimeout, 1) + cancel() + + if err != nil { + continue + } + + // Release semaphore to allow other peer to start sending transactions. + defer peerSemaphore.Release(1) + break + } + } + } + + memR.mempool.metrics.ActiveOutboundConnections.Add(1) + defer memR.mempool.metrics.ActiveOutboundConnections.Add(-1) + memR.broadcastTxRoutine(peer) + }() + } } // Receive implements Reactor. @@ -94,24 +150,37 @@ func (memR *Reactor) Receive(e p2p.Envelope) { memR.Logger.Debug("Receive", "src", e.Src, "chId", e.ChannelID, "msg", e.Message) switch msg := e.Message.(type) { case *protomem.Txs: + if memR.WaitSync() { + memR.Logger.Debug("Ignored message received while syncing", "msg", msg) + return + } + protoTxs := msg.GetTxs() if len(protoTxs) == 0 { memR.Logger.Error("received empty txs from peer", "src", e.Src) return } - txInfo := TxInfo{SenderID: memR.ids.GetForPeer(e.Src)} - if e.Src != nil { - txInfo.SenderP2PID = e.Src.ID() - } - var err error - for _, tx := range protoTxs { - ntx := types.Tx(tx) - err = memR.mempool.CheckTx(ntx, nil, txInfo) - if errors.Is(err, ErrTxInCache) { - memR.Logger.Debug("Tx already exists in cache", "tx", ntx.String()) - } else if err != nil { - memR.Logger.Info("Could not check tx", "tx", ntx.String(), "err", err) + for _, txBytes := range protoTxs { + tx := types.Tx(txBytes) + reqRes, err := memR.mempool.CheckTx(tx) + switch { + case errors.Is(err, ErrTxInCache): + memR.Logger.Debug("Tx already exists in cache", "tx", tx.Hash()) + case err != nil: + memR.Logger.Info("Could not check tx", "tx", tx.Hash(), "err", err) + default: + // Record the sender only when the transaction is valid and, as + // a consequence, added to the mempool. Senders are stored until + // the transaction is removed from the mempool. Note that it's + // possible a tx is still in the cache but no longer in the + // mempool. For example, after committing a block, txs are + // removed from mempool but not the cache. + reqRes.SetCallback(func(res *abci.Response) { + if res.GetCheckTx().Code == abci.CodeTypeOK { + memR.addSender(tx.Key(), e.Src.ID()) + } + }) } } default: @@ -123,6 +192,22 @@ func (memR *Reactor) Receive(e p2p.Envelope) { // broadcasting happens from go routines per peer } +func (memR *Reactor) EnableInOutTxs() { + memR.Logger.Info("enabling inbound and outbound transactions") + if !memR.waitSync.CompareAndSwap(true, false) { + return + } + + // Releases all the blocked broadcastTxRoutine instances. + if memR.config.Broadcast { + close(memR.waitSyncCh) + } +} + +func (memR *Reactor) WaitSync() bool { + return memR.waitSync.Load() +} + // PeerState describes the state of a peer. type PeerState interface { GetHeight() int64 @@ -130,14 +215,24 @@ type PeerState interface { // Send new mempool txs to peer. func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { - peerID := memR.ids.GetForPeer(peer) var next *clist.CElement + // If the node is catching up, don't start this routine immediately. + if memR.WaitSync() { + select { + case <-memR.waitSyncCh: + // EnableInOutTxs() has set WaitSync() to false. + case <-memR.Quit(): + return + } + } + for { // In case of both next.NextWaitChan() and peer.Quit() are variable at the same time if !memR.IsRunning() || !peer.IsRunning() { return } + // This happens because the CElement we were looking at got garbage // collected (removed). That is, .NextWait() returned nil. Go ahead and // start from the beginning. @@ -166,7 +261,12 @@ func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { continue } - // Allow for a lag of 1 block. + // If we suspect that the peer is lagging behind, at least by more than + // one block, we don't send the transaction immediately. This code + // reduces the mempool size and the recheck-tx rate of the receiving + // node. See [RFC 103] for an analysis on this optimization. + // + // [RFC 103]: https://github.com/cometbft/cometbft/pull/735 memTx := next.Value.(*mempoolTx) if peerState.GetHeight() < memTx.Height()-1 { time.Sleep(PeerCatchupSleepIntervalMS * time.Millisecond) @@ -176,7 +276,7 @@ func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { // NOTE: Transaction batching was disabled due to // https://github.com/tendermint/tendermint/issues/5796 - if _, ok := memTx.senders.Load(peerID); !ok { + if !memR.isSender(memTx.tx.Key(), peer.ID()) { success := peer.Send(p2p.Envelope{ ChannelID: MempoolChannel, Message: &protomem.Txs{Txs: [][]byte{memTx.tx}}, @@ -199,12 +299,30 @@ func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { } } -// TxsMessage is a Message containing transactions. -type TxsMessage struct { - Txs []types.Tx +func (memR *Reactor) isSender(txKey types.TxKey, peerID p2p.ID) bool { + memR.txSendersMtx.Lock() + defer memR.txSendersMtx.Unlock() + + sendersSet, ok := memR.txSenders[txKey] + return ok && sendersSet[peerID] } -// String returns a string representation of the TxsMessage. -func (m *TxsMessage) String() string { - return fmt.Sprintf("[TxsMessage %v]", m.Txs) +func (memR *Reactor) addSender(txKey types.TxKey, senderID p2p.ID) { + memR.txSendersMtx.Lock() + defer memR.txSendersMtx.Unlock() + + if sendersSet, ok := memR.txSenders[txKey]; ok { + sendersSet[senderID] = true + return + } + memR.txSenders[txKey] = map[p2p.ID]bool{senderID: true} +} + +func (memR *Reactor) removeSenders(txKey types.TxKey) { + memR.txSendersMtx.Lock() + defer memR.txSendersMtx.Unlock() + + if memR.txSenders != nil { + delete(memR.txSenders, txKey) + } } diff --git a/mempool/reactor_test.go b/mempool/reactor_test.go index 6d07e4a09b3..1528fcb14f8 100644 --- a/mempool/reactor_test.go +++ b/mempool/reactor_test.go @@ -14,11 +14,10 @@ import ( "github.com/cometbft/cometbft/abci/example/kvstore" abci "github.com/cometbft/cometbft/abci/types" + memproto "github.com/cometbft/cometbft/api/cometbft/mempool/v1" cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/p2p" - "github.com/cometbft/cometbft/p2p/mock" - memproto "github.com/cometbft/cometbft/proto/tendermint/mempool" "github.com/cometbft/cometbft/proxy" "github.com/cometbft/cometbft/types" ) @@ -44,39 +43,41 @@ func TestReactorBroadcastTxsMessage(t *testing.T) { // asserted in waitForTxsOnReactors (due to transactions gossiping). If we // replace Connect2Switches (full mesh) with a func, which connects first // reactor to others and nothing else, this test should also pass with >2 reactors. - const N = 2 - reactors, _ := makeAndConnectReactors(config, N) + const n = 2 + reactors, _ := makeAndConnectReactors(config, n) defer func() { for _, r := range reactors { if err := r.Stop(); err != nil { - assert.NoError(t, err) + require.NoError(t, err) } } }() for _, r := range reactors { - for _, peer := range r.Switch.Peers().List() { + for _, peer := range r.Switch.Peers().Copy() { peer.Set(types.PeerStateKey, peerState{1}) } } - txs := checkTxs(t, reactors[0].mempool, numTxs, UnknownPeerID) - waitForTxsOnReactors(t, txs, reactors) + txs := checkTxs(t, reactors[0].mempool, numTxs) + waitForReactors(t, txs, reactors, checkTxsInOrder) } -// regression test for https://github.com/cometbft/cometbft/issues/5408 +// regression test for https://github.com/tendermint/tendermint/issues/5408 func TestReactorConcurrency(t *testing.T) { config := cfg.TestConfig() - const N = 2 - reactors, _ := makeAndConnectReactors(config, N) + config.Mempool.Size = 5000 + config.Mempool.CacheSize = 5000 + const n = 2 + reactors, _ := makeAndConnectReactors(config, n) defer func() { for _, r := range reactors { if err := r.Stop(); err != nil { - assert.NoError(t, err) + require.NoError(t, err) } } }() for _, r := range reactors { - for _, peer := range r.Switch.Peers().List() { + for _, peer := range r.Switch.Peers().Copy() { peer.Set(types.PeerStateKey, peerState{1}) } } @@ -89,31 +90,27 @@ func TestReactorConcurrency(t *testing.T) { // 1. submit a bunch of txs // 2. update the whole mempool - txs := checkTxs(t, reactors[0].mempool, numTxs, UnknownPeerID) + txs := checkTxs(t, reactors[0].mempool, numTxs) go func() { defer wg.Done() reactors[0].mempool.Lock() defer reactors[0].mempool.Unlock() - txResponses := make([]*abci.ExecTxResult, len(txs)) - for i := range txs { - txResponses[i] = &abci.ExecTxResult{Code: 0} - } - err := reactors[0].mempool.Update(1, txs, txResponses, nil, nil) - assert.NoError(t, err) + err := reactors[0].mempool.Update(1, txs, abciResponses(len(txs), abci.CodeTypeOK), nil, nil) + require.NoError(t, err) }() // 1. submit a bunch of txs // 2. update none - _ = checkTxs(t, reactors[1].mempool, numTxs, UnknownPeerID) + _ = checkTxs(t, reactors[1].mempool, numTxs) go func() { defer wg.Done() reactors[1].mempool.Lock() defer reactors[1].mempool.Unlock() err := reactors[1].mempool.Update(1, []types.Tx{}, make([]*abci.ExecTxResult, 0), nil, nil) - assert.NoError(t, err) + require.NoError(t, err) }() // 1. flush the mempool @@ -127,40 +124,50 @@ func TestReactorConcurrency(t *testing.T) { // ensure peer gets no txs. func TestReactorNoBroadcastToSender(t *testing.T) { config := cfg.TestConfig() - const N = 2 - reactors, _ := makeAndConnectReactors(config, N) + const n = 2 + reactors, _ := makeAndConnectReactors(config, n) defer func() { for _, r := range reactors { if err := r.Stop(); err != nil { - assert.NoError(t, err) + require.NoError(t, err) } } }() for _, r := range reactors { - for _, peer := range r.Switch.Peers().List() { + for _, peer := range r.Switch.Peers().Copy() { peer.Set(types.PeerStateKey, peerState{1}) } } - const peerID = 1 - checkTxs(t, reactors[0].mempool, numTxs, peerID) - ensureNoTxs(t, reactors[peerID], 100*time.Millisecond) + // create random transactions + txs := NewRandomTxs(numTxs, 20) + + // the second peer sends all the transactions to the first peer + secondNodeID := reactors[1].Switch.NodeInfo().ID() + for _, tx := range txs { + reactors[0].addSender(tx.Key(), secondNodeID) + _, err := reactors[0].mempool.CheckTx(tx) + require.NoError(t, err) + } + + // the second peer should not receive any transaction + ensureNoTxs(t, reactors[1], 100*time.Millisecond) } func TestReactor_MaxTxBytes(t *testing.T) { config := cfg.TestConfig() - const N = 2 - reactors, _ := makeAndConnectReactors(config, N) + const n = 2 + reactors, _ := makeAndConnectReactors(config, n) defer func() { for _, r := range reactors { if err := r.Stop(); err != nil { - assert.NoError(t, err) + require.NoError(t, err) } } }() for _, r := range reactors { - for _, peer := range r.Switch.Peers().List() { + for _, peer := range r.Switch.Peers().Copy() { peer.Set(types.PeerStateKey, peerState{1}) } } @@ -168,11 +175,10 @@ func TestReactor_MaxTxBytes(t *testing.T) { // Broadcast a tx, which has the max size // => ensure it's received by the second reactor. tx1 := kvstore.NewRandomTx(config.Mempool.MaxTxBytes) - err := reactors[0].mempool.CheckTx(tx1, func(resp *abci.ResponseCheckTx) { - require.False(t, resp.IsErr()) - }, TxInfo{SenderID: UnknownPeerID}) + reqRes, err := reactors[0].mempool.CheckTx(tx1) require.NoError(t, err) - waitForTxsOnReactors(t, []types.Tx{tx1}, reactors) + require.False(t, reqRes.Response.GetCheckTx().IsErr()) + waitForReactors(t, []types.Tx{tx1}, reactors, checkTxsInOrder) reactors[0].mempool.Flush() reactors[1].mempool.Flush() @@ -180,10 +186,9 @@ func TestReactor_MaxTxBytes(t *testing.T) { // Broadcast a tx, which is beyond the max size // => ensure it's not sent tx2 := kvstore.NewRandomTx(config.Mempool.MaxTxBytes + 1) - err = reactors[0].mempool.CheckTx(tx2, func(resp *abci.ResponseCheckTx) { - require.False(t, resp.IsErr()) - }, TxInfo{SenderID: UnknownPeerID}) + reqRes, err = reactors[0].mempool.CheckTx(tx2) require.Error(t, err) + require.Nil(t, reqRes) } func TestBroadcastTxForPeerStopsWhenPeerStops(t *testing.T) { @@ -192,19 +197,19 @@ func TestBroadcastTxForPeerStopsWhenPeerStops(t *testing.T) { } config := cfg.TestConfig() - const N = 2 - reactors, _ := makeAndConnectReactors(config, N) + const n = 2 + reactors, _ := makeAndConnectReactors(config, n) defer func() { for _, r := range reactors { if err := r.Stop(); err != nil { - assert.NoError(t, err) + require.NoError(t, err) } } }() // stop peer sw := reactors[1].Switch - sw.StopPeerForError(sw.Peers().List()[0], errors.New("some reason")) + sw.StopPeerForError(sw.Peers().Copy()[0], errors.New("some reason")) // check that we are not leaking any go-routines // i.e. broadcastTxRoutine finishes when peer is stopped @@ -217,12 +222,12 @@ func TestBroadcastTxForPeerStopsWhenReactorStops(t *testing.T) { } config := cfg.TestConfig() - const N = 2 - _, switches := makeAndConnectReactors(config, N) + const n = 2 + _, switches := makeAndConnectReactors(config, n) // stop reactors for _, s := range switches { - assert.NoError(t, s.Stop()) + require.NoError(t, s.Stop()) } // check that we are not leaking any go-routines @@ -230,39 +235,314 @@ func TestBroadcastTxForPeerStopsWhenReactorStops(t *testing.T) { leaktest.CheckTimeout(t, 10*time.Second)() } -// 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. -// https://github.com/cometbft/cometbft/issues/9639 -func TestDontExhaustMaxActiveIDs(t *testing.T) { +func TestReactorTxSendersLocal(t *testing.T) { config := cfg.TestConfig() - const N = 1 - reactors, _ := makeAndConnectReactors(config, N) + const n = 1 + reactors, _ := makeAndConnectReactors(config, n) defer func() { for _, r := range reactors { if err := r.Stop(); err != nil { - assert.NoError(t, err) + require.NoError(t, err) } } }() reactor := reactors[0] - for i := 0; i < MaxActiveIDs+1; i++ { - peer := mock.NewPeer(nil) - reactor.Receive(p2p.Envelope{ - ChannelID: MempoolChannel, - Src: peer, - Message: &memproto.Message{}, // This uses the wrong message type on purpose to stop the peer as in an error state in the reactor. - }, - ) - reactor.AddPeer(peer) + tx1 := kvstore.NewTxFromID(1) + tx2 := kvstore.NewTxFromID(2) + require.False(t, reactor.isSender(types.Tx(tx1).Key(), "peer1")) + + reactor.addSender(types.Tx(tx1).Key(), "peer1") + reactor.addSender(types.Tx(tx1).Key(), "peer2") + reactor.addSender(types.Tx(tx2).Key(), "peer1") + require.True(t, reactor.isSender(types.Tx(tx1).Key(), "peer1")) + require.True(t, reactor.isSender(types.Tx(tx1).Key(), "peer2")) + require.True(t, reactor.isSender(types.Tx(tx2).Key(), "peer1")) + + reactor.removeSenders(types.Tx(tx1).Key()) + require.False(t, reactor.isSender(types.Tx(tx1).Key(), "peer1")) + require.False(t, reactor.isSender(types.Tx(tx1).Key(), "peer2")) + require.True(t, reactor.isSender(types.Tx(tx2).Key(), "peer1")) +} + +// Test that: +// - If a transaction came from a peer AND if the transaction is added to the +// mempool, it must have a non-empty list of senders in the reactor. +// - If a transaction is removed from the mempool, it must also be removed from +// the list of senders in the reactor. +func TestReactorTxSendersMultiNode(t *testing.T) { + config := cfg.TestConfig() + config.Mempool.Size = 1000 + config.Mempool.CacheSize = 1000 + const n = 3 + reactors, _ := makeAndConnectReactors(config, n) + defer func() { + for _, r := range reactors { + if err := r.Stop(); err != nil { + require.NoError(t, err) + } + } + }() + for _, r := range reactors { + for _, peer := range r.Switch.Peers().Copy() { + peer.Set(types.PeerStateKey, peerState{1}) + } + } + firstReactor := reactors[0] + + numTxs := config.Mempool.Size + txs := newUniqueTxs(numTxs) + + // Initially, there are no transactions (and no senders). + for _, r := range reactors { + require.Zero(t, len(r.txSenders)) + } + + // Add transactions to the first reactor. + callCheckTx(t, firstReactor.mempool, txs) + + // Wait for all txs to be in the mempool of each reactor. + waitForReactors(t, txs, reactors, checkTxsInMempool) + for i, r := range reactors { + checkTxsInMempoolAndSenders(t, r, txs, i) + } + + // Split the transactions in three groups of different sizes. + splitIndex := numTxs / 6 + validTxs := txs[:splitIndex] // will be used to update the mempool, as valid txs + invalidTxs := txs[splitIndex : 3*splitIndex] // will be used to update the mempool, as invalid txs + ignoredTxs := txs[3*splitIndex:] // will remain in the mempool + + // Update the mempools with a list of valid and invalid transactions. + for i, r := range reactors { + updateMempool(t, r.mempool, validTxs, invalidTxs) + + // Txs included in a block should have been removed from the mempool and + // have no senders. + for _, tx := range append(validTxs, invalidTxs...) { + require.False(t, r.mempool.InMempool(tx.Key())) + _, hasSenders := r.txSenders[tx.Key()] + require.False(t, hasSenders) + } + + // Ignored txs should still be in the mempool. + checkTxsInMempoolAndSenders(t, r, ignoredTxs, i) + } + + // The first reactor should not receive transactions from other peers. + require.Zero(t, len(firstReactor.txSenders)) +} + +// Finding a solution for guaranteeing FIFO ordering is not easy; it would +// require changes at the p2p level. The order of messages is just best-effort, +// but this is not documented anywhere. If this is well understood and +// documented, we don't need this test. Until then, let's keep the test. +func TestMempoolFIFOWithParallelCheckTx(t *testing.T) { + t.Skip("FIFO is not supposed to be guaranteed and this this is just used to evidence one of the cases where it does not happen. Hence we skip this test.") + + config := cfg.TestConfig() + reactors, _ := makeAndConnectReactors(config, 4) + defer func() { + for _, r := range reactors { + if err := r.Stop(); err != nil { + require.NoError(t, err) + } + } + }() + for _, r := range reactors { + for _, peer := range r.Switch.Peers().Copy() { + peer.Set(types.PeerStateKey, peerState{1}) + } + } + + // Deliver the same sequence of transactions from multiple sources, in parallel. + txs := newUniqueTxs(200) + mp := reactors[0].mempool + for i := 0; i < 3; i++ { + go func() { + for _, tx := range txs { + mp.CheckTx(tx) //nolint:errcheck + } + }() + } + + // Confirm that FIFO order was respected. + checkTxsInOrder(t, txs, reactors[0], 0) +} + +// Test the experimental feature that limits the number of outgoing connections for gossiping +// transactions (only non-persistent peers). +// Note: in this test we know which gossip connections are active or not because of how the p2p +// functions are currently implemented, which affects the order in which peers are added to the +// mempool reactor. +func TestMempoolReactorMaxActiveOutboundConnections(t *testing.T) { + config := cfg.TestConfig() + config.Mempool.ExperimentalMaxGossipConnectionsToNonPersistentPeers = 1 + reactors, _ := makeAndConnectReactors(config, 4) + defer func() { + for _, r := range reactors { + if err := r.Stop(); err != nil { + require.NoError(t, err) + } + } + }() + for _, r := range reactors { + for _, peer := range r.Switch.Peers().Copy() { + peer.Set(types.PeerStateKey, peerState{1}) + } + } + + // Add a bunch transactions to the first reactor. + txs := newUniqueTxs(100) + callCheckTx(t, reactors[0].mempool, txs) + + // Wait for all txs to be in the mempool of the second reactor; the other reactors should not + // receive any tx. (The second reactor only sends transactions to the first reactor.) + checkTxsInMempool(t, txs, reactors[1], 0) + for _, r := range reactors[2:] { + require.Zero(t, r.mempool.Size()) + } + + // Disconnect the second reactor from the first reactor. + firstPeer := reactors[0].Switch.Peers().Copy()[0] + reactors[0].Switch.StopPeerGracefully(firstPeer) + + // Now the third reactor should start receiving transactions from the first reactor; the fourth + // reactor's mempool should still be empty. + checkTxsInMempool(t, txs, reactors[2], 0) + for _, r := range reactors[3:] { + require.Zero(t, r.mempool.Size()) + } +} + +// Test the experimental feature that limits the number of outgoing connections for gossiping +// transactions (only non-persistent peers). +// Given the disconnections, no transaction should be received in duplicate. +// Note: in this test we know which gossip connections are active or not because of how the p2p +// functions are currently implemented, which affects the order in which peers are added to the +// mempool reactor. +func TestMempoolReactorMaxActiveOutboundConnectionsNoDuplicate(t *testing.T) { + config := cfg.TestConfig() + config.Mempool.ExperimentalMaxGossipConnectionsToNonPersistentPeers = 1 + reactors, _ := makeAndConnectReactors(config, 4) + defer func() { + for _, r := range reactors { + if err := r.Stop(); err != nil { + require.NoError(t, err) + } + } + }() + for _, r := range reactors { + for _, peer := range r.Switch.Peers().Copy() { + peer.Set(types.PeerStateKey, peerState{1}) + } + } + + // Disconnect the second reactor from the third reactor. + pCon1_2 := reactors[1].Switch.Peers().Copy()[1] + reactors[1].Switch.StopPeerGracefully(pCon1_2) + + // Add a bunch transactions to the first reactor. + txs := newUniqueTxs(100) + callCheckTx(t, reactors[0].mempool, txs) + + // Wait for all txs to be in the mempool of the second reactor; the other reactors should not + // receive any tx. (The second reactor only sends transactions to the first reactor.) + checkTxsInOrder(t, txs, reactors[1], 0) + for _, r := range reactors[2:] { + require.Zero(t, r.mempool.Size()) + } + + // Disconnect the second reactor from the first reactor. + pCon0_1 := reactors[0].Switch.Peers().Copy()[0] + reactors[0].Switch.StopPeerGracefully(pCon0_1) + + // Now the third reactor should start receiving transactions from the first reactor and + // the fourth reactor from the second + checkTxsInOrder(t, txs, reactors[2], 0) + checkTxsInOrder(t, txs, reactors[3], 0) +} + +// Test the experimental feature that limits the number of outgoing connections for gossiping +// transactions (only non-persistent peers) on a star shaped network. +// The star center will need to deliver the transactions to each point. +// Note: in this test we know which gossip connections are active or not because of how the p2p +// functions are currently implemented, which affects the order in which peers are added to the +// mempool reactor. +func TestMempoolReactorMaxActiveOutboundConnectionsStar(t *testing.T) { + config := cfg.TestConfig() + config.Mempool.ExperimentalMaxGossipConnectionsToNonPersistentPeers = 1 + reactors, _ := makeAndConnectReactorsStar(config, 0, 4) + defer func() { + for _, r := range reactors { + if err := r.Stop(); err != nil { + require.NoError(t, err) + } + } + }() + for _, r := range reactors { + for _, peer := range r.Switch.Peers().Copy() { + peer.Set(types.PeerStateKey, peerState{1}) + } + } + // Add a bunch transactions to the first reactor. + txs := newUniqueTxs(5) + callCheckTx(t, reactors[0].mempool, txs) + + // Wait for all txs to be in the mempool of the second reactor; the other reactors should not + // receive any tx. (The second reactor only sends transactions to the first reactor.) + checkTxsInOrder(t, txs, reactors[0], 0) + checkTxsInOrder(t, txs, reactors[1], 0) + + for _, r := range reactors[2:] { + require.Zero(t, r.mempool.Size()) + } + + // Disconnect the second reactor from the first reactor. + firstPeer := reactors[0].Switch.Peers().Copy()[0] + reactors[0].Switch.StopPeerGracefully(firstPeer) + + // Now the third reactor should start receiving transactions from the first reactor; the fourth + // reactor's mempool should still be empty. + checkTxsInOrder(t, txs, reactors[0], 0) + checkTxsInOrder(t, txs, reactors[1], 0) + checkTxsInOrder(t, txs, reactors[2], 0) + for _, r := range reactors[3:] { + require.Zero(t, r.mempool.Size()) + } +} + +// Check that the mempool has exactly the given list of txs and, if it's not the +// first reactor (reactorIndex == 0), then each tx has a non-empty list of senders. +func checkTxsInMempoolAndSenders(t *testing.T, r *Reactor, txs types.Txs, reactorIndex int) { + t.Helper() + r.txSendersMtx.Lock() + defer r.txSendersMtx.Unlock() + + require.Len(t, txs, r.mempool.Size()) + if reactorIndex == 0 { + require.Zero(t, len(r.txSenders)) + } else { + require.Equal(t, len(txs), len(r.txSenders)) + } + + // Each transaction is in the mempool and, if it's not the first reactor, it + // has a non-empty list of senders. + for _, tx := range txs { + assert.True(t, r.mempool.InMempool(tx.Key())) + senders, hasSenders := r.txSenders[tx.Key()] + if reactorIndex == 0 { + require.False(t, hasSenders) + } else { + require.True(t, hasSenders && len(senders) > 0) + } } } // mempoolLogger is a TestingLogger which uses a different // color for each validator ("validator" key must exist). func mempoolLogger() log.Logger { - return log.TestingLoggerWithColorFn(func(keyvals ...interface{}) term.FgBgColor { + return log.TestingLoggerWithColorFn(func(keyvals ...any) term.FgBgColor { for i := 0; i < len(keyvals)-1; i += 2 { if keyvals[i] == "validator" { return term.FgBgColor{Fg: term.Color(uint8(keyvals[i+1].(int) + 1))} @@ -272,7 +552,7 @@ func mempoolLogger() log.Logger { }) } -// connect N mempool reactors through N switches +// connect N mempool reactors through N switches. func makeAndConnectReactors(config *cfg.Config, n int) ([]*Reactor, []*p2p.Switch) { reactors := make([]*Reactor, n) logger := mempoolLogger() @@ -282,26 +562,56 @@ func makeAndConnectReactors(config *cfg.Config, n int) ([]*Reactor, []*p2p.Switc mempool, cleanup := newMempoolWithApp(cc) defer cleanup() - reactors[i] = NewReactor(config.Mempool, mempool) // so we dont start the consensus states + reactors[i] = NewReactor(config.Mempool, mempool, false) // so we dont start the consensus states reactors[i].SetLogger(logger.With("validator", i)) } switches := p2p.MakeConnectedSwitches(config.P2P, n, func(i int, s *p2p.Switch) *p2p.Switch { s.AddReactor("MEMPOOL", reactors[i]) return s - }, p2p.Connect2Switches) return reactors, switches } -func waitForTxsOnReactors(t *testing.T, txs types.Txs, reactors []*Reactor) { - // wait for the txs in all mempools +// connect N mempool reactors through N switches as a star centered in c. +func makeAndConnectReactorsStar(config *cfg.Config, c, n int) ([]*Reactor, []*p2p.Switch) { + reactors := make([]*Reactor, n) + logger := mempoolLogger() + for i := 0; i < n; i++ { + app := kvstore.NewInMemoryApplication() + cc := proxy.NewLocalClientCreator(app) + mempool, cleanup := newMempoolWithApp(cc) + defer cleanup() + + reactors[i] = NewReactor(config.Mempool, mempool, false) // so we dont start the consensus states + reactors[i].SetLogger(logger.With("validator", i)) + } + + switches := p2p.MakeConnectedSwitches(config.P2P, n, func(i int, s *p2p.Switch) *p2p.Switch { + s.AddReactor("MEMPOOL", reactors[i]) + return s + }, p2p.ConnectStarSwitches(c)) + return reactors, switches +} + +func newUniqueTxs(n int) types.Txs { + txs := make(types.Txs, n) + for i := 0; i < n; i++ { + txs[i] = kvstore.NewTxFromID(i) + } + return txs +} + +// Wait for all reactors to finish applying a testing function to a list of +// transactions. +func waitForReactors(t *testing.T, txs types.Txs, reactors []*Reactor, testFunc func(*testing.T, types.Txs, *Reactor, int)) { + t.Helper() wg := new(sync.WaitGroup) for i, reactor := range reactors { wg.Add(1) go func(r *Reactor, reactorIndex int) { defer wg.Done() - waitForTxsOnReactor(t, txs, r, reactorIndex) + testFunc(t, txs, r, reactorIndex) }(reactor, i) } @@ -319,21 +629,56 @@ func waitForTxsOnReactors(t *testing.T, txs types.Txs, reactors []*Reactor) { } } -func waitForTxsOnReactor(t *testing.T, txs types.Txs, reactor *Reactor, reactorIndex int) { - mempool := reactor.mempool - for mempool.Size() < len(txs) { +// Wait until the mempool has a certain number of transactions. +func waitForNumTxsInMempool(numTxs int, mempool Mempool) { + for mempool.Size() < numTxs { time.Sleep(time.Millisecond * 100) } +} - reapedTxs := mempool.ReapMaxTxs(len(txs)) +// Wait until all txs are in the mempool and check that the number of txs in the +// mempool is as expected. +func checkTxsInMempool(t *testing.T, txs types.Txs, reactor *Reactor, _ int) { + t.Helper() + waitForNumTxsInMempool(len(txs), reactor.mempool) + + reapedTxs := reactor.mempool.ReapMaxTxs(len(txs)) + require.Len(t, txs, len(reapedTxs)) + require.Len(t, txs, reactor.mempool.Size()) +} + +// Wait until all txs are in the mempool and check that they are in the same +// order as given. +func checkTxsInOrder(t *testing.T, txs types.Txs, reactor *Reactor, reactorIndex int) { + t.Helper() + waitForNumTxsInMempool(len(txs), reactor.mempool) + + // Check that all transactions in the mempool are in the same order as txs. + reapedTxs := reactor.mempool.ReapMaxTxs(len(txs)) for i, tx := range txs { assert.Equalf(t, tx, reapedTxs[i], "txs at index %d on reactor %d don't match: %v vs %v", i, reactorIndex, tx, reapedTxs[i]) } } -// ensure no txs on reactor after some timeout +func updateMempool(t *testing.T, mp Mempool, validTxs types.Txs, invalidTxs types.Txs) { + t.Helper() + allTxs := append(validTxs, invalidTxs...) + + validTxResponses := abciResponses(len(validTxs), abci.CodeTypeOK) + invalidTxResponses := abciResponses(len(invalidTxs), 1) + allResponses := append(validTxResponses, invalidTxResponses...) + + mp.Lock() + err := mp.Update(1, allTxs, allResponses, nil, nil) + mp.Unlock() + + require.NoError(t, err) +} + +// ensure no txs on reactor after some timeout. func ensureNoTxs(t *testing.T, reactor *Reactor, timeout time.Duration) { + t.Helper() time.Sleep(timeout) // wait for the txs in all mempools assert.Zero(t, reactor.mempool.Size()) } diff --git a/mempool/tx.go b/mempool/tx.go deleted file mode 100644 index bbc5060c384..00000000000 --- a/mempool/tx.go +++ /dev/null @@ -1,17 +0,0 @@ -package mempool - -import ( - "github.com/cometbft/cometbft/p2p" -) - -// TxInfo are parameters that get passed when attempting to add a tx to the -// mempool. -type TxInfo struct { - // SenderID is the internal peer ID used in the mempool to identify the - // sender, storing two bytes with each transaction instead of 20 bytes for - // the types.NodeID. - SenderID uint16 - - // SenderP2PID is the actual p2p.ID of the sender, used e.g. for logging. - SenderP2PID p2p.ID -} diff --git a/mempool/types.go b/mempool/types.go new file mode 100644 index 00000000000..ee3f694b71a --- /dev/null +++ b/mempool/types.go @@ -0,0 +1,11 @@ +package mempool + +import ( + memprotos "github.com/cometbft/cometbft/api/cometbft/mempool/v1" + "github.com/cometbft/cometbft/types" +) + +var ( + _ types.Wrapper = &memprotos.Txs{} + _ types.Unwrapper = &memprotos.Message{} +) diff --git a/networks/local/Makefile b/networks/local/Makefile index c2d52334e96..6d96fe2f591 100644 --- a/networks/local/Makefile +++ b/networks/local/Makefile @@ -1,7 +1,7 @@ # Makefile for the "localnode" docker image. all: - docker build --tag cometbft/localnode localnode + docker buildx build --platform linux/amd64 --tag cometbft/localnode localnode .PHONY: all diff --git a/networks/local/localnode/Dockerfile b/networks/local/localnode/Dockerfile index e1c3c452701..3049b72601b 100644 --- a/networks/local/localnode/Dockerfile +++ b/networks/local/localnode/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.7 +FROM alpine:3.19 RUN apk update && \ apk upgrade && \ @@ -6,7 +6,7 @@ RUN apk update && \ VOLUME /cometbft WORKDIR /cometbft -EXPOSE 26656 26657 +EXPOSE 26656 26657 26660 ENTRYPOINT ["/usr/bin/wrapper.sh"] CMD ["node", "--proxy_app", "kvstore"] STOPSIGNAL SIGTERM diff --git a/networks/local/localnode/config-template.toml b/networks/local/localnode/config-template.toml index a90eb7bd5f0..bfb19792042 100644 --- a/networks/local/localnode/config-template.toml +++ b/networks/local/localnode/config-template.toml @@ -1,2 +1,4 @@ [rpc] laddr = "tcp://0.0.0.0:26657" +[instrumentation] +prometheus = true diff --git a/node/node.go b/node/node.go index 7810b0c0997..c7304986341 100644 --- a/node/node.go +++ b/node/node.go @@ -1,42 +1,46 @@ package node import ( + "bytes" "context" + "errors" "fmt" "net" "net/http" + "os" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/rs/cors" - bc "github.com/cometbft/cometbft/blocksync" - cfg "github.com/cometbft/cometbft/config" - cs "github.com/cometbft/cometbft/consensus" - "github.com/cometbft/cometbft/evidence" + _ "net/http/pprof" //nolint: gosec + cfg "github.com/cometbft/cometbft/config" + bc "github.com/cometbft/cometbft/internal/blocksync" + cs "github.com/cometbft/cometbft/internal/consensus" + "github.com/cometbft/cometbft/internal/evidence" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + "github.com/cometbft/cometbft/internal/service" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/internal/state/txindex/null" + "github.com/cometbft/cometbft/internal/statesync" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/libs/log" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - "github.com/cometbft/cometbft/libs/service" + "github.com/cometbft/cometbft/light" mempl "github.com/cometbft/cometbft/mempool" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/p2p/pex" "github.com/cometbft/cometbft/proxy" rpccore "github.com/cometbft/cometbft/rpc/core" - grpccore "github.com/cometbft/cometbft/rpc/grpc" + grpcserver "github.com/cometbft/cometbft/rpc/grpc/server" + grpcprivserver "github.com/cometbft/cometbft/rpc/grpc/server/privileged" rpcserver "github.com/cometbft/cometbft/rpc/jsonrpc/server" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/state/txindex" - "github.com/cometbft/cometbft/state/txindex/null" - "github.com/cometbft/cometbft/statesync" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" - - _ "net/http/pprof" //nolint: gosec ) // Node is the highest level interface to a full CometBFT node. @@ -61,7 +65,9 @@ type Node struct { eventBus *types.EventBus // pub/sub for services stateStore sm.Store blockStore *store.BlockStore // store the blockchain to disk - bcReactor p2p.Reactor // for block-syncing + pruner *sm.Pruner + bcReactor p2p.Reactor // for block-syncing + mempoolReactor waitSyncP2PReactor // for gossipping transactions mempool mempl.Mempool stateSync bool // whether the node should state sync on startup stateSyncReactor *statesync.Reactor // for hosting and restoring state sync snapshots @@ -69,6 +75,7 @@ type Node struct { stateSyncGenesis sm.State // provides the genesis state for state sync consensusState *cs.State // latest consensus state consensusReactor *cs.Reactor // for participating in the consensus + pexReactor *pex.Reactor // for exchanging peer addresses evidencePool *evidence.Pool // tracking evidence proxyApp proxy.AppConns // connection to the application rpcListeners []net.Listener // rpc servers @@ -79,6 +86,12 @@ type Node struct { pprofSrv *http.Server } +type waitSyncP2PReactor interface { + p2p.Reactor + // required by RPC service + WaitSync() bool +} + // Option sets a parameter for the node. type Option func(*Node) @@ -131,10 +144,134 @@ func StateProvider(stateProvider statesync.StateProvider) Option { } } -//------------------------------------------------------------------------------ +// BootstrapState synchronizes the stores with the application after state sync +// has been performed offline. It is expected that the block store and state +// store are empty at the time the function is called. +// +// If the block store is not empty, the function returns an error. +func BootstrapState(ctx context.Context, config *cfg.Config, dbProvider cfg.DBProvider, genProvider GenesisDocProvider, height uint64, appHash []byte) (err error) { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + if ctx == nil { + ctx = context.Background() + } + + if config == nil { + logger.Info("no config provided, using default configuration") + config = cfg.DefaultConfig() + } + + if dbProvider == nil { + dbProvider = cfg.DefaultDBProvider + } + blockStoreDB, stateDB, err := initDBs(config, dbProvider) + + blockStore := store.NewBlockStore(blockStoreDB, store.WithMetrics(store.NopMetrics()), store.WithCompaction(config.Storage.Compact, config.Storage.CompactionInterval), store.WithDBKeyLayout(config.Storage.ExperimentalKeyLayout)) + logger.Info("Blockstore version", "version", blockStore.GetVersion()) + + defer func() { + if derr := blockStore.Close(); derr != nil { + logger.Error("Failed to close blockstore", "err", derr) + // Set the return value + err = derr + } + }() + + if err != nil { + return err + } + + if !blockStore.IsEmpty() { + return errors.New("blockstore not empty, trying to initialize non empty state") + } + + stateStore := sm.NewStore(stateDB, sm.StoreOptions{ + DiscardABCIResponses: config.Storage.DiscardABCIResponses, + Logger: logger, + DBKeyLayout: config.Storage.ExperimentalKeyLayout, + }) + + defer func() { + if derr := stateStore.Close(); derr != nil { + logger.Error("Failed to close statestore", "err", derr) + // Set the return value + err = derr + } + }() + state, err := stateStore.Load() + if err != nil { + return err + } + + if !state.IsEmpty() { + return errors.New("state not empty, trying to initialize non empty state") + } + + // The state store will use the DBKeyLayout set in config or already existing in the DB. + genState, _, err := LoadStateFromDBOrGenesisDocProvider(stateDB, genProvider, config.Storage.GenesisHash) + if err != nil { + return err + } + + stateProvider, err := statesync.NewLightClientStateProviderWithDBKeyVersion( + ctx, + genState.ChainID, genState.Version, genState.InitialHeight, + config.StateSync.RPCServers, light.TrustOptions{ + Period: config.StateSync.TrustPeriod, + Height: config.StateSync.TrustHeight, + Hash: config.StateSync.TrustHashBytes(), + }, logger.With("module", "light"), + config.Storage.ExperimentalKeyLayout) + if err != nil { + return fmt.Errorf("failed to set up light client state provider: %w", err) + } + + state, err = stateProvider.State(ctx, height) + if err != nil { + return err + } + if appHash == nil { + logger.Info("warning: cannot verify appHash. Verification will happen when node boots up!") + } else if !bytes.Equal(appHash, state.AppHash) { + if err := blockStore.Close(); err != nil { + logger.Error("failed to close blockstore: %w", err) + } + if err := stateStore.Close(); err != nil { + logger.Error("failed to close statestore: %w", err) + } + return fmt.Errorf("the app hash returned by the light client does not match the provided appHash, expected %X, got %X", state.AppHash, appHash) + } + + commit, err := stateProvider.Commit(ctx, height) + if err != nil { + return err + } + + if err = stateStore.Bootstrap(state); err != nil { + return err + } + + err = blockStore.SaveSeenCommit(state.LastBlockHeight, commit) + if err != nil { + return err + } + + // Once the stores are bootstrapped, we need to set the height at which the node has finished + // statesyncing. This will allow the blocksync reactor to fetch blocks at a proper height. + // In case this operation fails, it is equivalent to a failure in online state sync where the operator + // needs to manually delete the state and blockstores and rerun the bootstrapping process. + err = stateStore.SetOfflineStateSyncHeight(state.LastBlockHeight) + if err != nil { + return fmt.Errorf("failed to set synced height: %w", err) + } + + return err +} + +// ------------------------------------------------------------------------------ // NewNode returns a new, ready to go, CometBFT Node. -func NewNode(config *cfg.Config, +func NewNode(ctx context.Context, + config *cfg.Config, privValidator types.PrivValidator, nodeKey *p2p.NodeKey, clientCreator proxy.ClientCreator, @@ -144,22 +281,40 @@ func NewNode(config *cfg.Config, logger log.Logger, options ...Option, ) (*Node, error) { - blockStore, stateDB, err := initDBs(config, dbProvider) + blockStoreDB, stateDB, err := initDBs(config, dbProvider) if err != nil { return nil, err } + state, genDoc, err := LoadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider, config.Storage.GenesisHash) + if err != nil { + return nil, err + } + + csMetrics, p2pMetrics, memplMetrics, smMetrics, bstMetrics, abciMetrics, bsMetrics, ssMetrics := metricsProvider(genDoc.ChainID) stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: config.Storage.DiscardABCIResponses, + Metrics: smMetrics, + Compact: config.Storage.Compact, + CompactionInterval: config.Storage.CompactionInterval, + Logger: logger, + DBKeyLayout: config.Storage.ExperimentalKeyLayout, }) - state, genDoc, err := LoadStateFromDBOrGenesisDocProvider(stateDB, genesisDocProvider) + blockStore := store.NewBlockStore(blockStoreDB, store.WithMetrics(bstMetrics), store.WithCompaction(config.Storage.Compact, config.Storage.CompactionInterval), store.WithDBKeyLayout(config.Storage.ExperimentalKeyLayout), store.WithDBKeyLayout(config.Storage.ExperimentalKeyLayout)) + logger.Info("Blockstore version", "version", blockStore.GetVersion()) + + // The key will be deleted if it existed. + // Not checking whether the key is there in case the genesis file was larger than + // the max size of a value (in rocksDB for example), which would cause the check + // to fail and prevent the node from booting. + logger.Info("WARNING: deleting genesis file from database if present, the database stores a hash of the original genesis file now") + + err = stateDB.Delete(genesisDocKey) if err != nil { - return nil, err + logger.Error("Failed to delete genesis doc from DB ", err) } - csMetrics, p2pMetrics, memplMetrics, smMetrics, abciMetrics, bsMetrics, ssMetrics := metricsProvider(genDoc.ChainID) - // Create the proxyApp and establish connections to the ABCI app (consensus, mempool, query). proxyApp, err := createAndStartProxyAppConns(clientCreator, logger, abciMetrics) if err != nil { @@ -207,7 +362,7 @@ func NewNode(config *cfg.Config, // and replays any blocks as necessary to sync CometBFT with the app. consensusLogger := logger.With("module", "consensus") if !stateSync { - if err := doHandshake(stateStore, state, blockStore, genDoc, eventBus, proxyApp, consensusLogger); err != nil { + if err := doHandshake(ctx, stateStore, state, blockStore, genDoc, eventBus, proxyApp, consensusLogger); err != nil { return nil, err } @@ -216,25 +371,37 @@ func NewNode(config *cfg.Config, // what happened during block replay). state, err = stateStore.Load() if err != nil { - return nil, fmt.Errorf("cannot load state: %w", err) + return nil, sm.ErrCannotLoadState{Err: err} } } // 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 := !onlyValidatorIsUs(state, pubKey) + waitSync := stateSync || blockSync logNodeStartupInfo(state, pubKey, logger, consensusLogger) - // Make MempoolReactor - mempool, mempoolReactor := createMempoolAndMempoolReactor(config, proxyApp, state, memplMetrics, logger) + mempool, mempoolReactor := createMempoolAndMempoolReactor(config, proxyApp, state, waitSync, memplMetrics, logger) - // Make Evidence Reactor evidenceReactor, evidencePool, err := createEvidenceReactor(config, dbProvider, stateStore, blockStore, logger) if err != nil { return nil, err } + pruner, err := createPruner( + config, + txIndexer, + blockIndexer, + stateStore, + blockStore, + smMetrics, + logger.With("module", "state"), + ) + if err != nil { + return nil, fmt.Errorf("failed to create pruner: %w", err) + } + // make block executor for consensus and blocksync reactors to execute blocks blockExec := sm.NewBlockExecutor( stateStore, @@ -243,21 +410,32 @@ func NewNode(config *cfg.Config, mempool, evidencePool, blockStore, + sm.BlockExecutorWithPruner(pruner), sm.BlockExecutorWithMetrics(smMetrics), ) - // Make BlocksyncReactor. Don't start block sync if we're doing a state sync first. - bcReactor, err := createBlocksyncReactor(config, state, blockExec, blockStore, blockSync && !stateSync, logger, bsMetrics) + offlineStateSyncHeight := int64(0) + if blockStore.Height() == 0 { + offlineStateSyncHeight, err = blockExec.Store().GetOfflineStateSyncHeight() + if err != nil && err.Error() != "value empty" { + panic(fmt.Sprintf("failed to retrieve statesynced height from store %s; expected state store height to be %v", err, state.LastBlockHeight)) + } + } + // Don't start block sync if we're doing a state sync first. + bcReactor, err := createBlocksyncReactor(config, state, blockExec, blockStore, blockSync && !stateSync, logger, bsMetrics, offlineStateSyncHeight) if err != nil { return nil, fmt.Errorf("could not create blocksync reactor: %w", err) } - // Make ConsensusReactor consensusReactor, consensusState := createConsensusReactor( config, state, blockExec, blockStore, mempool, evidencePool, - privValidator, csMetrics, stateSync || blockSync, eventBus, consensusLogger, + privValidator, csMetrics, waitSync, eventBus, consensusLogger, offlineStateSyncHeight, ) + err = stateStore.SetOfflineStateSyncHeight(0) + if err != nil { + panic(fmt.Sprintf("failed to reset the offline state sync height %s", err)) + } // Set up state sync reactor, and schedule a sync if requested. // FIXME The way we do phased startups (e.g. replay -> block sync -> consensus) is very messy, // we should clean this whole thing up. See: @@ -266,7 +444,6 @@ func NewNode(config *cfg.Config, *config.StateSync, proxyApp.Snapshot(), proxyApp.Query(), - config.StateSync.TempDir, ssMetrics, ) stateSyncReactor.SetLogger(logger.With("module", "statesync")) @@ -276,10 +453,8 @@ func NewNode(config *cfg.Config, return nil, err } - // Setup Transport. transport, peerFilters := createTransport(config, nodeInfo, nodeKey, proxyApp) - // Setup Switch. p2pLogger := logger.With("module", "p2p") sw := createSwitch( config, transport, p2pMetrics, peerFilters, mempoolReactor, bcReactor, @@ -301,17 +476,6 @@ func NewNode(config *cfg.Config, return nil, fmt.Errorf("could not create addrbook: %w", err) } - for _, addr := range splitAndTrimEmpty(config.P2P.BootstrapPeers, ",", " ") { - netAddrs, err := p2p.NewNetAddressString(addr) - if err != nil { - return nil, fmt.Errorf("invalid bootstrap peer address: %w", err) - } - err = addrBook.AddAddress(netAddrs, netAddrs) - if err != nil { - return nil, fmt.Errorf("adding bootstrap address to addressbook: %w", err) - } - } - // Optionally, start the pex reactor // // TODO: @@ -324,8 +488,9 @@ func NewNode(config *cfg.Config, // // If PEX is on, it should handle dialing the seeds. Otherwise the switch does it. // Note we currently use the addrBook regardless at least for AddOurAddress + var pexReactor *pex.Reactor if config.P2P.PexReactor { - createPEXReactorAndAddToSwitch(addrBook, config, sw, logger) + pexReactor = createPEXReactorAndAddToSwitch(addrBook, config, sw, logger) } // Add private IDs to addrbook to block those peers being added @@ -344,13 +509,16 @@ func NewNode(config *cfg.Config, stateStore: stateStore, blockStore: blockStore, + pruner: pruner, bcReactor: bcReactor, + mempoolReactor: mempoolReactor, mempool: mempool, consensusState: consensusState, consensusReactor: consensusReactor, stateSyncReactor: stateSyncReactor, stateSync: stateSync, stateSyncGenesis: state, // Shouldn't be necessary, but need a way to pass the genesis state + pexReactor: pexReactor, evidencePool: evidencePool, proxyApp: proxyApp, txIndexer: txIndexer, @@ -423,15 +591,20 @@ func (n *Node) OnStart() error { if n.stateSync { bcR, ok := n.bcReactor.(blockSyncReactor) if !ok { - return fmt.Errorf("this blocksync reactor does not support switching from state sync") + return errors.New("this blocksync reactor does not support switching from state sync") } - err := startStateSync(n.stateSyncReactor, bcR, n.consensusReactor, n.stateSyncProvider, - n.config.StateSync, n.stateStore, n.blockStore, n.stateSyncGenesis) + err := startStateSync(n.stateSyncReactor, bcR, n.stateSyncProvider, + n.config.StateSync, n.stateStore, n.blockStore, n.stateSyncGenesis, n.config.Storage.ExperimentalKeyLayout) if err != nil { return fmt.Errorf("failed to start state sync: %w", err) } } + // Start background pruning + if err := n.pruner.Start(); err != nil { + return fmt.Errorf("failed to start background pruning routine: %w", err) + } + return nil } @@ -442,6 +615,9 @@ func (n *Node) OnStop() { n.Logger.Info("Stopping Node") // first stop the non-reactor services + if err := n.pruner.Stop(); err != nil { + n.Logger.Error("Error stopping the pruning service", "err", err) + } if err := n.eventBus.Stop(); err != nil { n.Logger.Error("Error closing eventBus", "err", err) } @@ -486,15 +662,23 @@ func (n *Node) OnStop() { } } if n.blockStore != nil { + n.Logger.Info("Closing blockstore") if err := n.blockStore.Close(); err != nil { n.Logger.Error("problem closing blockstore", "err", err) } } if n.stateStore != nil { + n.Logger.Info("Closing statestore") if err := n.stateStore.Close(); err != nil { n.Logger.Error("problem closing statestore", "err", err) } } + if n.evidencePool != nil { + n.Logger.Info("Closing evidencestore") + if err := n.EvidencePool().Close(); err != nil { + n.Logger.Error("problem closing evidencestore", "err", err) + } + } } // ConfigureRPC makes sure RPC has all the objects it needs to operate. @@ -519,6 +703,7 @@ func (n *Node) ConfigureRPC() (*rpccore.Environment, error) { TxIndexer: n.txIndexer, BlockIndexer: n.blockIndexer, ConsensusReactor: n.consensusReactor, + MempoolReactor: n.mempoolReactor, EventBus: n.eventBus, Mempool: n.mempool, @@ -557,8 +742,8 @@ func (n *Node) startRPC() ([]net.Listener, error) { } // we may expose the rpc over both a unix and tcp socket - listeners := make([]net.Listener, len(listenAddrs)) - for i, listenAddr := range listenAddrs { + listeners := make([]net.Listener, 0, len(listenAddrs)) + for _, listenAddr := range listenAddrs { mux := http.NewServeMux() rpcLogger := n.Logger.With("module", "rpc-server") wmLogger := rpcLogger.With("protocol", "websocket") @@ -574,6 +759,7 @@ func (n *Node) startRPC() ([]net.Listener, error) { ) wm.SetLogger(wmLogger) mux.HandleFunc("/websocket", wm.WebsocketHandler) + mux.HandleFunc("/v1/websocket", wm.WebsocketHandler) rpcserver.RegisterRPCFuncs(mux, routes, rpcLogger) listener, err := rpcserver.Listen( listenAddr, @@ -618,34 +804,51 @@ func (n *Node) startRPC() ([]net.Listener, error) { }() } - listeners[i] = listener + listeners = append(listeners, listener) } - // we expose a simplified api over grpc for convenience to app devs - grpcListenAddr := n.config.RPC.GRPCListenAddress - if grpcListenAddr != "" { - config := rpcserver.DefaultConfig() - config.MaxBodyBytes = n.config.RPC.MaxBodyBytes - config.MaxHeaderBytes = n.config.RPC.MaxHeaderBytes - // NOTE: GRPCMaxOpenConnections is used, not MaxOpenConnections - config.MaxOpenConnections = n.config.RPC.GRPCMaxOpenConnections - // If necessary adjust global WriteTimeout to ensure it's greater than - // TimeoutBroadcastTxCommit. - // See https://github.com/tendermint/tendermint/issues/3435 - if config.WriteTimeout <= n.config.RPC.TimeoutBroadcastTxCommit { - config.WriteTimeout = n.config.RPC.TimeoutBroadcastTxCommit + 1*time.Second - } - listener, err := rpcserver.Listen(grpcListenAddr, config.MaxOpenConnections) + if n.config.GRPC.ListenAddress != "" { + listener, err := grpcserver.Listen(n.config.GRPC.ListenAddress) if err != nil { return nil, err } + opts := []grpcserver.Option{ + grpcserver.WithLogger(n.Logger), + } + if n.config.GRPC.VersionService.Enabled { + opts = append(opts, grpcserver.WithVersionService()) + } + if n.config.GRPC.BlockService.Enabled { + opts = append(opts, grpcserver.WithBlockService(n.blockStore, n.eventBus, n.Logger)) + } + if n.config.GRPC.BlockResultsService.Enabled { + opts = append(opts, grpcserver.WithBlockResultsService(n.blockStore, n.stateStore, n.Logger)) + } go func() { - if err := grpccore.StartGRPCServer(env, listener); err != nil { + if err := grpcserver.Serve(listener, opts...); err != nil { n.Logger.Error("Error starting gRPC server", "err", err) } }() listeners = append(listeners, listener) + } + if n.config.GRPC.Privileged.ListenAddress != "" { + listener, err := grpcserver.Listen(n.config.GRPC.Privileged.ListenAddress) + if err != nil { + return nil, err + } + opts := []grpcprivserver.Option{ + grpcprivserver.WithLogger(n.Logger), + } + if n.config.GRPC.Privileged.PruningService.Enabled { + opts = append(opts, grpcprivserver.WithPruningService(n.pruner, n.Logger)) + } + go func() { + if err := grpcprivserver.Serve(listener, opts...); err != nil { + n.Logger.Error("Error starting privileged gRPC server", "err", err) + } + }() + listeners = append(listeners, listener) } return listeners, nil @@ -673,7 +876,7 @@ func (n *Node) startPrometheusServer() *http.Server { return srv } -// starts a ppro +// starts a ppro. func (n *Node) startPprofServer() *http.Server { srv := &http.Server{ Addr: n.config.RPC.PprofListenAddress, @@ -694,11 +897,36 @@ func (n *Node) Switch() *p2p.Switch { return n.sw } +// BlockStore returns the Node's BlockStore. +func (n *Node) BlockStore() *store.BlockStore { + return n.blockStore +} + +// ConsensusReactor returns the Node's ConsensusReactor. +func (n *Node) ConsensusReactor() *cs.Reactor { + return n.consensusReactor +} + +// MempoolReactor returns the Node's mempool reactor. +func (n *Node) MempoolReactor() p2p.Reactor { + return n.mempoolReactor +} + // Mempool returns the Node's mempool. func (n *Node) Mempool() mempl.Mempool { return n.mempool } +// PEXReactor returns the Node's PEXReactor. It returns nil if PEX is disabled. +func (n *Node) PEXReactor() *pex.Reactor { + return n.pexReactor +} + +// EvidencePool returns the Node's EvidencePool. +func (n *Node) EvidencePool() *evidence.Pool { + return n.evidencePool +} + // EventBus returns the Node's EventBus. func (n *Node) EventBus() *types.EventBus { return n.eventBus @@ -715,12 +943,17 @@ func (n *Node) GenesisDoc() *types.GenesisDoc { return n.genesisDoc } +// ProxyApp returns the Node's AppConns, representing its connections to the ABCI application. +func (n *Node) ProxyApp() proxy.AppConns { + return n.proxyApp +} + // Config returns the Node's config. func (n *Node) Config() *cfg.Config { return n.config } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ func (n *Node) Listeners() []string { return []string{ @@ -757,7 +990,7 @@ func makeNodeInfo( ), DefaultNodeID: nodeKey.ID(), Network: genDoc.ChainID, - Version: version.TMCoreSemVer, + Version: version.CMTSemVer, Channels: []byte{ bc.BlocksyncChannel, cs.StateChannel, cs.DataChannel, cs.VoteChannel, cs.VoteSetBitsChannel, @@ -787,3 +1020,75 @@ func makeNodeInfo( err := nodeInfo.Validate() return nodeInfo, err } + +func createPruner( + config *cfg.Config, + txIndexer txindex.TxIndexer, + blockIndexer indexer.BlockIndexer, + stateStore sm.Store, + blockStore *store.BlockStore, + metrics *sm.Metrics, + logger log.Logger, +) (*sm.Pruner, error) { + if err := initApplicationRetainHeight(stateStore); err != nil { + return nil, err + } + + prunerOpts := []sm.PrunerOption{ + sm.WithPrunerInterval(config.Storage.Pruning.Interval), + sm.WithPrunerMetrics(metrics), + } + + if config.Storage.Pruning.DataCompanion.Enabled { + err := initCompanionRetainHeights( + stateStore, + config.Storage.Pruning.DataCompanion.InitialBlockRetainHeight, + config.Storage.Pruning.DataCompanion.InitialBlockResultsRetainHeight, + ) + if err != nil { + return nil, err + } + prunerOpts = append(prunerOpts, sm.WithPrunerCompanionEnabled()) + } + + return sm.NewPruner(stateStore, blockStore, blockIndexer, txIndexer, logger, prunerOpts...), nil +} + +// Set the initial application retain height to 0 to avoid the data companion +// pruning blocks before the application indicates it is OK. We set this to 0 +// only if the retain height was not set before by the application. +func initApplicationRetainHeight(stateStore sm.Store) error { + if _, err := stateStore.GetApplicationRetainHeight(); err != nil { + if errors.Is(err, sm.ErrKeyNotFound) { + return stateStore.SaveApplicationRetainHeight(0) + } + return err + } + return nil +} + +// Sets the data companion retain heights if one of two possible conditions is +// met: +// 1. One or more of the retain heights has not yet been set. +// 2. One or more of the retain heights is currently 0. +func initCompanionRetainHeights(stateStore sm.Store, initBlockRH, initBlockResultsRH int64) error { + curBlockRH, err := stateStore.GetCompanionBlockRetainHeight() + if err != nil && !errors.Is(err, sm.ErrKeyNotFound) { + return fmt.Errorf("failed to obtain companion block retain height: %w", err) + } + if curBlockRH == 0 { + if err := stateStore.SaveCompanionBlockRetainHeight(initBlockRH); err != nil { + return fmt.Errorf("failed to set initial data companion block retain height: %w", err) + } + } + curBlockResultsRH, err := stateStore.GetABCIResRetainHeight() + if err != nil && !errors.Is(err, sm.ErrKeyNotFound) { + return fmt.Errorf("failed to obtain companion block results retain height: %w", err) + } + if curBlockResultsRH == 0 { + if err := stateStore.SaveABCIResRetainHeight(initBlockResultsRH); err != nil { + return fmt.Errorf("failed to set initial data companion block results retain height: %w", err) + } + } + return nil +} diff --git a/node/node_test.go b/node/node_test.go index 031ca6e8fe2..71ca28009e9 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -1,7 +1,9 @@ package node import ( + "bytes" "context" + "encoding/hex" "fmt" "net" "net/http" @@ -14,22 +16,24 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - "github.com/cometbft/cometbft/abci/example/kvstore" cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto/ed25519" - "github.com/cometbft/cometbft/evidence" + "github.com/cometbft/cometbft/crypto/tmhash" + "github.com/cometbft/cometbft/internal/evidence" + cmtos "github.com/cometbft/cometbft/internal/os" + cmtrand "github.com/cometbft/cometbft/internal/rand" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/internal/test" + cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" - cmtrand "github.com/cometbft/cometbft/libs/rand" mempl "github.com/cometbft/cometbft/mempool" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/p2p/conn" p2pmock "github.com/cometbft/cometbft/p2p/mock" "github.com/cometbft/cometbft/privval" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -96,6 +100,20 @@ func TestSplitAndTrimEmpty(t *testing.T) { } } +func TestCompanionInitialHeightSetup(t *testing.T) { + config := test.ResetTestRoot("companion_initial_height") + defer os.RemoveAll(config.RootDir) + config.Storage.Pruning.DataCompanion.Enabled = true + config.Storage.Pruning.DataCompanion.InitialBlockRetainHeight = 1 + // create & start node + n, err := DefaultNewNode(config, log.TestingLogger()) + require.NoError(t, err) + + companionRetainHeight, err := n.stateStore.GetCompanionBlockRetainHeight() + require.NoError(t, err) + require.Equal(t, int64(1), companionRetainHeight) +} + func TestNodeDelayedStart(t *testing.T) { config := test.ResetTestRoot("node_delayed_start_test") defer os.RemoveAll(config.RootDir) @@ -111,7 +129,7 @@ func TestNodeDelayedStart(t *testing.T) { defer n.Stop() //nolint:errcheck // ignore for tests startTime := cmttime.Now() - assert.Equal(t, true, startTime.After(n.GenesisDoc().GenesisTime)) + assert.True(t, true, startTime.After(n.GenesisDoc().GenesisTime)) } func TestNodeSetAppVersion(t *testing.T) { @@ -141,18 +159,18 @@ func TestPprofServer(t *testing.T) { // should not work yet _, err := http.Get("http://" + config.RPC.PprofListenAddress) //nolint: bodyclose - assert.Error(t, err) + require.Error(t, err) n, err := DefaultNewNode(config, log.TestingLogger()) - assert.NoError(t, err) - assert.NoError(t, n.Start()) + require.NoError(t, err) + require.NoError(t, n.Start()) defer func() { require.NoError(t, n.Stop()) }() assert.NotNil(t, n.pprofSrv) resp, err := http.Get("http://" + config.RPC.PprofListenAddress + "/debug/pprof") - assert.NoError(t, err) + require.NoError(t, err) defer resp.Body.Close() assert.Equal(t, 200, resp.StatusCode) } @@ -190,7 +208,7 @@ func TestNodeSetPrivValTCP(t *testing.T) { assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator()) } -// address without a protocol must result in error +// address without a protocol must result in error. func TestPrivValidatorListenAddrNoProtocol(t *testing.T) { addrNoPrefix := testFreeAddr(t) @@ -199,7 +217,7 @@ func TestPrivValidatorListenAddrNoProtocol(t *testing.T) { config.BaseConfig.PrivValidatorListenAddr = addrNoPrefix _, err := DefaultNewNode(config, log.TestingLogger()) - assert.Error(t, err) + require.Error(t, err) } func TestNodeSetPrivValIPC(t *testing.T) { @@ -236,6 +254,7 @@ func TestNodeSetPrivValIPC(t *testing.T) { // testFreeAddr claims a free port so we don't block on listener being ready. func testFreeAddr(t *testing.T) string { + t.Helper() ln, err := net.Listen("tcp", "127.0.0.1:0") require.NoError(t, err) defer ln.Close() @@ -254,7 +273,7 @@ func TestCreateProposalBlock(t *testing.T) { cc := proxy.NewLocalClientCreator(kvstore.NewInMemoryApplication()) proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) err := proxyApp.Start() - require.Nil(t, err) + require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests logger := log.TestingLogger() @@ -264,10 +283,12 @@ func TestCreateProposalBlock(t *testing.T) { stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, }) - maxBytes := 16384 - var partSize uint32 = 256 - maxEvidenceBytes := int64(maxBytes / 2) - state.ConsensusParams.Block.MaxBytes = int64(maxBytes) + var ( + partSize uint32 = 256 + maxBytes int64 = 16384 + ) + maxEvidenceBytes := maxBytes / 2 + state.ConsensusParams.Block.MaxBytes = maxBytes state.ConsensusParams.Evidence.MaxBytes = maxEvidenceBytes proposerAddr, _ := state.Validators.GetByIndex(0) @@ -291,7 +312,7 @@ func TestCreateProposalBlock(t *testing.T) { // than can fit in a block var currentBytes int64 for currentBytes <= maxEvidenceBytes { - ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), privVals[0], "test-chain") + ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(height, cmttime.Now(), privVals[0], "test-chain") require.NoError(t, err) currentBytes += int64(len(ev.Bytes())) evidencePool.ReportConflictingVotes(ev.VoteA, ev.VoteB) @@ -305,10 +326,10 @@ func TestCreateProposalBlock(t *testing.T) { // fill the mempool with more txs // than can fit in a block txLength := 100 - for i := 0; i <= maxBytes/txLength; i++ { + for i := 0; i <= int(maxBytes)/txLength; i++ { tx := cmtrand.Bytes(txLength) - err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) - assert.NoError(t, err) + _, err := mempool.CheckTx(tx) + require.NoError(t, err) } blockExec := sm.NewBlockExecutor( @@ -333,7 +354,7 @@ func TestCreateProposalBlock(t *testing.T) { // check that the part set does not exceed the maximum block size partSet, err := block.MakePartSet(partSize) require.NoError(t, err) - assert.Less(t, partSet.ByteSize(), int64(maxBytes)) + assert.Less(t, partSet.ByteSize(), maxBytes) partSetFromHeader := types.NewPartSetFromHeader(partSet.Header()) for partSetFromHeader.Count() < partSetFromHeader.Total() { @@ -344,7 +365,7 @@ func TestCreateProposalBlock(t *testing.T) { assert.EqualValues(t, partSetFromHeader.ByteSize(), partSet.ByteSize()) err = blockExec.ValidateBlock(state, block) - assert.NoError(t, err) + require.NoError(t, err) } func TestMaxProposalBlockSize(t *testing.T) { @@ -356,7 +377,7 @@ func TestMaxProposalBlockSize(t *testing.T) { cc := proxy.NewLocalClientCreator(kvstore.NewInMemoryApplication()) proxyApp := proxy.NewAppConns(cc, proxy.NopMetrics()) err := proxyApp.Start() - require.Nil(t, err) + require.NoError(t, err) defer proxyApp.Stop() //nolint:errcheck // ignore for tests logger := log.TestingLogger() @@ -385,8 +406,8 @@ func TestMaxProposalBlockSize(t *testing.T) { // fill the mempool with one txs just below the maximum size txLength := int(types.MaxDataBytesNoEvidence(maxBytes, 1)) tx := cmtrand.Bytes(txLength - 4) // to account for the varint - err = mempool.CheckTx(tx, nil, mempl.TxInfo{}) - assert.NoError(t, err) + _, err = mempool.CheckTx(tx) + require.NoError(t, err) blockExec := sm.NewBlockExecutor( stateStore, @@ -435,7 +456,8 @@ func TestNodeNewNodeCustomReactors(t *testing.T) { nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) require.NoError(t, err) - n, err := NewNode(config, + n, err := NewNode(context.Background(), + config, privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), nodeKey, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), @@ -462,6 +484,197 @@ func TestNodeNewNodeCustomReactors(t *testing.T) { assert.Contains(t, channels, cr.Channels[0].ID) } +// Simple test to confirm that an existing genesis file will be deleted from the DB +// TODO Confirm that the deletion of a very big file does not crash the machine. +func TestNodeNewNodeDeleteGenesisFileFromDB(t *testing.T) { + config := test.ResetTestRoot("node_new_node_delete_genesis_from_db") + defer os.RemoveAll(config.RootDir) + // Use goleveldb so we can reuse the same db for the second NewNode() + config.DBBackend = string(dbm.GoLevelDBBackend) + // Ensure the genesis doc hash is saved to db + stateDB, err := cfg.DefaultDBProvider(&cfg.DBContext{ID: "state", Config: config}) + require.NoError(t, err) + + err = stateDB.SetSync(genesisDocKey, []byte("genFile")) + require.NoError(t, err) + + genDocFromDB, err := stateDB.Get(genesisDocKey) + require.NoError(t, err) + require.Equal(t, genDocFromDB, []byte("genFile")) + + stateDB.Close() + nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) + require.NoError(t, err) + + n, err := NewNode( + context.Background(), + config, + privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), + nodeKey, + proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), + DefaultGenesisDocProviderFunc(config), + cfg.DefaultDBProvider, + DefaultMetricsProvider(config.Instrumentation), + log.TestingLogger(), + ) + require.NoError(t, err) + + _, err = stateDB.Get(genesisDocKey) + require.Error(t, err) + + // Start and stop to close the db for later reading + err = n.Start() + require.NoError(t, err) + + err = n.Stop() + require.NoError(t, err) + + stateDB, err = cfg.DefaultDBProvider(&cfg.DBContext{ID: "state", Config: config}) + require.NoError(t, err) + genDocHash, err := stateDB.Get(genesisDocHashKey) + require.NoError(t, err) + require.NotNil(t, genDocHash, "genesis doc hash should be saved in db") + require.Len(t, genDocHash, tmhash.Size) + + err = stateDB.Close() + require.NoError(t, err) +} + +func TestNodeNewNodeGenesisHashMismatch(t *testing.T) { + config := test.ResetTestRoot("node_new_node_genesis_hash") + defer os.RemoveAll(config.RootDir) + + // Use goleveldb so we can reuse the same db for the second NewNode() + config.DBBackend = string(dbm.GoLevelDBBackend) + + nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) + require.NoError(t, err) + + n, err := NewNode( + context.Background(), + config, + privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), + nodeKey, + proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), + DefaultGenesisDocProviderFunc(config), + cfg.DefaultDBProvider, + DefaultMetricsProvider(config.Instrumentation), + log.TestingLogger(), + ) + require.NoError(t, err) + + // Start and stop to close the db for later reading + err = n.Start() + require.NoError(t, err) + + err = n.Stop() + require.NoError(t, err) + + // Ensure the genesis doc hash is saved to db + stateDB, err := cfg.DefaultDBProvider(&cfg.DBContext{ID: "state", Config: config}) + require.NoError(t, err) + + genDocHash, err := stateDB.Get(genesisDocHashKey) + require.NoError(t, err) + require.NotNil(t, genDocHash, "genesis doc hash should be saved in db") + require.Len(t, genDocHash, tmhash.Size) + + err = stateDB.Close() + require.NoError(t, err) + + // Modify the genesis file chain ID to get a different hash + genBytes := cmtos.MustReadFile(config.GenesisFile()) + var genesisDoc types.GenesisDoc + err = cmtjson.Unmarshal(genBytes, &genesisDoc) + require.NoError(t, err) + + genesisDoc.ChainID = "different-chain-id" + err = genesisDoc.SaveAs(config.GenesisFile()) + require.NoError(t, err) + + _, err = NewNode( + context.Background(), + config, + privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), + nodeKey, + proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), + DefaultGenesisDocProviderFunc(config), + cfg.DefaultDBProvider, + DefaultMetricsProvider(config.Instrumentation), + log.TestingLogger(), + ) + require.Error(t, err, "NewNode should error when genesisDoc is changed") + require.Equal(t, "genesis doc hash in db does not match loaded genesis doc", err.Error()) +} + +func TestNodeGenesisHashFlagMatch(t *testing.T) { + config := test.ResetTestRoot("node_new_node_genesis_hash_flag_match") + defer os.RemoveAll(config.RootDir) + + config.DBBackend = string(dbm.GoLevelDBBackend) + nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) + require.NoError(t, err) + // Get correct hash of correct genesis file + jsonBlob, err := os.ReadFile(config.GenesisFile()) + require.NoError(t, err) + + incomingChecksum := tmhash.Sum(jsonBlob) + // Set genesis flag value to incorrect hash + config.Storage.GenesisHash = hex.EncodeToString(incomingChecksum) + _, err = NewNode( + context.Background(), + config, + privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), + nodeKey, + proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), + DefaultGenesisDocProviderFunc(config), + cfg.DefaultDBProvider, + DefaultMetricsProvider(config.Instrumentation), + log.TestingLogger(), + ) + require.NoError(t, err) +} + +func TestNodeGenesisHashFlagMismatch(t *testing.T) { + config := test.ResetTestRoot("node_new_node_genesis_hash_flag_mismatch") + defer os.RemoveAll(config.RootDir) + + // Use goleveldb so we can reuse the same db for the second NewNode() + config.DBBackend = string(dbm.GoLevelDBBackend) + + nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) + require.NoError(t, err) + + // Generate hash of wrong file + f, err := os.ReadFile(config.PrivValidatorKeyFile()) + require.NoError(t, err) + flagHash := tmhash.Sum(f) + + // Set genesis flag value to incorrect hash + config.Storage.GenesisHash = hex.EncodeToString(flagHash) + + _, err = NewNode( + context.Background(), + config, + privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), + nodeKey, + proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), + DefaultGenesisDocProviderFunc(config), + cfg.DefaultDBProvider, + DefaultMetricsProvider(config.Instrumentation), + log.TestingLogger(), + ) + require.Error(t, err) + + f, err = os.ReadFile(config.GenesisFile()) + require.NoError(t, err) + + genHash := tmhash.Sum(f) + + genHashMismatch := bytes.Equal(genHash, flagHash) + require.False(t, genHashMismatch) +} + func state(nVals int, height int64) (sm.State, dbm.DB, []types.PrivValidator) { privVals := make([]types.PrivValidator, nVals) vals := make([]types.GenesisValidator, nVals) diff --git a/node/setup.go b/node/setup.go index c118d724bcb..4b0a2824208 100644 --- a/node/setup.go +++ b/node/setup.go @@ -3,25 +3,32 @@ package node import ( "bytes" "context" + "encoding/hex" "errors" "fmt" "net" + "os" "strings" "time" - _ "net/http/pprof" //nolint: gosec // securely exposed on separate, optional port + _ "net/http/pprof" //nolint: gosec,gci // securely exposed on separate, optional port - dbm "github.com/cometbft/cometbft-db" + _ "github.com/lib/pq" //nolint: gci // provide the psql db driver. + dbm "github.com/cometbft/cometbft-db" abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/blocksync" cfg "github.com/cometbft/cometbft/config" - cs "github.com/cometbft/cometbft/consensus" "github.com/cometbft/cometbft/crypto" - "github.com/cometbft/cometbft/evidence" - "github.com/cometbft/cometbft/statesync" - - cmtjson "github.com/cometbft/cometbft/libs/json" + "github.com/cometbft/cometbft/crypto/tmhash" + "github.com/cometbft/cometbft/internal/blocksync" + cs "github.com/cometbft/cometbft/internal/consensus" + "github.com/cometbft/cometbft/internal/evidence" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/indexer/block" + "github.com/cometbft/cometbft/internal/state/txindex" + "github.com/cometbft/cometbft/internal/statesync" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/light" mempl "github.com/cometbft/cometbft/mempool" @@ -29,29 +36,41 @@ import ( "github.com/cometbft/cometbft/p2p/pex" "github.com/cometbft/cometbft/privval" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/state/indexer/block" - "github.com/cometbft/cometbft/state/txindex" - "github.com/cometbft/cometbft/store" "github.com/cometbft/cometbft/types" "github.com/cometbft/cometbft/version" - - _ "github.com/lib/pq" // provide the psql db driver ) const readHeaderTimeout = 10 * time.Second -// GenesisDocProvider returns a GenesisDoc. +// ChecksummedGenesisDoc combines a GenesisDoc together with its +// SHA256 checksum. +type ChecksummedGenesisDoc struct { + GenesisDoc *types.GenesisDoc + Sha256Checksum []byte +} + +// GenesisDocProvider returns a GenesisDoc together with its SHA256 checksum. // It allows the GenesisDoc to be pulled from sources other than the // filesystem, for instance from a distributed key-value store cluster. -type GenesisDocProvider func() (*types.GenesisDoc, error) +type GenesisDocProvider func() (ChecksummedGenesisDoc, error) // DefaultGenesisDocProviderFunc returns a GenesisDocProvider that loads // the GenesisDoc from the config.GenesisFile() on the filesystem. func DefaultGenesisDocProviderFunc(config *cfg.Config) GenesisDocProvider { - return func() (*types.GenesisDoc, error) { - return types.GenesisDocFromFile(config.GenesisFile()) + return func() (ChecksummedGenesisDoc, error) { + // FIXME: find a way to stream the file incrementally, + // for the JSON parser and the checksum computation. + // https://github.com/cometbft/cometbft/issues/1302 + jsonBlob, err := os.ReadFile(config.GenesisFile()) + if err != nil { + return ChecksummedGenesisDoc{}, fmt.Errorf("couldn't read GenesisDoc file: %w", err) + } + incomingChecksum := tmhash.Sum(jsonBlob) + genDoc, err := types.GenesisDocFromJSON(jsonBlob) + if err != nil { + return ChecksummedGenesisDoc{}, err + } + return ChecksummedGenesisDoc{GenesisDoc: genDoc, Sha256Checksum: incomingChecksum}, nil } } @@ -67,7 +86,7 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) { return nil, fmt.Errorf("failed to load or gen node key %s: %w", config.NodeKeyFile(), err) } - return NewNode(config, + return NewNode(context.Background(), config, privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), nodeKey, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), @@ -79,45 +98,44 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) { } // MetricsProvider returns a consensus, p2p and mempool Metrics. -type MetricsProvider func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempl.Metrics, *sm.Metrics, *proxy.Metrics, *blocksync.Metrics, *statesync.Metrics) +type MetricsProvider func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempl.Metrics, *sm.Metrics, *store.Metrics, *proxy.Metrics, *blocksync.Metrics, *statesync.Metrics) // DefaultMetricsProvider returns Metrics build using Prometheus client library // if Prometheus is enabled. Otherwise, it returns no-op Metrics. func DefaultMetricsProvider(config *cfg.InstrumentationConfig) MetricsProvider { - return func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempl.Metrics, *sm.Metrics, *proxy.Metrics, *blocksync.Metrics, *statesync.Metrics) { + return func(chainID string) (*cs.Metrics, *p2p.Metrics, *mempl.Metrics, *sm.Metrics, *store.Metrics, *proxy.Metrics, *blocksync.Metrics, *statesync.Metrics) { if config.Prometheus { return cs.PrometheusMetrics(config.Namespace, "chain_id", chainID), p2p.PrometheusMetrics(config.Namespace, "chain_id", chainID), mempl.PrometheusMetrics(config.Namespace, "chain_id", chainID), sm.PrometheusMetrics(config.Namespace, "chain_id", chainID), + store.PrometheusMetrics(config.Namespace, "chain_id", chainID), proxy.PrometheusMetrics(config.Namespace, "chain_id", chainID), blocksync.PrometheusMetrics(config.Namespace, "chain_id", chainID), statesync.PrometheusMetrics(config.Namespace, "chain_id", chainID) } - return cs.NopMetrics(), p2p.NopMetrics(), mempl.NopMetrics(), sm.NopMetrics(), proxy.NopMetrics(), blocksync.NopMetrics(), statesync.NopMetrics() + return cs.NopMetrics(), p2p.NopMetrics(), mempl.NopMetrics(), sm.NopMetrics(), store.NopMetrics(), proxy.NopMetrics(), blocksync.NopMetrics(), statesync.NopMetrics() } } type blockSyncReactor interface { - SwitchToBlockSync(sm.State) error + SwitchToBlockSync(state sm.State) error } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ -func initDBs(config *cfg.Config, dbProvider cfg.DBProvider) (blockStore *store.BlockStore, stateDB dbm.DB, err error) { - var blockStoreDB dbm.DB - blockStoreDB, err = dbProvider(&cfg.DBContext{ID: "blockstore", Config: config}) +func initDBs(config *cfg.Config, dbProvider cfg.DBProvider) (bsDB dbm.DB, stateDB dbm.DB, err error) { + bsDB, err = dbProvider(&cfg.DBContext{ID: "blockstore", Config: config}) if err != nil { - return + return nil, nil, err } - blockStore = store.NewBlockStore(blockStoreDB) stateDB, err = dbProvider(&cfg.DBContext{ID: "state", Config: config}) if err != nil { - return + return nil, nil, err } - return + return bsDB, stateDB, nil } func createAndStartProxyAppConns(clientCreator proxy.ClientCreator, logger log.Logger, metrics *proxy.Metrics) (proxy.AppConns, error) { @@ -154,6 +172,8 @@ func createAndStartIndexerService( return nil, nil, nil, err } + txIndexer.SetLogger(logger.With("module", "txindex")) + blockIndexer.SetLogger(logger.With("module", "txindex")) indexerService := txindex.NewIndexerService(txIndexer, blockIndexer, eventBus, false) indexerService.SetLogger(logger.With("module", "txindex")) @@ -165,6 +185,7 @@ func createAndStartIndexerService( } func doHandshake( + ctx context.Context, stateStore sm.Store, state sm.State, blockStore sm.BlockStore, @@ -176,7 +197,7 @@ func doHandshake( handshaker := cs.NewHandshaker(stateStore, state, blockStore, genDoc) handshaker.SetLogger(consensusLogger) handshaker.SetEventBus(eventBus) - if err := handshaker.Handshake(proxyApp); err != nil { + if err := handshaker.Handshake(ctx, proxyApp); err != nil { return fmt.Errorf("error during handshake: %v", err) } return nil @@ -185,11 +206,11 @@ func doHandshake( func logNodeStartupInfo(state sm.State, pubKey crypto.PubKey, logger, consensusLogger log.Logger) { // Log the version info. logger.Info("Version info", - "tendermint_version", version.TMCoreSemVer, + "tendermint_version", version.CMTSemVer, "abci", version.ABCISemVer, "block", version.BlockProtocol, "p2p", version.P2PProtocol, - "commit_hash", version.TMGitCommitHash, + "commit_hash", version.CMTGitCommitHash, ) // If the state and software differ in block version, at least log it. @@ -217,35 +238,46 @@ func onlyValidatorIsUs(state sm.State, pubKey crypto.PubKey) bool { return bytes.Equal(pubKey.Address(), addr) } +// createMempoolAndMempoolReactor creates a mempool and a mempool reactor based on the config. func createMempoolAndMempoolReactor( config *cfg.Config, proxyApp proxy.AppConns, state sm.State, + waitSync bool, memplMetrics *mempl.Metrics, logger log.Logger, -) (mempl.Mempool, p2p.Reactor) { - logger = logger.With("module", "mempool") - mp := mempl.NewCListMempool( - config.Mempool, - proxyApp.Mempool(), - state.LastBlockHeight, - mempl.WithMetrics(memplMetrics), - mempl.WithPreCheck(sm.TxPreCheck(state)), - mempl.WithPostCheck(sm.TxPostCheck(state)), - ) - - mp.SetLogger(logger) +) (mempl.Mempool, waitSyncP2PReactor) { + switch config.Mempool.Type { + // allow empty string for backward compatibility + case cfg.MempoolTypeFlood, "": + logger = logger.With("module", "mempool") + mp := mempl.NewCListMempool( + config.Mempool, + proxyApp.Mempool(), + state.LastBlockHeight, + mempl.WithMetrics(memplMetrics), + mempl.WithPreCheck(sm.TxPreCheck(state)), + mempl.WithPostCheck(sm.TxPostCheck(state)), + ) + mp.SetLogger(logger) + reactor := mempl.NewReactor( + config.Mempool, + mp, + waitSync, + ) + if config.Consensus.WaitForTxs() { + mp.EnableTxsAvailable() + } + reactor.SetLogger(logger) - reactor := mempl.NewReactor( - config.Mempool, - mp, - ) - if config.Consensus.WaitForTxs() { - mp.EnableTxsAvailable() + return mp, reactor + case cfg.MempoolTypeNop: + // Strictly speaking, there's no need to have a `mempl.NopMempoolReactor`, but + // adding it leads to a cleaner code. + return &mempl.NopMempool{}, mempl.NewNopMempoolReactor() + default: + panic(fmt.Sprintf("unknown mempool type: %q", config.Mempool.Type)) } - reactor.SetLogger(logger) - - return mp, reactor } func createEvidenceReactor(config *cfg.Config, dbProvider cfg.DBProvider, @@ -256,7 +288,7 @@ func createEvidenceReactor(config *cfg.Config, dbProvider cfg.DBProvider, return nil, nil, err } evidenceLogger := logger.With("module", "evidence") - evidencePool, err := evidence.NewPool(evidenceDB, stateStore, blockStore) + evidencePool, err := evidence.NewPool(evidenceDB, stateStore, blockStore, evidence.WithDBKeyLayout(config.Storage.ExperimentalKeyLayout)) if err != nil { return nil, nil, err } @@ -272,10 +304,11 @@ func createBlocksyncReactor(config *cfg.Config, blockSync bool, logger log.Logger, metrics *blocksync.Metrics, + offlineStateSyncHeight int64, ) (bcReactor p2p.Reactor, err error) { switch config.BlockSync.Version { case "v0": - bcReactor = blocksync.NewReactor(state.Copy(), blockExec, blockStore, blockSync, metrics) + bcReactor = blocksync.NewReactor(state.Copy(), blockExec, blockStore, blockSync, metrics, offlineStateSyncHeight) case "v1", "v2": return nil, fmt.Errorf("block sync version %s has been deprecated. Please use v0", config.BlockSync.Version) default: @@ -297,6 +330,7 @@ func createConsensusReactor(config *cfg.Config, waitSync bool, eventBus *types.EventBus, consensusLogger log.Logger, + offlineStateSyncHeight int64, ) (*cs.Reactor, *cs.State) { consensusState := cs.NewState( config.Consensus, @@ -306,6 +340,7 @@ func createConsensusReactor(config *cfg.Config, mempool, evidencePool, cs.StateMetrics(csMetrics), + cs.OfflineStateSyncHeight(offlineStateSyncHeight), ) consensusState.SetLogger(consensusLogger) if privValidator != nil { @@ -346,8 +381,8 @@ func createTransport( connFilters, // ABCI query for address filtering. func(_ p2p.ConnSet, c net.Conn, _ []net.IP) error { - res, err := proxyApp.Query().Query(context.TODO(), &abci.RequestQuery{ - Path: fmt.Sprintf("/p2p/filter/addr/%s", c.RemoteAddr().String()), + res, err := proxyApp.Query().Query(context.TODO(), &abci.QueryRequest{ + Path: "/p2p/filter/addr/" + c.RemoteAddr().String(), }) if err != nil { return err @@ -364,7 +399,7 @@ func createTransport( peerFilters, // ABCI query for ID filtering. func(_ p2p.IPeerSet, p p2p.Peer) error { - res, err := proxyApp.Query().Query(context.TODO(), &abci.RequestQuery{ + res, err := proxyApp.Query().Query(context.TODO(), &abci.QueryRequest{ Path: fmt.Sprintf("/p2p/filter/id/%s", p.ID()), }) if err != nil { @@ -408,7 +443,9 @@ func createSwitch(config *cfg.Config, p2p.SwitchPeerFilters(peerFilters...), ) sw.SetLogger(p2pLogger) - sw.AddReactor("MEMPOOL", mempoolReactor) + if config.Mempool.Type != cfg.MempoolTypeNop { + sw.AddReactor("MEMPOOL", mempoolReactor) + } sw.AddReactor("BLOCKSYNC", bcReactor) sw.AddReactor("CONSENSUS", consensusReactor) sw.AddReactor("EVIDENCE", evidenceReactor) @@ -450,7 +487,7 @@ func createAddrBookAndSetOnSwitch(config *cfg.Config, sw *p2p.Switch, func createPEXReactorAndAddToSwitch(addrBook pex.AddrBook, config *cfg.Config, sw *p2p.Switch, logger log.Logger, -) { +) *pex.Reactor { // TODO persistent peers ? so we can have their DNS addrs saved pexReactor := pex.NewReactor(addrBook, &pex.ReactorConfig{ @@ -466,12 +503,19 @@ func createPEXReactorAndAddToSwitch(addrBook pex.AddrBook, config *cfg.Config, }) pexReactor.SetLogger(logger.With("module", "pex")) sw.AddReactor("PEX", pexReactor) + return pexReactor } // 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, - stateStore sm.Store, blockStore *store.BlockStore, state sm.State, +func startStateSync( + ssR *statesync.Reactor, + bcR blockSyncReactor, + stateProvider statesync.StateProvider, + config *cfg.StateSyncConfig, + stateStore sm.Store, + blockStore *store.BlockStore, + state sm.State, + dbKeyLayoutVersion string, ) error { ssR.Logger.Info("Starting state sync") @@ -479,14 +523,15 @@ func startStateSync(ssR *statesync.Reactor, bcR blockSyncReactor, conR *cs.React var err error ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - stateProvider, err = statesync.NewLightClientStateProvider( + stateProvider, err = statesync.NewLightClientStateProviderWithDBKeyVersion( ctx, state.ChainID, state.Version, state.InitialHeight, config.RPCServers, light.TrustOptions{ Period: config.TrustPeriod, Height: config.TrustHeight, Hash: config.TrustHashBytes(), - }, ssR.Logger.With("module", "light")) + }, ssR.Logger.With("module", "light"), + dbKeyLayoutVersion) if err != nil { return fmt.Errorf("failed to set up light client state provider: %w", err) } @@ -518,73 +563,83 @@ func startStateSync(ssR *statesync.Reactor, bcR blockSyncReactor, conR *cs.React return nil } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ -var genesisDocKey = []byte("genesisDoc") +var ( + genesisDocKey = []byte("genesisDoc") + genesisDocHashKey = []byte("genesisDocHash") +) -// LoadStateFromDBOrGenesisDocProvider attempts to load the state from the -// database, or creates one using the given genesisDocProvider. On success this also -// returns the genesis doc loaded through the given provider. -func LoadStateFromDBOrGenesisDocProvider( +func LoadStateFromDBOrGenesisDocProviderWithConfig( stateDB dbm.DB, genesisDocProvider GenesisDocProvider, + operatorGenesisHashHex string, + config *cfg.Config, ) (sm.State, *types.GenesisDoc, error) { - // Get genesis doc - genDoc, err := loadGenesisDoc(stateDB) + // Get genesis doc hash + genDocHash, err := stateDB.Get(genesisDocHashKey) if err != nil { - genDoc, err = genesisDocProvider() + return sm.State{}, nil, fmt.Errorf("error retrieving genesis doc hash: %w", err) + } + csGenDoc, err := genesisDocProvider() + if err != nil { + return sm.State{}, nil, err + } + + if err = csGenDoc.GenesisDoc.ValidateAndComplete(); err != nil { + return sm.State{}, nil, fmt.Errorf("error in genesis doc: %w", err) + } + + // Validate that existing or recently saved genesis file hash matches optional --genesis_hash passed by operator + if operatorGenesisHashHex != "" { + decodedOperatorGenesisHash, err := hex.DecodeString(operatorGenesisHashHex) if err != nil { - return sm.State{}, nil, err + return sm.State{}, nil, errors.New("genesis hash provided by operator cannot be decoded") + } + if !bytes.Equal(csGenDoc.Sha256Checksum, decodedOperatorGenesisHash) { + return sm.State{}, nil, errors.New("genesis doc hash in db does not match passed --genesis_hash value") } + } - err = genDoc.ValidateAndComplete() - if err != nil { - return sm.State{}, nil, fmt.Errorf("error in genesis doc: %w", err) + if len(genDocHash) == 0 { + // Save the genDoc hash in the store if it doesn't already exist for future verification + if err = stateDB.SetSync(genesisDocHashKey, csGenDoc.Sha256Checksum); err != nil { + return sm.State{}, nil, fmt.Errorf("failed to save genesis doc hash to db: %w", err) } - // save genesis doc to prevent a certain class of user errors (e.g. when it - // was changed, accidentally or not). Also good for audit trail. - if err := saveGenesisDoc(stateDB, genDoc); err != nil { - return sm.State{}, nil, err + } else { + if !bytes.Equal(genDocHash, csGenDoc.Sha256Checksum) { + return sm.State{}, nil, errors.New("genesis doc hash in db does not match loaded genesis doc") } } + + dbKeyLayoutVersion := "" + if config != nil { + dbKeyLayoutVersion = config.Storage.ExperimentalKeyLayout + } stateStore := sm.NewStore(stateDB, sm.StoreOptions{ DiscardABCIResponses: false, + DBKeyLayout: dbKeyLayoutVersion, }) - state, err := stateStore.LoadFromDBOrGenesisDoc(genDoc) - if err != nil { - return sm.State{}, nil, err - } - return state, genDoc, nil -} -// panics if failed to unmarshal bytes -func loadGenesisDoc(db dbm.DB) (*types.GenesisDoc, error) { - b, err := db.Get(genesisDocKey) - if err != nil { - panic(err) - } - if len(b) == 0 { - return nil, errors.New("genesis doc not found") - } - var genDoc *types.GenesisDoc - err = cmtjson.Unmarshal(b, &genDoc) + state, err := stateStore.LoadFromDBOrGenesisDoc(csGenDoc.GenesisDoc) if err != nil { - panic(fmt.Sprintf("Failed to load genesis doc due to unmarshaling error: %v (bytes: %X)", err, b)) + return sm.State{}, nil, err } - return genDoc, nil + return state, csGenDoc.GenesisDoc, nil } -// panics if failed to marshal the given genesis document -func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) error { - b, err := cmtjson.Marshal(genDoc) - if err != nil { - return fmt.Errorf("failed to save genesis doc due to marshaling error: %w", err) - } - if err := db.SetSync(genesisDocKey, b); err != nil { - return err - } +// LoadStateFromDBOrGenesisDocProvider attempts to load the state from the +// database, or creates one using the given genesisDocProvider. On success this also +// returns the genesis doc loaded through the given provider. - return nil +// Note that if you don't have a version of the key layout set in your DB already, +// and no config is passed, it will default to v1. +func LoadStateFromDBOrGenesisDocProvider( + stateDB dbm.DB, + genesisDocProvider GenesisDocProvider, + operatorGenesisHashHex string, +) (sm.State, *types.GenesisDoc, error) { + return LoadStateFromDBOrGenesisDocProviderWithConfig(stateDB, genesisDocProvider, operatorGenesisHashHex, nil) } func createAndStartPrivValidatorSocketClient( diff --git a/p2p/README.md b/p2p/README.md index 85bb404aa55..aeaa3271dcb 100644 --- a/p2p/README.md +++ b/p2p/README.md @@ -4,7 +4,7 @@ The p2p package provides an abstraction around peer-to-peer communication. Docs: -- [Connection](https://github.com/cometbft/cometbft/blob/main/spec/p2p/connection.md) for details on how connections and multiplexing work -- [Peer](https://github.com/cometbft/cometbft/blob/main/spec/p2p/node.md) for details on peer ID, handshakes, and peer exchange -- [Node](https://github.com/cometbft/cometbft/blob/main/spec/p2p/node.md) for details about different types of nodes and how they should work -- [Config](https://github.com/cometbft/cometbft/blob/main/spec/p2p/config.md) for details on some config option +- [Connection](https://github.com/cometbft/cometbft/blob/main/spec/p2p/legacy-docs/connection.md) for details on how connections and multiplexing work +- [Peer](https://github.com/cometbft/cometbft/blob/main/spec/p2p/legacy-docs/node.md) for details on peer ID, handshakes, and peer exchange +- [Node](https://github.com/cometbft/cometbft/blob/main/spec/p2p/legacy-docs/node.md) for details about different types of nodes and how they should work +- [Config](https://github.com/cometbft/cometbft/blob/main/spec/p2p/legacy-docs/config.md) for details on some config option diff --git a/p2p/base_reactor.go b/p2p/base_reactor.go index aaee128f99d..515bbcdfb9f 100644 --- a/p2p/base_reactor.go +++ b/p2p/base_reactor.go @@ -1,7 +1,7 @@ package p2p import ( - "github.com/cometbft/cometbft/libs/service" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/p2p/conn" ) @@ -16,7 +16,7 @@ type Reactor interface { service.Service // Start, Stop // SetSwitch allows setting a switch. - SetSwitch(*Switch) + SetSwitch(sw *Switch) // GetChannels returns the list of MConnection.ChannelDescriptor. Make sure // that each ID is unique across all the reactors added to the switch. @@ -36,14 +36,14 @@ type Reactor interface { // RemovePeer is called by the switch when the peer is stopped (due to error // or other reason). - RemovePeer(peer Peer, reason interface{}) + RemovePeer(peer Peer, reason any) // Receive is called by the switch when an envelope is received from any connected // peer on any of the channels registered by the reactor - Receive(Envelope) + Receive(e Envelope) } -//-------------------------------------- +// -------------------------------------- type BaseReactor struct { service.BaseService // Provides Start, Stop, .Quit @@ -60,8 +60,8 @@ func NewBaseReactor(name string, impl Reactor) *BaseReactor { func (br *BaseReactor) SetSwitch(sw *Switch) { br.Switch = sw } -func (*BaseReactor) GetChannels() []*conn.ChannelDescriptor { return nil } -func (*BaseReactor) AddPeer(peer Peer) {} -func (*BaseReactor) RemovePeer(peer Peer, reason interface{}) {} -func (*BaseReactor) Receive(e Envelope) {} -func (*BaseReactor) InitPeer(peer Peer) Peer { return peer } +func (*BaseReactor) GetChannels() []*conn.ChannelDescriptor { return nil } +func (*BaseReactor) AddPeer(Peer) {} +func (*BaseReactor) RemovePeer(Peer, any) {} +func (*BaseReactor) Receive(Envelope) {} +func (*BaseReactor) InitPeer(peer Peer) Peer { return peer } diff --git a/p2p/conn/conn_go110.go b/p2p/conn/conn_go110.go index 459c3169b14..e39f3fed828 100644 --- a/p2p/conn/conn_go110.go +++ b/p2p/conn/conn_go110.go @@ -1,14 +1,5 @@ -//go:build go1.10 -// +build go1.10 - package conn -// Go1.10 has a proper net.Conn implementation that -// has the SetDeadline method implemented as per -// https://github.com/golang/go/commit/e2dd8ca946be884bb877e074a21727f1a685a706 -// lest we run into problems like -// https://github.com/tendermint/tendermint/issues/851 - import "net" func NetPipe() (net.Conn, net.Conn) { diff --git a/p2p/conn/conn_notgo110.go b/p2p/conn/conn_notgo110.go deleted file mode 100644 index 37de8afcc12..00000000000 --- a/p2p/conn/conn_notgo110.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build !go1.10 -// +build !go1.10 - -package conn - -import ( - "net" - "time" -) - -// Only Go1.10 has a proper net.Conn implementation that -// has the SetDeadline method implemented as per -// https://github.com/golang/go/commit/e2dd8ca946be884bb877e074a21727f1a685a706 -// lest we run into problems like -// https://github.com/tendermint/tendermint/issues/851 -// so for go versions < Go1.10 use our custom net.Conn creator -// that doesn't return an `Unimplemented error` for net.Conn. -// Before https://github.com/cometbft/cometbft/commit/49faa79bdce5663894b3febbf4955fb1d172df04 -// we hadn't cared about errors from SetDeadline so swallow them up anyways. -type pipe struct { - net.Conn -} - -func (p *pipe) SetDeadline(t time.Time) error { - return nil -} - -func NetPipe() (net.Conn, net.Conn) { - p1, p2 := net.Pipe() - return &pipe{p1}, &pipe{p2} -} - -var _ net.Conn = (*pipe)(nil) diff --git a/p2p/conn/connection.go b/p2p/conn/connection.go index cc2dcaf98d2..8ce52f58b8d 100644 --- a/p2p/conn/connection.go +++ b/p2p/conn/connection.go @@ -14,14 +14,15 @@ import ( "github.com/cosmos/gogoproto/proto" - flow "github.com/cometbft/cometbft/libs/flowrate" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" + "github.com/cometbft/cometbft/config" + flow "github.com/cometbft/cometbft/internal/flowrate" + "github.com/cometbft/cometbft/internal/protoio" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" + "github.com/cometbft/cometbft/internal/timer" "github.com/cometbft/cometbft/libs/log" cmtmath "github.com/cometbft/cometbft/libs/math" - "github.com/cometbft/cometbft/libs/protoio" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" - "github.com/cometbft/cometbft/libs/timer" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" ) const ( @@ -34,7 +35,7 @@ const ( // some of these defaults are written in the user config // flushThrottle, sendRate, recvRate - // TODO: remove values present in config + // TODO: remove values present in config. defaultFlushThrottle = 100 * time.Millisecond defaultSendQueueCapacity = 1 @@ -47,8 +48,10 @@ const ( defaultPongTimeout = 45 * time.Second ) -type receiveCbFunc func(chID byte, msgBytes []byte) -type errorCbFunc func(interface{}) +type ( + receiveCbFunc func(chID byte, msgBytes []byte) + errorCbFunc func(any) +) /* Each peer has one `MConnection` (multiplex connection) instance. @@ -134,6 +137,10 @@ type MConnConfig struct { // Maximum wait time for pongs PongTimeout time.Duration `mapstructure:"pong_timeout"` + + // Fuzz connection + TestFuzz bool `mapstructure:"test_fuzz"` + TestFuzzConfig *config.FuzzConnConfig `mapstructure:"test_fuzz_config"` } // DefaultMConnConfig returns the default config. @@ -148,7 +155,7 @@ func DefaultMConnConfig() MConnConfig { } } -// NewMConnection wraps net.Conn and creates multiplex connection +// NewMConnection wraps net.Conn and creates multiplex connection. func NewMConnection( conn net.Conn, chDescs []*ChannelDescriptor, @@ -163,7 +170,7 @@ func NewMConnection( DefaultMConnConfig()) } -// NewMConnectionWithConfig wraps net.Conn and creates multiplex connection with a config +// NewMConnectionWithConfig wraps net.Conn and creates multiplex connection with a config. func NewMConnectionWithConfig( conn net.Conn, chDescs []*ChannelDescriptor, @@ -190,8 +197,8 @@ func NewMConnectionWithConfig( } // Create channels - var channelsIdx = map[byte]*Channel{} - var channels = []*Channel{} + channelsIdx := map[byte]*Channel{} + channels := []*Channel{} for _, desc := range chDescs { channel := newChannel(mconn, *desc) @@ -216,7 +223,7 @@ func (c *MConnection) SetLogger(l log.Logger) { } } -// OnStart implements BaseService +// OnStart implements BaseService. func (c *MConnection) OnStart() error { if err := c.BaseService.OnStart(); err != nil { return err @@ -302,7 +309,7 @@ func (c *MConnection) FlushStop() { // c.Stop() } -// OnStop implements BaseService +// OnStop implements BaseService. func (c *MConnection) OnStop() { if c.stopServices() { return @@ -336,7 +343,7 @@ func (c *MConnection) _recover() { } } -func (c *MConnection) stopForError(r interface{}) { +func (c *MConnection) stopForError(r any) { if err := c.Stop(); err != nil { c.Logger.Error("Error stopping connection", "err", err) } @@ -588,7 +595,7 @@ FOR_LOOP: c.recvMonitor.Update(_n) if err != nil { // stopServices was invoked and we are shutting down - // receiving is excpected to fail since we will close the connection + // receiving is expected to fail since we will close the connection select { case <-c.quitRecvRoutine: break FOR_LOOP @@ -657,12 +664,9 @@ FOR_LOOP: // Cleanup close(c.pong) - for range c.pong { - // Drain - } } -// not goroutine-safe +// not goroutine-safe. func (c *MConnection) stopPongTimer() { if c.pongTimer != nil { _ = c.pongTimer.Stop() @@ -670,7 +674,7 @@ func (c *MConnection) stopPongTimer() { } } -// maxPacketMsgSize returns a maximum size of PacketMsg +// maxPacketMsgSize returns a maximum size of PacketMsg. func (c *MConnection) maxPacketMsgSize() int { bz, err := proto.Marshal(mustWrapPacket(&tmp2p.PacketMsg{ ChannelID: 0x01, @@ -705,6 +709,7 @@ func (c *MConnection) Status() ConnectionStatus { status.RecvMonitor = c.recvMonitor.Status() status.Channels = make([]ChannelStatus, len(c.channels)) for i, channel := range c.channels { + channel := channel status.Channels[i] = ChannelStatus{ ID: channel.desc.ID, SendQueueCapacity: cap(channel.sendQueue), @@ -716,7 +721,7 @@ func (c *MConnection) Status() ConnectionStatus { return status } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- type ChannelDescriptor struct { ID byte @@ -738,7 +743,7 @@ func (chDesc ChannelDescriptor) FillDefaults() (filled ChannelDescriptor) { chDesc.RecvMessageCapacity = defaultRecvMessageCapacity } filled = chDesc - return + return filled } // TODO: lowercase. @@ -777,7 +782,7 @@ func (ch *Channel) SetLogger(l log.Logger) { // Queues message to send to this channel. // Goroutine-safe -// Times out (and returns false) after defaultSendTimeout +// Times out (and returns false) after defaultSendTimeout. func (ch *Channel) sendBytes(bytes []byte) bool { select { case ch.sendQueue <- bytes: @@ -790,7 +795,7 @@ func (ch *Channel) sendBytes(bytes []byte) bool { // Queues message to send to this channel. // Nonblocking, returns true if successful. -// Goroutine-safe +// Goroutine-safe. func (ch *Channel) trySendBytes(bytes []byte) bool { select { case ch.sendQueue <- bytes: @@ -801,7 +806,7 @@ func (ch *Channel) trySendBytes(bytes []byte) bool { } } -// Goroutine-safe +// Goroutine-safe. func (ch *Channel) loadSendQueueSize() (size int) { return int(atomic.LoadInt32(&ch.sendQueueSize)) } @@ -814,7 +819,7 @@ func (ch *Channel) canSend() bool { // Returns true if any PacketMsgs are pending to be sent. // Call before calling nextPacketMsg() -// Goroutine-safe +// Goroutine-safe. func (ch *Channel) isSendPending() bool { if len(ch.sending) == 0 { if len(ch.sendQueue) == 0 { @@ -826,7 +831,7 @@ func (ch *Channel) isSendPending() bool { } // Creates a new PacketMsg to send. -// Not goroutine-safe +// Not goroutine-safe. func (ch *Channel) nextPacketMsg() tmp2p.PacketMsg { packet := tmp2p.PacketMsg{ChannelID: int32(ch.desc.ID)} maxSize := ch.maxPacketMsgPayloadSize @@ -843,23 +848,28 @@ func (ch *Channel) nextPacketMsg() tmp2p.PacketMsg { } // Writes next PacketMsg to w and updates c.recentlySent. -// Not goroutine-safe +// Not goroutine-safe. func (ch *Channel) writePacketMsgTo(w io.Writer) (n int, err error) { packet := ch.nextPacketMsg() n, err = protoio.NewDelimitedWriter(w).WriteMsg(mustWrapPacket(&packet)) + if err != nil { + err = ErrPacketWrite{Source: err} + } + atomic.AddInt64(&ch.recentlySent, int64(n)) - return + return n, err } // Handles incoming PacketMsgs. It returns a message bytes if message is // complete. NOTE message bytes may change on next call to recvPacketMsg. -// Not goroutine-safe +// Not goroutine-safe. func (ch *Channel) recvPacketMsg(packet tmp2p.PacketMsg) ([]byte, error) { ch.Logger.Debug("Read PacketMsg", "conn", ch.conn, "packet", packet) - var recvCap, recvReceived = ch.desc.RecvMessageCapacity, len(ch.recving) + len(packet.Data) + recvCap, recvReceived := ch.desc.RecvMessageCapacity, len(ch.recving)+len(packet.Data) if recvCap < recvReceived { - return nil, fmt.Errorf("received message exceeds available capacity: %v < %v", recvCap, recvReceived) + return nil, ErrPacketTooBig{Max: recvCap, Received: recvReceived} } + ch.recving = append(ch.recving, packet.Data...) if packet.EOF { msgBytes := ch.recving @@ -875,14 +885,14 @@ func (ch *Channel) recvPacketMsg(packet tmp2p.PacketMsg) ([]byte, error) { } // Call this periodically to update stats for throttling purposes. -// Not goroutine-safe +// Not goroutine-safe. func (ch *Channel) updateStats() { // Exponential decay of stats. // TODO: optimize. atomic.StoreInt64(&ch.recentlySent, int64(float64(atomic.LoadInt64(&ch.recentlySent))*0.8)) } -//---------------------------------------- +// ---------------------------------------- // Packet // mustWrapPacket takes a packet kind (oneof) and wraps it in a tmp2p.Packet message. diff --git a/p2p/conn/connection_test.go b/p2p/conn/connection_test.go index 731fe5c5459..58c809c2d93 100644 --- a/p2p/conn/connection_test.go +++ b/p2p/conn/connection_test.go @@ -11,18 +11,18 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" + pbtypes "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/internal/protoio" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/protoio" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" - "github.com/cometbft/cometbft/proto/tendermint/types" ) const maxPingPongPacketSize = 1024 // bytes func createTestMConnection(conn net.Conn) *MConnection { - onReceive := func(chID byte, msgBytes []byte) { + onReceive := func(_ byte, _ []byte) { } - onError := func(r interface{}) { + onError := func(_ any) { } c := createMConnectionWithCallbacks(conn, onReceive, onError) c.SetLogger(log.TestingLogger()) @@ -32,7 +32,7 @@ func createTestMConnection(conn net.Conn) *MConnection { func createMConnectionWithCallbacks( conn net.Conn, onReceive func(chID byte, msgBytes []byte), - onError func(r interface{}), + onError func(r any), ) *MConnection { cfg := DefaultMConnConfig() cfg.PingInterval = 90 * time.Millisecond @@ -50,7 +50,7 @@ func TestMConnectionSendFlushStop(t *testing.T) { clientConn := createTestMConnection(client) err := clientConn.Start() - require.Nil(t, err) + require.NoError(t, err) defer clientConn.Stop() //nolint:errcheck // ignore for tests msg := []byte("abc") @@ -88,7 +88,7 @@ func TestMConnectionSend(t *testing.T) { mconn := createTestMConnection(client) err := mconn.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn.Stop() //nolint:errcheck // ignore for tests msg := []byte("Ant-Man") @@ -118,21 +118,21 @@ func TestMConnectionReceive(t *testing.T) { defer client.Close() receivedCh := make(chan []byte) - errorsCh := make(chan interface{}) - onReceive := func(chID byte, msgBytes []byte) { + errorsCh := make(chan any) + onReceive := func(_ byte, msgBytes []byte) { receivedCh <- msgBytes } - onError := func(r interface{}) { + onError := func(r any) { errorsCh <- r } mconn1 := createMConnectionWithCallbacks(client, onReceive, onError) err := mconn1.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn1.Stop() //nolint:errcheck // ignore for tests mconn2 := createTestMConnection(server) err = mconn2.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn2.Stop() //nolint:errcheck // ignore for tests msg := []byte("Cyclops") @@ -155,7 +155,7 @@ func TestMConnectionStatus(t *testing.T) { mconn := createTestMConnection(client) err := mconn.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn.Stop() //nolint:errcheck // ignore for tests status := mconn.Status() @@ -169,16 +169,16 @@ func TestMConnectionPongTimeoutResultsInError(t *testing.T) { defer client.Close() receivedCh := make(chan []byte) - errorsCh := make(chan interface{}) - onReceive := func(chID byte, msgBytes []byte) { + errorsCh := make(chan any) + onReceive := func(_ byte, msgBytes []byte) { receivedCh <- msgBytes } - onError := func(r interface{}) { + onError := func(r any) { errorsCh <- r } mconn := createMConnectionWithCallbacks(client, onReceive, onError) err := mconn.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn.Stop() //nolint:errcheck // ignore for tests serverGotPing := make(chan struct{}) @@ -208,16 +208,16 @@ func TestMConnectionMultiplePongsInTheBeginning(t *testing.T) { defer client.Close() receivedCh := make(chan []byte) - errorsCh := make(chan interface{}) - onReceive := func(chID byte, msgBytes []byte) { + errorsCh := make(chan any) + onReceive := func(_ byte, msgBytes []byte) { receivedCh <- msgBytes } - onError := func(r interface{}) { + onError := func(r any) { errorsCh <- r } mconn := createMConnectionWithCallbacks(client, onReceive, onError) err := mconn.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn.Stop() //nolint:errcheck // ignore for tests // sending 3 pongs in a row (abuse) @@ -263,16 +263,16 @@ func TestMConnectionMultiplePings(t *testing.T) { defer client.Close() receivedCh := make(chan []byte) - errorsCh := make(chan interface{}) - onReceive := func(chID byte, msgBytes []byte) { + errorsCh := make(chan any) + onReceive := func(_ byte, msgBytes []byte) { receivedCh <- msgBytes } - onError := func(r interface{}) { + onError := func(r any) { errorsCh <- r } mconn := createMConnectionWithCallbacks(client, onReceive, onError) err := mconn.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn.Stop() //nolint:errcheck // ignore for tests // sending 3 pings in a row (abuse) @@ -312,16 +312,16 @@ func TestMConnectionPingPongs(t *testing.T) { defer client.Close() receivedCh := make(chan []byte) - errorsCh := make(chan interface{}) - onReceive := func(chID byte, msgBytes []byte) { + errorsCh := make(chan any) + onReceive := func(_ byte, msgBytes []byte) { receivedCh <- msgBytes } - onError := func(r interface{}) { + onError := func(r any) { errorsCh <- r } mconn := createMConnectionWithCallbacks(client, onReceive, onError) err := mconn.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn.Stop() //nolint:errcheck // ignore for tests serverGotPing := make(chan struct{}) @@ -370,16 +370,16 @@ func TestMConnectionStopsAndReturnsError(t *testing.T) { defer client.Close() receivedCh := make(chan []byte) - errorsCh := make(chan interface{}) - onReceive := func(chID byte, msgBytes []byte) { + errorsCh := make(chan any) + onReceive := func(_ byte, msgBytes []byte) { receivedCh <- msgBytes } - onError := func(r interface{}) { + onError := func(r any) { errorsCh <- r } mconn := createMConnectionWithCallbacks(client, onReceive, onError) err := mconn.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn.Stop() //nolint:errcheck // ignore for tests if err := client.Close(); err != nil { @@ -398,10 +398,11 @@ func TestMConnectionStopsAndReturnsError(t *testing.T) { } func newClientAndServerConnsForReadErrors(t *testing.T, chOnErr chan struct{}) (*MConnection, *MConnection) { + t.Helper() server, client := NetPipe() - onReceive := func(chID byte, msgBytes []byte) {} - onError := func(r interface{}) {} + onReceive := func(_ byte, _ []byte) {} + onError := func(_ any) {} // create client conn with two channels chDescs := []*ChannelDescriptor{ @@ -411,18 +412,18 @@ func newClientAndServerConnsForReadErrors(t *testing.T, chOnErr chan struct{}) ( mconnClient := NewMConnection(client, chDescs, onReceive, onError) mconnClient.SetLogger(log.TestingLogger().With("module", "client")) err := mconnClient.Start() - require.Nil(t, err) + require.NoError(t, err) // create server conn with 1 channel // it fires on chOnErr when there's an error serverLogger := log.TestingLogger().With("module", "server") - onError = func(r interface{}) { + onError = func(_ any) { chOnErr <- struct{}{} } mconnServer := createMConnectionWithCallbacks(server, onReceive, onError) mconnServer.SetLogger(serverLogger) err = mconnServer.Start() - require.Nil(t, err) + require.NoError(t, err) return mconnClient, mconnServer } @@ -495,15 +496,15 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) { defer mconnClient.Stop() //nolint:errcheck // ignore for tests defer mconnServer.Stop() //nolint:errcheck // ignore for tests - mconnServer.onReceive = func(chID byte, msgBytes []byte) { + mconnServer.onReceive = func(_ byte, _ []byte) { chOnRcv <- struct{}{} } client := mconnClient.conn protoWriter := protoio.NewDelimitedWriter(client) - // send msg thats just right - var packet = tmp2p.PacketMsg{ + // send msg that's just right + packet := tmp2p.PacketMsg{ ChannelID: 0x01, EOF: true, Data: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize), @@ -513,7 +514,7 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) { require.NoError(t, err) assert.True(t, expectSend(chOnRcv), "msg just right") - // send msg thats too long + // send msg that's too long packet = tmp2p.PacketMsg{ ChannelID: 0x01, EOF: true, @@ -532,7 +533,7 @@ func TestMConnectionReadErrorUnknownMsgType(t *testing.T) { defer mconnServer.Stop() //nolint:errcheck // ignore for tests // send msg with unknown msg type - _, err := protoio.NewDelimitedWriter(mconnClient.conn).WriteMsg(&types.Header{ChainID: "x"}) + _, err := protoio.NewDelimitedWriter(mconnClient.conn).WriteMsg(&pbtypes.Header{ChainID: "x"}) require.NoError(t, err) assert.True(t, expectSend(chOnErr), "unknown msg type") } @@ -544,7 +545,7 @@ func TestMConnectionTrySend(t *testing.T) { mconn := createTestMConnection(client) err := mconn.Start() - require.Nil(t, err) + require.NoError(t, err) defer mconn.Stop() //nolint:errcheck // ignore for tests msg := []byte("Semicolon-Woman") @@ -566,7 +567,6 @@ func TestMConnectionTrySend(t *testing.T) { //nolint:lll //ignore line length for tests func TestConnVectors(t *testing.T) { - testCases := []struct { testName string msg proto.Message @@ -595,14 +595,14 @@ func TestMConnectionChannelOverflow(t *testing.T) { mconnClient, mconnServer := newClientAndServerConnsForReadErrors(t, chOnErr) t.Cleanup(stopAll(t, mconnClient, mconnServer)) - mconnServer.onReceive = func(chID byte, msgBytes []byte) { + mconnServer.onReceive = func(_ byte, _ []byte) { chOnRcv <- struct{}{} } client := mconnClient.conn protoWriter := protoio.NewDelimitedWriter(client) - var packet = tmp2p.PacketMsg{ + packet := tmp2p.PacketMsg{ ChannelID: 0x01, EOF: true, Data: []byte(`42`), @@ -615,7 +615,6 @@ func TestMConnectionChannelOverflow(t *testing.T) { _, err = protoWriter.WriteMsg(mustWrapPacket(&packet)) require.NoError(t, err) assert.False(t, expectSend(chOnRcv)) - } type stopper interface { @@ -623,6 +622,7 @@ type stopper interface { } func stopAll(t *testing.T, stoppers ...stopper) func() { + t.Helper() return func() { for _, s := range stoppers { if err := s.Stop(); err != nil { diff --git a/p2p/conn/errors.go b/p2p/conn/errors.go new file mode 100644 index 00000000000..01ee5586a1d --- /dev/null +++ b/p2p/conn/errors.go @@ -0,0 +1,64 @@ +package conn + +import ( + "errors" + "fmt" +) + +var ( + ErrInvalidSecretConnKeySend = errors.New("send invalid secret connection key") + ErrInvalidSecretConnKeyRecv = errors.New("invalid receive SecretConnection Key") + ErrChallengeVerification = errors.New("challenge verification failed") +) + +// ErrPacketWrite Packet error when writing. +type ErrPacketWrite struct { + Source error +} + +func (e ErrPacketWrite) Error() string { + return fmt.Sprintf("failed to write packet message: %v", e.Source) +} + +func (e ErrPacketWrite) Unwrap() error { + return e.Source +} + +type ErrUnexpectedPubKeyType struct { + Expected string + Got string +} + +func (e ErrUnexpectedPubKeyType) Error() string { + return fmt.Sprintf("expected pubkey type %s, got %s", e.Expected, e.Got) +} + +type ErrDecryptFrame struct { + Source error +} + +func (e ErrDecryptFrame) Error() string { + return fmt.Sprintf("SecretConnection: failed to decrypt the frame: %v", e.Source) +} + +func (e ErrDecryptFrame) Unwrap() error { + return e.Source +} + +type ErrPacketTooBig struct { + Received int + Max int +} + +func (e ErrPacketTooBig) Error() string { + return fmt.Sprintf("received message exceeds available capacity (max: %d, got: %d)", e.Max, e.Received) +} + +type ErrChunkTooBig struct { + Received int + Max int +} + +func (e ErrChunkTooBig) Error() string { + return fmt.Sprintf("chunk too big (max: %d, got %d)", e.Max, e.Received) +} diff --git a/p2p/conn/evil_secret_connection_test.go b/p2p/conn/evil_secret_connection_test.go index 6cb3a9b71db..b9522609743 100644 --- a/p2p/conn/evil_secret_connection_test.go +++ b/p2p/conn/evil_secret_connection_test.go @@ -9,13 +9,14 @@ import ( gogotypes "github.com/cosmos/gogoproto/types" "github.com/oasisprotocol/curve25519-voi/primitives/merlin" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/crypto/chacha20poly1305" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" - "github.com/cometbft/cometbft/libs/protoio" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" + "github.com/cometbft/cometbft/internal/protoio" ) type buffer struct { @@ -34,7 +35,7 @@ func (b *buffer) Bytes() []byte { return b.next.Bytes() } -func (b *buffer) Close() error { +func (*buffer) Close() error { return nil } @@ -176,7 +177,7 @@ func (c *evilConn) Write(data []byte) (n int, err error) { } } -func (c *evilConn) Close() error { +func (*evilConn) Close() error { return nil } @@ -243,15 +244,15 @@ func (c *evilConn) signChallenge() []byte { // MakeSecretConnection errors at different stages. func TestMakeSecretConnection(t *testing.T) { testCases := []struct { - name string - conn *evilConn - errMsg string + name string + conn *evilConn + checkError func(error) bool // Function to check if the error matches the expectation }{ - {"refuse to share ethimeral key", newEvilConn(false, false, false, false), "EOF"}, - {"share bad ethimeral key", newEvilConn(true, true, false, false), "wrong wireType"}, - {"refuse to share auth signature", newEvilConn(true, false, false, false), "EOF"}, - {"share bad auth signature", newEvilConn(true, false, true, true), "failed to decrypt SecretConnection"}, - {"all good", newEvilConn(true, false, true, false), ""}, + {"refuse to share ethimeral key", newEvilConn(false, false, false, false), func(err error) bool { return err == io.EOF }}, + {"share bad ethimeral key", newEvilConn(true, true, false, false), func(err error) bool { return assert.Contains(t, err.Error(), "wrong wireType") }}, + {"refuse to share auth signature", newEvilConn(true, false, false, false), func(err error) bool { return err == io.EOF }}, + {"share bad auth signature", newEvilConn(true, false, true, true), func(err error) bool { return errors.As(err, &ErrDecryptFrame{}) }}, + {"all good", newEvilConn(true, false, true, false), func(err error) bool { return err == nil }}, } for _, tc := range testCases { @@ -259,12 +260,10 @@ func TestMakeSecretConnection(t *testing.T) { t.Run(tc.name, func(t *testing.T) { privKey := ed25519.GenPrivKey() _, err := MakeSecretConnection(tc.conn, privKey) - if tc.errMsg != "" { - if assert.Error(t, err) { - assert.Contains(t, err.Error(), tc.errMsg) - } + if tc.checkError != nil { + assert.True(t, tc.checkError(err)) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } diff --git a/p2p/conn/secret_connection.go b/p2p/conn/secret_connection.go index 942220240b4..24584277764 100644 --- a/p2p/conn/secret_connection.go +++ b/p2p/conn/secret_connection.go @@ -7,7 +7,6 @@ import ( "crypto/sha256" "encoding/binary" "errors" - "fmt" "io" "math" "net" @@ -21,16 +20,16 @@ import ( "golang.org/x/crypto/hkdf" "golang.org/x/crypto/nacl/box" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" - "github.com/cometbft/cometbft/libs/async" - "github.com/cometbft/cometbft/libs/protoio" - cmtsync "github.com/cometbft/cometbft/libs/sync" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" + "github.com/cometbft/cometbft/internal/async" + "github.com/cometbft/cometbft/internal/protoio" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) -// 4 + 1024 == 1028 total frame size +// 4 + 1024 == 1028 total frame size. const ( dataLenSize = 4 dataMaxSize = 1024 @@ -46,8 +45,7 @@ const ( ) var ( - ErrSmallOrderRemotePubKey = errors.New("detected low order point from remote peer") - + ErrSmallOrderRemotePubKey = errors.New("detected low order point from remote peer") secretConnKeyAndChallengeGen = []byte("TENDERMINT_SECRET_CONNECTION_KEY_AND_CHALLENGE_GEN") ) @@ -61,7 +59,6 @@ var ( // Otherwise they are vulnerable to MITM. // (TODO(ismail): see also https://github.com/tendermint/tendermint/issues/3010) type SecretConnection struct { - // immutable recvAead cipher.AEAD sendAead cipher.AEAD @@ -90,9 +87,7 @@ type SecretConnection struct { // Caller should call conn.Close() // See docs/sts-final.pdf for more information. func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*SecretConnection, error) { - var ( - locPubKey = locPrivKey.PubKey() - ) + locPubKey := locPrivKey.PubKey() // Generate ephemeral keys for perfect forward secrecy. locEphPub, locEphPriv := genEphKeys() @@ -136,11 +131,12 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (* sendAead, err := chacha20poly1305.New(sendSecret[:]) if err != nil { - return nil, errors.New("invalid send SecretConnection Key") + return nil, ErrInvalidSecretConnKeySend } + recvAead, err := chacha20poly1305.New(recvSecret[:]) if err != nil { - return nil, errors.New("invalid receive SecretConnection Key") + return nil, ErrInvalidSecretConnKeyRecv } sc := &SecretConnection{ @@ -165,11 +161,16 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (* } remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig + // Usage in your function if _, ok := remPubKey.(ed25519.PubKey); !ok { - return nil, fmt.Errorf("expected ed25519 pubkey, got %T", remPubKey) + return nil, ErrUnexpectedPubKeyType{ + Expected: ed25519.KeyType, + Got: remPubKey.Type(), + } } + if !remPubKey.VerifySignature(challenge[:], remSignature) { - return nil, errors.New("challenge verification failed") + return nil, ErrChallengeVerification } // We've authorized. @@ -177,7 +178,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (* return sc, nil } -// RemotePubKey returns authenticated remote pubkey +// RemotePubKey returns authenticated remote pubkey. func (sc *SecretConnection) RemotePubKey() crypto.PubKey { return sc.remPubKey } @@ -190,8 +191,8 @@ func (sc *SecretConnection) Write(data []byte) (n int, err error) { for 0 < len(data) { if err := func() error { - var sealedFrame = pool.Get(aeadSizeOverhead + totalFrameSize) - var frame = pool.Get(totalFrameSize) + sealedFrame := pool.Get(aeadSizeOverhead + totalFrameSize) + frame := pool.Get(totalFrameSize) defer func() { pool.Put(sealedFrame) pool.Put(frame) @@ -217,6 +218,7 @@ func (sc *SecretConnection) Write(data []byte) (n int, err error) { if err != nil { return err } + n += len(chunk) return nil }(); err != nil { @@ -235,35 +237,40 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) { if 0 < len(sc.recvBuffer) { n = copy(data, sc.recvBuffer) sc.recvBuffer = sc.recvBuffer[n:] - return + return n, err } // read off the conn - var sealedFrame = pool.Get(aeadSizeOverhead + totalFrameSize) + sealedFrame := pool.Get(aeadSizeOverhead + totalFrameSize) defer pool.Put(sealedFrame) _, err = io.ReadFull(sc.conn, sealedFrame) if err != nil { - return + return n, err } // decrypt the frame. // reads and updates the sc.recvNonce - var frame = pool.Get(totalFrameSize) + frame := pool.Get(totalFrameSize) defer pool.Put(frame) _, err = sc.recvAead.Open(frame[:0], sc.recvNonce[:], sealedFrame, nil) if err != nil { - return n, fmt.Errorf("failed to decrypt SecretConnection: %w", err) + return n, ErrDecryptFrame{Source: err} } + incrNonce(sc.recvNonce) // end decryption // copy checkLength worth into data, // set recvBuffer to the rest. - var chunkLength = binary.LittleEndian.Uint32(frame) // read the first four bytes + chunkLength := binary.LittleEndian.Uint32(frame) // read the first four bytes if chunkLength > dataMaxSize { - return 0, errors.New("chunkLength is greater than dataMaxSize") + return 0, ErrChunkTooBig{ + Received: int(chunkLength), + Max: dataMaxSize, + } } - var chunk = frame[dataLenSize : dataLenSize+chunkLength] + + chunk := frame[dataLenSize : dataLenSize+chunkLength] n = copy(data, chunk) if n < len(chunk) { sc.recvBuffer = make([]byte, len(chunk)-n) @@ -272,7 +279,7 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) { return n, err } -// Implements net.Conn +// Implements net.Conn. func (sc *SecretConnection) Close() error { return sc.conn.Close() } func (sc *SecretConnection) LocalAddr() net.Addr { return sc.conn.(net.Conn).LocalAddr() } func (sc *SecretConnection) RemoteAddr() net.Addr { return sc.conn.(net.Conn).RemoteAddr() } @@ -280,6 +287,7 @@ func (sc *SecretConnection) SetDeadline(t time.Time) error { return sc.conn.(net func (sc *SecretConnection) SetReadDeadline(t time.Time) error { return sc.conn.(net.Conn).SetReadDeadline(t) } + func (sc *SecretConnection) SetWriteDeadline(t time.Time) error { return sc.conn.(net.Conn).SetWriteDeadline(t) } @@ -291,16 +299,15 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) { // see: https://github.com/dalek-cryptography/x25519-dalek/blob/34676d336049df2bba763cc076a75e47ae1f170f/src/x25519.rs#L56-L74 ephPub, ephPriv, err = box.GenerateKey(crand.Reader) if err != nil { - panic("Could not generate ephemeral key-pair") + panic("failed to generate ephemeral key-pair") } - return + return ephPub, ephPriv } func shareEphPubKey(conn io.ReadWriter, locEphPub *[32]byte) (remEphPub *[32]byte, err error) { - // Send our pubkey and receive theirs in tandem. - var trs, _ = async.Parallel( - func(_ int) (val interface{}, abort bool, err error) { + trs, _ := async.Parallel( + func(_ int) (val any, abort bool, err error) { lc := *locEphPub _, err = protoio.NewDelimitedWriter(conn).WriteMsg(&gogotypes.BytesValue{Value: lc[:]}) if err != nil { @@ -308,7 +315,7 @@ func shareEphPubKey(conn io.ReadWriter, locEphPub *[32]byte) (remEphPub *[32]byt } return nil, false, nil }, - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { var bytes gogotypes.BytesValue _, err = protoio.NewDelimitedReader(conn, 1024*1024).ReadMsg(&bytes) if err != nil { @@ -324,11 +331,11 @@ func shareEphPubKey(conn io.ReadWriter, locEphPub *[32]byte) (remEphPub *[32]byt // If error: if trs.FirstError() != nil { err = trs.FirstError() - return + return remEphPub, err } // Otherwise: - var _remEphPub = trs.FirstValue().([32]byte) + _remEphPub := trs.FirstValue().([32]byte) return &_remEphPub, nil } @@ -360,7 +367,7 @@ func deriveSecrets( copy(recvSecret[:], res[aeadKeySize:aeadKeySize*2]) } - return + return recvSecret, sendSecret } // computeDHSecret computes a Diffie-Hellman shared secret key @@ -383,7 +390,7 @@ func sort32(foo, bar *[32]byte) (lo, hi *[32]byte) { lo = bar hi = foo } - return + return lo, hi } func signChallenge(challenge *[32]byte, locPrivKey crypto.PrivKey) ([]byte, error) { @@ -400,10 +407,9 @@ type authSigMessage struct { } func shareAuthSignature(sc io.ReadWriter, pubKey crypto.PubKey, signature []byte) (recvMsg authSigMessage, err error) { - // Send our info and receive theirs in tandem. - var trs, _ = async.Parallel( - func(_ int) (val interface{}, abort bool, err error) { + trs, _ := async.Parallel( + func(_ int) (val any, abort bool, err error) { pbpk, err := cryptoenc.PubKeyToProto(pubKey) if err != nil { return nil, true, err @@ -414,7 +420,7 @@ func shareAuthSignature(sc io.ReadWriter, pubKey crypto.PubKey, signature []byte } return nil, false, nil }, - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { var pba tmp2p.AuthSigMessage _, err = protoio.NewDelimitedReader(sc, 1024*1024).ReadMsg(&pba) if err != nil { @@ -437,14 +443,14 @@ func shareAuthSignature(sc io.ReadWriter, pubKey crypto.PubKey, signature []byte // If error: if trs.FirstError() != nil { err = trs.FirstError() - return + return recvMsg, err } - var _recvMsg = trs.FirstValue().(authSigMessage) + _recvMsg := trs.FirstValue().(authSigMessage) return _recvMsg, nil } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- // Increment nonce little-endian by 1 with wraparound. // Due to chacha20poly1305 expecting a 12 byte nonce we do not use the first four diff --git a/p2p/conn/secret_connection_test.go b/p2p/conn/secret_connection_test.go index 516302c35b9..e85441c411b 100644 --- a/p2p/conn/secret_connection_test.go +++ b/p2p/conn/secret_connection_test.go @@ -3,6 +3,7 @@ package conn import ( "bufio" "encoding/hex" + "errors" "flag" "fmt" "io" @@ -20,13 +21,13 @@ import ( "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/crypto/sr25519" - "github.com/cometbft/cometbft/libs/async" - cmtos "github.com/cometbft/cometbft/libs/os" - cmtrand "github.com/cometbft/cometbft/libs/rand" + "github.com/cometbft/cometbft/internal/async" + cmtos "github.com/cometbft/cometbft/internal/os" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) // Run go test -update from within this module -// to update the golden test vector file +// to update the golden test vector file. var update = flag.Bool("update", false, "update .golden files") type kvstoreConn struct { @@ -38,7 +39,7 @@ func (drw kvstoreConn) Close() (err error) { err2 := drw.PipeWriter.CloseWithError(io.EOF) err1 := drw.PipeReader.Close() if err2 != nil { - return err + return err2 } return err1 } @@ -49,9 +50,9 @@ type privKeyWithNilPubKey struct { func (pk privKeyWithNilPubKey) Bytes() []byte { return pk.orig.Bytes() } func (pk privKeyWithNilPubKey) Sign(msg []byte) ([]byte, error) { return pk.orig.Sign(msg) } -func (pk privKeyWithNilPubKey) PubKey() crypto.PubKey { return nil } +func (privKeyWithNilPubKey) PubKey() crypto.PubKey { return nil } func (pk privKeyWithNilPubKey) Equals(pk2 crypto.PrivKey) bool { return pk.orig.Equals(pk2) } -func (pk privKeyWithNilPubKey) Type() string { return "privKeyWithNilPubKey" } +func (privKeyWithNilPubKey) Type() string { return "privKeyWithNilPubKey" } func TestSecretConnectionHandshake(t *testing.T) { fooSecConn, barSecConn := makeSecretConnPair(t) @@ -119,9 +120,9 @@ func TestSecretConnectionReadWrite(t *testing.T) { } // A helper that will run with (fooConn, fooWrites, fooReads) and vice versa - genNodeRunner := func(id string, nodeConn kvstoreConn, nodeWrites []string, nodeReads *[]string) async.Task { - return func(_ int) (interface{}, bool, error) { - // Initiate cryptographic private key and secret connection trhough nodeConn. + genNodeRunner := func(nodeConn kvstoreConn, nodeWrites []string, nodeReads *[]string) async.Task { + return func(_ int) (any, bool, error) { + // Initiate cryptographic private key and secret connection through nodeConn. nodePrvKey := ed25519.GenPrivKey() nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey) if err != nil { @@ -129,8 +130,8 @@ func TestSecretConnectionReadWrite(t *testing.T) { return nil, true, err } // In parallel, handle some reads and writes. - var trs, ok = async.Parallel( - func(_ int) (interface{}, bool, error) { + trs, ok := async.Parallel( + func(_ int) (any, bool, error) { // Node writes: for _, nodeWrite := range nodeWrites { n, err := nodeSecretConn.Write([]byte(nodeWrite)) @@ -150,12 +151,12 @@ func TestSecretConnectionReadWrite(t *testing.T) { } return nil, false, nil }, - func(_ int) (interface{}, bool, error) { + func(_ int) (any, bool, error) { // Node reads: readBuffer := make([]byte, dataMaxSize) for { n, err := nodeSecretConn.Read(readBuffer) - if err == io.EOF { + if errors.Is(err, io.EOF) { if err := nodeConn.PipeReader.Close(); err != nil { t.Error(err) return nil, true, err @@ -182,11 +183,11 @@ func TestSecretConnectionReadWrite(t *testing.T) { } // Run foo & bar in parallel - var trs, ok = async.Parallel( - genNodeRunner("foo", fooConn, fooWrites, &fooReads), - genNodeRunner("bar", barConn, barWrites, &barReads), + trs, ok := async.Parallel( + genNodeRunner(fooConn, fooWrites, &fooReads), + genNodeRunner(barConn, barWrites, &barReads), ) - require.Nil(t, trs.FirstError()) + require.NoError(t, trs.FirstError()) require.True(t, ok, "unexpected task abortion") // A helper to ensure that the writes and reads match. @@ -194,9 +195,9 @@ func TestSecretConnectionReadWrite(t *testing.T) { compareWritesReads := func(writes []string, reads []string) { for { // Pop next write & corresponding reads - var read = "" - var write = writes[0] - var readCount = 0 + read := "" + write := writes[0] + readCount := 0 for _, readChunk := range reads { read += readChunk readCount++ @@ -229,7 +230,7 @@ func TestDeriveSecretsAndChallengeGolden(t *testing.T) { if *update { t.Logf("Updating golden test vector file %s", goldenFilepath) data := createGoldenTestVectors(t) - err := cmtos.WriteFile(goldenFilepath, []byte(data), 0644) + err := cmtos.WriteFile(goldenFilepath, []byte(data), 0o644) require.NoError(t, err) } f, err := os.Open(goldenFilepath) @@ -242,15 +243,15 @@ func TestDeriveSecretsAndChallengeGolden(t *testing.T) { line := scanner.Text() params := strings.Split(line, ",") randSecretVector, err := hex.DecodeString(params[0]) - require.Nil(t, err) + require.NoError(t, err) randSecret := new([32]byte) copy((*randSecret)[:], randSecretVector) locIsLeast, err := strconv.ParseBool(params[1]) - require.Nil(t, err) + require.NoError(t, err) expectedRecvSecret, err := hex.DecodeString(params[2]) - require.Nil(t, err) + require.NoError(t, err) expectedSendSecret, err := hex.DecodeString(params[3]) - require.Nil(t, err) + require.NoError(t, err) recvSecret, sendSecret := deriveSecrets(randSecret, locIsLeast) require.Equal(t, expectedRecvSecret, (*recvSecret)[:], "Recv Secrets aren't equal") @@ -259,34 +260,35 @@ func TestDeriveSecretsAndChallengeGolden(t *testing.T) { } func TestNilPubkey(t *testing.T) { - var fooConn, barConn = makeKVStoreConnPair() + fooConn, barConn := makeKVStoreConnPair() defer fooConn.Close() defer barConn.Close() - var fooPrvKey = ed25519.GenPrivKey() - var barPrvKey = privKeyWithNilPubKey{ed25519.GenPrivKey()} + fooPrvKey := ed25519.GenPrivKey() + barPrvKey := privKeyWithNilPubKey{ed25519.GenPrivKey()} go MakeSecretConnection(fooConn, fooPrvKey) //nolint:errcheck // ignore for tests _, err := MakeSecretConnection(barConn, barPrvKey) require.Error(t, err) - assert.Equal(t, "toproto: key type is not supported", err.Error()) + assert.Equal(t, "encoding: unsupported key ", err.Error()) } func TestNonEd25519Pubkey(t *testing.T) { - var fooConn, barConn = makeKVStoreConnPair() + fooConn, barConn := makeKVStoreConnPair() defer fooConn.Close() defer barConn.Close() - var fooPrvKey = ed25519.GenPrivKey() - var barPrvKey = sr25519.GenPrivKey() + fooPrvKey := ed25519.GenPrivKey() + barPrvKey := sr25519.GenPrivKey() go MakeSecretConnection(fooConn, fooPrvKey) //nolint:errcheck // ignore for tests _, err := MakeSecretConnection(barConn, barPrvKey) require.Error(t, err) - assert.Contains(t, err.Error(), "is not supported") + assert.Contains(t, err.Error(), "unsupported key") } func writeLots(t *testing.T, wg *sync.WaitGroup, conn io.Writer, txt string, n int) { + t.Helper() defer wg.Done() for i := 0; i < n; i++ { _, err := conn.Write([]byte(txt)) @@ -298,18 +300,19 @@ func writeLots(t *testing.T, wg *sync.WaitGroup, conn io.Writer, txt string, n i } func readLots(t *testing.T, wg *sync.WaitGroup, conn io.Reader, n int) { + t.Helper() readBuffer := make([]byte, dataMaxSize) for i := 0; i < n; i++ { _, err := conn.Read(readBuffer) - assert.NoError(t, err) + require.NoError(t, err) } wg.Done() } // Creates the data for a test vector file. // The file format is: -// Hex(diffie_hellman_secret), loc_is_least, Hex(recvSecret), Hex(sendSecret), Hex(challenge) -func createGoldenTestVectors(t *testing.T) string { +// Hex(diffie_hellman_secret), loc_is_least, Hex(recvSecret), Hex(sendSecret), Hex(challenge). +func createGoldenTestVectors(*testing.T) string { data := "" for i := 0; i < 32; i++ { randSecretVector := cmtrand.Bytes(32) @@ -325,7 +328,7 @@ func createGoldenTestVectors(t *testing.T) string { return data } -// Each returned ReadWriteCloser is akin to a net.Connection +// Each returned ReadWriteCloser is akin to a net.Connection. func makeKVStoreConnPair() (fooConn, barConn kvstoreConn) { barReader, fooWriter := io.Pipe() fooReader, barWriter := io.Pipe() @@ -333,6 +336,7 @@ func makeKVStoreConnPair() (fooConn, barConn kvstoreConn) { } func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) { + tb.Helper() var ( fooConn, barConn = makeKVStoreConnPair() fooPrvKey = ed25519.GenPrivKey() @@ -342,8 +346,8 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection ) // Make connections from both sides in parallel. - var trs, ok = async.Parallel( - func(_ int) (val interface{}, abort bool, err error) { + trs, ok := async.Parallel( + func(_ int) (val any, abort bool, err error) { fooSecConn, err = MakeSecretConnection(fooConn, fooPrvKey) if err != nil { tb.Errorf("failed to establish SecretConnection for foo: %v", err) @@ -358,7 +362,7 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection } return nil, false, nil }, - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { barSecConn, err = MakeSecretConnection(barConn, barPrvKey) if barSecConn == nil { tb.Errorf("failed to establish SecretConnection for bar: %v", err) @@ -375,7 +379,7 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection }, ) - require.Nil(tb, trs.FirstError()) + require.NoError(tb, trs.FirstError()) require.True(tb, ok, "Unexpected task abortion") return fooSecConn, barSecConn diff --git a/p2p/conn_set.go b/p2p/conn_set.go index 44eff4a0cf1..2cdb61ecf11 100644 --- a/p2p/conn_set.go +++ b/p2p/conn_set.go @@ -3,16 +3,16 @@ package p2p import ( "net" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) // ConnSet is a lookup table for connections and all their ips. type ConnSet interface { - Has(net.Conn) bool - HasIP(net.IP) bool - Set(net.Conn, []net.IP) - Remove(net.Conn) - RemoveAddr(net.Addr) + Has(conn net.Conn) bool + HasIP(ip net.IP) bool + Set(conn net.Conn, ip []net.IP) + Remove(conn net.Conn) + RemoveAddr(addr net.Addr) } type connSetItem struct { diff --git a/p2p/errors.go b/p2p/errors.go index 4fc915292fb..61e3d1e8bca 100644 --- a/p2p/errors.go +++ b/p2p/errors.go @@ -1,14 +1,24 @@ package p2p import ( + "errors" "fmt" "net" + + "github.com/cometbft/cometbft/libs/bytes" +) + +var ( + ErrEmptyHost = errors.New("host is empty") + ErrNoIP = errors.New("no IP address found") + ErrNoNodeInfo = errors.New("no node info found") + ErrInvalidIP = errors.New("invalid IP address") ) // ErrFilterTimeout indicates that a filter operation timed out. type ErrFilterTimeout struct{} -func (e ErrFilterTimeout) Error() string { +func (ErrFilterTimeout) Error() string { return "filter timed out" } @@ -75,7 +85,7 @@ func (e ErrRejected) Error() string { return fmt.Sprintf("self ID<%v>", e.id) } - return fmt.Sprintf("%s", e.err) + return e.err.Error() } // IsAuthFailure when Peer authentication was unsuccessful. @@ -141,18 +151,18 @@ func (e ErrSwitchAuthenticationFailure) Error() string { // ErrTransportClosed is raised when the Transport has been closed. type ErrTransportClosed struct{} -func (e ErrTransportClosed) Error() string { +func (ErrTransportClosed) Error() string { return "transport has been closed" } // ErrPeerRemoval is raised when attempting to remove a peer results in an error. type ErrPeerRemoval struct{} -func (e ErrPeerRemoval) Error() string { +func (ErrPeerRemoval) Error() string { return "peer removal failed" } -//------------------------------------------------------------------- +// ------------------------------------------------------------------- type ErrNetAddressNoID struct { Addr string @@ -171,6 +181,8 @@ func (e ErrNetAddressInvalid) Error() string { return fmt.Sprintf("invalid address (%s): %v", e.Addr, e.Err) } +func (e ErrNetAddressInvalid) Unwrap() error { return e.Err } + type ErrNetAddressLookup struct { Addr string Err error @@ -180,6 +192,8 @@ func (e ErrNetAddressLookup) Error() string { return fmt.Sprintf("error looking up host (%s): %v", e.Addr, e.Err) } +func (e ErrNetAddressLookup) Unwrap() error { return e.Err } + // ErrCurrentlyDialingOrExistingAddress indicates that we're currently // dialing this address or it belongs to an existing peer. type ErrCurrentlyDialingOrExistingAddress struct { @@ -189,3 +203,132 @@ type ErrCurrentlyDialingOrExistingAddress struct { func (e ErrCurrentlyDialingOrExistingAddress) Error() string { return fmt.Sprintf("connection with %s has been established or dialed", e.Addr) } + +type ErrInvalidPort struct { + Port uint32 +} + +func (e ErrInvalidPort) Error() string { + return fmt.Sprintf("invalid port: %d", e.Port) +} + +type ErrInvalidPeerID struct { + ID ID + Source error +} + +func (e ErrInvalidPeerID) Error() string { + return fmt.Sprintf("invalid peer ID (%v): %v", e.ID, e.Source) +} + +func (e ErrInvalidPeerID) Unwrap() error { + return e.Source +} + +type ErrInvalidNodeVersion struct { + Version string +} + +func (e ErrInvalidNodeVersion) Error() string { + return fmt.Sprintf("invalid version %s: version must be valid ASCII text without tabs", e.Version) +} + +type ErrDuplicateChannelID struct { + ID byte +} + +func (e ErrDuplicateChannelID) Error() string { + return fmt.Sprintf("channels contains duplicate channel id %v", e.ID) +} + +type ErrChannelsTooLong struct { + Length int + Max int +} + +func (e ErrChannelsTooLong) Error() string { + return fmt.Sprintf("channels is too long (max: %d, got: %d)", e.Max, e.Length) +} + +type ErrInvalidMoniker struct { + Moniker string +} + +func (e ErrInvalidMoniker) Error() string { + return fmt.Sprintf("moniker must be valid non-empty ASCII text without tabs, but got %v", e.Moniker) +} + +type ErrInvalidTxIndex struct { + TxIndex string +} + +func (e ErrInvalidTxIndex) Error() string { + return fmt.Sprintf("tx index must be either 'on', 'off', or empty string, got '%v'", e.TxIndex) +} + +type ErrInvalidRPCAddress struct { + RPCAddress string +} + +func (e ErrInvalidRPCAddress) Error() string { + return fmt.Sprintf("rpc address must be valid ASCII text without tabs, but got %v", e.RPCAddress) +} + +type ErrInvalidNodeInfoType struct { + Type string + Expected string +} + +func (e ErrInvalidNodeInfoType) Error() string { + return fmt.Sprintf("invalid NodeInfo type, Expected %s but got %s", e.Expected, e.Type) +} + +type ErrDifferentBlockVersion struct { + Other uint64 + Our uint64 +} + +func (e ErrDifferentBlockVersion) Error() string { + return fmt.Sprintf("peer is on a different Block version. Got %d, expected %d", + e.Other, e.Our) +} + +type ErrDifferentNetwork struct { + Other string + Our string +} + +func (e ErrDifferentNetwork) Error() string { + return fmt.Sprintf("peer is on a different network. Got %s, expected %s", e.Other, e.Our) +} + +type ErrNoCommonChannels struct { + OtherChannels bytes.HexBytes + OurChannels bytes.HexBytes +} + +func (e ErrNoCommonChannels) Error() string { + return fmt.Sprintf("no common channels between us (%v) and peer (%v)", e.OurChannels, e.OtherChannels) +} + +type ErrStart struct { + Service any + Err error +} + +func (e ErrStart) Error() string { + return fmt.Sprintf("failed to start %v: %v", e.Service, e.Err) +} + +func (e ErrStart) Unwrap() error { + return e.Err +} + +type ErrInvalidPeerIDLength struct { + Got int + Expected int +} + +func (e ErrInvalidPeerIDLength) Error() string { + return fmt.Sprintf("invalid peer ID length, got %d, expected %d", e.Expected, e.Got) +} diff --git a/p2p/fuzz.go b/p2p/fuzz.go index 23ad8c5907f..6da1d1e82b5 100644 --- a/p2p/fuzz.go +++ b/p2p/fuzz.go @@ -5,8 +5,8 @@ import ( "time" "github.com/cometbft/cometbft/config" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtrand "github.com/cometbft/cometbft/internal/rand" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) // FuzzedConnection wraps any net.Conn and depending on the mode either delays @@ -107,7 +107,7 @@ func (fc *FuzzedConnection) randomDuration() time.Duration { } // implements the fuzz (delay, kill conn) -// and returns whether or not the read/write should be ignored +// and returns whether or not the read/write should be ignored. func (fc *FuzzedConnection) fuzz() bool { if !fc.shouldFuzz() { return false diff --git a/p2p/key.go b/p2p/key.go index b30dca1dcde..4e3defb7810 100644 --- a/p2p/key.go +++ b/p2p/key.go @@ -8,18 +8,18 @@ import ( "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" + cmtos "github.com/cometbft/cometbft/internal/os" cmtjson "github.com/cometbft/cometbft/libs/json" - cmtos "github.com/cometbft/cometbft/libs/os" ) -// ID is a hex-encoded crypto.Address +// ID is a hex-encoded crypto.Address. type ID string // IDByteLength is the length of a crypto.Address. Currently only 20. // TODO: support other length addresses ? const IDByteLength = crypto.AddressSize -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ // Persistent peer ID // TODO: encrypt on disk @@ -34,7 +34,7 @@ func (nodeKey *NodeKey) ID() ID { return PubKeyToID(nodeKey.PubKey()) } -// PubKey returns the peer's PubKey +// PubKey returns the peer's PubKey. func (nodeKey *NodeKey) PubKey() crypto.PubKey { return nodeKey.PrivKey.PubKey() } @@ -88,14 +88,14 @@ func (nodeKey *NodeKey) SaveAs(filePath string) error { if err != nil { return err } - err = os.WriteFile(filePath, jsonBytes, 0600) + err = os.WriteFile(filePath, jsonBytes, 0o600) if err != nil { return err } return nil } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ // MakePoWTarget returns the big-endian encoding of 2^(targetBits - difficulty) - 1. // It can be used as a Proof of Work target. diff --git a/p2p/key_test.go b/p2p/key_test.go index e87bfe88d63..c8e4ea6c9f0 100644 --- a/p2p/key_test.go +++ b/p2p/key_test.go @@ -10,17 +10,17 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/crypto/ed25519" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) func TestLoadOrGenNodeKey(t *testing.T) { filePath := filepath.Join(os.TempDir(), cmtrand.Str(12)+"_peer_id.json") nodeKey, err := LoadOrGenNodeKey(filePath) - assert.Nil(t, err) + require.NoError(t, err) nodeKey2, err := LoadOrGenNodeKey(filePath) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, nodeKey, nodeKey2) } @@ -35,7 +35,7 @@ func TestLoadNodeKey(t *testing.T) { require.NoError(t, err) nodeKey, err := LoadNodeKey(filePath) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, nodeKey) } @@ -49,30 +49,29 @@ func TestNodeKeySaveAs(t *testing.T) { PrivKey: privKey, } err := nodeKey.SaveAs(filePath) - assert.NoError(t, err) + require.NoError(t, err) assert.FileExists(t, filePath) } -//---------------------------------------------------------- +// ---------------------------------------------------------- -func padBytes(bz []byte, targetBytes int) []byte { +func padBytes(bz []byte) []byte { + targetBytes := 20 return append(bz, bytes.Repeat([]byte{0xFF}, targetBytes-len(bz))...) } func TestPoWTarget(t *testing.T) { - - targetBytes := 20 cases := []struct { difficulty uint target []byte }{ - {0, padBytes([]byte{}, targetBytes)}, - {1, padBytes([]byte{127}, targetBytes)}, - {8, padBytes([]byte{0}, targetBytes)}, - {9, padBytes([]byte{0, 127}, targetBytes)}, - {10, padBytes([]byte{0, 63}, targetBytes)}, - {16, padBytes([]byte{0, 0}, targetBytes)}, - {17, padBytes([]byte{0, 0, 127}, targetBytes)}, + {0, padBytes([]byte{})}, + {1, padBytes([]byte{127})}, + {8, padBytes([]byte{0})}, + {9, padBytes([]byte{0, 127})}, + {10, padBytes([]byte{0, 63})}, + {16, padBytes([]byte{0, 0})}, + {17, padBytes([]byte{0, 0, 127})}, } for _, c := range cases { diff --git a/p2p/metrics.go b/p2p/metrics.go index 808142e9afc..768c4c31cb0 100644 --- a/p2p/metrics.go +++ b/p2p/metrics.go @@ -15,12 +15,10 @@ const ( MetricsSubsystem = "p2p" ) -var ( - // valueToLabelRegexp is used to find the golang package name and type name - // so that the name can be turned into a prometheus label where the characters - // in the label do not include prometheus special characters such as '*' and '.'. - valueToLabelRegexp = regexp.MustCompile(`\*?(\w+)\.(.*)`) -) +// valueToLabelRegexp is used to find the golang package name and type name +// so that the name can be turned into a prometheus label where the characters +// in the label do not include prometheus special characters such as '*' and '.'. +var valueToLabelRegexp = regexp.MustCompile(`\*?(\w+)\.(.*)`) //go:generate go run ../scripts/metricsgen -struct=Metrics @@ -51,7 +49,7 @@ type metricsLabelCache struct { // type that is passed in. // This method uses a map on the Metrics struct so that each label name only needs // to be produced once to prevent expensive string operations. -func (m *metricsLabelCache) ValueToMetricLabel(i interface{}) string { +func (m *metricsLabelCache) ValueToMetricLabel(i any) string { t := reflect.TypeOf(i) m.mtx.RLock() diff --git a/p2p/mock/peer.go b/p2p/mock/peer.go index 3e137af89f8..3a70eae1662 100644 --- a/p2p/mock/peer.go +++ b/p2p/mock/peer.go @@ -4,7 +4,7 @@ import ( "net" "github.com/cometbft/cometbft/crypto/ed25519" - "github.com/cometbft/cometbft/libs/service" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/p2p/conn" ) @@ -14,7 +14,7 @@ type Peer struct { ip net.IP id p2p.ID addr *p2p.NetAddress - kv map[string]interface{} + kv map[string]any Outbound, Persistent bool } @@ -33,7 +33,7 @@ func NewPeer(ip net.IP) *Peer { ip: ip, id: nodeKey.ID(), addr: netAddr, - kv: make(map[string]interface{}), + kv: make(map[string]any), } mp.BaseService = service.NewBaseService(nil, "MockPeer", mp) if err := mp.Start(); err != nil { @@ -42,31 +42,32 @@ func NewPeer(ip net.IP) *Peer { return mp } -func (mp *Peer) FlushStop() { mp.Stop() } //nolint:errcheck //ignore error -func (mp *Peer) TrySend(e p2p.Envelope) bool { return true } -func (mp *Peer) Send(e p2p.Envelope) bool { return true } +func (mp *Peer) FlushStop() { mp.Stop() } //nolint:errcheck //ignore error +func (*Peer) TrySend(_ p2p.Envelope) bool { return true } +func (*Peer) Send(_ p2p.Envelope) bool { return true } func (mp *Peer) NodeInfo() p2p.NodeInfo { return p2p.DefaultNodeInfo{ DefaultNodeID: mp.addr.ID, ListenAddr: mp.addr.DialString(), } } -func (mp *Peer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} } -func (mp *Peer) ID() p2p.ID { return mp.id } -func (mp *Peer) IsOutbound() bool { return mp.Outbound } -func (mp *Peer) IsPersistent() bool { return mp.Persistent } -func (mp *Peer) Get(key string) interface{} { +func (*Peer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} } +func (mp *Peer) ID() p2p.ID { return mp.id } +func (mp *Peer) IsOutbound() bool { return mp.Outbound } +func (mp *Peer) IsPersistent() bool { return mp.Persistent } +func (mp *Peer) Get(key string) any { if value, ok := mp.kv[key]; ok { return value } return nil } -func (mp *Peer) Set(key string, value interface{}) { + +func (mp *Peer) Set(key string, value any) { mp.kv[key] = value } func (mp *Peer) RemoteIP() net.IP { return mp.ip } func (mp *Peer) SocketAddr() *p2p.NetAddress { return mp.addr } func (mp *Peer) RemoteAddr() net.Addr { return &net.TCPAddr{IP: mp.ip, Port: 8800} } -func (mp *Peer) CloseConn() error { return nil } -func (mp *Peer) SetRemovalFailed() {} -func (mp *Peer) GetRemovalFailed() bool { return false } +func (*Peer) CloseConn() error { return nil } +func (*Peer) SetRemovalFailed() {} +func (*Peer) GetRemovalFailed() bool { return false } diff --git a/p2p/mock/reactor.go b/p2p/mock/reactor.go index adc0b2113ed..6419c4abb7c 100644 --- a/p2p/mock/reactor.go +++ b/p2p/mock/reactor.go @@ -19,7 +19,7 @@ func NewReactor() *Reactor { return r } -func (r *Reactor) GetChannels() []*conn.ChannelDescriptor { return r.Channels } -func (r *Reactor) AddPeer(peer p2p.Peer) {} -func (r *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) {} -func (r *Reactor) Receive(e p2p.Envelope) {} +func (r *Reactor) GetChannels() []*conn.ChannelDescriptor { return r.Channels } +func (*Reactor) AddPeer(_ p2p.Peer) {} +func (*Reactor) RemovePeer(_ p2p.Peer, _ any) {} +func (*Reactor) Receive(_ p2p.Envelope) {} diff --git a/p2p/mocks/peer.go b/p2p/mocks/peer.go index 235b0e976fb..bce2c24d03f 100644 --- a/p2p/mocks/peer.go +++ b/p2p/mocks/peer.go @@ -22,6 +22,10 @@ type Peer struct { func (_m *Peer) CloseConn() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for CloseConn") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -37,13 +41,17 @@ func (_m *Peer) FlushStop() { _m.Called() } -// Get provides a mock function with given fields: _a0 -func (_m *Peer) Get(_a0 string) interface{} { - ret := _m.Called(_a0) +// Get provides a mock function with given fields: key +func (_m *Peer) Get(key string) interface{} { + ret := _m.Called(key) + + if len(ret) == 0 { + panic("no return value specified for Get") + } var r0 interface{} if rf, ok := ret.Get(0).(func(string) interface{}); ok { - r0 = rf(_a0) + r0 = rf(key) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(interface{}) @@ -57,6 +65,10 @@ func (_m *Peer) Get(_a0 string) interface{} { func (_m *Peer) GetRemovalFailed() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetRemovalFailed") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -71,6 +83,10 @@ func (_m *Peer) GetRemovalFailed() bool { func (_m *Peer) ID() p2p.ID { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for ID") + } + var r0 p2p.ID if rf, ok := ret.Get(0).(func() p2p.ID); ok { r0 = rf() @@ -85,6 +101,10 @@ func (_m *Peer) ID() p2p.ID { func (_m *Peer) IsOutbound() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsOutbound") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -99,6 +119,10 @@ func (_m *Peer) IsOutbound() bool { func (_m *Peer) IsPersistent() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsPersistent") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -113,6 +137,10 @@ func (_m *Peer) IsPersistent() bool { func (_m *Peer) IsRunning() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsRunning") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() @@ -127,6 +155,10 @@ func (_m *Peer) IsRunning() bool { func (_m *Peer) NodeInfo() p2p.NodeInfo { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for NodeInfo") + } + var r0 p2p.NodeInfo if rf, ok := ret.Get(0).(func() p2p.NodeInfo); ok { r0 = rf() @@ -143,6 +175,10 @@ func (_m *Peer) NodeInfo() p2p.NodeInfo { func (_m *Peer) OnReset() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for OnReset") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -157,6 +193,10 @@ func (_m *Peer) OnReset() error { func (_m *Peer) OnStart() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for OnStart") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -176,6 +216,10 @@ func (_m *Peer) OnStop() { func (_m *Peer) Quit() <-chan struct{} { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Quit") + } + var r0 <-chan struct{} if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { r0 = rf() @@ -192,6 +236,10 @@ func (_m *Peer) Quit() <-chan struct{} { func (_m *Peer) RemoteAddr() net.Addr { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for RemoteAddr") + } + var r0 net.Addr if rf, ok := ret.Get(0).(func() net.Addr); ok { r0 = rf() @@ -208,6 +256,10 @@ func (_m *Peer) RemoteAddr() net.Addr { func (_m *Peer) RemoteIP() net.IP { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for RemoteIP") + } + var r0 net.IP if rf, ok := ret.Get(0).(func() net.IP); ok { r0 = rf() @@ -224,6 +276,10 @@ func (_m *Peer) RemoteIP() net.IP { func (_m *Peer) Reset() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Reset") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -234,13 +290,17 @@ func (_m *Peer) Reset() error { return r0 } -// Send provides a mock function with given fields: _a0 -func (_m *Peer) Send(_a0 p2p.Envelope) bool { - ret := _m.Called(_a0) +// Send provides a mock function with given fields: e +func (_m *Peer) Send(e p2p.Envelope) bool { + ret := _m.Called(e) + + if len(ret) == 0 { + panic("no return value specified for Send") + } var r0 bool if rf, ok := ret.Get(0).(func(p2p.Envelope) bool); ok { - r0 = rf(_a0) + r0 = rf(e) } else { r0 = ret.Get(0).(bool) } @@ -248,14 +308,14 @@ func (_m *Peer) Send(_a0 p2p.Envelope) bool { return r0 } -// Set provides a mock function with given fields: _a0, _a1 -func (_m *Peer) Set(_a0 string, _a1 interface{}) { - _m.Called(_a0, _a1) +// Set provides a mock function with given fields: key, value +func (_m *Peer) Set(key string, value interface{}) { + _m.Called(key, value) } -// SetLogger provides a mock function with given fields: _a0 -func (_m *Peer) SetLogger(_a0 log.Logger) { - _m.Called(_a0) +// SetLogger provides a mock function with given fields: l +func (_m *Peer) SetLogger(l log.Logger) { + _m.Called(l) } // SetRemovalFailed provides a mock function with given fields: @@ -267,6 +327,10 @@ func (_m *Peer) SetRemovalFailed() { func (_m *Peer) SocketAddr() *p2p.NetAddress { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for SocketAddr") + } + var r0 *p2p.NetAddress if rf, ok := ret.Get(0).(func() *p2p.NetAddress); ok { r0 = rf() @@ -283,6 +347,10 @@ func (_m *Peer) SocketAddr() *p2p.NetAddress { func (_m *Peer) Start() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Start") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -297,6 +365,10 @@ func (_m *Peer) Start() error { func (_m *Peer) Status() conn.ConnectionStatus { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Status") + } + var r0 conn.ConnectionStatus if rf, ok := ret.Get(0).(func() conn.ConnectionStatus); ok { r0 = rf() @@ -311,6 +383,10 @@ func (_m *Peer) Status() conn.ConnectionStatus { func (_m *Peer) Stop() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Stop") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -325,6 +401,10 @@ func (_m *Peer) Stop() error { func (_m *Peer) String() string { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for String") + } + var r0 string if rf, ok := ret.Get(0).(func() string); ok { r0 = rf() @@ -335,13 +415,17 @@ func (_m *Peer) String() string { return r0 } -// TrySend provides a mock function with given fields: _a0 -func (_m *Peer) TrySend(_a0 p2p.Envelope) bool { - ret := _m.Called(_a0) +// TrySend provides a mock function with given fields: e +func (_m *Peer) TrySend(e p2p.Envelope) bool { + ret := _m.Called(e) + + if len(ret) == 0 { + panic("no return value specified for TrySend") + } var r0 bool if rf, ok := ret.Get(0).(func(p2p.Envelope) bool); ok { - r0 = rf(_a0) + r0 = rf(e) } else { r0 = ret.Get(0).(bool) } @@ -349,13 +433,12 @@ func (_m *Peer) TrySend(_a0 p2p.Envelope) bool { return r0 } -type mockConstructorTestingTNewPeer interface { +// NewPeer creates a new instance of Peer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewPeer(t interface { mock.TestingT Cleanup(func()) -} - -// NewPeer creates a new instance of Peer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewPeer(t mockConstructorTestingTNewPeer) *Peer { +}) *Peer { mock := &Peer{} mock.Mock.Test(t) diff --git a/p2p/netaddress.go b/p2p/netaddress.go index fef9afd165d..56a79517c0d 100644 --- a/p2p/netaddress.go +++ b/p2p/netaddress.go @@ -6,7 +6,6 @@ package p2p import ( "encoding/hex" - "errors" "flag" "fmt" "net" @@ -14,10 +13,10 @@ import ( "strings" "time" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" ) -// EmptyNetAddress defines the string representation of an empty NetAddress +// EmptyNetAddress defines the string representation of an empty NetAddress. const EmptyNetAddress = "" // NetAddress defines information about a peer on the network @@ -45,11 +44,11 @@ func NewNetAddress(id ID, addr net.Addr) *NetAddress { if !ok { if flag.Lookup("test.v") == nil { // normal run panic(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr)) - } else { // in testing - netAddr := NewNetAddressIPPort(net.IP("127.0.0.1"), 0) - netAddr.ID = id - return netAddr } + // in testing + netAddr := NewNetAddressIPPort(net.IP("127.0.0.1"), 0) + netAddr.ID = id + return netAddr } if err := validateID(id); err != nil { @@ -66,12 +65,12 @@ func NewNetAddress(id ID, addr net.Addr) *NetAddress { // NewNetAddressString returns a new NetAddress using the provided address in // the form of "ID@IP:Port". // Also resolves the host if host is not an IP. -// Errors are of type ErrNetAddressXxx where Xxx is in (NoID, Invalid, Lookup) +// Errors are of type ErrNetAddressXxx where Xxx is in (NoID, Invalid, Lookup). func NewNetAddressString(addr string) (*NetAddress, error) { addrWithoutProtocol := removeProtocolIfDefined(addr) spl := strings.Split(addrWithoutProtocol, "@") if len(spl) != 2 { - return nil, ErrNetAddressNoID{addr} + return nil, ErrNetAddressInvalid{Addr: addr, Err: ErrNetAddressNoID{addr}} } // get ID @@ -89,7 +88,8 @@ func NewNetAddressString(addr string) (*NetAddress, error) { if len(host) == 0 { return nil, ErrNetAddressInvalid{ addrWithoutProtocol, - errors.New("host is empty")} + ErrEmptyHost, + } } ip := net.ParseIP(host) @@ -140,10 +140,11 @@ func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress { func NetAddressFromProto(pb tmp2p.NetAddress) (*NetAddress, error) { ip := net.ParseIP(pb.IP) if ip == nil { - return nil, fmt.Errorf("invalid IP address %v", pb.IP) + return nil, ErrNetAddressInvalid{Addr: pb.IP, Err: ErrInvalidIP} } + if pb.Port >= 1<<16 { - return nil, fmt.Errorf("invalid port number %v", pb.Port) + return nil, ErrNetAddressInvalid{Addr: pb.IP, Err: ErrInvalidPort{pb.Port}} } return &NetAddress{ ID: ID(pb.ID), @@ -187,7 +188,7 @@ func (na *NetAddress) ToProto() tmp2p.NetAddress { // Equals reports whether na and other are the same addresses, // including their ID, IP, and Port. -func (na *NetAddress) Equals(other interface{}) bool { +func (na *NetAddress) Equals(other any) bool { if o, ok := other.(*NetAddress); ok { return na.String() == o.String() } @@ -195,7 +196,7 @@ func (na *NetAddress) Equals(other interface{}) bool { } // Same returns true is na has the same non-empty ID or DialString as other. -func (na *NetAddress) Same(other interface{}) bool { +func (na *NetAddress) Same(other any) bool { if o, ok := other.(*NetAddress); ok { if na.DialString() == o.DialString() { return true @@ -207,7 +208,7 @@ func (na *NetAddress) Same(other interface{}) bool { return false } -// String representation: @: +// String representation: @:. func (na *NetAddress) String() string { if na == nil { return EmptyNetAddress @@ -263,14 +264,14 @@ func (na *NetAddress) Routable() bool { // address or one that matches the RFC3849 documentation address format. func (na *NetAddress) Valid() error { if err := validateID(na.ID); err != nil { - return fmt.Errorf("invalid ID: %w", err) + return ErrInvalidPeerID{na.ID, err} } if na.IP == nil { - return errors.New("no IP") + return ErrNoIP } if na.IP.IsUnspecified() || na.RFC3849() || na.IP.Equal(net.IPv4bcast) { - return errors.New("invalid IP") + return ErrNetAddressInvalid{na.IP.String(), ErrInvalidIP} } return nil } @@ -289,7 +290,7 @@ func (na *NetAddress) Local() bool { // ReachabilityTo checks whenever o can be reached from na. func (na *NetAddress) ReachabilityTo(o *NetAddress) int { const ( - Unreachable = 0 + unreachable = 0 Default = iota Teredo Ipv6Weak @@ -298,7 +299,7 @@ func (na *NetAddress) ReachabilityTo(o *NetAddress) int { ) switch { case !na.Routable(): - return Unreachable + return unreachable case na.RFC4380(): switch { case !o.Routable(): @@ -345,32 +346,33 @@ func (na *NetAddress) ReachabilityTo(o *NetAddress) int { // RFC4843: IPv6 ORCHID: (2001:10::/28) // RFC4862: IPv6 Autoconfig (FE80::/64) // RFC6052: IPv6 well known prefix (64:FF9B::/96) -// RFC6145: IPv6 IPv4 translated address ::FFFF:0:0:0/96 -var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)} -var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)} -var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)} -var rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)} -var rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)} -var rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)} -var rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)} -var rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)} -var rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)} -var rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)} -var rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)} -var rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)} -var zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)} +// RFC6145: IPv6 IPv4 translated address ::FFFF:0:0:0/96. var ( + rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)} + rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)} + rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)} + rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)} + rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)} + rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)} + rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)} + rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)} + rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)} + rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)} + rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)} + rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)} + zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)} + // onionCatNet defines the IPv6 address block used to support Tor. // bitcoind encodes a .onion address as a 16 byte number by decoding the // address prior to the .onion (i.e. the key hash) base32 into a ten // byte number. It then stores the first 6 bytes of the address as // 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43. // - // This is the same range used by OnionCat, which is part part of the + // This is the same range used by OnionCat, which is part of the // RFC4193 unique local IPv6 range. // // In summary the format is: - // { magic 6 bytes, 10 bytes base32 decode of key hash } + // { magic 6 bytes, 10 bytes base32 decode of key hash }. onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128) ) @@ -402,19 +404,18 @@ func removeProtocolIfDefined(addr string) string { return strings.Split(addr, "://")[1] } return addr - } func validateID(id ID) error { if len(id) == 0 { - return errors.New("no ID") + return ErrNoIP } idBytes, err := hex.DecodeString(string(id)) if err != nil { return err } if len(idBytes) != IDByteLength { - return fmt.Errorf("invalid hex length - got %d, expected %d", len(idBytes), IDByteLength) + return ErrInvalidPeerIDLength{Got: len(idBytes), Expected: IDByteLength} } return nil } diff --git a/p2p/netaddress_test.go b/p2p/netaddress_test.go index 65f9fb834ef..85ee7c8a160 100644 --- a/p2p/netaddress_test.go +++ b/p2p/netaddress_test.go @@ -11,7 +11,7 @@ import ( func TestNetAddress_String(t *testing.T) { tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8080") - require.Nil(t, err) + require.NoError(t, err) netAddr := NewNetAddress("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef", tcpAddr) @@ -33,7 +33,7 @@ func TestNetAddress_String(t *testing.T) { func TestNewNetAddress(t *testing.T) { tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8080") - require.Nil(t, err) + require.NoError(t, err) assert.Panics(t, func() { NewNetAddress("", tcpAddr) @@ -114,11 +114,11 @@ func TestNewNetAddressString(t *testing.T) { t.Run(tc.name, func(t *testing.T) { addr, err := NewNetAddressString(tc.addr) if tc.correct { - if assert.Nil(t, err, tc.addr) { + if assert.NoError(t, err, tc.addr) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, tc.expected, addr.String()) } } else { - assert.NotNil(t, err, tc.addr) + require.ErrorAs(t, err, &ErrNetAddressInvalid{Addr: addr.String(), Err: err}) } }) } @@ -128,9 +128,10 @@ func TestNewNetAddressStrings(t *testing.T) { addrs, errs := NewNetAddressStrings([]string{ "127.0.0.1:8080", "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", - "deadbeefdeadbeefdeadbeefdeadbeefdeadbeed@127.0.0.2:8080"}) + "deadbeefdeadbeefdeadbeefdeadbeefdeadbeed@127.0.0.2:8080", + }) + assert.Len(t, addrs, 2) assert.Len(t, errs, 1) - assert.Equal(t, 2, len(addrs)) } func TestNewNetAddressIPPort(t *testing.T) { @@ -152,13 +153,13 @@ func TestNetAddressProperties(t *testing.T) { for _, tc := range testCases { addr, err := NewNetAddressString(tc.addr) - require.Nil(t, err) + require.NoError(t, err) err = addr.Valid() if tc.valid { - assert.NoError(t, err) + require.NoError(t, err) } else { - assert.Error(t, err) + require.Error(t, err) } assert.Equal(t, tc.local, addr.Local()) assert.Equal(t, tc.routable, addr.Routable()) @@ -182,10 +183,10 @@ func TestNetAddressReachabilityTo(t *testing.T) { for _, tc := range testCases { addr, err := NewNetAddressString(tc.addr) - require.Nil(t, err) + require.NoError(t, err) other, err := NewNetAddressString(tc.other) - require.Nil(t, err) + require.NoError(t, err) assert.Equal(t, tc.reachability, addr.ReachabilityTo(other)) } diff --git a/p2p/node_info.go b/p2p/node_info.go index 59cf885cb1f..81c3d55bb2b 100644 --- a/p2p/node_info.go +++ b/p2p/node_info.go @@ -2,13 +2,12 @@ package p2p import ( "bytes" - "errors" "fmt" "reflect" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" + cmtstrings "github.com/cometbft/cometbft/internal/strings" cmtbytes "github.com/cometbft/cometbft/libs/bytes" - cmtstrings "github.com/cometbft/cometbft/libs/strings" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" "github.com/cometbft/cometbft/version" ) @@ -17,12 +16,12 @@ const ( maxNumChannels = 16 // plenty of room for upgrades, for now ) -// Max size of the NodeInfo struct +// Max size of the NodeInfo struct. func MaxNodeInfoSize() int { return maxNodeInfoSize } -//------------------------------------------------------------- +// ------------------------------------------------------------- // NodeInfo exposes basic info of a node // and determines if we're compatible. @@ -43,7 +42,7 @@ type nodeInfoTransport interface { CompatibleWith(other NodeInfo) error } -//------------------------------------------------------------- +// ------------------------------------------------------------- // ProtocolVersion contains the protocol versions for the software. type ProtocolVersion struct { @@ -69,9 +68,9 @@ func NewProtocolVersion(p2p, block, app uint64) ProtocolVersion { } } -//------------------------------------------------------------- +// ------------------------------------------------------------- -// Assert DefaultNodeInfo satisfies NodeInfo +// Assert DefaultNodeInfo satisfies NodeInfo. var _ NodeInfo = DefaultNodeInfo{} // DefaultNodeInfo is the basic node information exchanged @@ -95,7 +94,7 @@ type DefaultNodeInfo struct { Other DefaultNodeInfoOther `json:"other"` // other application specific data } -// DefaultNodeInfoOther is the misc. applcation specific data +// DefaultNodeInfoOther is the misc. application specific data. type DefaultNodeInfoOther struct { TxIndex string `json:"tx_index"` RPCAddress string `json:"rpc_address"` @@ -120,7 +119,6 @@ func (info DefaultNodeInfo) ID() ID { // url-encoding), and we just need to be careful with how we handle that in our // clients. (e.g. off by default). func (info DefaultNodeInfo) Validate() error { - // ID is already validated. // Validate ListenAddr. @@ -134,26 +132,26 @@ func (info DefaultNodeInfo) Validate() error { // Validate Version if len(info.Version) > 0 && (!cmtstrings.IsASCIIText(info.Version) || cmtstrings.ASCIITrim(info.Version) == "") { - - return fmt.Errorf("info.Version must be valid ASCII text without tabs, but got %v", info.Version) + return ErrInvalidNodeVersion{Version: info.Version} } // Validate Channels - ensure max and check for duplicates. if len(info.Channels) > maxNumChannels { - return fmt.Errorf("info.Channels is too long (%v). Max is %v", len(info.Channels), maxNumChannels) + return ErrChannelsTooLong{Length: len(info.Channels), Max: maxNumChannels} } + channels := make(map[byte]struct{}) for _, ch := range info.Channels { _, ok := channels[ch] if ok { - return fmt.Errorf("info.Channels contains duplicate channel id %v", ch) + return ErrDuplicateChannelID{ID: ch} } channels[ch] = struct{}{} } // Validate Moniker. if !cmtstrings.IsASCIIText(info.Moniker) || cmtstrings.ASCIITrim(info.Moniker) == "" { - return fmt.Errorf("info.Moniker must be valid non-empty ASCII text without tabs, but got %v", info.Moniker) + return ErrInvalidMoniker{Moniker: info.Moniker} } // Validate Other. @@ -162,34 +160,42 @@ func (info DefaultNodeInfo) Validate() error { switch txIndex { case "", "on", "off": default: - return fmt.Errorf("info.Other.TxIndex should be either 'on', 'off', or empty string, got '%v'", txIndex) + return ErrInvalidTxIndex{TxIndex: txIndex} } // XXX: Should we be more strict about address formats? rpcAddr := other.RPCAddress if len(rpcAddr) > 0 && (!cmtstrings.IsASCIIText(rpcAddr) || cmtstrings.ASCIITrim(rpcAddr) == "") { - return fmt.Errorf("info.Other.RPCAddress=%v must be valid ASCII text without tabs", rpcAddr) + return ErrInvalidRPCAddress{RPCAddress: rpcAddr} } return nil } -// CompatibleWith checks if two DefaultNodeInfo are compatible with eachother. +// CompatibleWith checks if two DefaultNodeInfo are compatible with each other. // CONTRACT: two nodes are compatible if the Block version and network match // and they have at least one channel in common. func (info DefaultNodeInfo) CompatibleWith(otherInfo NodeInfo) error { other, ok := otherInfo.(DefaultNodeInfo) if !ok { - return fmt.Errorf("wrong NodeInfo type. Expected DefaultNodeInfo, got %v", reflect.TypeOf(otherInfo)) + return ErrInvalidNodeInfoType{ + Type: reflect.TypeOf(otherInfo).String(), + Expected: fmt.Sprintf("%T", DefaultNodeInfo{}), + } } if info.ProtocolVersion.Block != other.ProtocolVersion.Block { - return fmt.Errorf("peer is on a different Block version. Got %v, expected %v", - other.ProtocolVersion.Block, info.ProtocolVersion.Block) + return ErrDifferentBlockVersion{ + Other: other.ProtocolVersion.Block, + Our: info.ProtocolVersion.Block, + } } // nodes must be on the same network if info.Network != other.Network { - return fmt.Errorf("peer is on a different network. Got %v, expected %v", other.Network, info.Network) + return ErrDifferentNetwork{ + Other: other.Network, + Our: info.Network, + } } // if we have no channels, we're just testing @@ -209,7 +215,10 @@ OUTER_LOOP: } } if !found { - return fmt.Errorf("peer has no common channels. Our channels: %v ; Peer channels: %v", info.Channels, other.Channels) + return ErrNoCommonChannels{ + OtherChannels: other.Channels, + OurChannels: info.Channels, + } } return nil } @@ -228,7 +237,6 @@ func (info DefaultNodeInfo) HasChannel(chID byte) bool { } func (info DefaultNodeInfo) ToProto() *tmp2p.DefaultNodeInfo { - dni := new(tmp2p.DefaultNodeInfo) dni.ProtocolVersion = tmp2p.ProtocolVersion{ P2P: info.ProtocolVersion.P2P, @@ -252,8 +260,9 @@ func (info DefaultNodeInfo) ToProto() *tmp2p.DefaultNodeInfo { func DefaultNodeInfoFromToProto(pb *tmp2p.DefaultNodeInfo) (DefaultNodeInfo, error) { if pb == nil { - return DefaultNodeInfo{}, errors.New("nil node info") + return DefaultNodeInfo{}, ErrNoNodeInfo } + dni := DefaultNodeInfo{ ProtocolVersion: ProtocolVersion{ P2P: pb.ProtocolVersion.P2P, diff --git a/p2p/node_info_test.go b/p2p/node_info_test.go index f1c43e35217..bb8b87dae36 100644 --- a/p2p/node_info_test.go +++ b/p2p/node_info_test.go @@ -4,15 +4,15 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/crypto/ed25519" ) func TestNodeInfoValidate(t *testing.T) { - // empty fails ni := DefaultNodeInfo{} - assert.Error(t, ni.Validate()) + require.Error(t, ni.Validate()) channels := make([]byte, maxNumChannels) for i := 0; i < maxNumChannels; i++ { @@ -20,7 +20,7 @@ func TestNodeInfoValidate(t *testing.T) { } dupChannels := make([]byte, 5) copy(dupChannels, channels[:5]) - dupChannels = append(dupChannels, testCh) + dupChannels = append(dupChannels, testCh) //nolint:makezero // huge errors when we don't do it the "wrong" way nonASCII := "¢§µ" emptyTab := "\t" @@ -33,7 +33,7 @@ func TestNodeInfoValidate(t *testing.T) { }{ { "Too Many Channels", - func(ni *DefaultNodeInfo) { ni.Channels = append(channels, byte(maxNumChannels)) }, //nolint: gocritic + func(ni *DefaultNodeInfo) { ni.Channels = append(channels, byte(maxNumChannels)) }, //nolint: makezero true, }, {"Duplicate Channel", func(ni *DefaultNodeInfo) { ni.Channels = dupChannels }, true}, @@ -72,7 +72,7 @@ func TestNodeInfoValidate(t *testing.T) { // test case passes ni = testNodeInfo(nodeKey.ID(), name).(DefaultNodeInfo) ni.Channels = channels - assert.NoError(t, ni.Validate()) + require.NoError(t, ni.Validate()) for _, tc := range testCases { ni := testNodeInfo(nodeKey.ID(), name).(DefaultNodeInfo) @@ -80,16 +80,14 @@ func TestNodeInfoValidate(t *testing.T) { tc.malleateNodeInfo(&ni) err := ni.Validate() if tc.expectErr { - assert.Error(t, err, tc.testName) + require.Error(t, err, tc.testName) } else { - assert.NoError(t, err, tc.testName) + require.NoError(t, err, tc.testName) } } - } func TestNodeInfoCompatible(t *testing.T) { - nodeKey1 := NodeKey{PrivKey: ed25519.GenPrivKey()} nodeKey2 := NodeKey{PrivKey: ed25519.GenPrivKey()} name := "testing" @@ -99,17 +97,17 @@ func TestNodeInfoCompatible(t *testing.T) { // test NodeInfo is compatible ni1 := testNodeInfo(nodeKey1.ID(), name).(DefaultNodeInfo) ni2 := testNodeInfo(nodeKey2.ID(), name).(DefaultNodeInfo) - assert.NoError(t, ni1.CompatibleWith(ni2)) + require.NoError(t, ni1.CompatibleWith(ni2)) // add another channel; still compatible ni2.Channels = append(ni2.Channels, newTestChannel) assert.True(t, ni2.HasChannel(newTestChannel)) - assert.NoError(t, ni1.CompatibleWith(ni2)) + require.NoError(t, ni1.CompatibleWith(ni2)) // wrong NodeInfo type is not compatible _, netAddr := CreateRoutableAddr() ni3 := mockNodeInfo{netAddr} - assert.Error(t, ni1.CompatibleWith(ni3)) + require.Error(t, ni1.CompatibleWith(ni3)) testCases := []struct { testName string @@ -123,6 +121,6 @@ func TestNodeInfoCompatible(t *testing.T) { for _, tc := range testCases { ni := testNodeInfo(nodeKey2.ID(), name).(DefaultNodeInfo) tc.malleateNodeInfo(&ni) - assert.Error(t, ni1.CompatibleWith(ni)) + require.Error(t, ni1.CompatibleWith(ni)) } } diff --git a/p2p/peer.go b/p2p/peer.go index dc88152df6d..1538df9ea2c 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -8,11 +8,11 @@ import ( "github.com/cosmos/gogoproto/proto" - "github.com/cometbft/cometbft/libs/cmap" + "github.com/cometbft/cometbft/internal/cmap" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" - cmtconn "github.com/cometbft/cometbft/p2p/conn" + "github.com/cometbft/cometbft/types" ) //go:generate ../scripts/mockery_generate.sh Peer @@ -37,23 +37,23 @@ type Peer interface { Status() cmtconn.ConnectionStatus SocketAddr() *NetAddress // actual address of the socket - Send(Envelope) bool - TrySend(Envelope) bool + Send(e Envelope) bool + TrySend(e Envelope) bool - Set(string, interface{}) - Get(string) interface{} + Set(key string, value any) + Get(key string) any SetRemovalFailed() GetRemovalFailed() bool } -//---------------------------------------------------------- +// ---------------------------------------------------------- // peerConn contains the raw connection and its config. type peerConn struct { outbound bool persistent bool - conn net.Conn // source connection + conn net.Conn // Source connection socketAddr *NetAddress @@ -66,7 +66,6 @@ func newPeerConn( conn net.Conn, socketAddr *NetAddress, ) peerConn { - return peerConn{ outbound: outbound, persistent: persistent, @@ -81,7 +80,7 @@ func (pc peerConn) ID() ID { return PubKeyToID(pc.conn.(*cmtconn.SecretConnection).RemotePubKey()) } -// Return the IP from the connection RemoteAddr +// Return the IP from the connection RemoteAddr. func (pc peerConn) RemoteIP() net.IP { if pc.ip != nil { return pc.ip @@ -121,9 +120,8 @@ type peer struct { // User data Data *cmap.CMap - metrics *Metrics - metricsTicker *time.Ticker - mlc *metricsLabelCache + metrics *Metrics + mlc *metricsLabelCache // When removal of a peer fails, we set this flag removalAttemptFailed bool @@ -138,18 +136,17 @@ func newPeer( reactorsByCh map[byte]Reactor, msgTypeByChID map[byte]proto.Message, chDescs []*cmtconn.ChannelDescriptor, - onPeerError func(Peer, interface{}), + onPeerError func(Peer, any), mlc *metricsLabelCache, options ...PeerOption, ) *peer { p := &peer{ - peerConn: pc, - nodeInfo: nodeInfo, - channels: nodeInfo.(DefaultNodeInfo).Channels, - Data: cmap.NewCMap(), - metricsTicker: time.NewTicker(metricsTickerDuration), - metrics: NopMetrics(), - mlc: mlc, + peerConn: pc, + nodeInfo: nodeInfo, + channels: nodeInfo.(DefaultNodeInfo).Channels, + Data: cmap.NewCMap(), + metrics: NopMetrics(), + mlc: mlc, } p.mconn = createMConnection( @@ -178,7 +175,7 @@ func (p *peer) String() string { return fmt.Sprintf("Peer{%v %v in}", p.mconn, p.ID()) } -//--------------------------------------------------- +// --------------------------------------------------- // Implements service.Service // SetLogger implements BaseService. @@ -203,23 +200,20 @@ func (p *peer) OnStart() error { // FlushStop mimics OnStop but additionally ensures that all successful // .Send() calls will get flushed before closing the connection. +// // NOTE: it is not safe to call this method more than once. func (p *peer) FlushStop() { - p.metricsTicker.Stop() - p.BaseService.OnStop() p.mconn.FlushStop() // stop everything and close the conn } // OnStop implements BaseService. func (p *peer) OnStop() { - p.metricsTicker.Stop() - p.BaseService.OnStop() if err := p.mconn.Stop(); err != nil { // stop everything and close the conn p.Logger.Debug("Error while stopping peer", "err", err) } } -//--------------------------------------------------- +// --------------------------------------------------- // Implements Peer // ID returns the peer's ID - the hex encoded hash of its pubkey. @@ -232,7 +226,7 @@ func (p *peer) IsOutbound() bool { return p.peerConn.outbound } -// IsPersistent returns true if the peer is persitent, false otherwise. +// IsPersistent returns true if the peer is persistent, false otherwise. func (p *peer) IsPersistent() bool { return p.peerConn.persistent } @@ -257,12 +251,16 @@ func (p *peer) Status() cmtconn.ConnectionStatus { // Send msg bytes to the channel identified by chID byte. Returns false if the // send queue is full after timeout, specified by MConnection. +// +// thread safe. func (p *peer) Send(e Envelope) bool { return p.send(e.ChannelID, e.Message, p.mconn.Send) } // TrySend msg bytes to the channel identified by chID byte. Immediately returns // false if the send queue is full. +// +// thread safe. func (p *peer) TrySend(e Envelope) bool { return p.send(e.ChannelID, e.Message, p.mconn.TrySend) } @@ -274,7 +272,7 @@ func (p *peer) send(chID byte, msg proto.Message, sendFunc func(byte, []byte) bo return false } metricLabelValue := p.mlc.ValueToMetricLabel(msg) - if w, ok := msg.(Wrapper); ok { + if w, ok := msg.(types.Wrapper); ok { msg = w.Wrap() } msgBytes, err := proto.Marshal(msg) @@ -295,12 +293,16 @@ func (p *peer) send(chID byte, msg proto.Message, sendFunc func(byte, []byte) bo } // Get the data for a given key. -func (p *peer) Get(key string) interface{} { +// +// thread safe. +func (p *peer) Get(key string) any { return p.Data.Get(key) } // Set sets the data for the given key. -func (p *peer) Set(key string, data interface{}) { +// +// thread safe. +func (p *peer) Set(key string, data any) { p.Data.Set(key, data) } @@ -337,11 +339,11 @@ func (p *peer) GetRemovalFailed() bool { return p.removalAttemptFailed } -//--------------------------------------------------- +// --------------------------------------------------- // methods only used for testing // TODO: can we remove these? -// CloseConn closes the underlying connection +// CloseConn closes the underlying connection. func (pc *peerConn) CloseConn() { pc.conn.Close() } @@ -359,7 +361,7 @@ func (p *peer) CanSend(chID byte) bool { return p.mconn.CanSend(chID) } -//--------------------------------------------------- +// --------------------------------------------------- func PeerMetrics(metrics *Metrics) PeerOption { return func(p *peer) { @@ -368,9 +370,12 @@ func PeerMetrics(metrics *Metrics) PeerOption { } func (p *peer) metricsReporter() { + metricsTicker := time.NewTicker(metricsTickerDuration) + defer metricsTicker.Stop() + for { select { - case <-p.metricsTicker.C: + case <-metricsTicker.C: status := p.mconn.Status() var sendQueueSize float64 for _, chStatus := range status.Channels { @@ -384,7 +389,7 @@ func (p *peer) metricsReporter() { } } -//------------------------------------------------------------------ +// ------------------------------------------------------------------ // helper funcs func createMConnection( @@ -393,10 +398,9 @@ func createMConnection( reactorsByCh map[byte]Reactor, msgTypeByChID map[byte]proto.Message, chDescs []*cmtconn.ChannelDescriptor, - onPeerError func(Peer, interface{}), + onPeerError func(Peer, any), config cmtconn.MConnConfig, ) *cmtconn.MConnection { - onReceive := func(chID byte, msgBytes []byte) { reactor := reactorsByCh[chID] if reactor == nil { @@ -408,16 +412,16 @@ func createMConnection( msg := proto.Clone(mt) err := proto.Unmarshal(msgBytes, msg) if err != nil { - panic(fmt.Errorf("unmarshaling message: %s into type: %s", err, reflect.TypeOf(mt))) + panic(fmt.Sprintf("unmarshaling message: %v into type: %s", err, reflect.TypeOf(mt))) } labels := []string{ "peer_id", string(p.ID()), "chID", fmt.Sprintf("%#x", chID), } - if w, ok := msg.(Unwrapper); ok { + if w, ok := msg.(types.Unwrapper); ok { msg, err = w.Unwrap() if err != nil { - panic(fmt.Errorf("unwrapping message: %s", err)) + panic(fmt.Sprintf("unwrapping message: %v", err)) } } p.metrics.PeerReceiveBytesTotal.With(labels...).Add(float64(len(msgBytes))) @@ -429,7 +433,7 @@ func createMConnection( }) } - onError := func(r interface{}) { + onError := func(r any) { onPeerError(p, r) } diff --git a/p2p/peer_set.go b/p2p/peer_set.go index 0a7727e6f1d..636e25475ad 100644 --- a/p2p/peer_set.go +++ b/p2p/peer_set.go @@ -3,22 +3,31 @@ package p2p import ( "net" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtrand "github.com/cometbft/cometbft/internal/rand" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) // IPeerSet has a (immutable) subset of the methods of PeerSet. type IPeerSet interface { + // Has returns true if the set contains the peer referred to by this key. Has(key ID) bool + // HasIP returns true if the set contains the peer referred to by this IP HasIP(ip net.IP) bool + // Get returns the peer with the given key, or nil if not found. Get(key ID) Peer - List() []Peer + // Copy returns a copy of the peers list. + Copy() []Peer + // Size returns the number of peers in the PeerSet. Size() int + // ForEach iterates over the PeerSet and calls the given function for each peer. + ForEach(peer func(Peer)) + // Random returns a random peer from the PeerSet. + Random() Peer } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- -// PeerSet is a special structure for keeping a table of peers. -// Iteration over the peers is super fast and thread-safe. +// PeerSet is a special thread-safe structure for keeping a table of peers. type PeerSet struct { mtx cmtsync.Mutex lookup map[ID]*peerSetItem @@ -74,14 +83,8 @@ func (ps *PeerSet) HasIP(peerIP net.IP) bool { ps.mtx.Lock() defer ps.mtx.Unlock() - return ps.hasIP(peerIP) -} - -// hasIP does not acquire a lock so it can be used in public methods which -// already lock. -func (ps *PeerSet) hasIP(peerIP net.IP) bool { - for _, item := range ps.lookup { - if item.peer.RemoteIP().Equal(peerIP) { + for _, peer := range ps.list { + if peer.RemoteIP().Equal(peerIP) { return true } } @@ -94,6 +97,7 @@ func (ps *PeerSet) hasIP(peerIP net.IP) bool { func (ps *PeerSet) Get(peerKey ID) Peer { ps.mtx.Lock() defer ps.mtx.Unlock() + item, ok := ps.lookup[peerKey] if ok { return item.peer @@ -101,15 +105,13 @@ func (ps *PeerSet) Get(peerKey ID) Peer { return nil } -// Remove discards peer by its Key, if the peer was previously memoized. -// Returns true if the peer was removed, and false if it was not found. -// in the set. +// Remove removes the peer from the PeerSet. func (ps *PeerSet) Remove(peer Peer) bool { ps.mtx.Lock() defer ps.mtx.Unlock() - item := ps.lookup[peer.ID()] - if item == nil { + item, ok := ps.lookup[peer.ID()] + if !ok || len(ps.list) == 0 { // Removing the peer has failed so we set a flag to mark that a removal was attempted. // This can happen when the peer add routine from the switch is running in // parallel to the receive routine of MConn. @@ -118,27 +120,24 @@ func (ps *PeerSet) Remove(peer Peer) bool { peer.SetRemovalFailed() return false } - index := item.index - // Create a new copy of the list but with one less item. - // (we must copy because we'll be mutating the list). - newList := make([]Peer, len(ps.list)-1) - copy(newList, ps.list) - // If it's the last peer, that's an easy special case. - if index == len(ps.list)-1 { - ps.list = newList - delete(ps.lookup, peer.ID()) - return true - } - // Replace the popped item with the last item in the old list. - lastPeer := ps.list[len(ps.list)-1] - lastPeerKey := lastPeer.ID() - lastPeerItem := ps.lookup[lastPeerKey] - newList[index] = lastPeer - lastPeerItem.index = index - ps.list = newList + // Remove from ps.lookup. delete(ps.lookup, peer.ID()) + + // If it's not the last item. + if index != len(ps.list)-1 { + // Swap it with the last item. + lastPeer := ps.list[len(ps.list)-1] + item := ps.lookup[lastPeer.ID()] + item.index = index + ps.list[index] = item.peer + } + + // Remove the last item from ps.list. + ps.list[len(ps.list)-1] = nil // nil the last entry of the slice to shorten, so it isn't reachable & can be GC'd. + ps.list = ps.list[:len(ps.list)-1] + return true } @@ -149,9 +148,36 @@ func (ps *PeerSet) Size() int { return len(ps.list) } -// List returns the threadsafe list of peers. -func (ps *PeerSet) List() []Peer { +// Copy returns the copy of the peers list. +// +// Note: there are no guarantees about the thread-safety of Peer objects. +func (ps *PeerSet) Copy() []Peer { ps.mtx.Lock() defer ps.mtx.Unlock() - return ps.list + + c := make([]Peer, len(ps.list)) + copy(c, ps.list) + return c +} + +// ForEach iterates over the PeerSet and calls the given function for each peer. +func (ps *PeerSet) ForEach(fn func(peer Peer)) { + ps.mtx.Lock() + defer ps.mtx.Unlock() + + for _, item := range ps.lookup { + fn(item.peer) + } +} + +// Random returns a random peer from the PeerSet. +func (ps *PeerSet) Random() Peer { + ps.mtx.Lock() + defer ps.mtx.Unlock() + + if len(ps.list) == 0 { + return nil + } + + return ps.list[cmtrand.Int()%len(ps.list)] } diff --git a/p2p/peer_set_test.go b/p2p/peer_set_test.go index 9d08e437c74..007167f8046 100644 --- a/p2p/peer_set_test.go +++ b/p2p/peer_set_test.go @@ -8,34 +8,34 @@ import ( "github.com/stretchr/testify/assert" "github.com/cometbft/cometbft/crypto/ed25519" - "github.com/cometbft/cometbft/libs/service" + "github.com/cometbft/cometbft/internal/service" ) -// mockPeer for testing the PeerSet +// mockPeer for testing the PeerSet. type mockPeer struct { service.BaseService ip net.IP id ID } -func (mp *mockPeer) FlushStop() { mp.Stop() } //nolint:errcheck // ignore error -func (mp *mockPeer) TrySend(e Envelope) bool { return true } -func (mp *mockPeer) Send(e Envelope) bool { return true } -func (mp *mockPeer) NodeInfo() NodeInfo { return DefaultNodeInfo{} } -func (mp *mockPeer) Status() ConnectionStatus { return ConnectionStatus{} } -func (mp *mockPeer) ID() ID { return mp.id } -func (mp *mockPeer) IsOutbound() bool { return false } -func (mp *mockPeer) IsPersistent() bool { return true } -func (mp *mockPeer) Get(s string) interface{} { return s } -func (mp *mockPeer) Set(string, interface{}) {} -func (mp *mockPeer) RemoteIP() net.IP { return mp.ip } -func (mp *mockPeer) SocketAddr() *NetAddress { return nil } -func (mp *mockPeer) RemoteAddr() net.Addr { return &net.TCPAddr{IP: mp.ip, Port: 8800} } -func (mp *mockPeer) CloseConn() error { return nil } -func (mp *mockPeer) SetRemovalFailed() {} -func (mp *mockPeer) GetRemovalFailed() bool { return false } - -// Returns a mock peer +func (mp *mockPeer) FlushStop() { mp.Stop() } //nolint:errcheck // ignore error +func (*mockPeer) TrySend(Envelope) bool { return true } +func (*mockPeer) Send(Envelope) bool { return true } +func (*mockPeer) NodeInfo() NodeInfo { return DefaultNodeInfo{} } +func (*mockPeer) Status() ConnectionStatus { return ConnectionStatus{} } +func (mp *mockPeer) ID() ID { return mp.id } +func (*mockPeer) IsOutbound() bool { return false } +func (*mockPeer) IsPersistent() bool { return true } +func (*mockPeer) Get(s string) any { return s } +func (*mockPeer) Set(string, any) {} +func (mp *mockPeer) RemoteIP() net.IP { return mp.ip } +func (*mockPeer) SocketAddr() *NetAddress { return nil } +func (mp *mockPeer) RemoteAddr() net.Addr { return &net.TCPAddr{IP: mp.ip, Port: 8800} } +func (*mockPeer) CloseConn() error { return nil } +func (*mockPeer) SetRemovalFailed() {} +func (*mockPeer) GetRemovalFailed() bool { return false } + +// Returns a mock peer. func newMockPeer(ip net.IP) *mockPeer { if ip == nil { ip = net.IP{127, 0, 0, 1} @@ -48,8 +48,6 @@ func newMockPeer(ip net.IP) *mockPeer { } func TestPeerSetAddRemoveOne(t *testing.T) { - t.Parallel() - peerSet := NewPeerSet() var peerList []Peer @@ -68,7 +66,7 @@ func TestPeerSetAddRemoveOne(t *testing.T) { assert.True(t, removed) wantSize := n - i - 1 for j := 0; j < 2; j++ { - assert.Equal(t, false, peerSet.Has(peerAtFront.ID()), "#%d Run #%d: failed to remove peer", i, j) + assert.False(t, false, peerSet.Has(peerAtFront.ID()), "#%d Run #%d: failed to remove peer", i, j) assert.Equal(t, wantSize, peerSet.Size(), "#%d Run #%d: failed to remove peer and decrement size", i, j) // Test the route of removing the now non-existent element removed := peerSet.Remove(peerAtFront) @@ -89,18 +87,17 @@ func TestPeerSetAddRemoveOne(t *testing.T) { peerAtEnd := peerList[i] removed := peerSet.Remove(peerAtEnd) assert.True(t, removed) - assert.Equal(t, false, peerSet.Has(peerAtEnd.ID()), "#%d: failed to remove item at end", i) + assert.False(t, false, peerSet.Has(peerAtEnd.ID()), "#%d: failed to remove item at end", i) assert.Equal(t, i, peerSet.Size(), "#%d: differing sizes after peerSet.Remove(atEndPeer)", i) } } func TestPeerSetAddRemoveMany(t *testing.T) { - t.Parallel() peerSet := NewPeerSet() peers := []Peer{} - N := 100 - for i := 0; i < N; i++ { + n := 100 + for i := 0; i < n; i++ { peer := newMockPeer(net.IP{127, 0, 0, byte(i)}) if err := peerSet.Add(peer); err != nil { t.Errorf("failed to add new peer") @@ -124,7 +121,6 @@ func TestPeerSetAddRemoveMany(t *testing.T) { } func TestPeerSetAddDuplicate(t *testing.T) { - t.Parallel() peerSet := NewPeerSet() peer := newMockPeer(nil) @@ -164,8 +160,6 @@ func TestPeerSetAddDuplicate(t *testing.T) { } func TestPeerSetGet(t *testing.T) { - t.Parallel() - var ( peerSet = NewPeerSet() peer = newMockPeer(nil) @@ -185,7 +179,7 @@ func TestPeerSetGet(t *testing.T) { go func(i int) { defer wg.Done() have, want := peerSet.Get(peer.ID()), peer - assert.Equal(t, have, want, "%d: have %v, want %v", i, have, want) + assert.Equal(t, want, have, "%d: have %v, want %v", i, want, have) }(i) } wg.Wait() diff --git a/p2p/peer_test.go b/p2p/peer_test.go index ce45b7fe3da..7b97042c79e 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -1,6 +1,7 @@ package p2p import ( + "errors" "fmt" golog "log" "net" @@ -11,13 +12,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + p2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" + "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/libs/bytes" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/proto/tendermint/p2p" - - "github.com/cometbft/cometbft/config" cmtconn "github.com/cometbft/cometbft/p2p/conn" ) @@ -30,10 +30,10 @@ func TestPeerBasic(t *testing.T) { t.Cleanup(rp.Stop) p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), cfg, cmtconn.DefaultMConnConfig()) - require.Nil(err) + require.NoError(err) err = p.Start() - require.Nil(err) + require.NoError(err) t.Cleanup(func() { if err := p.Stop(); err != nil { t.Error(err) @@ -60,10 +60,10 @@ func TestPeerSend(t *testing.T) { t.Cleanup(rp.Stop) p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), config, cmtconn.DefaultMConnConfig()) - require.Nil(err) + require.NoError(err) err = p.Start() - require.Nil(err) + require.NoError(err) t.Cleanup(func() { if err := p.Stop(); err != nil { @@ -99,14 +99,14 @@ func createOutboundPeerAndPerformHandshake( return nil, err } - p := newPeer(pc, mConfig, peerNodeInfo, reactorsByCh, msgTypeByChID, chDescs, func(p Peer, r interface{}) {}, newMetricsLabelCache()) + p := newPeer(pc, mConfig, peerNodeInfo, reactorsByCh, msgTypeByChID, chDescs, func(_ Peer, _ any) {}, newMetricsLabelCache()) p.SetLogger(log.TestingLogger().With("peer", addr)) return p, nil } func testDial(addr *NetAddress, cfg *config.P2PConfig) (net.Conn, error) { if cfg.TestDialFail { - return nil, fmt.Errorf("dial err (peerConfig.DialFail == true)") + return nil, errors.New("dial err (peerConfig.DialFail == true)") } conn, err := addr.DialTimeout(cfg.DialTimeout) @@ -122,7 +122,6 @@ func testOutboundPeerConn( persistent bool, ourNodePrivKey crypto.PrivKey, ) (peerConn, error) { - var pc peerConn conn, err := testDial(addr, config) if err != nil { diff --git a/p2p/pex/addrbook.go b/p2p/pex/addrbook.go index 2dc3fd8a834..1d73d99b061 100644 --- a/p2p/pex/addrbook.go +++ b/p2p/pex/addrbook.go @@ -17,11 +17,11 @@ import ( "github.com/minio/highwayhash" "github.com/cometbft/cometbft/crypto" + cmtrand "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtrand "github.com/cometbft/cometbft/libs/rand" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/p2p" ) @@ -38,18 +38,18 @@ type AddrBook interface { service.Service // Add our own addresses so we don't later add ourselves - AddOurAddress(*p2p.NetAddress) + AddOurAddress(addr *p2p.NetAddress) // Check if it is our address - OurAddress(*p2p.NetAddress) bool + OurAddress(addr *p2p.NetAddress) bool - AddPrivateIDs([]string) + AddPrivateIDs(ids []string) // Add and remove an address AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error - RemoveAddress(*p2p.NetAddress) + RemoveAddress(addr *p2p.NetAddress) // Check if the address is in the book - HasAddress(*p2p.NetAddress) bool + HasAddress(addr *p2p.NetAddress) bool // Do we need more peers? NeedMoreAddrs() bool @@ -61,14 +61,14 @@ type AddrBook interface { PickAddress(biasTowardsNewAddrs int) *p2p.NetAddress // Mark address - MarkGood(p2p.ID) - MarkAttempt(*p2p.NetAddress) - MarkBad(*p2p.NetAddress, time.Duration) // Move peer to bad peers list + MarkGood(id p2p.ID) + MarkAttempt(addr *p2p.NetAddress) + MarkBad(addr *p2p.NetAddress, dur time.Duration) // Move peer to bad peers list // Add bad peers back to addrBook ReinstateBadPeers() - IsGood(*p2p.NetAddress) bool - IsBanned(*p2p.NetAddress) bool + IsGood(addr *p2p.NetAddress) bool + IsBanned(addr *p2p.NetAddress) bool // Send a selection of addresses to peers GetSelection() []*p2p.NetAddress @@ -136,7 +136,7 @@ func NewAddrBook(filePath string, routabilityStrict bool) AddrBook { } // Initialize the buckets. -// When modifying this, don't forget to update loadFromFile() +// When modifying this, don't forget to update loadFromFile(). func (a *addrBook) init() { a.key = crypto.CRandHex(24) // 24/2 * 8 = 96 bits // New addr buckets @@ -154,33 +154,30 @@ func (a *addrBook) init() { // OnStart implements Service. func (a *addrBook) OnStart() error { - if err := a.BaseService.OnStart(); err != nil { - return err - } a.loadFromFile(a.filePath) - // wg.Add to ensure that any invocation of .Wait() - // later on will wait for saveRoutine to terminate. a.wg.Add(1) go a.saveRoutine() return nil } -// OnStop implements Service. -func (a *addrBook) OnStop() { - a.BaseService.OnStop() -} - -func (a *addrBook) Wait() { +// Stop overrides Service.Stop(). +func (a *addrBook) Stop() error { + // Closes the Service.Quit() channel. + // This enables a.saveRoutine() to quit. + if err := a.BaseService.Stop(); err != nil { + return err + } a.wg.Wait() + return nil } func (a *addrBook) FilePath() string { return a.filePath } -//------------------------------------------------------- +// ------------------------------------------------------- // AddOurAddress one of our addresses. func (a *addrBook) AddOurAddress(addr *p2p.NetAddress) { @@ -212,7 +209,7 @@ func (a *addrBook) AddPrivateIDs(ids []string) { // AddAddress implements AddrBook // Add address to a "new" bucket. If it's already in one, only add it probabilistically. // Returns error if the addr is non-routable. Does not add self. -// NOTE: addr must not be nil +// NOTE: addr must not be nil. func (a *addrBook) AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error { a.mtx.Lock() defer a.mtx.Unlock() @@ -237,7 +234,7 @@ func (a *addrBook) IsGood(addr *p2p.NetAddress) bool { return a.addrLookup[addr.ID].isOld() } -// IsBanned returns true if the peer is currently banned +// IsBanned returns true if the peer is currently banned. func (a *addrBook) IsBanned(addr *p2p.NetAddress) bool { a.mtx.Lock() _, ok := a.badPeers[addr.ID] @@ -332,9 +329,7 @@ func (a *addrBook) MarkGood(id p2p.ID) { } ka.markGood() if ka.isNew() { - if err := a.moveToOld(ka); err != nil { - a.Logger.Error("Error moving address to old", "err", err) - } + a.moveToOld(ka) } } @@ -372,12 +367,7 @@ func (a *addrBook) ReinstateBadPeers() { continue } - bucket, err := a.calcNewBucket(ka.Addr, ka.Src) - if err != nil { - a.Logger.Error("Failed to calculate new bucket (bad peer won't be reinstantiated)", - "addr", ka.Addr, "err", err) - continue - } + bucket := a.calcNewBucket(ka.Addr, ka.Src) if err := a.addToNewBucket(ka, bucket); err != nil { a.Logger.Error("Error adding peer to new bucket", "err", err) @@ -473,7 +463,7 @@ func (a *addrBook) GetSelectionWithBias(biasTowardsNewAddrs int) []*p2p.NetAddre return selection } -//------------------------------------------------ +// ------------------------------------------------ // Size returns the number of addresses in the book. func (a *addrBook) Size() int { @@ -487,7 +477,7 @@ func (a *addrBook) size() int { return a.nNew + a.nOld } -//---------------------------------------------------------- +// ---------------------------------------------------------- // Save persists the address book to disk. func (a *addrBook) Save() { @@ -498,20 +488,19 @@ func (a *addrBook) saveRoutine() { defer a.wg.Done() saveFileTicker := time.NewTicker(dumpAddressInterval) -out: + defer saveFileTicker.Stop() for { select { case <-saveFileTicker.C: - a.saveToFile(a.filePath) + a.Save() case <-a.Quit(): - break out + a.Save() + return } } - saveFileTicker.Stop() - a.saveToFile(a.filePath) } -//---------------------------------------------------------- +// ---------------------------------------------------------- func (a *addrBook) getBucket(bucketType byte, bucketIdx int) map[string]*knownAddress { switch bucketType { @@ -529,7 +518,7 @@ func (a *addrBook) getBucket(bucketType byte, bucketIdx int) map[string]*knownAd func (a *addrBook) addToNewBucket(ka *knownAddress, bucketIdx int) error { // Consistency check to ensure we don't add an already known address if ka.isOld() { - return errAddrBookOldAddressNewBucket{ka.Addr, bucketIdx} + return ErrAddrBookOldAddressNewBucket{ka.Addr, bucketIdx} } addrStr := ka.Addr.String() @@ -548,7 +537,7 @@ func (a *addrBook) addToNewBucket(ka *knownAddress, bucketIdx int) error { // Add to bucket. bucket[addrStr] = ka - // increment nNew if the peer doesnt already exist in a bucket + // increment nNew if the peer doesn't already exist in a bucket if ka.addBucketRef(bucketIdx) == 1 { a.nNew++ } @@ -626,7 +615,7 @@ func (a *addrBook) removeFromAllBuckets(ka *knownAddress) { delete(a.addrLookup, ka.ID()) } -//---------------------------------------------------------- +// ---------------------------------------------------------- func (a *addrBook) pickOldest(bucketType byte, bucketIdx int) *knownAddress { bucket := a.getBucket(bucketType, bucketIdx) @@ -640,7 +629,7 @@ func (a *addrBook) pickOldest(bucketType byte, bucketIdx int) *knownAddress { } // adds the address to a "new" bucket. if its already in one, -// it only adds it probabilistically +// it only adds it probabilistically. func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error { if addr == nil || src == nil { return ErrAddrBookNilAddr{addr, src} @@ -692,10 +681,8 @@ func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error { ka = newKnownAddress(addr, src) } - bucket, err := a.calcNewBucket(addr, src) - if err != nil { - return err - } + bucket := a.calcNewBucket(addr, src) + return a.addToNewBucket(ka, bucket) } @@ -707,7 +694,7 @@ func (a *addrBook) randomPickAddresses(bucketType byte, num int) []*p2p.NetAddre case bucketTypeOld: buckets = a.bucketsOld default: - panic("unexpected bucketType") + panic("unexpected bucket type") } total := 0 for _, bucket := range buckets { @@ -757,15 +744,15 @@ func (a *addrBook) expireNew(bucketIdx int) { // Promotes an address from new to old. If the destination bucket is full, // demote the oldest one to a "new" bucket. // TODO: Demote more probabilistically? -func (a *addrBook) moveToOld(ka *knownAddress) error { +func (a *addrBook) moveToOld(ka *knownAddress) { // Sanity check if ka.isOld() { a.Logger.Error(fmt.Sprintf("Cannot promote address that is already old %v", ka)) - return nil + return } if len(ka.Buckets) == 0 { a.Logger.Error(fmt.Sprintf("Cannot promote address that isn't in any new buckets %v", ka)) - return nil + return } // Remove from all (new) buckets. @@ -774,19 +761,15 @@ func (a *addrBook) moveToOld(ka *knownAddress) error { ka.BucketType = bucketTypeOld // Try to add it to its oldBucket destination. - oldBucketIdx, err := a.calcOldBucket(ka.Addr) - if err != nil { - return err - } + oldBucketIdx := a.calcOldBucket(ka.Addr) + added := a.addToOldBucket(ka, oldBucketIdx) if !added { // No room; move the oldest to a new bucket oldest := a.pickOldest(bucketTypeOld, oldBucketIdx) a.removeFromBucket(oldest, bucketTypeOld, oldBucketIdx) - newBucketIdx, err := a.calcNewBucket(oldest.Addr, oldest.Src) - if err != nil { - return err - } + newBucketIdx := a.calcNewBucket(oldest.Addr, oldest.Src) + if err := a.addToNewBucket(oldest, newBucketIdx); err != nil { a.Logger.Error("Error adding peer to old bucket", "err", err) } @@ -797,7 +780,6 @@ func (a *addrBook) moveToOld(ka *knownAddress) error { a.Logger.Error(fmt.Sprintf("Could not re-add ka %v to oldBucketIdx %v", ka, oldBucketIdx)) } } - return nil } func (a *addrBook) removeAddress(addr *p2p.NetAddress) { @@ -826,19 +808,16 @@ func (a *addrBook) addBadPeer(addr *p2p.NetAddress, banTime time.Duration) bool return true } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- // calculate bucket placements -// hash(key + sourcegroup + int64(hash(key + group + sourcegroup)) % bucket_per_group) % num_new_buckets -func (a *addrBook) calcNewBucket(addr, src *p2p.NetAddress) (int, error) { +// hash(key + sourcegroup + int64(hash(key + group + sourcegroup)) % bucket_per_group) % num_new_buckets. +func (a *addrBook) calcNewBucket(addr, src *p2p.NetAddress) int { data1 := []byte{} data1 = append(data1, []byte(a.key)...) data1 = append(data1, []byte(a.groupKey(addr))...) data1 = append(data1, []byte(a.groupKey(src))...) - hash1, err := a.hash(data1) - if err != nil { - return 0, err - } + hash1 := a.hash(data1) hash64 := binary.BigEndian.Uint64(hash1) hash64 %= newBucketsPerGroup var hashbuf [8]byte @@ -848,23 +827,18 @@ func (a *addrBook) calcNewBucket(addr, src *p2p.NetAddress) (int, error) { data2 = append(data2, a.groupKey(src)...) data2 = append(data2, hashbuf[:]...) - hash2, err := a.hash(data2) - if err != nil { - return 0, err - } + hash2 := a.hash(data2) result := int(binary.BigEndian.Uint64(hash2) % newBucketCount) - return result, nil + return result } -// hash(key + group + int64(hash(key + addr)) % buckets_per_group) % num_old_buckets -func (a *addrBook) calcOldBucket(addr *p2p.NetAddress) (int, error) { +// hash(key + group + int64(hash(key + addr)) % buckets_per_group) % num_old_buckets. +func (a *addrBook) calcOldBucket(addr *p2p.NetAddress) int { data1 := []byte{} data1 = append(data1, []byte(a.key)...) data1 = append(data1, []byte(addr.String())...) - hash1, err := a.hash(data1) - if err != nil { - return 0, err - } + hash1 := a.hash(data1) + hash64 := binary.BigEndian.Uint64(hash1) hash64 %= oldBucketsPerGroup var hashbuf [8]byte @@ -874,12 +848,10 @@ func (a *addrBook) calcOldBucket(addr *p2p.NetAddress) (int, error) { data2 = append(data2, a.groupKey(addr)...) data2 = append(data2, hashbuf[:]...) - hash2, err := a.hash(data2) - if err != nil { - return 0, err - } + hash2 := a.hash(data2) + result := int(binary.BigEndian.Uint64(hash2) % oldBucketCount) - return result, nil + return result } // Return a string representing the network group of this address. @@ -940,8 +912,9 @@ func groupKeyFor(na *p2p.NetAddress, routabilityStrict bool) string { return na.IP.Mask(ipv6Mask).String() } -func (a *addrBook) hash(b []byte) ([]byte, error) { +// hash returns the hash of b. +func (a *addrBook) hash(b []byte) []byte { a.hasher.Reset() a.hasher.Write(b) - return a.hasher.Sum(nil), nil + return a.hasher.Sum(nil) } diff --git a/p2p/pex/addrbook_test.go b/p2p/pex/addrbook_test.go index c34ee412dbc..6dec258af11 100644 --- a/p2p/pex/addrbook_test.go +++ b/p2p/pex/addrbook_test.go @@ -12,16 +12,16 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/libs/log" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/p2p" ) // FIXME These tests should not rely on .(*addrBook) assertions func TestAddrBookPickAddress(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) // 0 addresses @@ -54,11 +54,11 @@ func TestAddrBookPickAddress(t *testing.T) { // in this case, nNew==0 but we biased 100% to new, so we return nil addr = book.PickAddress(100) - assert.Nil(t, addr, "did not expected an address") + assert.Nil(t, addr, "did not expect an address") } func TestAddrBookSaveLoad(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) // 0 addresses @@ -93,7 +93,7 @@ func TestAddrBookSaveLoad(t *testing.T) { } func TestAddrBookLookup(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) randAddrs := randNetAddressPairs(t, 100) @@ -112,7 +112,7 @@ func TestAddrBookLookup(t *testing.T) { } func TestAddrBookPromoteToOld(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) randAddrs := randNetAddressPairs(t, 100) @@ -152,11 +152,11 @@ func TestAddrBookPromoteToOld(t *testing.T) { t.Errorf("selection with bias could not be bigger than the book") } - assert.Equal(t, book.Size(), 100, "expecting book size to be 100") + assert.Equal(t, 100, book.Size(), "expecting book size to be 100") } func TestAddrBookHandlesDuplicates(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) book := NewAddrBook(fname, true) @@ -183,6 +183,7 @@ type netAddressPair struct { } func randNetAddressPairs(t *testing.T, n int) []netAddressPair { + t.Helper() randAddrs := make([]netAddressPair, n) for i := 0; i < n; i++ { randAddrs[i] = netAddressPair{addr: randIPv4Address(t), src: randIPv4Address(t)} @@ -191,6 +192,7 @@ func randNetAddressPairs(t *testing.T, n int) []netAddressPair { } func randIPv4Address(t *testing.T) *p2p.NetAddress { + t.Helper() for { ip := fmt.Sprintf("%v.%v.%v.%v", cmtrand.Intn(254)+1, @@ -202,7 +204,7 @@ func randIPv4Address(t *testing.T) *p2p.NetAddress { id := p2p.ID(hex.EncodeToString(cmtrand.Bytes(p2p.IDByteLength))) idAddr := p2p.IDAddressString(id, fmt.Sprintf("%v:%v", ip, port)) addr, err := p2p.NewNetAddressString(idAddr) - assert.Nil(t, err, "error generating rand network address") + require.NoError(t, err) if addr.Routable() { return addr } @@ -210,7 +212,7 @@ func randIPv4Address(t *testing.T) *p2p.NetAddress { } func TestAddrBookRemoveAddress(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) book := NewAddrBook(fname, true) @@ -258,7 +260,7 @@ func TestAddrBookGetSelectionReturnsNilWhenAddrBookIsEmpty(t *testing.T) { } func TestAddrBookGetSelection(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) book := NewAddrBook(fname, true) @@ -272,7 +274,7 @@ func TestAddrBookGetSelection(t *testing.T) { err := book.AddAddress(addr, addr) require.NoError(t, err) - assert.Equal(t, 1, len(book.GetSelection())) + assert.Len(t, book.GetSelection(), 1) assert.Equal(t, addr, book.GetSelection()[0]) // 3) add a bunch of addresses @@ -300,7 +302,7 @@ func TestAddrBookGetSelection(t *testing.T) { func TestAddrBookGetSelectionWithBias(t *testing.T) { const biasTowardsNewAddrs = 30 - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) book := NewAddrBook(fname, true) @@ -316,7 +318,7 @@ func TestAddrBookGetSelectionWithBias(t *testing.T) { require.NoError(t, err) selection = book.GetSelectionWithBias(biasTowardsNewAddrs) - assert.Equal(t, 1, len(selection)) + assert.Len(t, selection, 1) assert.Equal(t, addr, selection[0]) // 3) add a bunch of addresses @@ -383,7 +385,7 @@ func TestAddrBookGetSelectionWithBias(t *testing.T) { } func TestAddrBookHasAddress(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) book := NewAddrBook(fname, true) @@ -400,6 +402,7 @@ func TestAddrBookHasAddress(t *testing.T) { } func testCreatePrivateAddrs(t *testing.T, numAddrs int) ([]*p2p.NetAddress, []string) { + t.Helper() addrs := make([]*p2p.NetAddress, numAddrs) for i := 0; i < numAddrs; i++ { addrs[i] = randIPv4Address(t) @@ -413,7 +416,7 @@ func testCreatePrivateAddrs(t *testing.T, numAddrs int) ([]*p2p.NetAddress, []st } func TestBanBadPeers(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) book := NewAddrBook(fname, true) @@ -429,7 +432,7 @@ func TestBanBadPeers(t *testing.T) { err := book.AddAddress(addr, addr) // book should not add address from the blacklist - assert.Error(t, err) + require.Error(t, err) time.Sleep(1 * time.Second) book.ReinstateBadPeers() @@ -440,7 +443,7 @@ func TestBanBadPeers(t *testing.T) { } func TestAddrBookEmpty(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) book := NewAddrBook(fname, true) @@ -451,8 +454,8 @@ func TestAddrBookEmpty(t *testing.T) { book.AddOurAddress(randIPv4Address(t)) require.True(t, book.Empty()) // Check that book with private addrs is empty - _, privateIds := testCreatePrivateAddrs(t, 5) - book.AddPrivateIDs(privateIds) + _, privateIDs := testCreatePrivateAddrs(t, 5) + book.AddPrivateIDs(privateIDs) require.True(t, book.Empty()) // Check that book with address is not empty @@ -462,7 +465,7 @@ func TestAddrBookEmpty(t *testing.T) { } func TestPrivatePeers(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) book := NewAddrBook(fname, true) @@ -474,7 +477,7 @@ func TestPrivatePeers(t *testing.T) { // private addrs must not be added for _, addr := range addrs { err := book.AddAddress(addr, addr) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here _, ok := err.(ErrAddrBookPrivate) assert.True(t, ok) } @@ -482,13 +485,14 @@ func TestPrivatePeers(t *testing.T) { // addrs coming from private peers must not be added err := book.AddAddress(randIPv4Address(t), addrs[0]) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here _, ok := err.(ErrAddrBookPrivateSrc) assert.True(t, ok) } } func testAddrBookAddressSelection(t *testing.T, bookSize int) { + t.Helper() // generate all combinations of old (m) and new addresses for nBookOld := 0; nBookOld <= bookSize; nBookOld++ { nBookNew := bookSize - nBookOld @@ -539,8 +543,7 @@ func testAddrBookAddressSelection(t *testing.T, bookSize int) { // Verify that the order of addresses is as expected // Get the sequence types and lengths of the selection - seqLens, seqTypes, err := analyseSelectionLayout(book, addrs) - assert.NoError(t, err, "%s", dbgStr) + seqLens, seqTypes := analyseSelectionLayout(book, addrs) // Build a list with the expected lengths of partitions and another with the expected types, e.g.: // expSeqLens = [10, 22], expSeqTypes = [1, 2] @@ -571,8 +574,8 @@ func testAddrBookAddressSelection(t *testing.T, bookSize int) { func TestMultipleAddrBookAddressSelection(t *testing.T) { // test books with smaller size, < N - const N = 32 - for bookSize := 1; bookSize < N; bookSize++ { + const n = 32 + for bookSize := 1; bookSize < n; bookSize++ { testAddrBookAddressSelection(t, bookSize) } @@ -589,7 +592,7 @@ func TestMultipleAddrBookAddressSelection(t *testing.T) { } func TestAddrBookAddDoesNotOverwriteOldIP(t *testing.T) { - fname := createTempFileName("addrbook_test") + fname := createTempFileName() defer deleteTempFile(fname) // This test creates adds a peer to the address book and marks it good @@ -598,7 +601,7 @@ func TestAddrBookAddDoesNotOverwriteOldIP(t *testing.T) { peerID := "678503e6c8f50db7279c7da3cb9b072aac4bc0d5" peerRealIP := "1.1.1.1:26656" peerOverrideAttemptIP := "2.2.2.2:26656" - SrcAddr := "b0dd378c3fbc4c156cd6d302a799f0d2e4227201@159.89.121.174:26656" + srcAddr := "b0dd378c3fbc4c156cd6d302a799f0d2e4227201@159.89.121.174:26656" // There is a chance that AddAddress will ignore the new peer its given. // So we repeat trying to override the peer several times, @@ -606,30 +609,30 @@ func TestAddrBookAddDoesNotOverwriteOldIP(t *testing.T) { numOverrideAttempts := 10 peerRealAddr, err := p2p.NewNetAddressString(peerID + "@" + peerRealIP) - require.Nil(t, err) + require.NoError(t, err) peerOverrideAttemptAddr, err := p2p.NewNetAddressString(peerID + "@" + peerOverrideAttemptIP) - require.Nil(t, err) + require.NoError(t, err) - src, err := p2p.NewNetAddressString(SrcAddr) - require.Nil(t, err) + src, err := p2p.NewNetAddressString(srcAddr) + require.NoError(t, err) book := NewAddrBook(fname, true) book.SetLogger(log.TestingLogger()) err = book.AddAddress(peerRealAddr, src) - require.Nil(t, err) + require.NoError(t, err) book.MarkAttempt(peerRealAddr) book.MarkGood(peerRealAddr.ID) // Double check that adding a peer again doesn't error err = book.AddAddress(peerRealAddr, src) - require.Nil(t, err) + require.NoError(t, err) // Try changing ip but keeping the same node id. (change 1.1.1.1 to 2.2.2.2) // This should just be ignored, and not error. for i := 0; i < numOverrideAttempts; i++ { err = book.AddAddress(peerOverrideAttemptAddr, src) - require.Nil(t, err) + require.NoError(t, err) } // Now check that the IP was not overridden. // This is done by sampling several peers from addr book @@ -711,12 +714,14 @@ func TestAddrBookGroupKey(t *testing.T) { } func assertMOldAndNNewAddrsInSelection(t *testing.T, m, n int, addrs []*p2p.NetAddress, book *addrBook) { + t.Helper() nOld, nNew := countOldAndNewAddrsInSelection(addrs, book) assert.Equal(t, m, nOld, "old addresses") assert.Equal(t, n, nNew, "new addresses") } -func createTempFileName(prefix string) string { +func createTempFileName() string { + prefix := "addrbook_test" f, err := os.CreateTemp("", prefix) if err != nil { panic(err) @@ -737,7 +742,8 @@ func deleteTempFile(fname string) { } func createAddrBookWithMOldAndNNewAddrs(t *testing.T, nOld, nNew int) (book *addrBook, fname string) { - fname = createTempFileName("addrbook_test") + t.Helper() + fname = createTempFileName() book = NewAddrBook(fname, true).(*addrBook) book.SetLogger(log.TestingLogger()) @@ -756,7 +762,7 @@ func createAddrBookWithMOldAndNNewAddrs(t *testing.T, nOld, nNew int) (book *add require.NoError(t, err) } - return + return book, fname } func countOldAndNewAddrsInSelection(addrs []*p2p.NetAddress, book *addrBook) (nOld, nNew int) { @@ -767,14 +773,14 @@ func countOldAndNewAddrsInSelection(addrs []*p2p.NetAddress, book *addrBook) (nO nNew++ } } - return + return nOld, nNew } // Analyze the layout of the selection specified by 'addrs' // Returns: // - seqLens - the lengths of the sequences of addresses of same type -// - seqTypes - the types of sequences in selection -func analyseSelectionLayout(book *addrBook, addrs []*p2p.NetAddress) (seqLens, seqTypes []int, err error) { +// - seqTypes - the types of sequences in selection. +func analyseSelectionLayout(book *addrBook, addrs []*p2p.NetAddress) (seqLens, seqTypes []int) { // address types are: 0 - nil, 1 - new, 2 - old var ( prevType = 0 @@ -782,7 +788,7 @@ func analyseSelectionLayout(book *addrBook, addrs []*p2p.NetAddress) (seqLens, s ) for _, addr := range addrs { - addrType := 0 + var addrType int if book.IsGood(addr) { addrType = 2 } else { @@ -800,5 +806,5 @@ func analyseSelectionLayout(book *addrBook, addrs []*p2p.NetAddress) (seqLens, s seqLens = append(seqLens, currentSeqLen) seqTypes = append(seqTypes, prevType) - return + return seqLens, seqTypes } diff --git a/p2p/pex/bench_test.go b/p2p/pex/bench_test.go index 00d2724bfa1..40327f89986 100644 --- a/p2p/pex/bench_test.go +++ b/p2p/pex/bench_test.go @@ -19,6 +19,6 @@ func BenchmarkAddrBook_hash(b *testing.B) { msg := []byte(`foobar`) b.ResetTimer() for i := 0; i < b.N; i++ { - _, _ = book.hash(msg) + _ = book.hash(msg) } } diff --git a/p2p/pex/errors.go b/p2p/pex/errors.go index f4551292b80..fa9c7eb834a 100644 --- a/p2p/pex/errors.go +++ b/p2p/pex/errors.go @@ -3,10 +3,17 @@ package pex import ( "errors" "fmt" + "time" "github.com/cometbft/cometbft/p2p" ) +var ( + ErrEmptyAddressBook = errors.New("address book is empty and couldn't resolve any seed nodes") + // ErrUnsolicitedList is thrown when a peer provides a list of addresses that have not been asked for. + ErrUnsolicitedList = errors.New("unsolicited pexAddrsMessage") +) + type ErrAddrBookNonRoutable struct { Addr *p2p.NetAddress } @@ -15,12 +22,12 @@ func (err ErrAddrBookNonRoutable) Error() string { return fmt.Sprintf("Cannot add non-routable address %v", err.Addr) } -type errAddrBookOldAddressNewBucket struct { +type ErrAddrBookOldAddressNewBucket struct { Addr *p2p.NetAddress BucketID int } -func (err errAddrBookOldAddressNewBucket) Error() string { +func (err ErrAddrBookOldAddressNewBucket) Error() string { return fmt.Sprintf("failed consistency check!"+ " Cannot add pre-existing address %v into new bucket %v", err.Addr, err.BucketID) @@ -42,7 +49,7 @@ func (err ErrAddrBookPrivate) Error() string { return fmt.Sprintf("Cannot add private peer with address %v", err.Addr) } -func (err ErrAddrBookPrivate) PrivateAddr() bool { +func (ErrAddrBookPrivate) PrivateAddr() bool { return true } @@ -54,7 +61,7 @@ func (err ErrAddrBookPrivateSrc) Error() string { return fmt.Sprintf("Cannot add peer coming from private peer with address %v", err.Src) } -func (err ErrAddrBookPrivateSrc) PrivateAddr() bool { +func (ErrAddrBookPrivateSrc) PrivateAddr() bool { return true } @@ -76,7 +83,7 @@ func (err ErrAddrBookInvalidAddr) Error() string { return fmt.Sprintf("Cannot add invalid address %v: %v", err.Addr, err.AddrErr) } -// ErrAddressBanned is thrown when the address has been banned and therefore cannot be used +// ErrAddressBanned is thrown when the address has been banned and therefore cannot be used. type ErrAddressBanned struct { Addr *p2p.NetAddress } @@ -85,5 +92,55 @@ func (err ErrAddressBanned) Error() string { return fmt.Sprintf("Address: %v is currently banned", err.Addr) } -// ErrUnsolicitedList is thrown when a peer provides a list of addresses that have not been asked for. -var ErrUnsolicitedList = errors.New("unsolicited pexAddrsMessage") +// ErrReceivedPEXRequestTooSoon is thrown when a peer sends a PEX request too soon after the last one. +type ErrReceivedPEXRequestTooSoon struct { + Peer p2p.ID + LastReceived time.Time + Now time.Time + MinInterval time.Duration +} + +func (err ErrReceivedPEXRequestTooSoon) Error() string { + return fmt.Sprintf("received PEX request from peer %v too soon (last received %v, now %v, min interval %v), Disconnecting peer", + err.Peer, err.LastReceived, err.Now, err.MinInterval) +} + +type ErrMaxAttemptsToDial struct { + Max int +} + +func (e ErrMaxAttemptsToDial) Error() string { + return fmt.Sprintf("reached max attempts %d to dial", e.Max) +} + +type ErrTooEarlyToDial struct { + BackoffDuration time.Duration + LastDialed time.Time +} + +func (e ErrTooEarlyToDial) Error() string { + return fmt.Sprintf( + "too early to dial (backoff duration: %d, last dialed: %v, time since: %v)", + e.BackoffDuration, e.LastDialed, time.Since(e.LastDialed)) +} + +type ErrFailedToDial struct { + TotalAttempts int + Err error +} + +func (e ErrFailedToDial) Error() string { + return fmt.Sprintf("failed to dial after %d attempts: %v", e.TotalAttempts, e.Err) +} + +func (e ErrFailedToDial) Unwrap() error { return e.Err } + +type ErrSeedNodeConfig struct { + Err error +} + +func (e ErrSeedNodeConfig) Error() string { + return fmt.Sprintf("failed to parse seed node config: %v", e.Err) +} + +func (e ErrSeedNodeConfig) Unwrap() error { return e.Err } diff --git a/p2p/pex/file.go b/p2p/pex/file.go index 38eec9636b9..59c642b4783 100644 --- a/p2p/pex/file.go +++ b/p2p/pex/file.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - "github.com/cometbft/cometbft/libs/tempfile" + "github.com/cometbft/cometbft/internal/tempfile" ) /* Loading & Saving */ @@ -35,7 +35,7 @@ func (a *addrBook) saveToFile(filePath string) { a.Logger.Error("Failed to save AddrBook to file", "err", err) return } - err = tempfile.WriteFileAtomic(filePath, jsonBytes, 0644) + err = tempfile.WriteFileAtomic(filePath, jsonBytes, 0o644) if err != nil { a.Logger.Error("Failed to save AddrBook to file", "file", filePath, "err", err) } diff --git a/p2p/pex/params.go b/p2p/pex/params.go index 29b4d45ab27..ac6c4ba4822 100644 --- a/p2p/pex/params.go +++ b/p2p/pex/params.go @@ -50,6 +50,6 @@ const ( minGetSelection = 32 // max addresses returned by GetSelection - // NOTE: this must match "maxMsgSize" + // NOTE: this must match "maxMsgSize". maxGetSelection = 250 ) diff --git a/p2p/pex/pex_reactor.go b/p2p/pex/pex_reactor.go index 780c2bad582..ec9ea6fc2ff 100644 --- a/p2p/pex/pex_reactor.go +++ b/p2p/pex/pex_reactor.go @@ -6,19 +6,19 @@ import ( "sync" "time" - "github.com/cometbft/cometbft/libs/cmap" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" + "github.com/cometbft/cometbft/internal/cmap" + cmtrand "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/internal/service" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtrand "github.com/cometbft/cometbft/libs/rand" - "github.com/cometbft/cometbft/libs/service" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/p2p/conn" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" ) type Peer = p2p.Peer const ( - // PexChannel is a channel for PEX messages + // PexChannel is a channel for PEX messages. PexChannel = byte(0x00) // over-estimate of max NetAddress size @@ -27,18 +27,18 @@ const ( maxAddressSize = 256 // NOTE: amplificaiton factor! - // small request results in up to maxMsgSize response + // small request results in up to maxMsgSize response. maxMsgSize = maxAddressSize * maxGetSelection - // ensure we have enough peers + // ensure we have enough peers. defaultEnsurePeersPeriod = 30 * time.Second - // Seed/Crawler constants + // Seed/Crawler constants. // minTimeBetweenCrawls is a minimum time between attempts to crawl a peer. minTimeBetweenCrawls = 2 * time.Minute - // check some peers every this + // check some peers every this. crawlPeerPeriod = 30 * time.Second maxAttemptsToDial = 16 // ~ 35h in total (last attempt - 18h) @@ -48,28 +48,10 @@ const ( // untrusted. biasToSelectNewPeers = 30 // 70 to select good peers - // if a peer is marked bad, it will be banned for at least this time period + // if a peer is marked bad, it will be banned for at least this time period. defaultBanTime = 24 * time.Hour ) -type errMaxAttemptsToDial struct { -} - -func (e errMaxAttemptsToDial) Error() string { - return fmt.Sprintf("reached max attempts %d to dial", maxAttemptsToDial) -} - -type errTooEarlyToDial struct { - backoffDuration time.Duration - lastDialed time.Time -} - -func (e errTooEarlyToDial) Error() string { - return fmt.Sprintf( - "too early to dial (backoff duration: %d, last dialed: %v, time since: %v)", - e.backoffDuration, e.lastDialed, time.Since(e.lastDialed)) -} - // Reactor handles PEX (peer exchange) and ensures that an // adequate number of peers are connected to the switch. // @@ -85,6 +67,7 @@ type Reactor struct { book AddrBook config *ReactorConfig ensurePeersPeriod time.Duration // TODO: should go in the config + peersRoutineWg sync.WaitGroup // maps to prevent abuse requestsSent *cmap.CMap // ID->struct{}: unanswered send requests @@ -141,10 +124,10 @@ func NewReactor(b AddrBook, config *ReactorConfig) *Reactor { return r } -// OnStart implements BaseService +// OnStart implements BaseService. func (r *Reactor) OnStart() error { err := r.book.Start() - if err != nil && err != service.ErrAlreadyStarted { + if err != nil && !errors.Is(err, service.ErrAlreadyStarted) { return err } @@ -152,11 +135,12 @@ func (r *Reactor) OnStart() error { if err != nil { return err } else if numOnline == 0 && r.book.Empty() { - return errors.New("address book is empty and couldn't resolve any seed nodes") + return ErrEmptyAddressBook } r.seedAddrs = seedAddrs + r.peersRoutineWg.Add(1) // Check if this node should run // in seed/crawler mode if r.config.SeedMode { @@ -167,15 +151,20 @@ func (r *Reactor) OnStart() error { return nil } -// OnStop implements BaseService -func (r *Reactor) OnStop() { +// Stop overrides `Service.Stop()`. +func (r *Reactor) Stop() error { + if err := r.BaseReactor.Stop(); err != nil { + return err + } if err := r.book.Stop(); err != nil { - r.Logger.Error("Error stopping address book", "err", err) + return fmt.Errorf("can't stop address book: %w", err) } + r.peersRoutineWg.Wait() + return nil } -// GetChannels implements Reactor -func (r *Reactor) GetChannels() []*conn.ChannelDescriptor { +// GetChannels implements Reactor. +func (*Reactor) GetChannels() []*conn.ChannelDescriptor { return []*conn.ChannelDescriptor{ { ID: PexChannel, @@ -216,7 +205,7 @@ func (r *Reactor) AddPeer(p Peer) { } // RemovePeer implements Reactor by resetting peer's requests info. -func (r *Reactor) RemovePeer(p Peer, reason interface{}) { +func (r *Reactor) RemovePeer(p Peer, _ any) { id := string(p.ID()) r.requestsSent.Delete(id) r.lastReceivedRequests.Delete(id) @@ -265,7 +254,6 @@ func (r *Reactor) Receive(e p2p.Envelope) { e.Src.FlushStop() r.Switch.StopPeerGracefully(e.Src) }() - } else { // Check we're not receiving requests too frequently. if err := r.receiveRequest(e.Src); err != nil { @@ -298,7 +286,7 @@ func (r *Reactor) Receive(e p2p.Envelope) { } } -// enforces a minimum amount of time between requests +// enforces a minimum amount of time between requests. func (r *Reactor) receiveRequest(src Peer) error { id := string(src.ID()) v := r.lastReceivedRequests.Get(id) @@ -320,13 +308,12 @@ func (r *Reactor) receiveRequest(src Peer) error { now := time.Now() minInterval := r.minReceiveRequestInterval() if now.Sub(lastReceived) < minInterval { - return fmt.Errorf( - "peer (%v) sent next PEX request too soon. lastReceived: %v, now: %v, minInterval: %v. Disconnecting", - src.ID(), - lastReceived, - now, - minInterval, - ) + return ErrReceivedPEXRequestTooSoon{ + Peer: src.ID(), + LastReceived: lastReceived, + Now: now, + MinInterval: minInterval, + } } r.lastReceivedRequests.Set(id, now) return nil @@ -347,7 +334,7 @@ func (r *Reactor) RequestAddrs(p Peer) { }) } -// ReceiveAddrs adds the given addrs to the addrbook if theres an open +// ReceiveAddrs adds the given addrs to the addrbook if there's an open // request for this peer and deletes the open request. // If there's no open request for the src peer, it returns an error. func (r *Reactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error { @@ -387,7 +374,7 @@ func (r *Reactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error { err := r.dialPeer(addr) if err != nil { switch err.(type) { - case errMaxAttemptsToDial, errTooEarlyToDial, p2p.ErrCurrentlyDialingOrExistingAddress: + case ErrMaxAttemptsToDial, ErrTooEarlyToDial, p2p.ErrCurrentlyDialingOrExistingAddress: r.Logger.Debug(err.Error(), "addr", addr) default: r.Logger.Debug(err.Error(), "addr", addr) @@ -401,7 +388,7 @@ func (r *Reactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error { } // SendAddrs sends addrs to the peer. -func (r *Reactor) SendAddrs(p Peer, netAddrs []*p2p.NetAddress) { +func (*Reactor) SendAddrs(p Peer, netAddrs []*p2p.NetAddress) { e := p2p.Envelope{ ChannelID: PexChannel, Message: &tmp2p.PexAddrs{Addrs: p2p.NetAddressesToProto(netAddrs)}, @@ -414,8 +401,10 @@ func (r *Reactor) SetEnsurePeersPeriod(d time.Duration) { r.ensurePeersPeriod = d } -// Ensures that sufficient peers are connected. (continuous) +// Ensures that sufficient peers are connected. (continuous). func (r *Reactor) ensurePeersRoutine() { + defer r.peersRoutineWg.Done() + var ( seed = cmtrand.NewRand() jitter = seed.Int63n(r.ensurePeersPeriod.Nanoseconds()) @@ -434,12 +423,14 @@ func (r *Reactor) ensurePeersRoutine() { // fire periodically ticker := time.NewTicker(r.ensurePeersPeriod) + defer ticker.Stop() for { select { case <-ticker.C: r.ensurePeers() + case <-r.book.Quit(): + return case <-r.Quit(): - ticker.Stop() return } } @@ -477,6 +468,10 @@ func (r *Reactor) ensurePeers() { maxAttempts := numToDial * 3 for i := 0; i < maxAttempts && len(toDial) < numToDial; i++ { + if !r.IsRunning() || !r.book.IsRunning() { + return + } + try := r.book.PickAddress(newBias) if try == nil { continue @@ -499,7 +494,7 @@ func (r *Reactor) ensurePeers() { err := r.dialPeer(addr) if err != nil { switch err.(type) { - case errMaxAttemptsToDial, errTooEarlyToDial: + case ErrMaxAttemptsToDial, ErrTooEarlyToDial: r.Logger.Debug(err.Error(), "addr", addr) default: r.Logger.Debug(err.Error(), "addr", addr) @@ -514,12 +509,9 @@ func (r *Reactor) ensurePeers() { } if r.book.NeedMoreAddrs() { - // 1) Pick a random peer and ask for more. - peers := r.Switch.Peers().List() - peersCount := len(peers) - if peersCount > 0 { - peer := peers[cmtrand.Int()%peersCount] + peer := r.Switch.Peers().Random() + if peer != nil { r.Logger.Info("We need more addresses. Sending pexRequest to random peer", "peer", peer) r.RequestAddrs(peer) } @@ -537,7 +529,7 @@ func (r *Reactor) ensurePeers() { func (r *Reactor) dialAttemptsInfo(addr *p2p.NetAddress) (attempts int, lastDialed time.Time) { _attempts, ok := r.attemptsToDial.Load(addr.DialString()) if !ok { - return + return 0, time.Time{} } atd := _attempts.(_attemptsToDial) return atd.number, atd.lastDialed @@ -547,7 +539,7 @@ func (r *Reactor) dialPeer(addr *p2p.NetAddress) error { attempts, lastDialed := r.dialAttemptsInfo(addr) if !r.Switch.IsPeerPersistent(addr) && attempts > maxAttemptsToDial { r.book.MarkBad(addr, defaultBanTime) - return errMaxAttemptsToDial{} + return ErrMaxAttemptsToDial{Max: maxAttemptsToDial} } // exponential backoff if it's not our first attempt to dial given address @@ -557,7 +549,7 @@ func (r *Reactor) dialPeer(addr *p2p.NetAddress) error { backoffDuration = r.maxBackoffDurationForPeer(addr, backoffDuration) sinceLastDialed := time.Since(lastDialed) if sinceLastDialed < backoffDuration { - return errTooEarlyToDial{backoffDuration, lastDialed} + return ErrTooEarlyToDial{backoffDuration, lastDialed} } } @@ -575,7 +567,7 @@ func (r *Reactor) dialPeer(addr *p2p.NetAddress) error { default: r.attemptsToDial.Store(addr.DialString(), _attemptsToDial{attempts + 1, time.Now()}) } - return fmt.Errorf("dialing failed (attempts: %d): %w", attempts+1, err) + return ErrFailedToDial{attempts + 1, err} } // cleanup any history @@ -610,13 +602,13 @@ func (r *Reactor) checkSeeds() (numOnline int, netAddrs []*p2p.NetAddress, err e case p2p.ErrNetAddressLookup: r.Logger.Error("Connecting to seed failed", "err", e) default: - return 0, nil, fmt.Errorf("seed node configuration has error: %w", e) + return 0, nil, ErrSeedNodeConfig{Err: err} } } return numOnline, netAddrs, nil } -// randomly dial seeds until we connect to one or exhaust them +// randomly dial seeds until we connect to one or exhaust them. func (r *Reactor) dialSeeds() { perm := cmtrand.Perm(len(r.seedAddrs)) // perm := r.Switch.rng.Perm(lSeeds) @@ -647,12 +639,14 @@ func (r *Reactor) AttemptsToDial(addr *p2p.NetAddress) int { return 0 } -//---------------------------------------------------------- +// ---------------------------------------------------------- // Explores the network searching for more peers. (continuous) // Seed/Crawler Mode causes this node to quickly disconnect // from peers, except other seed nodes. func (r *Reactor) crawlPeersRoutine() { + defer r.peersRoutineWg.Done() + // If we have any seed nodes, consult them first if len(r.seedAddrs) > 0 { r.dialSeeds() @@ -663,13 +657,15 @@ func (r *Reactor) crawlPeersRoutine() { // Fire periodically ticker := time.NewTicker(crawlPeerPeriod) - + defer ticker.Stop() for { select { case <-ticker.C: r.attemptDisconnects() r.crawlPeers(r.book.GetSelection()) r.cleanupCrawlPeerInfos() + case <-r.book.Quit(): + return case <-r.Quit(): return } @@ -712,7 +708,7 @@ func (r *Reactor) crawlPeers(addrs []*p2p.NetAddress) { err := r.dialPeer(addr) if err != nil { switch err.(type) { - case errMaxAttemptsToDial, errTooEarlyToDial, p2p.ErrCurrentlyDialingOrExistingAddress: + case ErrMaxAttemptsToDial, ErrTooEarlyToDial, p2p.ErrCurrentlyDialingOrExistingAddress: r.Logger.Debug(err.Error(), "addr", addr) default: r.Logger.Debug(err.Error(), "addr", addr) @@ -741,9 +737,9 @@ func (r *Reactor) cleanupCrawlPeerInfos() { } } -// attemptDisconnects checks if we've been with each peer long enough to disconnect +// attemptDisconnects checks if we've been with each peer long enough to disconnect. func (r *Reactor) attemptDisconnects() { - for _, peer := range r.Switch.Peers().List() { + for _, peer := range r.Switch.Peers().Copy() { if peer.Status().Duration < r.config.SeedDisconnectWaitPeriod { continue } diff --git a/p2p/pex/pex_reactor_test.go b/p2p/pex/pex_reactor_test.go index 5c2bebf6649..77f75f8426e 100644 --- a/p2p/pex/pex_reactor_test.go +++ b/p2p/pex/pex_reactor_test.go @@ -12,16 +12,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/libs/log" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/p2p/mock" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" + "github.com/cometbft/cometbft/types" ) -var ( - cfg *config.P2PConfig -) +var cfg *config.P2PConfig func init() { cfg = config.DefaultP2PConfig() @@ -68,20 +67,20 @@ func TestPEXReactorAddRemovePeer(t *testing.T) { // peers have different IP addresses, they all have the same underlying remote // IP: 127.0.0.1. func TestPEXReactorRunning(t *testing.T) { - N := 3 - switches := make([]*p2p.Switch, N) + n := 3 + switches := make([]*p2p.Switch, n) // directory to store address books dir, err := os.MkdirTemp("", "pex_reactor") - require.Nil(t, err) + require.NoError(t, err) defer os.RemoveAll(dir) - books := make([]AddrBook, N) + books := make([]AddrBook, n) logger := log.TestingLogger() // create switches - for i := 0; i < N; i++ { - switches[i] = p2p.MakeSwitch(cfg, i, "testing", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { + for i := 0; i < n; i++ { + switches[i] = p2p.MakeSwitch(cfg, i, func(i int, sw *p2p.Switch) *p2p.Switch { books[i] = NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", i)), false) books[i].SetLogger(logger.With("pex", i)) sw.SetAddrBook(books[i]) @@ -109,10 +108,10 @@ func TestPEXReactorRunning(t *testing.T) { for _, sw := range switches { err := sw.Start() // start switch and reactors - require.Nil(t, err) + require.NoError(t, err) } - assertPeersWithTimeout(t, switches, 10*time.Millisecond, 10*time.Second, N-1) + assertPeersWithTimeout(t, switches, 10*time.Second, n-1) // stop them for _, s := range switches { @@ -206,12 +205,12 @@ func TestPEXReactorAddrsMessageAbuse(t *testing.T) { func TestCheckSeeds(t *testing.T) { // directory to store address books dir, err := os.MkdirTemp("", "pex_reactor") - require.Nil(t, err) + require.NoError(t, err) defer os.RemoveAll(dir) // 1. test creating peer with no seeds works peerSwitch := testCreateDefaultPeer(dir, 0) - require.Nil(t, peerSwitch.Start()) + require.NoError(t, peerSwitch.Start()) peerSwitch.Stop() //nolint:errcheck // ignore for tests // 2. create seed @@ -219,13 +218,15 @@ func TestCheckSeeds(t *testing.T) { // 3. test create peer with online seed works peerSwitch = testCreatePeerWithSeed(dir, 2, seed) - require.Nil(t, peerSwitch.Start()) + require.NoError(t, peerSwitch.Start()) peerSwitch.Stop() //nolint:errcheck // ignore for tests // 4. test create peer with all seeds having unresolvable DNS fails badPeerConfig := &ReactorConfig{ - Seeds: []string{"ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657", - "d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657"}, + Seeds: []string{ + "ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657", + "d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657", + }, } peerSwitch = testCreatePeerWithConfig(dir, 2, badPeerConfig) require.Error(t, peerSwitch.Start()) @@ -233,68 +234,70 @@ func TestCheckSeeds(t *testing.T) { // 5. test create peer with one good seed address succeeds badPeerConfig = &ReactorConfig{ - Seeds: []string{"ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657", + Seeds: []string{ + "ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657", "d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657", - seed.NetAddress().String()}, + seed.NetAddress().String(), + }, } peerSwitch = testCreatePeerWithConfig(dir, 2, badPeerConfig) - require.Nil(t, peerSwitch.Start()) + require.NoError(t, peerSwitch.Start()) peerSwitch.Stop() //nolint:errcheck // ignore for tests } func TestPEXReactorUsesSeedsIfNeeded(t *testing.T) { // directory to store address books dir, err := os.MkdirTemp("", "pex_reactor") - require.Nil(t, err) + require.NoError(t, err) defer os.RemoveAll(dir) // 1. create seed seed := testCreateSeed(dir, 0, []*p2p.NetAddress{}, []*p2p.NetAddress{}) - require.Nil(t, seed.Start()) + require.NoError(t, seed.Start()) defer seed.Stop() //nolint:errcheck // ignore for tests // 2. create usual peer with only seed configured. peer := testCreatePeerWithSeed(dir, 1, seed) - require.Nil(t, peer.Start()) + require.NoError(t, peer.Start()) defer peer.Stop() //nolint:errcheck // ignore for tests // 3. check that the peer connects to seed immediately - assertPeersWithTimeout(t, []*p2p.Switch{peer}, 10*time.Millisecond, 3*time.Second, 1) + assertPeersWithTimeout(t, []*p2p.Switch{peer}, 3*time.Second, 1) } func TestConnectionSpeedForPeerReceivedFromSeed(t *testing.T) { // directory to store address books dir, err := os.MkdirTemp("", "pex_reactor") - require.Nil(t, err) + require.NoError(t, err) defer os.RemoveAll(dir) // 1. create peer peerSwitch := testCreateDefaultPeer(dir, 1) - require.Nil(t, peerSwitch.Start()) + require.NoError(t, peerSwitch.Start()) defer peerSwitch.Stop() //nolint:errcheck // ignore for tests // 2. Create seed which knows about the peer peerAddr := peerSwitch.NetAddress() seed := testCreateSeed(dir, 2, []*p2p.NetAddress{peerAddr}, []*p2p.NetAddress{peerAddr}) - require.Nil(t, seed.Start()) + require.NoError(t, seed.Start()) defer seed.Stop() //nolint:errcheck // ignore for tests // 3. create another peer with only seed configured. secondPeer := testCreatePeerWithSeed(dir, 3, seed) - require.Nil(t, secondPeer.Start()) + require.NoError(t, secondPeer.Start()) defer secondPeer.Stop() //nolint:errcheck // ignore for tests // 4. check that the second peer connects to seed immediately - assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 10*time.Millisecond, 3*time.Second, 1) + assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 3*time.Second, 1) // 5. check that the second peer connects to the first peer immediately - assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 10*time.Millisecond, 1*time.Second, 2) + assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 1*time.Second, 2) } func TestPEXReactorSeedMode(t *testing.T) { // directory to store address books dir, err := os.MkdirTemp("", "pex_reactor") - require.Nil(t, err) + require.NoError(t, err) defer os.RemoveAll(dir) pexRConfig := &ReactorConfig{SeedMode: true, SeedDisconnectWaitPeriod: 10 * time.Millisecond} @@ -333,7 +336,7 @@ func TestPEXReactorSeedMode(t *testing.T) { func TestPEXReactorDoesNotDisconnectFromPersistentPeerInSeedMode(t *testing.T) { // directory to store address books dir, err := os.MkdirTemp("", "pex_reactor") - require.Nil(t, err) + require.NoError(t, err) defer os.RemoveAll(dir) pexRConfig := &ReactorConfig{SeedMode: true, SeedDisconnectWaitPeriod: 1 * time.Millisecond} @@ -371,7 +374,7 @@ func TestPEXReactorDoesNotDisconnectFromPersistentPeerInSeedMode(t *testing.T) { func TestPEXReactorDialsPeerUpToMaxAttemptsInSeedMode(t *testing.T) { // directory to store address books dir, err := os.MkdirTemp("", "pex_reactor") - require.Nil(t, err) + require.NoError(t, err) defer os.RemoveAll(dir) pexR, book := createReactor(&ReactorConfig{SeedMode: true}) @@ -402,20 +405,20 @@ func TestPEXReactorDialsPeerUpToMaxAttemptsInSeedMode(t *testing.T) { // with FlushStop. Before a fix, this non-deterministically reproduced // https://github.com/tendermint/tendermint/issues/3231. func TestPEXReactorSeedModeFlushStop(t *testing.T) { - N := 2 - switches := make([]*p2p.Switch, N) + n := 2 + switches := make([]*p2p.Switch, n) // directory to store address books dir, err := os.MkdirTemp("", "pex_reactor") - require.Nil(t, err) + require.NoError(t, err) defer os.RemoveAll(dir) - books := make([]AddrBook, N) + books := make([]AddrBook, n) logger := log.TestingLogger() // create switches - for i := 0; i < N; i++ { - switches[i] = p2p.MakeSwitch(cfg, i, "testing", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { + for i := 0; i < n; i++ { + switches[i] = p2p.MakeSwitch(cfg, i, func(i int, sw *p2p.Switch) *p2p.Switch { books[i] = NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", i)), false) books[i].SetLogger(logger.With("pex", i)) sw.SetAddrBook(books[i]) @@ -438,14 +441,14 @@ func TestPEXReactorSeedModeFlushStop(t *testing.T) { for _, sw := range switches { err := sw.Start() // start switch and reactors - require.Nil(t, err) + require.NoError(t, err) } reactor := switches[0].Reactors()["pex"].(*Reactor) peerID := switches[1].NodeInfo().ID() err = switches[1].DialPeerWithAddress(switches[0].NetAddress()) - assert.NoError(t, err) + require.NoError(t, err) // sleep up to a second while waiting for the peer to send us a message. // this isn't perfect since it's possible the peer sends us a msg and we FlushStop @@ -460,7 +463,7 @@ func TestPEXReactorSeedModeFlushStop(t *testing.T) { // by now the FlushStop should have happened. Try stopping the peer. // it should be safe to do this. - peers := switches[0].Peers().List() + peers := switches[0].Peers().Copy() for _, peer := range peers { err := peer.Stop() require.NoError(t, err) @@ -535,9 +538,12 @@ func TestPEXReactorDialPeer(t *testing.T) { func assertPeersWithTimeout( t *testing.T, switches []*p2p.Switch, - checkPeriod, timeout time.Duration, + timeout time.Duration, nPeers int, ) { + t.Helper() + checkPeriod := 10 * time.Millisecond + var ( ticker = time.NewTicker(checkPeriod) remaining = timeout @@ -577,14 +583,12 @@ func assertPeersWithTimeout( } } -// Creates a peer with the provided config +// Creates a peer with the provided config. func testCreatePeerWithConfig(dir string, id int, config *ReactorConfig) *p2p.Switch { peer := p2p.MakeSwitch( cfg, id, - "127.0.0.1", - "123.123.123", - func(i int, sw *p2p.Switch) *p2p.Switch { + func(_ int, sw *p2p.Switch) *p2p.Switch { book := NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", id)), false) book.SetLogger(log.TestingLogger()) sw.SetAddrBook(book) @@ -603,20 +607,18 @@ func testCreatePeerWithConfig(dir string, id int, config *ReactorConfig) *p2p.Sw return peer } -// Creates a peer with the default config +// Creates a peer with the default config. func testCreateDefaultPeer(dir string, id int) *p2p.Switch { return testCreatePeerWithConfig(dir, id, &ReactorConfig{}) } // Creates a seed which knows about the provided addresses / source address pairs. -// Starting and stopping the seed is left to the caller +// Starting and stopping the seed is left to the caller. func testCreateSeed(dir string, id int, knownAddrs, srcAddrs []*p2p.NetAddress) *p2p.Switch { seed := p2p.MakeSwitch( cfg, id, - "127.0.0.1", - "123.123.123", - func(i int, sw *p2p.Switch) *p2p.Switch { + func(_ int, sw *p2p.Switch) *p2p.Switch { book := NewAddrBook(filepath.Join(dir, "addrbookSeed.json"), false) book.SetLogger(log.TestingLogger()) for j := 0; j < len(knownAddrs); j++ { @@ -637,7 +639,7 @@ func testCreateSeed(dir string, id int, knownAddrs, srcAddrs []*p2p.NetAddress) } // Creates a peer which knows about the provided seed. -// Starting and stopping the peer is left to the caller +// Starting and stopping the peer is left to the caller. func testCreatePeerWithSeed(dir string, id int, seed *p2p.Switch) *p2p.Switch { conf := &ReactorConfig{ Seeds: []string{seed.NetAddress().String()}, @@ -656,7 +658,7 @@ func createReactor(conf *ReactorConfig) (r *Reactor, book AddrBook) { r = NewReactor(book, conf) r.SetLogger(log.TestingLogger()) - return + return r, book } func teardownReactor(book AddrBook) { @@ -668,7 +670,7 @@ func teardownReactor(book AddrBook) { } func createSwitchAndAddReactors(reactors ...p2p.Reactor) *p2p.Switch { - sw := p2p.MakeSwitch(cfg, 0, "127.0.0.1", "123.123.123", func(i int, sw *p2p.Switch) *p2p.Switch { return sw }) + sw := p2p.MakeSwitch(cfg, 0, func(_ int, sw *p2p.Switch) *p2p.Switch { return sw }) sw.SetLogger(log.TestingLogger()) for _, r := range reactors { sw.AddReactor(r.String(), r) @@ -678,7 +680,6 @@ func createSwitchAndAddReactors(reactors ...p2p.Reactor) *p2p.Switch { } func TestPexVectors(t *testing.T) { - addr := tmp2p.NetAddress{ ID: "1", IP: "127.0.0.1", @@ -697,7 +698,7 @@ func TestPexVectors(t *testing.T) { for _, tc := range testCases { tc := tc - w := tc.msg.(p2p.Wrapper).Wrap() + w := tc.msg.(types.Wrapper).Wrap() bz, err := proto.Marshal(w) require.NoError(t, err) diff --git a/p2p/switch.go b/p2p/switch.go index f7159f9d41e..6aa0b57c360 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -1,6 +1,7 @@ package p2p import ( + "errors" "fmt" "math" "sync" @@ -9,24 +10,24 @@ import ( "github.com/cosmos/gogoproto/proto" "github.com/cometbft/cometbft/config" - "github.com/cometbft/cometbft/libs/cmap" - "github.com/cometbft/cometbft/libs/rand" - "github.com/cometbft/cometbft/libs/service" + "github.com/cometbft/cometbft/internal/cmap" + "github.com/cometbft/cometbft/internal/rand" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/p2p/conn" ) const ( // wait a random amount of time from this interval - // before dialing peers or reconnecting to help prevent DoS + // before dialing peers or reconnecting to help prevent DoS. dialRandomizerIntervalMilliseconds = 3000 // repeatedly try to reconnect for a few minutes - // ie. 5 * 20 = 100s + // ie. 5 * 20 = 100s. reconnectAttempts = 20 reconnectInterval = 5 * time.Second // then move into exponential backoff mode for ~1day - // ie. 3**10 = 16hrs + // ie. 3**10 = 16hrs. reconnectBackOffAttempts = 10 reconnectBackOffBaseSeconds = 3 ) @@ -39,21 +40,23 @@ func MConnConfig(cfg *config.P2PConfig) conn.MConnConfig { mConfig.SendRate = cfg.SendRate mConfig.RecvRate = cfg.RecvRate mConfig.MaxPacketMsgPayloadSize = cfg.MaxPacketMsgPayloadSize + mConfig.TestFuzz = cfg.TestFuzz + mConfig.TestFuzzConfig = cfg.TestFuzzConfig return mConfig } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // An AddrBook represents an address book from the pex package, which is used // to store peer addresses. type AddrBook interface { AddAddress(addr *NetAddress, src *NetAddress) error - AddPrivateIDs([]string) - AddOurAddress(*NetAddress) - OurAddress(*NetAddress) bool - MarkGood(ID) - RemoveAddress(*NetAddress) - HasAddress(*NetAddress) bool + AddPrivateIDs(ids []string) + AddOurAddress(addr *NetAddress) + OurAddress(addr *NetAddress) bool + MarkGood(id ID) + RemoveAddress(addr *NetAddress) + HasAddress(addr *NetAddress) bool Save() } @@ -61,7 +64,7 @@ type AddrBook interface { // fully setup. type PeerFilterFunc func(IPeerSet, Peer) error -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Switch handles peer connections and exposes an API to receive incoming messages // on `Reactors`. Each `Reactor` is responsible for handling incoming messages of one @@ -111,7 +114,6 @@ func NewSwitch( transport Transport, options ...SwitchOption, ) *Switch { - sw := &Switch{ config: cfg, reactors: make(map[string]Reactor), @@ -156,12 +158,12 @@ func WithMetrics(metrics *Metrics) SwitchOption { return func(sw *Switch) { sw.metrics = metrics } } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- // Switch setup // AddReactor adds the given reactor to the switch. // NOTE: Not goroutine safe. -func (sw *Switch) AddReactor(name string, reactor Reactor) { +func (sw *Switch) AddReactor(name string, reactor Reactor) Reactor { for _, chDesc := range reactor.GetChannels() { chID := chDesc.ID // No two reactors can share the same channel. @@ -174,6 +176,7 @@ func (sw *Switch) AddReactor(name string, reactor Reactor) { } sw.reactors[name] = reactor reactor.SetSwitch(sw) + return reactor } // RemoveReactor removes the given Reactor from the Switch. @@ -224,7 +227,7 @@ func (sw *Switch) SetNodeKey(nodeKey *NodeKey) { sw.nodeKey = nodeKey } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- // Service start/stop // OnStart implements BaseService. It starts all the reactors and peers. @@ -233,7 +236,7 @@ func (sw *Switch) OnStart() error { for _, reactor := range sw.reactors { err := reactor.Start() if err != nil { - return fmt.Errorf("failed to start %v: %w", reactor, err) + return ErrStart{reactor, err} } } @@ -246,7 +249,7 @@ func (sw *Switch) OnStart() error { // OnStop implements BaseService. It stops all peers and reactors. func (sw *Switch) OnStop() { // Stop peers - for _, p := range sw.peers.List() { + for _, p := range sw.peers.Copy() { sw.stopAndRemovePeer(p, nil) } @@ -254,12 +257,12 @@ func (sw *Switch) OnStop() { sw.Logger.Debug("Switch: Stopping reactors") for _, reactor := range sw.reactors { if err := reactor.Stop(); err != nil { - sw.Logger.Error("error while stopped reactor", "reactor", reactor, "error", err) + sw.Logger.Error("error while stopped reactor", "reactor", reactor, "err", err) } } } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- // Peers // Broadcast runs a go routine for each attempted send, which will block trying @@ -271,18 +274,21 @@ func (sw *Switch) OnStop() { func (sw *Switch) Broadcast(e Envelope) chan bool { sw.Logger.Debug("Broadcast", "channel", e.ChannelID) - peers := sw.peers.List() var wg sync.WaitGroup - wg.Add(len(peers)) - successChan := make(chan bool, len(peers)) + successChan := make(chan bool, sw.peers.Size()) - for _, peer := range peers { - go func(p Peer) { + sw.peers.ForEach(func(p Peer) { + wg.Add(1) // Incrementing by one is safer. + go func(peer Peer) { defer wg.Done() - success := p.Send(e) - successChan <- success - }(peer) - } + success := peer.Send(e) + // For rare cases where PeerSet changes between a call to `peers.Size()` and `peers.ForEach()`. + select { + case successChan <- success: + default: + } + }(p) + }) go func() { wg.Wait() @@ -295,20 +301,15 @@ func (sw *Switch) Broadcast(e Envelope) chan bool { // NumPeers returns the count of outbound/inbound and outbound-dialing peers. // unconditional peers are not counted here. func (sw *Switch) NumPeers() (outbound, inbound, dialing int) { - peers := sw.peers.List() - for _, peer := range peers { - if peer.IsOutbound() { - if !sw.IsPeerUnconditional(peer.ID()) { - outbound++ - } - } else { - if !sw.IsPeerUnconditional(peer.ID()) { - inbound++ - } + sw.peers.ForEach(func(peer Peer) { + if peer.IsOutbound() && !sw.IsPeerUnconditional(peer.ID()) { + outbound++ + } else if !sw.IsPeerUnconditional(peer.ID()) { + inbound++ } - } + }) dialing = sw.dialing.Size() - return + return outbound, inbound, dialing } func (sw *Switch) IsPeerUnconditional(id ID) bool { @@ -329,7 +330,7 @@ func (sw *Switch) Peers() IPeerSet { // StopPeerForError disconnects from a peer due to external error. // If the peer is persistent, it will attempt to reconnect. // TODO: make record depending on reason. -func (sw *Switch) StopPeerForError(peer Peer, reason interface{}) { +func (sw *Switch) StopPeerForError(peer Peer, reason any) { if !peer.IsRunning() { return } @@ -361,12 +362,15 @@ func (sw *Switch) StopPeerGracefully(peer Peer) { sw.stopAndRemovePeer(peer, nil) } -func (sw *Switch) stopAndRemovePeer(peer Peer, reason interface{}) { - sw.transport.Cleanup(peer) +func (sw *Switch) stopAndRemovePeer(peer Peer, reason any) { + // Returning early if the peer is already stopped prevents data races because + // this function may be called from multiple places at once. if err := peer.Stop(); err != nil { - sw.Logger.Error("error while stopping peer", "error", err) // TODO: should return error to be handled accordingly + sw.Logger.Error("error stopping peer", "peer", peer.ID(), "err", err) + return } + sw.transport.Cleanup(peer) for _, reactor := range sw.reactors { reactor.RemovePeer(peer, reason) } @@ -375,13 +379,14 @@ func (sw *Switch) stopAndRemovePeer(peer Peer, reason interface{}) { // reconnect to our node and the switch calls InitPeer before // RemovePeer is finished. // https://github.com/tendermint/tendermint/issues/3338 - if sw.peers.Remove(peer) { - sw.metrics.Peers.Add(float64(-1)) - } else { + if !sw.peers.Remove(peer) { // Removal of the peer has failed. The function above sets a flag within the peer to mark this. // We keep this message here as information to the developer. - sw.Logger.Debug("error on peer removal", ",", "peer", peer.ID()) + sw.Logger.Debug("error on peer removal", "peer", peer.ID()) + return } + + sw.metrics.Peers.Add(float64(-1)) } // reconnectToPeer tries to reconnect to the addr, first repeatedly @@ -454,7 +459,7 @@ func (sw *Switch) MarkPeerAsGood(peer Peer) { } } -//--------------------------------------------------------------------- +// --------------------------------------------------------------------- // Dialing type privateAddr interface { @@ -462,8 +467,8 @@ type privateAddr interface { } func isPrivateAddr(err error) bool { - te, ok := err.(privateAddr) - return ok && te.PrivateAddr() + e, ok := err.(privateAddr) + return ok && e.PrivateAddr() } // DialPeersAsync dials a list of peers asynchronously in random order. @@ -479,7 +484,7 @@ func (sw *Switch) DialPeersAsync(peers []string) error { } // return first non-ErrNetAddressLookup error for _, err := range errs { - if _, ok := err.(ErrNetAddressLookup); ok { + if errors.As(err, &ErrNetAddressLookup{}) { continue } return err @@ -556,7 +561,7 @@ func (sw *Switch) DialPeerWithAddress(addr *NetAddress) error { return sw.addOutboundPeerWithConfig(addr, sw.config) } -// sleep for interval plus some random amount of ms on [0, dialRandomizerIntervalMilliseconds] +// sleep for interval plus some random amount of ms on [0, dialRandomizerIntervalMilliseconds]. func (sw *Switch) randomSleep(interval time.Duration) { r := time.Duration(sw.rng.Int63n(dialRandomizerIntervalMilliseconds)) * time.Millisecond time.Sleep(r + interval) @@ -582,7 +587,7 @@ func (sw *Switch) AddPersistentPeers(addrs []string) error { } // return first non-ErrNetAddressLookup error for _, err := range errs { - if _, ok := err.(ErrNetAddressLookup); ok { + if errors.As(err, &ErrNetAddressLookup{}) { continue } return err @@ -593,11 +598,12 @@ func (sw *Switch) AddPersistentPeers(addrs []string) error { func (sw *Switch) AddUnconditionalPeerIDs(ids []string) error { sw.Logger.Info("Adding unconditional peer ids", "ids", ids) - for i, id := range ids { + for _, id := range ids { err := validateID(ID(id)) if err != nil { - return fmt.Errorf("wrong ID #%d: %w", i, err) + return ErrInvalidPeerID{ID: ID(id), Source: err} } + sw.unconditionalPeerIDs[ID(id)] = struct{}{} } return nil @@ -605,11 +611,12 @@ func (sw *Switch) AddUnconditionalPeerIDs(ids []string) error { func (sw *Switch) AddPrivatePeerIDs(ids []string) error { validIDs := make([]string, 0, len(ids)) - for i, id := range ids { + for _, id := range ids { err := validateID(ID(id)) if err != nil { - return fmt.Errorf("wrong ID #%d: %w", i, err) + return ErrInvalidPeerID{ID: ID(id), Source: err} } + validIDs = append(validIDs, id) } @@ -679,7 +686,7 @@ func (sw *Switch) acceptRoutine() { // So might as well panic and let process managers restart the node. // There's no point in letting the node run without the acceptRoutine, // since it won't be able to accept new connections. - panic(fmt.Errorf("accept routine exited: %v", err)) + panic(fmt.Sprintf("accept routine exited: %v", err)) } break @@ -700,7 +707,6 @@ func (sw *Switch) acceptRoutine() { continue } - } if err := sw.addPeer(p); err != nil { @@ -731,7 +737,7 @@ func (sw *Switch) addOutboundPeerWithConfig( // XXX(xla): Remove the leakage of test concerns in implementation. if cfg.TestDialFail { go sw.reconnectToPeer(addr) - return fmt.Errorf("dial err (peerConfig.DialFail == true)") + return errors.New("dial err (peerConfig.DialFail == true)") } p, err := sw.transport.Dial(*addr, peerConfig{ @@ -839,8 +845,7 @@ func (sw *Switch) addPeer(p Peer) error { // so that if Receive errors, we will find the peer and remove it. // Add should not err since we already checked peers.Has(). if err := sw.peers.Add(p); err != nil { - switch err.(type) { - case ErrPeerRemoval: + if _, ok := err.(ErrPeerRemoval); ok { sw.Logger.Error("Error starting peer ", " err ", "Peer has already errored and removal was attempted.", "peer", p.ID()) diff --git a/p2p/switch_test.go b/p2p/switch_test.go index 4dce6fa105d..12c097e294b 100644 --- a/p2p/switch_test.go +++ b/p2p/switch_test.go @@ -19,17 +19,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + p2pproto "github.com/cometbft/cometbft/api/cometbft/p2p/v1" "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto/ed25519" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/p2p/conn" - p2pproto "github.com/cometbft/cometbft/proto/tendermint/p2p" ) -var ( - cfg *config.P2PConfig -) +var cfg *config.P2PConfig func init() { cfg = config.DefaultP2PConfig() @@ -67,9 +65,9 @@ func (tr *TestReactor) GetChannels() []*conn.ChannelDescriptor { return tr.channels } -func (tr *TestReactor) AddPeer(peer Peer) {} +func (*TestReactor) AddPeer(Peer) {} -func (tr *TestReactor) RemovePeer(peer Peer, reason interface{}) {} +func (*TestReactor) RemovePeer(Peer, any) {} func (tr *TestReactor) Receive(e Envelope) { if tr.logMessages { @@ -87,20 +85,21 @@ func (tr *TestReactor) getMsgs(chID byte) []PeerMessage { return tr.msgsReceived[chID] } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // convenience method for creating two switches connected to each other. -// XXX: note this uses net.Pipe and not a proper TCP conn -func MakeSwitchPair(t testing.TB, initSwitch func(int, *Switch) *Switch) (*Switch, *Switch) { +// XXX: note this uses net.Pipe and not a proper TCP conn. +func MakeSwitchPair(initSwitch func(int, *Switch) *Switch) (*Switch, *Switch) { // Create two switches that will be interconnected. switches := MakeConnectedSwitches(cfg, 2, initSwitch, Connect2Switches) return switches[0], switches[1] } -func initSwitchFunc(i int, sw *Switch) *Switch { +func initSwitchFunc(_ int, sw *Switch) *Switch { sw.SetAddrBook(&AddrBookMock{ Addrs: make(map[string]struct{}), - OurAddrs: make(map[string]struct{})}) + OurAddrs: make(map[string]struct{}), + }) // Make two reactors of two channels each sw.AddReactor("foo", NewTestReactor([]*conn.ChannelDescriptor{ @@ -116,7 +115,7 @@ func initSwitchFunc(i int, sw *Switch) *Switch { } func TestSwitches(t *testing.T) { - s1, s2 := MakeSwitchPair(t, initSwitchFunc) + s1, s2 := MakeSwitchPair(initSwitchFunc) t.Cleanup(func() { if err := s1.Stop(); err != nil { t.Error(err) @@ -182,6 +181,7 @@ func assertMsgReceivedWithTimeout( checkPeriod, timeout time.Duration, ) { + t.Helper() ticker := time.NewTicker(checkPeriod) for { select { @@ -205,7 +205,7 @@ func assertMsgReceivedWithTimeout( } func TestSwitchFiltersOutItself(t *testing.T) { - s1 := MakeSwitch(cfg, 1, "127.0.0.1", "123.123.123", initSwitchFunc) + s1 := MakeSwitch(cfg, 1, initSwitchFunc) // simulate s1 having a public IP by creating a remote peer with the same ID rp := &remotePeer{PrivKey: s1.nodeKey.PrivKey, Config: cfg} @@ -213,7 +213,7 @@ func TestSwitchFiltersOutItself(t *testing.T) { // addr should be rejected in addPeer based on the same ID err := s1.DialPeerWithAddress(rp.Addr()) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here if err, ok := err.(ErrRejected); ok { if !err.IsSelf() { t.Errorf("expected self to be rejected") @@ -235,14 +235,12 @@ func TestSwitchPeerFilter(t *testing.T) { var ( filters = []PeerFilterFunc{ func(_ IPeerSet, _ Peer) error { return nil }, - func(_ IPeerSet, _ Peer) error { return fmt.Errorf("denied") }, + func(_ IPeerSet, _ Peer) error { return errors.New("denied") }, func(_ IPeerSet, _ Peer) error { return nil }, } sw = MakeSwitch( cfg, 1, - "testing", - "123.123.123", initSwitchFunc, SwitchPeerFilters(filters...), ) @@ -291,8 +289,6 @@ func TestSwitchPeerFilterTimeout(t *testing.T) { sw = MakeSwitch( cfg, 1, - "testing", - "123.123.123", initSwitchFunc, SwitchFilterTimeout(5*time.Millisecond), SwitchPeerFilters(filters...), @@ -328,7 +324,7 @@ func TestSwitchPeerFilterTimeout(t *testing.T) { } func TestSwitchPeerFilterDuplicate(t *testing.T) { - sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) + sw := MakeSwitch(cfg, 1, initSwitchFunc) err := sw.Start() require.NoError(t, err) t.Cleanup(func() { @@ -367,6 +363,7 @@ func TestSwitchPeerFilterDuplicate(t *testing.T) { } func assertNoPeersAfterTimeout(t *testing.T, sw *Switch, timeout time.Duration) { + t.Helper() time.Sleep(timeout) if sw.Peers().Size() != 0 { t.Fatalf("Expected %v to not connect to some peers, got %d", sw, sw.Peers().Size()) @@ -376,7 +373,7 @@ func assertNoPeersAfterTimeout(t *testing.T, sw *Switch, timeout time.Duration) func TestSwitchStopsNonPersistentPeerOnError(t *testing.T) { assert, require := assert.New(t), require.New(t) - sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) + sw := MakeSwitch(cfg, 1, initSwitchFunc) err := sw.Start() if err != nil { t.Error(err) @@ -398,10 +395,10 @@ func TestSwitchStopsNonPersistentPeerOnError(t *testing.T) { isPersistent: sw.IsPeerPersistent, reactorsByCh: sw.reactorsByCh, }) - require.Nil(err) + require.NoError(err) err = sw.addPeer(p) - require.Nil(err) + require.NoError(err) require.NotNil(sw.Peers().Get(rp.ID())) @@ -436,7 +433,7 @@ func TestSwitchStopPeerForError(t *testing.T) { p2pMetrics := PrometheusMetrics(namespace) // make two connected switches - sw1, sw2 := MakeSwitchPair(t, func(i int, sw *Switch) *Switch { + sw1, sw2 := MakeSwitchPair(func(i int, sw *Switch) *Switch { // set metrics on sw1 if i == 0 { opt := WithMetrics(p2pMetrics) @@ -445,11 +442,11 @@ func TestSwitchStopPeerForError(t *testing.T) { return initSwitchFunc(i, sw) }) - assert.Equal(t, len(sw1.Peers().List()), 1) + assert.Len(t, sw1.Peers().Copy(), 1) assert.EqualValues(t, 1, peersMetricValue()) // send messages to the peer from sw1 - p := sw1.Peers().List()[0] + p := sw1.Peers().Copy()[0] p.Send(Envelope{ ChannelID: 0x1, Message: &p2pproto.Message{}, @@ -464,14 +461,14 @@ func TestSwitchStopPeerForError(t *testing.T) { }) // now call StopPeerForError explicitly, eg. from a reactor - sw1.StopPeerForError(p, fmt.Errorf("some err")) + sw1.StopPeerForError(p, errors.New("some err")) - assert.Equal(t, len(sw1.Peers().List()), 0) + require.Empty(t, len(sw1.Peers().Copy()), 0) assert.EqualValues(t, 0, peersMetricValue()) } func TestSwitchReconnectsToOutboundPersistentPeer(t *testing.T) { - sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) + sw := MakeSwitch(cfg, 1, initSwitchFunc) err := sw.Start() require.NoError(t, err) t.Cleanup(func() { @@ -489,10 +486,10 @@ func TestSwitchReconnectsToOutboundPersistentPeer(t *testing.T) { require.NoError(t, err) err = sw.DialPeerWithAddress(rp.Addr()) - require.Nil(t, err) + require.NoError(t, err) require.NotNil(t, sw.Peers().Get(rp.ID())) - p := sw.Peers().List()[0] + p := sw.Peers().Copy()[0] err = p.(*peer).CloseConn() require.NoError(t, err) @@ -514,14 +511,14 @@ func TestSwitchReconnectsToOutboundPersistentPeer(t *testing.T) { conf := config.DefaultP2PConfig() conf.TestDialFail = true // will trigger a reconnect err = sw.addOutboundPeerWithConfig(rp.Addr(), conf) - require.NotNil(t, err) + require.Error(t, err) // DialPeerWithAddres - sw.peerConfig resets the dialer waitUntilSwitchHasAtLeastNPeers(sw, 2) assert.Equal(t, 2, sw.Peers().Size()) } func TestSwitchReconnectsToInboundPersistentPeer(t *testing.T) { - sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) + sw := MakeSwitch(cfg, 1, initSwitchFunc) err := sw.Start() require.NoError(t, err) t.Cleanup(func() { @@ -554,7 +551,7 @@ func TestSwitchDialPeersAsync(t *testing.T) { return } - sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) + sw := MakeSwitch(cfg, 1, initSwitchFunc) err := sw.Start() require.NoError(t, err) t.Cleanup(func() { @@ -620,7 +617,7 @@ func TestSwitchAcceptRoutine(t *testing.T) { } // make switch - sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) + sw := MakeSwitch(cfg, 1, initSwitchFunc) err := sw.AddUnconditionalPeerIDs(unconditionalPeerIDs) require.NoError(t, err) err = sw.Start() @@ -664,7 +661,7 @@ func TestSwitchAcceptRoutine(t *testing.T) { one := make([]byte, 1) _ = conn.SetReadDeadline(time.Now().Add(10 * time.Millisecond)) _, err = conn.Read(one) - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, cfg.MaxNumInboundPeers, sw.Peers().Size()) peer.Stop() @@ -698,16 +695,18 @@ type errorTransport struct { acceptErr error } -func (et errorTransport) NetAddress() NetAddress { +func (errorTransport) NetAddress() NetAddress { panic("not implemented") } -func (et errorTransport) Accept(c peerConfig) (Peer, error) { +func (et errorTransport) Accept(peerConfig) (Peer, error) { return nil, et.acceptErr } + func (errorTransport) Dial(NetAddress, peerConfig) (Peer, error) { panic("not implemented") } + func (errorTransport) Cleanup(Peer) { panic("not implemented") } @@ -749,7 +748,7 @@ type mockReactor struct { initCalledBeforeRemoveFinished uint32 } -func (r *mockReactor) RemovePeer(peer Peer, reason interface{}) { +func (r *mockReactor) RemovePeer(Peer, any) { atomic.StoreUint32(&r.removePeerInProgress, 1) defer atomic.StoreUint32(&r.removePeerInProgress, 0) time.Sleep(100 * time.Millisecond) @@ -767,14 +766,14 @@ func (r *mockReactor) InitCalledBeforeRemoveFinished() bool { return atomic.LoadUint32(&r.initCalledBeforeRemoveFinished) == 1 } -// see stopAndRemovePeer +// see stopAndRemovePeer. func TestSwitchInitPeerIsNotCalledBeforeRemovePeer(t *testing.T) { // make reactor reactor := &mockReactor{} reactor.BaseReactor = NewBaseReactor("mockReactor", reactor) // make switch - sw := MakeSwitch(cfg, 1, "testing", "123.123.123", func(i int, sw *Switch) *Switch { + sw := MakeSwitch(cfg, 1, func(_ int, sw *Switch) *Switch { sw.AddReactor("mock", reactor) return sw }) @@ -813,7 +812,7 @@ func TestSwitchInitPeerIsNotCalledBeforeRemovePeer(t *testing.T) { } func BenchmarkSwitchBroadcast(b *testing.B) { - s1, s2 := MakeSwitchPair(b, func(i int, sw *Switch) *Switch { + s1, s2 := MakeSwitchPair(func(_ int, sw *Switch) *Switch { // Make bar reactors of bar channels each sw.AddReactor("foo", NewTestReactor([]*conn.ChannelDescriptor{ {ID: byte(0x00), Priority: 10}, @@ -862,14 +861,13 @@ func BenchmarkSwitchBroadcast(b *testing.B) { } func TestSwitchRemovalErr(t *testing.T) { - - sw1, sw2 := MakeSwitchPair(t, func(i int, sw *Switch) *Switch { + sw1, sw2 := MakeSwitchPair(func(i int, sw *Switch) *Switch { return initSwitchFunc(i, sw) }) - assert.Equal(t, len(sw1.Peers().List()), 1) - p := sw1.Peers().List()[0] + require.Len(t, sw1.Peers().Copy(), 1) + p := sw1.Peers().Copy()[0] - sw2.StopPeerForError(p, fmt.Errorf("peer should error")) + sw2.StopPeerForError(p, errors.New("peer should error")) assert.Equal(t, sw2.peers.Add(p).Error(), ErrPeerRemoval{}.Error()) } diff --git a/p2p/test_util.go b/p2p/test_util.go index 2941c102d7c..0ac2090b5d9 100644 --- a/p2p/test_util.go +++ b/p2p/test_util.go @@ -5,28 +5,27 @@ import ( "net" "time" + "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" + cmtnet "github.com/cometbft/cometbft/internal/net" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/libs/log" - cmtnet "github.com/cometbft/cometbft/libs/net" - cmtrand "github.com/cometbft/cometbft/libs/rand" - - "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/p2p/conn" ) const testCh = 0x01 -//------------------------------------------------ +// ------------------------------------------------ type mockNodeInfo struct { addr *NetAddress } -func (ni mockNodeInfo) ID() ID { return ni.addr.ID } -func (ni mockNodeInfo) NetAddress() (*NetAddress, error) { return ni.addr, nil } -func (ni mockNodeInfo) Validate() error { return nil } -func (ni mockNodeInfo) CompatibleWith(other NodeInfo) error { return nil } +func (ni mockNodeInfo) ID() ID { return ni.addr.ID } +func (ni mockNodeInfo) NetAddress() (*NetAddress, error) { return ni.addr, nil } +func (mockNodeInfo) Validate() error { return nil } +func (mockNodeInfo) CompatibleWith(NodeInfo) error { return nil } func AddPeerToSwitchPeerSet(sw *Switch, peer Peer) { sw.peers.Add(peer) //nolint:errcheck // ignore error @@ -64,10 +63,10 @@ func CreateRoutableAddr() (addr string, netAddr *NetAddress) { break } } - return + return addr, netAddr } -//------------------------------------------------------------------ +// ------------------------------------------------------------------ // Connects switches via arbitrary net.Conn. Used for testing. const TestHost = "localhost" @@ -83,7 +82,7 @@ func MakeConnectedSwitches(cfg *config.P2PConfig, ) []*Switch { switches := make([]*Switch, n) for i := 0; i < n; i++ { - switches[i] = MakeSwitch(cfg, i, TestHost, "123.123.123", initSwitch) + switches[i] = MakeSwitch(cfg, i, initSwitch) } if err := StartSwitches(switches); err != nil { @@ -127,6 +126,40 @@ func Connect2Switches(switches []*Switch, i, j int) { <-doneCh } +// ConnectStartSwitches will connect switches c and j via net.Pipe(). +func ConnectStarSwitches(c int) func([]*Switch, int, int) { + // Blocks until a connection is established. + // NOTE: caller ensures i and j is within bounds. + return func(switches []*Switch, i, j int) { + if i != c { + return + } + + switchI := switches[i] + switchJ := switches[j] + + c1, c2 := conn.NetPipe() + + doneCh := make(chan struct{}) + go func() { + err := switchI.addPeerWithConnection(c1) + if err != nil { + panic(err) + } + doneCh <- struct{}{} + }() + go func() { + err := switchJ.addPeerWithConnection(c2) + if err != nil { + panic(err) + } + doneCh <- struct{}{} + }() + <-doneCh + <-doneCh + } +} + func (sw *Switch) addPeerWithConnection(conn net.Conn) error { pc, err := testInboundPeerConn(conn, sw.config, sw.nodeKey.PrivKey) if err != nil { @@ -178,11 +211,9 @@ func StartSwitches(switches []*Switch) error { func MakeSwitch( cfg *config.P2PConfig, i int, - network, version string, initSwitch func(int, *Switch) *Switch, opts ...SwitchOption, ) *Switch { - nodeKey := NodeKey{ PrivKey: ed25519.GenPrivKey(), } @@ -252,7 +283,7 @@ func testPeerConn( return newPeerConn(outbound, persistent, conn, socketAddr), nil } -//---------------------------------------------------------------- +// ---------------------------------------------------------------- // rand node info func testNodeInfo(id ID, name string) NodeInfo { @@ -291,7 +322,7 @@ type AddrBookMock struct { var _ AddrBook = (*AddrBookMock)(nil) -func (book *AddrBookMock) AddAddress(addr *NetAddress, src *NetAddress) error { +func (book *AddrBookMock) AddAddress(addr *NetAddress, _ *NetAddress) error { book.Addrs[addr.String()] = struct{}{} return nil } @@ -300,15 +331,16 @@ func (book *AddrBookMock) OurAddress(addr *NetAddress) bool { _, ok := book.OurAddrs[addr.String()] return ok } -func (book *AddrBookMock) MarkGood(ID) {} +func (*AddrBookMock) MarkGood(ID) {} func (book *AddrBookMock) HasAddress(addr *NetAddress) bool { _, ok := book.Addrs[addr.String()] return ok } + func (book *AddrBookMock) RemoveAddress(addr *NetAddress) { delete(book.Addrs, addr.String()) } -func (book *AddrBookMock) Save() {} +func (*AddrBookMock) Save() {} func (book *AddrBookMock) AddPrivateIDs(addrs []string) { for _, addr := range addrs { book.PrivateAddrs[addr] = struct{}{} diff --git a/p2p/transport.go b/p2p/transport.go index 96d3738d662..f915ce94cb5 100644 --- a/p2p/transport.go +++ b/p2p/transport.go @@ -6,14 +6,13 @@ import ( "net" "time" - "golang.org/x/net/netutil" - "github.com/cosmos/gogoproto/proto" + "golang.org/x/net/netutil" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" "github.com/cometbft/cometbft/crypto" - "github.com/cometbft/cometbft/libs/protoio" + "github.com/cometbft/cometbft/internal/protoio" "github.com/cometbft/cometbft/p2p/conn" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" ) const ( @@ -24,7 +23,7 @@ const ( // IPResolver is a behavior subset of net.Resolver. type IPResolver interface { - LookupIPAddr(context.Context, string) ([]net.IPAddr, error) + LookupIPAddr(ctx context.Context, host string) ([]net.IPAddr, error) } // accept is the container to carry the upgraded connection and NodeInfo from an @@ -44,7 +43,7 @@ type accept struct { // TODO(xla): Refactor out with more static Reactor setup and PeerBehaviour. type peerConfig struct { chDescs []*conn.ChannelDescriptor - onPeerError func(Peer, interface{}) + onPeerError func(Peer, any) outbound bool // isPersistent allows you to set a function, which, given socket address // (for outbound peers) OR self-reported address (for inbound peers), tells @@ -64,24 +63,24 @@ type Transport interface { NetAddress() NetAddress // Accept returns a newly connected Peer. - Accept(peerConfig) (Peer, error) + Accept(config peerConfig) (Peer, error) // Dial connects to the Peer for the address. - Dial(NetAddress, peerConfig) (Peer, error) + Dial(addr NetAddress, config peerConfig) (Peer, error) // Cleanup any resources associated with Peer. - Cleanup(Peer) + Cleanup(peer Peer) } // transportLifecycle bundles the methods for callers to control start and stop // behavior. type transportLifecycle interface { Close() error - Listen(NetAddress) error + Listen(addr NetAddress) error } // ConnFilterFunc to be implemented by filter hooks after a new connection has -// been established. The set of exisiting connections is passed along together +// been established. The set of existing connections is passed along together // with all resolved IPs for the new connection. type ConnFilterFunc func(ConnSet, net.Conn, []net.IP) error @@ -129,7 +128,7 @@ func MultiplexTransportResolver(resolver IPResolver) MultiplexTransportOption { } // MultiplexTransportMaxIncomingConnections sets the maximum number of -// simultaneous connections (incoming). Default: 0 (unlimited) +// simultaneous connections (incoming). Default: 0 (unlimited). func MultiplexTransportMaxIncomingConnections(n int) MultiplexTransportOption { return func(mt *MultiplexTransport) { mt.maxIncomingConnections = n } } @@ -162,8 +161,10 @@ type MultiplexTransport struct { } // Test multiplexTransport for interface completeness. -var _ Transport = (*MultiplexTransport)(nil) -var _ transportLifecycle = (*MultiplexTransport)(nil) +var ( + _ Transport = (*MultiplexTransport)(nil) + _ transportLifecycle = (*MultiplexTransport)(nil) +) // NewMultiplexTransport returns a tcp connected multiplexed peer. func NewMultiplexTransport( @@ -218,6 +219,11 @@ func (mt *MultiplexTransport) Dial( return nil, err } + if mt.mConfig.TestFuzz { + // so we have time to do peer handshakes and get set up. + c = FuzzConnAfterFromConfig(c, 10*time.Second, mt.mConfig.TestFuzzConfig) + } + // TODO(xla): Evaluate if we should apply filters if we explicitly dial. if err := mt.filterConn(c); err != nil { return nil, err @@ -268,7 +274,7 @@ func (mt *MultiplexTransport) Listen(addr NetAddress) error { // AddChannel registers a channel to nodeInfo. // NOTE: NodeInfo must be of type DefaultNodeInfo else channels won't be updated // This is a bit messy at the moment but is cleaned up in the following version -// when NodeInfo changes from an interface to a concrete type +// when NodeInfo changes from an interface to a concrete type. func (mt *MultiplexTransport) AddChannel(chID byte) { if ni, ok := mt.nodeInfo.(DefaultNodeInfo); ok { if !ni.HasChannel(chID) { @@ -395,7 +401,6 @@ func (mt *MultiplexTransport) filterConn(c net.Conn) (err error) { case <-time.After(mt.filterTimeout): return ErrFilterTimeout{} } - } mt.conns.Set(c, ips) @@ -417,7 +422,7 @@ func (mt *MultiplexTransport) upgrade( if err != nil { return nil, nil, ErrRejected{ conn: c, - err: fmt.Errorf("secret conn failed: %v", err), + err: fmt.Errorf("secret conn failed: %w", err), isAuthFailure: true, } } @@ -443,7 +448,7 @@ func (mt *MultiplexTransport) upgrade( if err != nil { return nil, nil, ErrRejected{ conn: c, - err: fmt.Errorf("handshake failed: %v", err), + err: fmt.Errorf("handshake failed: %w", err), isAuthFailure: true, } } @@ -498,7 +503,6 @@ func (mt *MultiplexTransport) wrapPeer( cfg peerConfig, socketAddr *NetAddress, ) Peer { - persistent := false if cfg.isPersistent != nil { if cfg.outbound { diff --git a/p2p/transport_test.go b/p2p/transport_test.go index 3c404f6a8dd..7e0f088cadf 100644 --- a/p2p/transport_test.go +++ b/p2p/transport_test.go @@ -1,7 +1,7 @@ package p2p import ( - "fmt" + "errors" "math/rand" "net" "reflect" @@ -10,10 +10,10 @@ import ( "testing" "time" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" "github.com/cometbft/cometbft/crypto/ed25519" - "github.com/cometbft/cometbft/libs/protoio" + "github.com/cometbft/cometbft/internal/protoio" "github.com/cometbft/cometbft/p2p/conn" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" ) var defaultNodeName = "host_peer" @@ -47,7 +47,7 @@ func TestTransportMultiplexConnFilter(t *testing.T) { func(_ ConnSet, _ net.Conn, _ []net.IP) error { return nil }, func(_ ConnSet, _ net.Conn, _ []net.IP) error { return nil }, func(_ ConnSet, _ net.Conn, _ []net.IP) error { - return fmt.Errorf("rejected") + return errors.New("rejected") }, )(mt) @@ -296,7 +296,7 @@ func TestTransportMultiplexAcceptNonBlocking(t *testing.T) { // Fast peer connected. case <-time.After(200 * time.Millisecond): // We error if the fast peer didn't succeed. - errc <- fmt.Errorf("fast peer timed out") + errc <- errors.New("fast peer timed out") } sc, err := upgradeSecretConn(c, 200*time.Millisecond, ed25519.GenPrivKey()) @@ -319,13 +319,11 @@ func TestTransportMultiplexAcceptNonBlocking(t *testing.T) { go func() { <-slowc - var ( - dialer = newMultiplexTransport( - fastNodeInfo, - NodeKey{ - PrivKey: fastNodePV, - }, - ) + dialer := newMultiplexTransport( + fastNodeInfo, + NodeKey{ + PrivKey: fastNodePV, + }, ) addr := NewNetAddress(mt.nodeKey.ID(), mt.listener.Addr()) @@ -588,10 +586,8 @@ func TestTransportHandshake(t *testing.T) { } }(c) go func(c net.Conn) { - var ( - // ni DefaultNodeInfo - pbni tmp2p.DefaultNodeInfo - ) + // ni DefaultNodeInfo + var pbni tmp2p.DefaultNodeInfo protoReader := protoio.NewDelimitedReader(c, MaxNodeInfoSize()) _, err := protoReader.ReadMsg(&pbni) @@ -636,8 +632,9 @@ func TestTransportAddChannel(t *testing.T) { } } -// create listener +// create listener. func testSetupMultiplexTransport(t *testing.T) *MultiplexTransport { + t.Helper() var ( pv = ed25519.GenPrivKey() id = PubKeyToID(pv.PubKey()) @@ -668,39 +665,39 @@ func testSetupMultiplexTransport(t *testing.T) *MultiplexTransport { type testTransportAddr struct{} -func (a *testTransportAddr) Network() string { return "tcp" } -func (a *testTransportAddr) String() string { return "test.local:1234" } +func (*testTransportAddr) Network() string { return "tcp" } +func (*testTransportAddr) String() string { return "test.local:1234" } type testTransportConn struct{} -func (c *testTransportConn) Close() error { - return fmt.Errorf("close() not implemented") +func (*testTransportConn) Close() error { + return errors.New("close() not implemented") } -func (c *testTransportConn) LocalAddr() net.Addr { +func (*testTransportConn) LocalAddr() net.Addr { return &testTransportAddr{} } -func (c *testTransportConn) RemoteAddr() net.Addr { +func (*testTransportConn) RemoteAddr() net.Addr { return &testTransportAddr{} } -func (c *testTransportConn) Read(_ []byte) (int, error) { - return -1, fmt.Errorf("read() not implemented") +func (*testTransportConn) Read(_ []byte) (int, error) { + return -1, errors.New("read() not implemented") } -func (c *testTransportConn) SetDeadline(_ time.Time) error { - return fmt.Errorf("setDeadline() not implemented") +func (*testTransportConn) SetDeadline(_ time.Time) error { + return errors.New("setDeadline() not implemented") } -func (c *testTransportConn) SetReadDeadline(_ time.Time) error { - return fmt.Errorf("setReadDeadline() not implemented") +func (*testTransportConn) SetReadDeadline(_ time.Time) error { + return errors.New("setReadDeadline() not implemented") } -func (c *testTransportConn) SetWriteDeadline(_ time.Time) error { - return fmt.Errorf("setWriteDeadline() not implemented") +func (*testTransportConn) SetWriteDeadline(_ time.Time) error { + return errors.New("setWriteDeadline() not implemented") } -func (c *testTransportConn) Write(_ []byte) (int, error) { - return -1, fmt.Errorf("write() not implemented") +func (*testTransportConn) Write(_ []byte) (int, error) { + return -1, errors.New("write() not implemented") } diff --git a/p2p/types.go b/p2p/types.go index 48a6746ceba..153c5d7b384 100644 --- a/p2p/types.go +++ b/p2p/types.go @@ -3,12 +3,15 @@ package p2p import ( "github.com/cosmos/gogoproto/proto" + tmp2p "github.com/cometbft/cometbft/api/cometbft/p2p/v1" "github.com/cometbft/cometbft/p2p/conn" - tmp2p "github.com/cometbft/cometbft/proto/tendermint/p2p" + "github.com/cometbft/cometbft/types" ) -type ChannelDescriptor = conn.ChannelDescriptor -type ConnectionStatus = conn.ConnectionStatus +type ( + ChannelDescriptor = conn.ChannelDescriptor + ConnectionStatus = conn.ConnectionStatus +) // Envelope contains a message with sender routing info. type Envelope struct { @@ -17,25 +20,7 @@ type Envelope struct { ChannelID byte } -// Unwrapper is a Protobuf message that can contain a variety of inner messages -// (e.g. via oneof fields). If a Channel's message type implements Unwrapper, the -// p2p layer will automatically unwrap inbound messages so that reactors do not have to do this themselves. -type Unwrapper interface { - proto.Message - - // Unwrap will unwrap the inner message contained in this message. - Unwrap() (proto.Message, error) -} - -// Wrapper is a companion type to Unwrapper. It is a Protobuf message that can contain a variety of inner messages. The p2p layer will automatically wrap outbound messages so that the reactors do not have to do it themselves. -type Wrapper interface { - proto.Message - - // Wrap will take the underlying message and wrap it in its wrapper type. - Wrap() proto.Message -} - var ( - _ Wrapper = &tmp2p.PexRequest{} - _ Wrapper = &tmp2p.PexAddrs{} + _ types.Wrapper = &tmp2p.PexRequest{} + _ types.Wrapper = &tmp2p.PexAddrs{} ) diff --git a/p2p/upnp/probe.go b/p2p/upnp/probe.go deleted file mode 100644 index b40d92e65ad..00000000000 --- a/p2p/upnp/probe.go +++ /dev/null @@ -1,117 +0,0 @@ -package upnp - -import ( - "fmt" - "net" - "time" - - "github.com/cometbft/cometbft/libs/log" -) - -type Capabilities struct { - PortMapping bool - Hairpin bool -} - -func makeUPNPListener(intPort int, extPort int, logger log.Logger) (NAT, net.Listener, net.IP, error) { - nat, err := Discover() - if err != nil { - return nil, nil, nil, fmt.Errorf("nat upnp could not be discovered: %v", err) - } - logger.Info("make upnp listener", "msg", log.NewLazySprintf("ourIP: %v", nat.(*upnpNAT).ourIP)) - - ext, err := nat.GetExternalAddress() - if err != nil { - return nat, nil, nil, fmt.Errorf("external address error: %v", err) - } - logger.Info("make upnp listener", "msg", log.NewLazySprintf("External address: %v", ext)) - - port, err := nat.AddPortMapping("tcp", extPort, intPort, "CometBFT UPnP Probe", 0) - if err != nil { - return nat, nil, ext, fmt.Errorf("port mapping error: %v", err) - } - logger.Info("make upnp listener", "msg", log.NewLazySprintf("Port mapping mapped: %v", port)) - - // also run the listener, open for all remote addresses. - listener, err := net.Listen("tcp", fmt.Sprintf(":%v", intPort)) - if err != nil { - return nat, nil, ext, fmt.Errorf("error establishing listener: %v", err) - } - return nat, listener, ext, nil -} - -func testHairpin(listener net.Listener, extAddr string, logger log.Logger) (supportsHairpin bool) { - // Listener - go func() { - inConn, err := listener.Accept() - if err != nil { - logger.Info("test hair pin", "msg", log.NewLazySprintf("Listener.Accept() error: %v", err)) - return - } - logger.Info("test hair pin", - "msg", - log.NewLazySprintf("Accepted incoming connection: %v -> %v", inConn.LocalAddr(), inConn.RemoteAddr())) - buf := make([]byte, 1024) - n, err := inConn.Read(buf) - if err != nil { - logger.Info("test hair pin", - "msg", - log.NewLazySprintf("Incoming connection read error: %v", err)) - return - } - logger.Info("test hair pin", - "msg", - log.NewLazySprintf("Incoming connection read %v bytes: %X", n, buf)) - if string(buf) == "test data" { - supportsHairpin = true - return - } - }() - - // Establish outgoing - outConn, err := net.Dial("tcp", extAddr) - if err != nil { - logger.Info("test hair pin", "msg", log.NewLazySprintf("Outgoing connection dial error: %v", err)) - return - } - - n, err := outConn.Write([]byte("test data")) - if err != nil { - logger.Info("test hair pin", "msg", log.NewLazySprintf("Outgoing connection write error: %v", err)) - return - } - logger.Info("test hair pin", "msg", log.NewLazySprintf("Outgoing connection wrote %v bytes", n)) - - // Wait for data receipt - time.Sleep(1 * time.Second) - return supportsHairpin -} - -func Probe(logger log.Logger) (caps Capabilities, err error) { - logger.Info("Probing for UPnP!") - - intPort, extPort := 8001, 8001 - - nat, listener, ext, err := makeUPNPListener(intPort, extPort, logger) - if err != nil { - return - } - caps.PortMapping = true - - // Deferred cleanup - defer func() { - if err := nat.DeletePortMapping("tcp", intPort, extPort); err != nil { - logger.Error(fmt.Sprintf("Port mapping delete error: %v", err)) - } - if err := listener.Close(); err != nil { - logger.Error(fmt.Sprintf("Listener closing error: %v", err)) - } - }() - - supportsHairpin := testHairpin(listener, fmt.Sprintf("%v:%v", ext, extPort), logger) - if supportsHairpin { - caps.Hairpin = true - } - - return -} diff --git a/p2p/upnp/upnp.go b/p2p/upnp/upnp.go deleted file mode 100644 index 45da9d33cb8..00000000000 --- a/p2p/upnp/upnp.go +++ /dev/null @@ -1,404 +0,0 @@ -// Taken from taipei-torrent. -// Just enough UPnP to be able to forward ports -// For more information, see: http://www.upnp-hacks.org/upnp.html -package upnp - -// TODO: use syscalls to get actual ourIP, see issue #712 - -import ( - "bytes" - "encoding/xml" - "errors" - "fmt" - "io" - "net" - "net/http" - "strconv" - "strings" - "time" -) - -type upnpNAT struct { - serviceURL string - ourIP string - urnDomain string -} - -// protocol is either "udp" or "tcp" -type NAT interface { - GetExternalAddress() (addr net.IP, err error) - AddPortMapping( - protocol string, - externalPort, - internalPort int, - description string, - timeout int) (mappedExternalPort int, err error) - DeletePortMapping(protocol string, externalPort, internalPort int) (err error) -} - -func Discover() (nat NAT, err error) { - ssdp, err := net.ResolveUDPAddr("udp4", "239.255.255.250:1900") - if err != nil { - return - } - conn, err := net.ListenPacket("udp4", ":0") - if err != nil { - return - } - socket := conn.(*net.UDPConn) - defer socket.Close() - - if err := socket.SetDeadline(time.Now().Add(3 * time.Second)); err != nil { - return nil, err - } - - st := "InternetGatewayDevice:1" - - buf := bytes.NewBufferString( - "M-SEARCH * HTTP/1.1\r\n" + - "HOST: 239.255.255.250:1900\r\n" + - "ST: ssdp:all\r\n" + - "MAN: \"ssdp:discover\"\r\n" + - "MX: 2\r\n\r\n") - message := buf.Bytes() - answerBytes := make([]byte, 1024) - for i := 0; i < 3; i++ { - _, err = socket.WriteToUDP(message, ssdp) - if err != nil { - return - } - var n int - _, _, err = socket.ReadFromUDP(answerBytes) - if err != nil { - return - } - for { - n, _, err = socket.ReadFromUDP(answerBytes) - if err != nil { - break - } - answer := string(answerBytes[0:n]) - if !strings.Contains(answer, st) { - continue - } - // HTTP header field names are case-insensitive. - // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 - locString := "\r\nlocation:" - answer = strings.ToLower(answer) - locIndex := strings.Index(answer, locString) - if locIndex < 0 { - continue - } - loc := answer[locIndex+len(locString):] - endIndex := strings.Index(loc, "\r\n") - if endIndex < 0 { - continue - } - locURL := strings.TrimSpace(loc[0:endIndex]) - var serviceURL, urnDomain string - serviceURL, urnDomain, err = getServiceURL(locURL) - if err != nil { - return - } - var ourIP net.IP - ourIP, err = localIPv4() - if err != nil { - return - } - nat = &upnpNAT{serviceURL: serviceURL, ourIP: ourIP.String(), urnDomain: urnDomain} - return - } - } - err = errors.New("upnp port discovery failed") - return nat, err -} - -type Envelope struct { - XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"` - Soap *SoapBody -} -type SoapBody struct { - XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"` - ExternalIP *ExternalIPAddressResponse -} - -type ExternalIPAddressResponse struct { - XMLName xml.Name `xml:"GetExternalIPAddressResponse"` - IPAddress string `xml:"NewExternalIPAddress"` -} - -type ExternalIPAddress struct { - XMLName xml.Name `xml:"NewExternalIPAddress"` - IP string -} - -type Service struct { - ServiceType string `xml:"serviceType"` - ControlURL string `xml:"controlURL"` -} - -type DeviceList struct { - Device []Device `xml:"device"` -} - -type ServiceList struct { - Service []Service `xml:"service"` -} - -type Device struct { - XMLName xml.Name `xml:"device"` - DeviceType string `xml:"deviceType"` - DeviceList DeviceList `xml:"deviceList"` - ServiceList ServiceList `xml:"serviceList"` -} - -type Root struct { - Device Device -} - -func getChildDevice(d *Device, deviceType string) *Device { - dl := d.DeviceList.Device - for i := 0; i < len(dl); i++ { - if strings.Contains(dl[i].DeviceType, deviceType) { - return &dl[i] - } - } - return nil -} - -func getChildService(d *Device, serviceType string) *Service { - sl := d.ServiceList.Service - for i := 0; i < len(sl); i++ { - if strings.Contains(sl[i].ServiceType, serviceType) { - return &sl[i] - } - } - return nil -} - -func localIPv4() (net.IP, error) { - tt, err := net.Interfaces() - if err != nil { - return nil, err - } - for _, t := range tt { - aa, err := t.Addrs() - if err != nil { - return nil, err - } - for _, a := range aa { - ipnet, ok := a.(*net.IPNet) - if !ok { - continue - } - v4 := ipnet.IP.To4() - if v4 == nil || v4[0] == 127 { // loopback address - continue - } - return v4, nil - } - } - return nil, errors.New("cannot find local IP address") -} - -func getServiceURL(rootURL string) (url, urnDomain string, err error) { - r, err := http.Get(rootURL) //nolint: gosec - if err != nil { - return - } - defer r.Body.Close() - - if r.StatusCode >= 400 { - err = errors.New(string(rune(r.StatusCode))) - return - } - var root Root - err = xml.NewDecoder(r.Body).Decode(&root) - if err != nil { - return - } - a := &root.Device - if !strings.Contains(a.DeviceType, "InternetGatewayDevice:1") { - err = errors.New("no InternetGatewayDevice") - return - } - b := getChildDevice(a, "WANDevice:1") - if b == nil { - err = errors.New("no WANDevice") - return - } - c := getChildDevice(b, "WANConnectionDevice:1") - if c == nil { - err = errors.New("no WANConnectionDevice") - return - } - d := getChildService(c, "WANIPConnection:1") - if d == nil { - // Some routers don't follow the UPnP spec, and put WanIPConnection under WanDevice, - // instead of under WanConnectionDevice - d = getChildService(b, "WANIPConnection:1") - - if d == nil { - err = errors.New("no WANIPConnection") - return - } - } - // Extract the domain name, which isn't always 'schemas-upnp-org' - urnDomain = strings.Split(d.ServiceType, ":")[1] - url = combineURL(rootURL, d.ControlURL) - return url, urnDomain, err -} - -func combineURL(rootURL, subURL string) string { - protocolEnd := "://" - protoEndIndex := strings.Index(rootURL, protocolEnd) - a := rootURL[protoEndIndex+len(protocolEnd):] - rootIndex := strings.Index(a, "/") - return rootURL[0:protoEndIndex+len(protocolEnd)+rootIndex] + subURL -} - -func soapRequest(url, function, message, domain string) (r *http.Response, err error) { - fullMessage := "" + - "\r\n" + - "" + message + "" - - req, err := http.NewRequest("POST", url, strings.NewReader(fullMessage)) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "text/xml ; charset=\"utf-8\"") - req.Header.Set("User-Agent", "Darwin/10.0.0, UPnP/1.0, MiniUPnPc/1.3") - // req.Header.Set("Transfer-Encoding", "chunked") - req.Header.Set("SOAPAction", "\"urn:"+domain+":service:WANIPConnection:1#"+function+"\"") - req.Header.Set("Connection", "Close") - req.Header.Set("Cache-Control", "no-cache") - req.Header.Set("Pragma", "no-cache") - - // log.Stderr("soapRequest ", req) - - r, err = http.DefaultClient.Do(req) - if err != nil { - return nil, err - } - /*if r.Body != nil { - defer r.Body.Close() - }*/ - - if r.StatusCode >= 400 { - // log.Stderr(function, r.StatusCode) - err = errors.New("error " + strconv.Itoa(r.StatusCode) + " for " + function) - r = nil - return - } - return r, err -} - -type statusInfo struct { - externalIPAddress string -} - -func (n *upnpNAT) getExternalIPAddress() (info statusInfo, err error) { - - message := "\r\n" + - "" - - var response *http.Response - response, err = soapRequest(n.serviceURL, "GetExternalIPAddress", message, n.urnDomain) - if response != nil { - defer response.Body.Close() - } - if err != nil { - return - } - var envelope Envelope - data, err := io.ReadAll(response.Body) - if err != nil { - return - } - reader := bytes.NewReader(data) - err = xml.NewDecoder(reader).Decode(&envelope) - if err != nil { - return - } - - info = statusInfo{envelope.Soap.ExternalIP.IPAddress} - - if err != nil { - return - } - - return info, err -} - -// GetExternalAddress returns an external IP. If GetExternalIPAddress action -// fails or IP returned is invalid, GetExternalAddress returns an error. -func (n *upnpNAT) GetExternalAddress() (addr net.IP, err error) { - info, err := n.getExternalIPAddress() - if err != nil { - return - } - addr = net.ParseIP(info.externalIPAddress) - if addr == nil { - err = fmt.Errorf("failed to parse IP: %v", info.externalIPAddress) - } - return -} - -func (n *upnpNAT) AddPortMapping( - protocol string, - externalPort, - internalPort int, - description string, - timeout int) (mappedExternalPort int, err error) { - // A single concatenation would break ARM compilation. - message := "\r\n" + - "" + strconv.Itoa(externalPort) - message += "" + protocol + "" - message += "" + strconv.Itoa(internalPort) + "" + - "" + n.ourIP + "" + - "1" - message += description + - "" + strconv.Itoa(timeout) + - "" - - var response *http.Response - response, err = soapRequest(n.serviceURL, "AddPortMapping", message, n.urnDomain) - if response != nil { - defer response.Body.Close() - } - if err != nil { - return - } - - // TODO: check response to see if the port was forwarded - // log.Println(message, response) - // JAE: - // body, err := io.ReadAll(response.Body) - // fmt.Println(string(body), err) - mappedExternalPort = externalPort - _ = response - return mappedExternalPort, err -} - -func (n *upnpNAT) DeletePortMapping(protocol string, externalPort, internalPort int) (err error) { - - message := "\r\n" + - "" + strconv.Itoa(externalPort) + - "" + protocol + "" + - "" - - var response *http.Response - response, err = soapRequest(n.serviceURL, "DeletePortMapping", message, n.urnDomain) - if response != nil { - defer response.Body.Close() - } - if err != nil { - return - } - - // TODO: check response to see if the port was deleted - // log.Println(message, response) - _ = response - return -} diff --git a/privval/errors.go b/privval/errors.go index 297d5dca278..28d64f0b086 100644 --- a/privval/errors.go +++ b/privval/errors.go @@ -9,17 +9,16 @@ import ( type EndpointTimeoutError struct{} // Implement the net.Error interface. -func (e EndpointTimeoutError) Error() string { return "endpoint connection timed out" } -func (e EndpointTimeoutError) Timeout() bool { return true } -func (e EndpointTimeoutError) Temporary() bool { return true } +func (EndpointTimeoutError) Error() string { return "endpoint connection timed out" } +func (EndpointTimeoutError) Timeout() bool { return true } +func (EndpointTimeoutError) Temporary() bool { return true } // Socket errors. var ( - ErrConnectionTimeout = EndpointTimeoutError{} - ErrNoConnection = errors.New("endpoint is not connected") - ErrReadTimeout = errors.New("endpoint read timed out") - ErrUnexpectedResponse = errors.New("empty response") - ErrWriteTimeout = errors.New("endpoint write timed out") + ErrConnectionTimeout = EndpointTimeoutError{} + ErrNoConnection = errors.New("endpoint is not connected") + ErrReadTimeout = errors.New("endpoint read timed out") + ErrWriteTimeout = errors.New("endpoint write timed out") ) // RemoteSignerError allows (remote) validators to include meaningful error diff --git a/privval/file.go b/privval/file.go index a092e38b087..3a58afc9f30 100644 --- a/privval/file.go +++ b/privval/file.go @@ -9,14 +9,14 @@ import ( "github.com/cosmos/gogoproto/proto" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" + cmtos "github.com/cometbft/cometbft/internal/os" + "github.com/cometbft/cometbft/internal/protoio" + "github.com/cometbft/cometbft/internal/tempfile" cmtbytes "github.com/cometbft/cometbft/libs/bytes" cmtjson "github.com/cometbft/cometbft/libs/json" - cmtos "github.com/cometbft/cometbft/libs/os" - "github.com/cometbft/cometbft/libs/protoio" - "github.com/cometbft/cometbft/libs/tempfile" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -32,16 +32,16 @@ const ( // A vote is either stepPrevote or stepPrecommit. func voteToStep(vote *cmtproto.Vote) int8 { switch vote.Type { - case cmtproto.PrevoteType: + case types.PrevoteType: return stepPrevote - case cmtproto.PrecommitType: + case types.PrecommitType: return stepPrecommit default: panic(fmt.Sprintf("Unknown vote type: %v", vote.Type)) } } -//------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- // FilePVKey stores the immutable part of PrivValidator. type FilePVKey struct { @@ -64,12 +64,12 @@ func (pvKey FilePVKey) Save() { panic(err) } - if err := tempfile.WriteFileAtomic(outFile, jsonBytes, 0600); err != nil { + if err := tempfile.WriteFileAtomic(outFile, jsonBytes, 0o600); err != nil { panic(err) } } -//------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- // FilePVLastSignState stores the mutable part of PrivValidator. type FilePVLastSignState struct { @@ -98,37 +98,44 @@ func (lss *FilePVLastSignState) reset() { // we have already signed for this HRS, and can reuse the existing signature). // It panics if the HRS matches the arguments, there's a SignBytes, but no Signature. func (lss *FilePVLastSignState) CheckHRS(height int64, round int32, step int8) (bool, error) { - if lss.Height > height { return false, fmt.Errorf("height regression. Got %v, last height %v", height, lss.Height) } - if lss.Height == height { - if lss.Round > round { - return false, fmt.Errorf("round regression at height %v. Got %v, last round %v", height, round, lss.Round) - } + if lss.Height != height { + return false, nil + } - if lss.Round == round { - if lss.Step > step { - return false, fmt.Errorf( - "step regression at height %v round %v. Got %v, last step %v", - height, - round, - step, - lss.Step, - ) - } else if lss.Step == step { - if lss.SignBytes != nil { - if lss.Signature == nil { - panic("pv: Signature is nil but SignBytes is not!") - } - return true, nil - } - return false, errors.New("no SignBytes found") - } - } + if lss.Round > round { + return false, fmt.Errorf("round regression at height %v. Got %v, last round %v", height, round, lss.Round) + } + + if lss.Round != round { + return false, nil + } + + if lss.Step > step { + return false, fmt.Errorf( + "step regression at height %v round %v. Got %v, last step %v", + height, + round, + step, + lss.Step, + ) + } + + if lss.Step < step { + return false, nil + } + + if lss.SignBytes == nil { + return false, errors.New("no SignBytes found") + } + + if lss.Signature == nil { + panic("pv: Signature is nil but SignBytes is not!") } - return false, nil + return true, nil } // Save persists the FilePvLastSignState to its filePath. @@ -141,13 +148,13 @@ func (lss *FilePVLastSignState) Save() { if err != nil { panic(err) } - err = tempfile.WriteFileAtomic(outFile, jsonBytes, 0600) + err = tempfile.WriteFileAtomic(outFile, jsonBytes, 0o600) if err != nil { panic(err) } } -//------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- // FilePV implements PrivValidator using data persisted to disk // to prevent double signing. @@ -259,8 +266,8 @@ func (pv *FilePV) GetPubKey() (crypto.PubKey, error) { // SignVote signs a canonical representation of the vote, along with the // chainID. Implements PrivValidator. -func (pv *FilePV) SignVote(chainID string, vote *cmtproto.Vote) error { - if err := pv.signVote(chainID, vote); err != nil { +func (pv *FilePV) SignVote(chainID string, vote *cmtproto.Vote, signExtension bool) error { + if err := pv.signVote(chainID, vote, signExtension); err != nil { return fmt.Errorf("error signing vote: %v", err) } return nil @@ -275,6 +282,11 @@ func (pv *FilePV) SignProposal(chainID string, proposal *cmtproto.Proposal) erro return nil } +// SignBytes signs the given bytes. Implements PrivValidator. +func (pv *FilePV) SignBytes(bytes []byte) ([]byte, error) { + return pv.Key.PrivKey.Sign(bytes) +} + // Save persists the FilePV to disk. func (pv *FilePV) Save() { pv.Key.Save() @@ -299,13 +311,13 @@ func (pv *FilePV) String() string { ) } -//------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------ // signVote checks if the vote is good to sign and sets the vote signature. // It may need to set the timestamp as well if the vote is otherwise the same as // a previously signed vote (ie. we crashed after signing but before the vote hit the WAL). // Extension signatures are always signed for non-nil precommits (even if the data is empty). -func (pv *FilePV) signVote(chainID string, vote *cmtproto.Vote) error { +func (pv *FilePV) signVote(chainID string, vote *cmtproto.Vote, signExtension bool) error { height, round, step := vote.Height, vote.Round, voteToStep(vote) lss := pv.LastSignState @@ -317,20 +329,24 @@ func (pv *FilePV) signVote(chainID string, vote *cmtproto.Vote) error { signBytes := types.VoteSignBytes(chainID, vote) - // Vote extensions are non-deterministic, so it is possible that an - // application may have created a different extension. We therefore always - // re-sign the vote extensions of precommits. For prevotes and nil - // precommits, the extension signature will always be empty. - // Even if the signed over data is empty, we still add the signature - var extSig []byte - if vote.Type == cmtproto.PrecommitType && !types.ProtoBlockIDIsNil(&vote.BlockID) { - extSignBytes := types.VoteExtensionSignBytes(chainID, vote) - extSig, err = pv.Key.PrivKey.Sign(extSignBytes) - if err != nil { - return err + if signExtension { + // Vote extensions are non-deterministic, so it is possible that an + // application may have created a different extension. We therefore always + // re-sign the vote extensions of precommits. For prevotes and nil + // precommits, the extension signature will always be empty. + // Even if the signed over data is empty, we still add the signature + var extSig []byte + if vote.Type == types.PrecommitType && !types.ProtoBlockIDIsNil(&vote.BlockID) { + extSignBytes := types.VoteExtensionSignBytes(chainID, vote) + extSig, err = pv.Key.PrivKey.Sign(extSignBytes) + if err != nil { + return err + } + } else if len(vote.Extension) > 0 { + return errors.New("unexpected vote extension - extensions are only allowed in non-nil precommits") } - } else if len(vote.Extension) > 0 { - return errors.New("unexpected vote extension - extensions are only allowed in non-nil precommits") + + vote.ExtensionSignature = extSig } // We might crash before writing to the wal, @@ -347,11 +363,9 @@ func (pv *FilePV) signVote(chainID string, vote *cmtproto.Vote) error { vote.Timestamp = timestamp vote.Signature = lss.Signature } else { - err = fmt.Errorf("conflicting data") + err = errors.New("conflicting data") } - vote.ExtensionSignature = extSig - return err } @@ -362,7 +376,6 @@ func (pv *FilePV) signVote(chainID string, vote *cmtproto.Vote) error { } pv.saveSigned(height, round, step, signBytes, sig) vote.Signature = sig - vote.ExtensionSignature = extSig return nil } @@ -394,7 +407,7 @@ func (pv *FilePV) signProposal(chainID string, proposal *cmtproto.Proposal) erro proposal.Timestamp = timestamp proposal.Signature = lss.Signature } else { - err = fmt.Errorf("conflicting data") + err = errors.New("conflicting data") } return err } @@ -409,10 +422,10 @@ func (pv *FilePV) signProposal(chainID string, proposal *cmtproto.Proposal) erro return nil } -// Persist height/round/step and signature +// Persist height/round/step and signature. func (pv *FilePV) saveSigned(height int64, round int32, step int8, - signBytes []byte, sig []byte) { - + signBytes []byte, sig []byte, +) { pv.LastSignState.Height = height pv.LastSignState.Round = round pv.LastSignState.Step = step @@ -421,7 +434,7 @@ func (pv *FilePV) saveSigned(height int64, round int32, step int8, pv.LastSignState.Save() } -//----------------------------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------- // Returns the timestamp from the lastSignBytes. // Returns true if the only difference in the votes is their timestamp. @@ -446,7 +459,7 @@ func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.T } // returns the timestamp from the lastSignBytes. -// returns true if the only difference in the proposals is their timestamp +// returns true if the only difference in the proposals is their timestamp. func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.Time, bool) { var lastProposal, newProposal cmtproto.CanonicalProposal if err := protoio.UnmarshalDelimited(lastSignBytes, &lastProposal); err != nil { diff --git a/privval/file_test.go b/privval/file_test.go index 6d8df0270fd..d62cd1615b1 100644 --- a/privval/file_test.go +++ b/privval/file_test.go @@ -12,9 +12,8 @@ import ( "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/crypto/tmhash" + cmtrand "github.com/cometbft/cometbft/internal/rand" cmtjson "github.com/cometbft/cometbft/libs/json" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -41,12 +40,12 @@ func TestResetValidator(t *testing.T) { // test vote height, round := int64(10), int32(1) - voteType := cmtproto.PrevoteType + voteType := types.PrevoteType randBytes := cmtrand.Bytes(tmhash.Size) blockID := types.BlockID{Hash: randBytes, PartSetHeader: types.PartSetHeader{}} - vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID, nil) - err := privVal.SignVote("mychainid", vote.ToProto()) - assert.NoError(t, err, "expected no error signing vote") + vote := newVote(privVal.Key.Address, height, round, voteType, blockID) + err := privVal.SignVote("mychainid", vote.ToProto(), false) + require.NoError(t, err, "expected no error signing vote") // priv val after signing is not same as empty assert.NotEqual(t, privVal.LastSignState, emptyState) @@ -60,9 +59,9 @@ func TestLoadOrGenValidator(t *testing.T) { assert := assert.New(t) tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") - require.Nil(t, err) + require.NoError(t, err) tempStateFile, err := os.CreateTemp("", "priv_validator_state_") - require.Nil(t, err) + require.NoError(t, err) tempKeyFilePath := tempKeyFile.Name() if err := os.Remove(tempKeyFilePath); err != nil { @@ -91,7 +90,7 @@ func TestUnmarshalValidatorState(t *testing.T) { val := FilePVLastSignState{} err := cmtjson.Unmarshal([]byte(serialized), &val) - require.Nil(err, "%+v", err) + require.NoError(err, "%+v", err) // make sure the values match assert.EqualValues(val.Height, 1) @@ -100,7 +99,7 @@ func TestUnmarshalValidatorState(t *testing.T) { // export it and make sure it is the same out, err := cmtjson.Marshal(val) - require.Nil(err, "%+v", err) + require.NoError(err, "%+v", err) assert.JSONEq(serialized, string(out)) } @@ -130,7 +129,7 @@ func TestUnmarshalValidatorKey(t *testing.T) { val := FilePVKey{} err := cmtjson.Unmarshal([]byte(serialized), &val) - require.Nil(err, "%+v", err) + require.NoError(err, "%+v", err) // make sure the values match assert.EqualValues(addr, val.Address) @@ -139,7 +138,7 @@ func TestUnmarshalValidatorKey(t *testing.T) { // export it and make sure it is the same out, err := cmtjson.Marshal(val) - require.Nil(err, "%+v", err) + require.NoError(err, "%+v", err) assert.JSONEq(serialized, string(out)) } @@ -151,43 +150,47 @@ func TestSignVote(t *testing.T) { randbytes := cmtrand.Bytes(tmhash.Size) randbytes2 := cmtrand.Bytes(tmhash.Size) - block1 := types.BlockID{Hash: randbytes, - PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}} - block2 := types.BlockID{Hash: randbytes2, - PartSetHeader: types.PartSetHeader{Total: 10, Hash: randbytes2}} + block1 := types.BlockID{ + Hash: randbytes, + PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}, + } + block2 := types.BlockID{ + Hash: randbytes2, + PartSetHeader: types.PartSetHeader{Total: 10, Hash: randbytes2}, + } height, round := int64(10), int32(1) - voteType := cmtproto.PrevoteType + voteType := types.PrevoteType // sign a vote for first time - vote := newVote(privVal.Key.Address, 0, height, round, voteType, block1, nil) + vote := newVote(privVal.Key.Address, height, round, voteType, block1) v := vote.ToProto() - err := privVal.SignVote("mychainid", v) - assert.NoError(err, "expected no error signing vote") + err := privVal.SignVote("mychainid", v, false) + require.NoError(t, err, "expected no error signing vote") // try to sign the same vote again; should be fine - err = privVal.SignVote("mychainid", v) - assert.NoError(err, "expected no error on signing same vote") + err = privVal.SignVote("mychainid", v, false) + require.NoError(t, err, "expected no error on signing same vote") // now try some bad votes cases := []*types.Vote{ - newVote(privVal.Key.Address, 0, height, round-1, voteType, block1, nil), // round regression - newVote(privVal.Key.Address, 0, height-1, round, voteType, block1, nil), // height regression - newVote(privVal.Key.Address, 0, height-2, round+4, voteType, block1, nil), // height regression and different round - newVote(privVal.Key.Address, 0, height, round, voteType, block2, nil), // different block + newVote(privVal.Key.Address, height, round-1, voteType, block1), // round regression + newVote(privVal.Key.Address, height-1, round, voteType, block1), // height regression + newVote(privVal.Key.Address, height-2, round+4, voteType, block1), // height regression and different round + newVote(privVal.Key.Address, height, round, voteType, block2), // different block } for _, c := range cases { cpb := c.ToProto() - err = privVal.SignVote("mychainid", cpb) - assert.Error(err, "expected error on signing conflicting vote") + err = privVal.SignVote("mychainid", cpb, false) + require.Error(t, err, "expected error on signing conflicting vote") } // try signing a vote with a different time stamp sig := vote.Signature vote.Timestamp = vote.Timestamp.Add(time.Duration(1000)) - err = privVal.SignVote("mychainid", v) - assert.NoError(err) + err = privVal.SignVote("mychainid", v, false) + require.NoError(t, err) assert.Equal(sig, vote.Signature) } @@ -199,21 +202,25 @@ func TestSignProposal(t *testing.T) { randbytes := cmtrand.Bytes(tmhash.Size) randbytes2 := cmtrand.Bytes(tmhash.Size) - block1 := types.BlockID{Hash: randbytes, - PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}} - block2 := types.BlockID{Hash: randbytes2, - PartSetHeader: types.PartSetHeader{Total: 10, Hash: randbytes2}} + block1 := types.BlockID{ + Hash: randbytes, + PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}, + } + block2 := types.BlockID{ + Hash: randbytes2, + PartSetHeader: types.PartSetHeader{Total: 10, Hash: randbytes2}, + } height, round := int64(10), int32(1) // sign a proposal for first time proposal := newProposal(height, round, block1) pbp := proposal.ToProto() err := privVal.SignProposal("mychainid", pbp) - assert.NoError(err, "expected no error signing proposal") + require.NoError(t, err, "expected no error signing proposal") // try to sign the same proposal again; should be fine err = privVal.SignProposal("mychainid", pbp) - assert.NoError(err, "expected no error on signing same proposal") + require.NoError(t, err, "expected no error on signing same proposal") // now try some bad Proposals cases := []*types.Proposal{ @@ -225,22 +232,36 @@ func TestSignProposal(t *testing.T) { for _, c := range cases { err = privVal.SignProposal("mychainid", c.ToProto()) - assert.Error(err, "expected error on signing conflicting proposal") + require.Error(t, err, "expected error on signing conflicting proposal") } // try signing a proposal with a different time stamp sig := proposal.Signature proposal.Timestamp = proposal.Timestamp.Add(time.Duration(1000)) err = privVal.SignProposal("mychainid", pbp) - assert.NoError(err) + require.NoError(t, err) assert.Equal(sig, proposal.Signature) } +func TestSignBytes(t *testing.T) { + privVal, _, _ := newTestFilePV(t) + testBytes := []byte("test bytes for signing") + + // Sign the test bytes + sig, err := privVal.SignBytes(testBytes) + require.NoError(t, err, "expected no error signing bytes") + + // Verify the signature + pubKey, err := privVal.GetPubKey() + require.NoError(t, err, "expected no error getting public key") + assert.True(t, pubKey.VerifySignature(testBytes, sig), "signature verification failed") +} + func TestDifferByTimestamp(t *testing.T) { tempKeyFile, err := os.CreateTemp("", "priv_validator_key_") - require.Nil(t, err) + require.NoError(t, err) tempStateFile, err := os.CreateTemp("", "priv_validator_state_") - require.Nil(t, err) + require.NoError(t, err) privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) randbytes := cmtrand.Bytes(tmhash.Size) @@ -253,7 +274,7 @@ func TestDifferByTimestamp(t *testing.T) { proposal := newProposal(height, round, block1) pb := proposal.ToProto() err := privVal.SignProposal(chainID, pb) - assert.NoError(t, err, "expected no error signing proposal") + require.NoError(t, err, "expected no error signing proposal") signBytes := types.ProposalSignBytes(chainID, pb) sig := proposal.Signature @@ -264,7 +285,7 @@ func TestDifferByTimestamp(t *testing.T) { var emptySig []byte proposal.Signature = emptySig err = privVal.SignProposal("mychainid", pb) - assert.NoError(t, err, "expected no error on signing same proposal") + require.NoError(t, err, "expected no error on signing same proposal") assert.Equal(t, timeStamp, pb.Timestamp) assert.Equal(t, signBytes, types.ProposalSignBytes(chainID, pb)) @@ -273,12 +294,12 @@ func TestDifferByTimestamp(t *testing.T) { // test vote { - voteType := cmtproto.PrevoteType + voteType := types.PrevoteType blockID := types.BlockID{Hash: randbytes, PartSetHeader: types.PartSetHeader{}} - vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID, nil) + vote := newVote(privVal.Key.Address, height, round, voteType, blockID) v := vote.ToProto() - err := privVal.SignVote("mychainid", v) - assert.NoError(t, err, "expected no error signing vote") + err := privVal.SignVote("mychainid", v, false) + require.NoError(t, err, "expected no error signing vote") signBytes := types.VoteSignBytes(chainID, v) sig := v.Signature @@ -290,8 +311,8 @@ func TestDifferByTimestamp(t *testing.T) { var emptySig []byte v.Signature = emptySig v.ExtensionSignature = emptySig - err = privVal.SignVote("mychainid", v) - assert.NoError(t, err, "expected no error on signing same vote") + err = privVal.SignVote("mychainid", v, false) + require.NoError(t, err, "expected no error on signing same vote") assert.Equal(t, timeStamp, v.Timestamp) assert.Equal(t, signBytes, types.VoteSignBytes(chainID, v)) @@ -300,10 +321,10 @@ func TestDifferByTimestamp(t *testing.T) { } } -func TestVoteExtensionsAreAlwaysSigned(t *testing.T) { +func TestVoteExtensionsAreSignedIfSignExtensionIsTrue(t *testing.T) { privVal, _, _ := newTestFilePV(t) pubKey, err := privVal.GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) block := types.BlockID{ Hash: cmtrand.Bytes(tmhash.Size), @@ -311,14 +332,14 @@ func TestVoteExtensionsAreAlwaysSigned(t *testing.T) { } height, round := int64(10), int32(1) - voteType := cmtproto.PrecommitType + voteType := types.PrecommitType // We initially sign this vote without an extension - vote1 := newVote(privVal.Key.Address, 0, height, round, voteType, block, nil) + vote1 := newVote(privVal.Key.Address, height, round, voteType, block) vpb1 := vote1.ToProto() - err = privVal.SignVote("mychainid", vpb1) - assert.NoError(t, err, "expected no error signing vote") + err = privVal.SignVote("mychainid", vpb1, true) + require.NoError(t, err, "expected no error signing vote") assert.NotNil(t, vpb1.ExtensionSignature) vesb1 := types.VoteExtensionSignBytes("mychainid", vpb1) @@ -330,8 +351,8 @@ func TestVoteExtensionsAreAlwaysSigned(t *testing.T) { vote2.Extension = []byte("new extension") vpb2 := vote2.ToProto() - err = privVal.SignVote("mychainid", vpb2) - assert.NoError(t, err, "expected no error signing same vote with manipulated vote extension") + err = privVal.SignVote("mychainid", vpb2, true) + require.NoError(t, err, "expected no error signing same vote with manipulated vote extension") // We need to ensure that a valid new extension signature has been created // that validates against the vote extension sign bytes with the new @@ -349,8 +370,8 @@ func TestVoteExtensionsAreAlwaysSigned(t *testing.T) { vpb2.Signature = nil vpb2.ExtensionSignature = nil - err = privVal.SignVote("mychainid", vpb2) - assert.NoError(t, err, "expected no error signing same vote with manipulated timestamp and vote extension") + err = privVal.SignVote("mychainid", vpb2, true) + require.NoError(t, err, "expected no error signing same vote with manipulated timestamp and vote extension") assert.Equal(t, expectedTimestamp, vpb2.Timestamp) vesb3 := types.VoteExtensionSignBytes("mychainid", vpb2) @@ -358,17 +379,37 @@ func TestVoteExtensionsAreAlwaysSigned(t *testing.T) { assert.False(t, pubKey.VerifySignature(vesb1, vpb2.ExtensionSignature)) } -func newVote(addr types.Address, idx int32, height int64, round int32, - typ cmtproto.SignedMsgType, blockID types.BlockID, extension []byte) *types.Vote { +func TestVoteExtensionsAreNotSignedIfSignExtensionIsFalse(t *testing.T) { + privVal, _, _ := newTestFilePV(t) + + block := types.BlockID{ + Hash: cmtrand.Bytes(tmhash.Size), + PartSetHeader: types.PartSetHeader{Total: 5, Hash: cmtrand.Bytes(tmhash.Size)}, + } + + height, round := int64(10), int32(1) + voteType := types.PrecommitType + + // We initially sign this vote without an extension + vote1 := newVote(privVal.Key.Address, height, round, voteType, block) + vpb1 := vote1.ToProto() + + err := privVal.SignVote("mychainid", vpb1, false) + require.NoError(t, err, "expected no error signing vote") + assert.Nil(t, vpb1.ExtensionSignature) +} + +func newVote(addr types.Address, height int64, round int32, + typ types.SignedMsgType, blockID types.BlockID, +) *types.Vote { return &types.Vote{ ValidatorAddress: addr, - ValidatorIndex: idx, + ValidatorIndex: 0, Height: height, Round: round, Type: typ, Timestamp: cmttime.Now(), BlockID: blockID, - Extension: extension, } } @@ -382,6 +423,7 @@ func newProposal(height int64, round int32, blockID types.BlockID) *types.Propos } func newTestFilePV(t *testing.T) (*FilePV, string, string) { + t.Helper() tempKeyFile, err := os.CreateTemp(t.TempDir(), "priv_validator_key_") require.NoError(t, err) tempStateFile, err := os.CreateTemp(t.TempDir(), "priv_validator_state_") diff --git a/privval/msgs.go b/privval/msgs.go index 4b440e612df..b4bcd232efc 100644 --- a/privval/msgs.go +++ b/privval/msgs.go @@ -5,33 +5,37 @@ import ( "github.com/cosmos/gogoproto/proto" - privvalproto "github.com/cometbft/cometbft/proto/tendermint/privval" + pvproto "github.com/cometbft/cometbft/api/cometbft/privval/v1" ) // TODO: Add ChainIDRequest -func mustWrapMsg(pb proto.Message) privvalproto.Message { - msg := privvalproto.Message{} +func mustWrapMsg(pb proto.Message) pvproto.Message { + msg := pvproto.Message{} switch pb := pb.(type) { - case *privvalproto.Message: + case *pvproto.Message: msg = *pb - case *privvalproto.PubKeyRequest: - msg.Sum = &privvalproto.Message_PubKeyRequest{PubKeyRequest: pb} - case *privvalproto.PubKeyResponse: - msg.Sum = &privvalproto.Message_PubKeyResponse{PubKeyResponse: pb} - case *privvalproto.SignVoteRequest: - msg.Sum = &privvalproto.Message_SignVoteRequest{SignVoteRequest: pb} - case *privvalproto.SignedVoteResponse: - msg.Sum = &privvalproto.Message_SignedVoteResponse{SignedVoteResponse: pb} - case *privvalproto.SignedProposalResponse: - msg.Sum = &privvalproto.Message_SignedProposalResponse{SignedProposalResponse: pb} - case *privvalproto.SignProposalRequest: - msg.Sum = &privvalproto.Message_SignProposalRequest{SignProposalRequest: pb} - case *privvalproto.PingRequest: - msg.Sum = &privvalproto.Message_PingRequest{PingRequest: pb} - case *privvalproto.PingResponse: - msg.Sum = &privvalproto.Message_PingResponse{PingResponse: pb} + case *pvproto.PubKeyRequest: + msg.Sum = &pvproto.Message_PubKeyRequest{PubKeyRequest: pb} + case *pvproto.PubKeyResponse: + msg.Sum = &pvproto.Message_PubKeyResponse{PubKeyResponse: pb} + case *pvproto.SignVoteRequest: + msg.Sum = &pvproto.Message_SignVoteRequest{SignVoteRequest: pb} + case *pvproto.SignBytesRequest: + msg.Sum = &pvproto.Message_SignBytesRequest{SignBytesRequest: pb} + case *pvproto.SignBytesResponse: + msg.Sum = &pvproto.Message_SignBytesResponse{SignBytesResponse: pb} + case *pvproto.SignedVoteResponse: + msg.Sum = &pvproto.Message_SignedVoteResponse{SignedVoteResponse: pb} + case *pvproto.SignedProposalResponse: + msg.Sum = &pvproto.Message_SignedProposalResponse{SignedProposalResponse: pb} + case *pvproto.SignProposalRequest: + msg.Sum = &pvproto.Message_SignProposalRequest{SignProposalRequest: pb} + case *pvproto.PingRequest: + msg.Sum = &pvproto.Message_PingRequest{PingRequest: pb} + case *pvproto.PingResponse: + msg.Sum = &pvproto.Message_PingResponse{PingResponse: pb} default: panic(fmt.Errorf("unknown message type %T", pb)) } diff --git a/privval/msgs_test.go b/privval/msgs_test.go index b305e208050..7911cfb489d 100644 --- a/privval/msgs_test.go +++ b/privval/msgs_test.go @@ -8,13 +8,13 @@ import ( "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/require" + cryptoproto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + privproto "github.com/cometbft/cometbft/api/cometbft/privval/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" "github.com/cometbft/cometbft/crypto/tmhash" - cryptoproto "github.com/cometbft/cometbft/proto/tendermint/crypto" - privproto "github.com/cometbft/cometbft/proto/tendermint/privval" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" ) @@ -22,7 +22,7 @@ var stamp = time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC) func exampleVote() *types.Vote { return &types.Vote{ - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, Height: 3, Round: 2, BlockID: types.BlockID{Hash: tmhash.Sum([]byte("blockID_hash")), PartSetHeader: types.PartSetHeader{Total: 1000000, Hash: tmhash.Sum([]byte("blockID_part_set_header_hash"))}}, @@ -34,9 +34,8 @@ func exampleVote() *types.Vote { } func exampleProposal() *types.Proposal { - return &types.Proposal{ - Type: cmtproto.SignedMsgType(1), + Type: types.SignedMsgType(1), Height: 3, Round: 2, Timestamp: stamp, @@ -66,7 +65,7 @@ func TestPrivvalVectors(t *testing.T) { proposal := exampleProposal() proposalpb := proposal.ToProto() - // Create a Reuseable remote error + // Create a reusable remote error remoteError := &privproto.RemoteSignerError{Code: 1, Description: "it's a error"} testCases := []struct { diff --git a/privval/retry_signer_client.go b/privval/retry_signer_client.go index 271e146474c..8c6b01e3afc 100644 --- a/privval/retry_signer_client.go +++ b/privval/retry_signer_client.go @@ -4,8 +4,8 @@ import ( "fmt" "time" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" ) @@ -37,7 +37,7 @@ func (sc *RetrySignerClient) WaitForConnection(maxWait time.Duration) error { return sc.next.WaitForConnection(maxWait) } -//-------------------------------------------------------- +// -------------------------------------------------------- // Implement PrivValidator func (sc *RetrySignerClient) Ping() error { @@ -63,10 +63,10 @@ func (sc *RetrySignerClient) GetPubKey() (crypto.PubKey, error) { return nil, fmt.Errorf("exhausted all attempts to get pubkey: %w", err) } -func (sc *RetrySignerClient) SignVote(chainID string, vote *cmtproto.Vote) error { +func (sc *RetrySignerClient) SignVote(chainID string, vote *cmtproto.Vote, signExtension bool) error { var err error for i := 0; i < sc.retries || sc.retries == 0; i++ { - err = sc.next.SignVote(chainID, vote) + err = sc.next.SignVote(chainID, vote, signExtension) if err == nil { return nil } @@ -94,3 +94,22 @@ func (sc *RetrySignerClient) SignProposal(chainID string, proposal *cmtproto.Pro } return fmt.Errorf("exhausted all attempts to sign proposal: %w", err) } + +func (sc *RetrySignerClient) SignBytes(bytes []byte) ([]byte, error) { + var ( + sig []byte + err error + ) + for i := 0; i < sc.retries || sc.retries == 0; i++ { + sig, err = sc.next.SignBytes(bytes) + if err == nil { + return sig, nil + } + // If remote signer errors, we don't retry. + if _, ok := err.(*RemoteSignerError); ok { + return nil, err + } + time.Sleep(sc.timeout) + } + return nil, fmt.Errorf("exhausted all attempts to sign bytes: %w", err) +} diff --git a/privval/signer_client.go b/privval/signer_client.go index 8ebb99fc408..2933eb82a4e 100644 --- a/privval/signer_client.go +++ b/privval/signer_client.go @@ -4,15 +4,16 @@ import ( "fmt" "time" + pvproto "github.com/cometbft/cometbft/api/cometbft/privval/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" - privvalproto "github.com/cometbft/cometbft/proto/tendermint/privval" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" ) // SignerClient implements PrivValidator. -// Handles remote validator connections that provide signing services +// Handles remote validator connections that provide signing services. type SignerClient struct { endpoint *SignerListenerEndpoint chainID string @@ -21,7 +22,7 @@ type SignerClient struct { var _ types.PrivValidator = (*SignerClient)(nil) // NewSignerClient returns an instance of SignerClient. -// it will start the endpoint (if not already started) +// it will start the endpoint (if not already started). func NewSignerClient(endpoint *SignerListenerEndpoint, chainID string) (*SignerClient, error) { if !endpoint.IsRunning() { if err := endpoint.Start(); err != nil { @@ -32,27 +33,27 @@ func NewSignerClient(endpoint *SignerListenerEndpoint, chainID string) (*SignerC return &SignerClient{endpoint: endpoint, chainID: chainID}, nil } -// Close closes the underlying connection +// Close closes the underlying connection. func (sc *SignerClient) Close() error { return sc.endpoint.Close() } -// IsConnected indicates with the signer is connected to a remote signing service +// IsConnected indicates with the signer is connected to a remote signing service. func (sc *SignerClient) IsConnected() bool { return sc.endpoint.IsConnected() } -// WaitForConnection waits maxWait for a connection or returns a timeout error +// WaitForConnection waits maxWait for a connection or returns a timeout error. func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error { return sc.endpoint.WaitForConnection(maxWait) } -//-------------------------------------------------------- +// -------------------------------------------------------- // Implement PrivValidator -// Ping sends a ping request to the remote signer +// Ping sends a ping request to the remote signer. func (sc *SignerClient) Ping() error { - response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PingRequest{})) + response, err := sc.endpoint.SendRequest(mustWrapMsg(&pvproto.PingRequest{})) if err != nil { sc.endpoint.Logger.Error("SignerClient::Ping", "err", err) return nil @@ -67,16 +68,16 @@ func (sc *SignerClient) Ping() error { } // GetPubKey retrieves a public key from a remote signer -// returns an error if client is not able to provide the key +// returns an error if client is not able to provide the key. func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) { - response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.PubKeyRequest{ChainId: sc.chainID})) + response, err := sc.endpoint.SendRequest(mustWrapMsg(&pvproto.PubKeyRequest{ChainId: sc.chainID})) if err != nil { return nil, fmt.Errorf("send: %w", err) } resp := response.GetPubKeyResponse() if resp == nil { - return nil, ErrUnexpectedResponse + return nil, cmterrors.ErrRequiredField{Field: "response"} } if resp.Error != nil { return nil, &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} @@ -90,16 +91,16 @@ func (sc *SignerClient) GetPubKey() (crypto.PubKey, error) { return pk, nil } -// SignVote requests a remote signer to sign a vote -func (sc *SignerClient) SignVote(chainID string, vote *cmtproto.Vote) error { - response, err := sc.endpoint.SendRequest(mustWrapMsg(&privvalproto.SignVoteRequest{Vote: vote, ChainId: chainID})) +// SignVote requests a remote signer to sign a vote. +func (sc *SignerClient) SignVote(chainID string, vote *cmtproto.Vote, signExtension bool) error { + response, err := sc.endpoint.SendRequest(mustWrapMsg(&pvproto.SignVoteRequest{Vote: vote, ChainId: chainID, SkipExtensionSigning: !signExtension})) if err != nil { return err } resp := response.GetSignedVoteResponse() if resp == nil { - return ErrUnexpectedResponse + return cmterrors.ErrRequiredField{Field: "response"} } if resp.Error != nil { return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} @@ -110,10 +111,10 @@ func (sc *SignerClient) SignVote(chainID string, vote *cmtproto.Vote) error { return nil } -// SignProposal requests a remote signer to sign a proposal +// SignProposal requests a remote signer to sign a proposal. func (sc *SignerClient) SignProposal(chainID string, proposal *cmtproto.Proposal) error { response, err := sc.endpoint.SendRequest(mustWrapMsg( - &privvalproto.SignProposalRequest{Proposal: proposal, ChainId: chainID}, + &pvproto.SignProposalRequest{Proposal: proposal, ChainId: chainID}, )) if err != nil { return err @@ -121,7 +122,7 @@ func (sc *SignerClient) SignProposal(chainID string, proposal *cmtproto.Proposal resp := response.GetSignedProposalResponse() if resp == nil { - return ErrUnexpectedResponse + return cmterrors.ErrRequiredField{Field: "response"} } if resp.Error != nil { return &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} @@ -131,3 +132,21 @@ func (sc *SignerClient) SignProposal(chainID string, proposal *cmtproto.Proposal return nil } + +// SignBytes requests a remote signer to sign bytes. +func (sc *SignerClient) SignBytes(bytes []byte) ([]byte, error) { + response, err := sc.endpoint.SendRequest(mustWrapMsg(&pvproto.SignBytesRequest{Value: bytes})) + if err != nil { + return nil, err + } + + resp := response.GetSignBytesResponse() + if resp == nil { + return nil, cmterrors.ErrRequiredField{Field: "response"} + } + if resp.Error != nil { + return nil, &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} + } + + return resp.Signature, nil +} diff --git a/privval/signer_client_test.go b/privval/signer_client_test.go index a7a4fbd2a03..4ae5c22c6da 100644 --- a/privval/signer_client_test.go +++ b/privval/signer_client_test.go @@ -8,13 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cryptoproto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + privvalproto "github.com/cometbft/cometbft/api/cometbft/privval/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/tmhash" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cryptoproto "github.com/cometbft/cometbft/proto/tendermint/crypto" - privvalproto "github.com/cometbft/cometbft/proto/tendermint/privval" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/types" + cmterrors "github.com/cometbft/cometbft/types/errors" + cmttime "github.com/cometbft/cometbft/types/time" ) type signerTestCase struct { @@ -25,6 +26,7 @@ type signerTestCase struct { } func getSignerTestCases(t *testing.T) []signerTestCase { + t.Helper() testCases := make([]signerTestCase, 0) // Get test cases for each possible dialer (DialTCP / DialUnix / etc) @@ -57,10 +59,10 @@ func getSignerTestCases(t *testing.T) []signerTestCase { func TestSignerClose(t *testing.T) { for _, tc := range getSignerTestCases(t) { err := tc.signerClient.Close() - assert.NoError(t, err) + require.NoError(t, err) err = tc.signerServer.Stop() - assert.NoError(t, err) + require.NoError(t, err) } } @@ -79,7 +81,7 @@ func TestSignerPing(t *testing.T) { }) err := tc.signerClient.Ping() - assert.NoError(t, err) + require.NoError(t, err) } } @@ -116,10 +118,10 @@ func TestSignerGetPubKey(t *testing.T) { func TestSignerProposal(t *testing.T) { for _, tc := range getSignerTestCases(t) { - ts := time.Now() + ts := cmttime.Now() hash := cmtrand.Bytes(tmhash.Size) have := &types.Proposal{ - Type: cmtproto.ProposalType, + Type: types.ProposalType, Height: 1, Round: 2, POLRound: 2, @@ -127,7 +129,7 @@ func TestSignerProposal(t *testing.T) { Timestamp: ts, } want := &types.Proposal{ - Type: cmtproto.ProposalType, + Type: types.ProposalType, Height: 1, Round: 2, POLRound: 2, @@ -156,11 +158,11 @@ func TestSignerProposal(t *testing.T) { func TestSignerVote(t *testing.T) { for _, tc := range getSignerTestCases(t) { - ts := time.Now() + ts := cmttime.Now() hash := cmtrand.Bytes(tmhash.Size) valAddr := cmtrand.Bytes(crypto.AddressSize) want := &types.Vote{ - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, Height: 1, Round: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, @@ -170,7 +172,7 @@ func TestSignerVote(t *testing.T) { } have := &types.Vote{ - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, Height: 1, Round: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, @@ -191,20 +193,22 @@ func TestSignerVote(t *testing.T) { } }) - require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto())) - require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto())) + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto(), false)) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto(), false)) assert.Equal(t, want.Signature, have.Signature) + assert.Nil(t, have.Signature) + assert.Equal(t, want.ExtensionSignature, have.ExtensionSignature) } } func TestSignerVoteResetDeadline(t *testing.T) { for _, tc := range getSignerTestCases(t) { - ts := time.Now() + ts := cmttime.Now() hash := cmtrand.Bytes(tmhash.Size) valAddr := cmtrand.Bytes(crypto.AddressSize) want := &types.Vote{ - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, Height: 1, Round: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, @@ -214,7 +218,7 @@ func TestSignerVoteResetDeadline(t *testing.T) { } have := &types.Vote{ - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, Height: 1, Round: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, @@ -237,28 +241,32 @@ func TestSignerVoteResetDeadline(t *testing.T) { time.Sleep(testTimeoutReadWrite2o3) - require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto())) - require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto())) + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto(), false)) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto(), false)) assert.Equal(t, want.Signature, have.Signature) + assert.Nil(t, have.Signature) + assert.Equal(t, want.ExtensionSignature, have.ExtensionSignature) // TODO(jleni): Clarify what is actually being tested // This would exceed the deadline if it was not extended by the previous message time.Sleep(testTimeoutReadWrite2o3) - require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto())) - require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto())) + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto(), false)) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto(), false)) assert.Equal(t, want.Signature, have.Signature) + assert.Nil(t, have.Signature) + assert.Equal(t, want.ExtensionSignature, have.ExtensionSignature) } } func TestSignerVoteKeepAlive(t *testing.T) { for _, tc := range getSignerTestCases(t) { - ts := time.Now() + ts := cmttime.Now() hash := cmtrand.Bytes(tmhash.Size) valAddr := cmtrand.Bytes(crypto.AddressSize) want := &types.Vote{ - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, Height: 1, Round: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, @@ -268,7 +276,7 @@ func TestSignerVoteKeepAlive(t *testing.T) { } have := &types.Vote{ - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, Height: 1, Round: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, @@ -298,10 +306,12 @@ func TestSignerVoteKeepAlive(t *testing.T) { time.Sleep(testTimeoutReadWrite * 3) tc.signerServer.Logger.Debug("TEST: Forced Wait DONE---------------------------------------------") - require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto())) - require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto())) + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto(), false)) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto(), false)) assert.Equal(t, want.Signature, have.Signature) + assert.Nil(t, have.Signature) + assert.Equal(t, want.ExtensionSignature, have.ExtensionSignature) } } @@ -323,10 +333,10 @@ func TestSignerSignProposalErrors(t *testing.T) { } }) - ts := time.Now() + ts := cmttime.Now() hash := cmtrand.Bytes(tmhash.Size) proposal := &types.Proposal{ - Type: cmtproto.ProposalType, + Type: types.ProposalType, Height: 1, Round: 2, POLRound: 2, @@ -348,11 +358,11 @@ func TestSignerSignProposalErrors(t *testing.T) { func TestSignerSignVoteErrors(t *testing.T) { for _, tc := range getSignerTestCases(t) { - ts := time.Now() + ts := cmttime.Now() hash := cmtrand.Bytes(tmhash.Size) valAddr := cmtrand.Bytes(crypto.AddressSize) vote := &types.Vote{ - Type: cmtproto.PrecommitType, + Type: types.PrecommitType, Height: 1, Round: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, @@ -378,19 +388,18 @@ func TestSignerSignVoteErrors(t *testing.T) { } }) - err := tc.signerClient.SignVote(tc.chainID, vote.ToProto()) + err := tc.signerClient.SignVote(tc.chainID, vote.ToProto(), false) require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error()) - err = tc.mockPV.SignVote(tc.chainID, vote.ToProto()) + err = tc.mockPV.SignVote(tc.chainID, vote.ToProto(), false) require.Error(t, err) - err = tc.signerClient.SignVote(tc.chainID, vote.ToProto()) + err = tc.signerClient.SignVote(tc.chainID, vote.ToProto(), false) require.Error(t, err) } } -func brokenHandler(privVal types.PrivValidator, request privvalproto.Message, - chainID string) (privvalproto.Message, error) { +func brokenHandler(_ types.PrivValidator, request privvalproto.Message, _ string) (privvalproto.Message, error) { var res privvalproto.Message var err error @@ -430,10 +439,81 @@ func TestSignerUnexpectedResponse(t *testing.T) { } }) - ts := time.Now() - want := &types.Vote{Timestamp: ts, Type: cmtproto.PrecommitType} + ts := cmttime.Now() + want := &types.Vote{Timestamp: ts, Type: types.PrecommitType} + + e := tc.signerClient.SignVote(tc.chainID, want.ToProto(), false) + require.ErrorIs(t, e, cmterrors.ErrRequiredField{Field: "response"}) + } +} + +func TestSignerVoteExtension(t *testing.T) { + for _, tc := range getSignerTestCases(t) { + ts := cmttime.Now() + hash := cmtrand.Bytes(tmhash.Size) + valAddr := cmtrand.Bytes(crypto.AddressSize) + want := &types.Vote{ + Type: types.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + Extension: []byte("hello"), + } + + have := &types.Vote{ + Type: types.PrecommitType, + Height: 1, + Round: 2, + BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, + Timestamp: ts, + ValidatorAddress: valAddr, + ValidatorIndex: 1, + Extension: []byte("world"), + } + + tc := tc + t.Cleanup(func() { + if err := tc.signerServer.Stop(); err != nil { + t.Error(err) + } + }) + t.Cleanup(func() { + if err := tc.signerClient.Close(); err != nil { + t.Error(err) + } + }) + + require.NoError(t, tc.mockPV.SignVote(tc.chainID, want.ToProto(), true)) + require.NoError(t, tc.signerClient.SignVote(tc.chainID, have.ToProto(), true)) + + assert.Equal(t, want.Signature, have.Signature) + assert.Equal(t, want.ExtensionSignature, have.ExtensionSignature) + } +} + +func TestSignerSignBytes(t *testing.T) { + for _, tc := range getSignerTestCases(t) { + tc := tc + t.Cleanup(func() { + if err := tc.signerServer.Stop(); err != nil { + t.Error(err) + } + }) + t.Cleanup(func() { + if err := tc.signerClient.Close(); err != nil { + t.Error(err) + } + }) + + bytes := cmtrand.Bytes(32) + signature, err := tc.signerClient.SignBytes(bytes) + require.NoError(t, err) - e := tc.signerClient.SignVote(tc.chainID, want.ToProto()) - assert.EqualError(t, e, "empty response") + pubKey, err := tc.mockPV.GetPubKey() + require.NoError(t, err) + require.True(t, pubKey.VerifySignature(bytes, signature)) } } diff --git a/privval/signer_dialer_endpoint.go b/privval/signer_dialer_endpoint.go index 9afb3aaa3ff..9c4af98bb0a 100644 --- a/privval/signer_dialer_endpoint.go +++ b/privval/signer_dialer_endpoint.go @@ -3,8 +3,8 @@ package privval import ( "time" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" ) const ( @@ -52,7 +52,6 @@ func NewSignerDialerEndpoint( dialer SocketDialer, options ...SignerServiceEndpointOption, ) *SignerDialerEndpoint { - sd := &SignerDialerEndpoint{ dialer: dialer, retryWait: defaultRetryWaitMilliseconds * time.Millisecond, @@ -77,17 +76,17 @@ func (sd *SignerDialerEndpoint) ensureConnection() error { retries := 0 for retries < sd.maxConnRetries { conn, err := sd.dialer() - if err != nil { retries++ sd.Logger.Debug("SignerDialer: Reconnection failed", "retries", retries, "max", sd.maxConnRetries, "err", err) // Wait between retries time.Sleep(sd.retryWait) - } else { - sd.SetConnection(conn) - sd.Logger.Debug("SignerDialer: Connection Ready") - return nil + continue } + + sd.SetConnection(conn) + sd.Logger.Debug("SignerDialer: Connection Ready") + return nil } sd.Logger.Debug("SignerDialer: Max retries exceeded", "retries", retries, "max", sd.maxConnRetries) diff --git a/privval/signer_endpoint.go b/privval/signer_endpoint.go index 2b4abe2dd96..95251c9fe32 100644 --- a/privval/signer_endpoint.go +++ b/privval/signer_endpoint.go @@ -5,10 +5,10 @@ import ( "net" "time" - "github.com/cometbft/cometbft/libs/protoio" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" - privvalproto "github.com/cometbft/cometbft/proto/tendermint/privval" + privvalproto "github.com/cometbft/cometbft/api/cometbft/privval/v1" + "github.com/cometbft/cometbft/internal/protoio" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" ) const ( @@ -30,14 +30,14 @@ func (se *signerEndpoint) Close() error { return nil } -// IsConnected indicates if there is an active connection +// IsConnected indicates if there is an active connection. func (se *signerEndpoint) IsConnected() bool { se.connMtx.Lock() defer se.connMtx.Unlock() return se.isConnected() } -// TryGetConnection retrieves a connection if it is already available +// TryGetConnection retrieves a connection if it is already available. func (se *signerEndpoint) GetAvailableConnection(connectionAvailableCh chan net.Conn) bool { se.connMtx.Lock() defer se.connMtx.Unlock() @@ -51,7 +51,7 @@ func (se *signerEndpoint) GetAvailableConnection(connectionAvailableCh chan net. return false } -// TryGetConnection retrieves a connection if it is already available +// TryGetConnection retrieves a connection if it is already available. func (se *signerEndpoint) WaitConnection(connectionAvailableCh chan net.Conn, maxWait time.Duration) error { se.connMtx.Lock() defer se.connMtx.Unlock() @@ -65,21 +65,21 @@ func (se *signerEndpoint) WaitConnection(connectionAvailableCh chan net.Conn, ma return nil } -// SetConnection replaces the current connection object +// SetConnection replaces the current connection object. func (se *signerEndpoint) SetConnection(newConnection net.Conn) { se.connMtx.Lock() defer se.connMtx.Unlock() se.conn = newConnection } -// IsConnected indicates if there is an active connection +// IsConnected indicates if there is an active connection. func (se *signerEndpoint) DropConnection() { se.connMtx.Lock() defer se.connMtx.Unlock() se.dropConnection() } -// ReadMessage reads a message from the endpoint +// ReadMessage reads a message from the endpoint. func (se *signerEndpoint) ReadMessage() (msg privvalproto.Message, err error) { se.connMtx.Lock() defer se.connMtx.Unlock() @@ -92,7 +92,7 @@ func (se *signerEndpoint) ReadMessage() (msg privvalproto.Message, err error) { err = se.conn.SetReadDeadline(deadline) if err != nil { - return + return msg, err } const maxRemoteSignerMsgSize = 1024 * 10 protoReader := protoio.NewDelimitedReader(se.conn, maxRemoteSignerMsgSize) @@ -108,10 +108,10 @@ func (se *signerEndpoint) ReadMessage() (msg privvalproto.Message, err error) { se.dropConnection() } - return + return msg, err } -// WriteMessage writes a message from the endpoint +// WriteMessage writes a message from the endpoint. func (se *signerEndpoint) WriteMessage(msg privvalproto.Message) (err error) { se.connMtx.Lock() defer se.connMtx.Unlock() @@ -126,7 +126,7 @@ func (se *signerEndpoint) WriteMessage(msg privvalproto.Message) (err error) { deadline := time.Now().Add(se.timeoutReadWrite) err = se.conn.SetWriteDeadline(deadline) if err != nil { - return + return err } _, err = protoWriter.WriteMsg(&msg) @@ -139,7 +139,7 @@ func (se *signerEndpoint) WriteMessage(msg privvalproto.Message) (err error) { se.dropConnection() } - return + return err } func (se *signerEndpoint) isConnected() bool { diff --git a/privval/signer_listener_endpoint.go b/privval/signer_listener_endpoint.go index 9b6b033cc5f..c02fbf19eff 100644 --- a/privval/signer_listener_endpoint.go +++ b/privval/signer_listener_endpoint.go @@ -1,14 +1,14 @@ package privval import ( - "fmt" + "errors" "net" "time" + privvalproto "github.com/cometbft/cometbft/api/cometbft/privval/v1" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" - privvalproto "github.com/cometbft/cometbft/proto/tendermint/privval" ) // SignerListenerEndpointOption sets an optional parameter on the SignerListenerEndpoint. @@ -17,7 +17,7 @@ type SignerListenerEndpointOption func(*SignerListenerEndpoint) // SignerListenerEndpointTimeoutReadWrite sets the read and write timeout for // connections from external signing processes. // -// Default: 5s +// Default: 5s. func SignerListenerEndpointTimeoutReadWrite(timeout time.Duration) SignerListenerEndpointOption { return func(sl *SignerListenerEndpoint) { sl.signerEndpoint.timeoutReadWrite = timeout } } @@ -64,10 +64,10 @@ func NewSignerListenerEndpoint( // OnStart implements service.Service. func (sl *SignerListenerEndpoint) OnStart() error { - sl.connectRequestCh = make(chan struct{}) + sl.connectRequestCh = make(chan struct{}, 1) // Buffer of 1 to allow `serviceLoop` to re-trigger itself. sl.connectionAvailableCh = make(chan net.Conn) - // NOTE: ping timeout must be less than read/write timeout + // NOTE: ping timeout must be less than read/write timeout. sl.pingInterval = time.Duration(sl.signerEndpoint.timeoutReadWrite.Milliseconds()*2/3) * time.Millisecond sl.pingTimer = time.NewTicker(sl.pingInterval) @@ -79,7 +79,7 @@ func (sl *SignerListenerEndpoint) OnStart() error { return nil } -// OnStop implements service.Service +// OnStop implements service.Service. func (sl *SignerListenerEndpoint) OnStop() { sl.instanceMtx.Lock() defer sl.instanceMtx.Unlock() @@ -96,14 +96,14 @@ func (sl *SignerListenerEndpoint) OnStop() { sl.pingTimer.Stop() } -// WaitForConnection waits maxWait for a connection or returns a timeout error +// WaitForConnection waits maxWait for a connection or returns a timeout error. func (sl *SignerListenerEndpoint) WaitForConnection(maxWait time.Duration) error { sl.instanceMtx.Lock() defer sl.instanceMtx.Unlock() return sl.ensureConnection(maxWait) } -// SendRequest ensures there is a connection, sends a request and waits for a response +// SendRequest ensures there is a connection, sends a request and waits for a response. func (sl *SignerListenerEndpoint) SendRequest(request privvalproto.Message) (*privvalproto.Message, error) { sl.instanceMtx.Lock() defer sl.instanceMtx.Unlock() @@ -152,7 +152,7 @@ func (sl *SignerListenerEndpoint) ensureConnection(maxWait time.Duration) error func (sl *SignerListenerEndpoint) acceptNewConnection() (net.Conn, error) { if !sl.IsRunning() || sl.listener == nil { - return nil, fmt.Errorf("endpoint is closing") + return nil, errors.New("endpoint is closing") } // wait for a new conn @@ -181,23 +181,19 @@ func (sl *SignerListenerEndpoint) serviceLoop() { for { select { case <-sl.connectRequestCh: - { - conn, err := sl.acceptNewConnection() - if err == nil { - sl.Logger.Info("SignerListener: Connected") - - // We have a good connection, wait for someone that needs one otherwise cancellation - select { - case sl.connectionAvailableCh <- conn: - case <-sl.Quit(): - return - } - } + conn, err := sl.acceptNewConnection() + if err != nil { + sl.Logger.Error("SignerListener: Error accepting connection", "err", err) + sl.triggerConnect() + continue + } - select { - case sl.connectRequestCh <- struct{}{}: - default: - } + // We have a good connection, wait for someone that needs one otherwise cancellation + sl.Logger.Info("SignerListener: Connected") + select { + case sl.connectionAvailableCh <- conn: + case <-sl.Quit(): + return } case <-sl.Quit(): return diff --git a/privval/signer_listener_endpoint_test.go b/privval/signer_listener_endpoint_test.go index c4e4c6b247e..3cd365ddf42 100644 --- a/privval/signer_listener_endpoint_test.go +++ b/privval/signer_listener_endpoint_test.go @@ -1,6 +1,7 @@ package privval import ( + "errors" "net" "testing" "time" @@ -9,9 +10,9 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/crypto/ed25519" + cmtnet "github.com/cometbft/cometbft/internal/net" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/libs/log" - cmtnet "github.com/cometbft/cometbft/libs/net" - cmtrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/types" ) @@ -176,6 +177,7 @@ func newSignerListenerEndpoint(logger log.Logger, addr string, timeoutReadWrite } func startListenerEndpointAsync(t *testing.T, sle *SignerListenerEndpoint, endpointIsOpenCh chan struct{}) { + t.Helper() go func(sle *SignerListenerEndpoint) { require.NoError(t, sle.Start()) assert.True(t, sle.IsRunning()) @@ -188,7 +190,7 @@ func getMockEndpoints( addr string, socketDialer SocketDialer, ) (*SignerListenerEndpoint, *SignerDialerEndpoint) { - + t.Helper() var ( logger = log.TestingLogger() endpointIsOpenCh = make(chan struct{}) @@ -213,3 +215,28 @@ func getMockEndpoints( return listenerEndpoint, dialerEndpoint } + +func TestSignerListenerEndpointServiceLoop(t *testing.T) { + listenerEndpoint := NewSignerListenerEndpoint( + log.TestingLogger(), + &testListener{initialErrs: 5}, + ) + + require.NoError(t, listenerEndpoint.Start()) + require.NoError(t, listenerEndpoint.WaitForConnection(time.Second)) +} + +type testListener struct { + net.Listener + initialErrs int +} + +func (l *testListener) Accept() (net.Conn, error) { + if l.initialErrs > 0 { + l.initialErrs-- + + return nil, errors.New("accept error") + } + + return nil, nil // Note this doesn't actually return a valid connection, it just doesn't error. +} diff --git a/privval/signer_requestHandler.go b/privval/signer_requestHandler.go index b0cbe127c90..81fed812026 100644 --- a/privval/signer_requestHandler.go +++ b/privval/signer_requestHandler.go @@ -3,30 +3,32 @@ package privval import ( "fmt" + cryptoproto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + pvproto "github.com/cometbft/cometbft/api/cometbft/privval/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" - cryptoproto "github.com/cometbft/cometbft/proto/tendermint/crypto" - privvalproto "github.com/cometbft/cometbft/proto/tendermint/privval" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" ) func DefaultValidationRequestHandler( privVal types.PrivValidator, - req privvalproto.Message, + req pvproto.Message, chainID string, -) (privvalproto.Message, error) { +) (pvproto.Message, error) { var ( - res privvalproto.Message + res pvproto.Message err error ) switch r := req.Sum.(type) { - case *privvalproto.Message_PubKeyRequest: + case *pvproto.Message_PubKeyRequest: if r.PubKeyRequest.GetChainId() != chainID { - res = mustWrapMsg(&privvalproto.PubKeyResponse{ - PubKey: cryptoproto.PublicKey{}, Error: &privvalproto.RemoteSignerError{ - Code: 0, Description: "unable to provide pubkey"}}) + res = mustWrapMsg(&pvproto.PubKeyResponse{ + PubKey: cryptoproto.PublicKey{}, Error: &pvproto.RemoteSignerError{ + Code: 0, Description: "unable to provide pubkey", + }, + }) return res, fmt.Errorf("want chainID: %s, got chainID: %s", r.PubKeyRequest.GetChainId(), chainID) } @@ -41,36 +43,42 @@ func DefaultValidationRequestHandler( } if err != nil { - res = mustWrapMsg(&privvalproto.PubKeyResponse{ - PubKey: cryptoproto.PublicKey{}, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}}) + res = mustWrapMsg(&pvproto.PubKeyResponse{ + PubKey: cryptoproto.PublicKey{}, Error: &pvproto.RemoteSignerError{Code: 0, Description: err.Error()}, + }) } else { - res = mustWrapMsg(&privvalproto.PubKeyResponse{PubKey: pk, Error: nil}) + res = mustWrapMsg(&pvproto.PubKeyResponse{PubKey: pk, Error: nil}) } - case *privvalproto.Message_SignVoteRequest: + case *pvproto.Message_SignVoteRequest: if r.SignVoteRequest.ChainId != chainID { - res = mustWrapMsg(&privvalproto.SignedVoteResponse{ - Vote: cmtproto.Vote{}, Error: &privvalproto.RemoteSignerError{ - Code: 0, Description: "unable to sign vote"}}) + res = mustWrapMsg(&pvproto.SignedVoteResponse{ + Vote: cmtproto.Vote{}, Error: &pvproto.RemoteSignerError{ + Code: 0, Description: "unable to sign vote", + }, + }) return res, fmt.Errorf("want chainID: %s, got chainID: %s", r.SignVoteRequest.GetChainId(), chainID) } vote := r.SignVoteRequest.Vote - err = privVal.SignVote(chainID, vote) + err = privVal.SignVote(chainID, vote, !r.SignVoteRequest.SkipExtensionSigning) if err != nil { - res = mustWrapMsg(&privvalproto.SignedVoteResponse{ - Vote: cmtproto.Vote{}, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}}) + res = mustWrapMsg(&pvproto.SignedVoteResponse{ + Vote: cmtproto.Vote{}, Error: &pvproto.RemoteSignerError{Code: 0, Description: err.Error()}, + }) } else { - res = mustWrapMsg(&privvalproto.SignedVoteResponse{Vote: *vote, Error: nil}) + res = mustWrapMsg(&pvproto.SignedVoteResponse{Vote: *vote, Error: nil}) } - case *privvalproto.Message_SignProposalRequest: + case *pvproto.Message_SignProposalRequest: if r.SignProposalRequest.GetChainId() != chainID { - res = mustWrapMsg(&privvalproto.SignedProposalResponse{ - Proposal: cmtproto.Proposal{}, Error: &privvalproto.RemoteSignerError{ + res = mustWrapMsg(&pvproto.SignedProposalResponse{ + Proposal: cmtproto.Proposal{}, Error: &pvproto.RemoteSignerError{ Code: 0, - Description: "unable to sign proposal"}}) + Description: "unable to sign proposal", + }, + }) return res, fmt.Errorf("want chainID: %s, got chainID: %s", r.SignProposalRequest.GetChainId(), chainID) } @@ -78,14 +86,24 @@ func DefaultValidationRequestHandler( err = privVal.SignProposal(chainID, proposal) if err != nil { - res = mustWrapMsg(&privvalproto.SignedProposalResponse{ - Proposal: cmtproto.Proposal{}, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}}) + res = mustWrapMsg(&pvproto.SignedProposalResponse{ + Proposal: cmtproto.Proposal{}, Error: &pvproto.RemoteSignerError{Code: 0, Description: err.Error()}, + }) } else { - res = mustWrapMsg(&privvalproto.SignedProposalResponse{Proposal: *proposal, Error: nil}) + res = mustWrapMsg(&pvproto.SignedProposalResponse{Proposal: *proposal, Error: nil}) } - case *privvalproto.Message_PingRequest: - err, res = nil, mustWrapMsg(&privvalproto.PingResponse{}) - + case *pvproto.Message_SignBytesRequest: + var signature []byte + signature, err = privVal.SignBytes(r.SignBytesRequest.Value) + if err != nil { + res = mustWrapMsg(&pvproto.SignBytesResponse{ + Signature: nil, Error: &pvproto.RemoteSignerError{Code: 0, Description: err.Error()}, + }) + } else { + res = mustWrapMsg(&pvproto.SignBytesResponse{Signature: signature, Error: nil}) + } + case *pvproto.Message_PingRequest: + err, res = nil, mustWrapMsg(&pvproto.PingResponse{}) default: err = fmt.Errorf("unknown msg: %v", r) } diff --git a/privval/signer_server.go b/privval/signer_server.go index 8c9abe717d4..6de252a96dd 100644 --- a/privval/signer_server.go +++ b/privval/signer_server.go @@ -3,17 +3,18 @@ package privval import ( "io" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" - privvalproto "github.com/cometbft/cometbft/proto/tendermint/privval" + privvalproto "github.com/cometbft/cometbft/api/cometbft/privval/v1" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/types" ) -// ValidationRequestHandlerFunc handles different remoteSigner requests +// ValidationRequestHandlerFunc handles different remoteSigner requests. type ValidationRequestHandlerFunc func( privVal types.PrivValidator, requestMessage privvalproto.Message, - chainID string) (privvalproto.Message, error) + chainID string, +) (privvalproto.Message, error) type SignerServer struct { service.BaseService @@ -51,7 +52,7 @@ func (ss *SignerServer) OnStop() { _ = ss.endpoint.Close() } -// SetRequestHandler override the default function that is used to service requests +// SetRequestHandler override the default function that is used to service requests. func (ss *SignerServer) SetRequestHandler(validationRequestHandler ValidationRequestHandlerFunc) { ss.handlerMtx.Lock() defer ss.handlerMtx.Unlock() diff --git a/privval/socket_dialers.go b/privval/socket_dialers.go index d49231c72c0..606ee7839e7 100644 --- a/privval/socket_dialers.go +++ b/privval/socket_dialers.go @@ -6,7 +6,7 @@ import ( "time" "github.com/cometbft/cometbft/crypto" - cmtnet "github.com/cometbft/cometbft/libs/net" + cmtnet "github.com/cometbft/cometbft/internal/net" p2pconn "github.com/cometbft/cometbft/p2p/conn" ) diff --git a/privval/socket_dialers_test.go b/privval/socket_dialers_test.go index f167a1daed3..cd3d9158794 100644 --- a/privval/socket_dialers_test.go +++ b/privval/socket_dialers_test.go @@ -12,10 +12,11 @@ import ( ) func getDialerTestCases(t *testing.T) []dialerTestCase { + t.Helper() tcpAddr := GetFreeLocalhostAddrPort() unixFilePath, err := testUnixAddr() require.NoError(t, err) - unixAddr := fmt.Sprintf("unix://%s", unixFilePath) + unixAddr := "unix://" + unixFilePath return []dialerTestCase{ { @@ -34,7 +35,7 @@ func TestIsConnTimeoutForFundamentalTimeouts(t *testing.T) { tcpAddr := GetFreeLocalhostAddrPort() dialer := DialTCPFn(tcpAddr, time.Millisecond, ed25519.GenPrivKey()) _, err := dialer() - assert.Error(t, err) + require.Error(t, err) assert.True(t, IsConnTimeout(err)) } @@ -42,7 +43,7 @@ func TestIsConnTimeoutForWrappedConnTimeouts(t *testing.T) { tcpAddr := GetFreeLocalhostAddrPort() dialer := DialTCPFn(tcpAddr, time.Millisecond, ed25519.GenPrivKey()) _, err := dialer() - assert.Error(t, err) + require.Error(t, err) err = fmt.Errorf("%v: %w", err, ErrConnectionTimeout) assert.True(t, IsConnTimeout(err)) } diff --git a/privval/socket_listeners.go b/privval/socket_listeners.go index 6d406bd6925..44faab218b3 100644 --- a/privval/socket_listeners.go +++ b/privval/socket_listeners.go @@ -18,7 +18,7 @@ type timeoutError interface { Timeout() bool } -//------------------------------------------------------------------ +// ------------------------------------------------------------------ // TCP Listener // TCPListenerOption sets an optional parameter on the tcpListener. @@ -84,7 +84,7 @@ func (ln *TCPListener) Accept() (net.Conn, error) { return secretConn, nil } -//------------------------------------------------------------------ +// ------------------------------------------------------------------ // Unix Listener // unixListener implements net.Listener. @@ -145,7 +145,7 @@ func (ln *UnixListener) Accept() (net.Conn, error) { return conn, nil } -//------------------------------------------------------------------ +// ------------------------------------------------------------------ // Connection // timeoutConn implements net.Conn. @@ -171,7 +171,7 @@ func (c timeoutConn) Read(b []byte) (n int, err error) { deadline := time.Now().Add(c.timeout) err = c.Conn.SetReadDeadline(deadline) if err != nil { - return + return 0, err } return c.Conn.Read(b) @@ -183,7 +183,7 @@ func (c timeoutConn) Write(b []byte) (n int, err error) { deadline := time.Now().Add(c.timeout) err = c.Conn.SetWriteDeadline(deadline) if err != nil { - return + return 0, err } return c.Conn.Write(b) diff --git a/privval/socket_listeners_test.go b/privval/socket_listeners_test.go index 28d94300d0e..2547dfc9142 100644 --- a/privval/socket_listeners_test.go +++ b/privval/socket_listeners_test.go @@ -9,14 +9,14 @@ import ( "github.com/cometbft/cometbft/crypto/ed25519" ) -//------------------------------------------- +// ------------------------------------------- // helper funcs func newPrivKey() ed25519.PrivKey { return ed25519.GenPrivKey() } -//------------------------------------------- +// ------------------------------------------- // tests type listenerTestCase struct { @@ -26,7 +26,7 @@ type listenerTestCase struct { } // testUnixAddr will attempt to obtain a platform-independent temporary file -// name for a Unix socket +// name for a Unix socket. func testUnixAddr() (string, error) { f, err := os.CreateTemp("", "cometbft-privval-test-*") if err != nil { @@ -39,6 +39,7 @@ func testUnixAddr() (string, error) { } func tcpListenerTestCase(t *testing.T, timeoutAccept, timeoutReadWrite time.Duration) listenerTestCase { + t.Helper() ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) @@ -55,6 +56,7 @@ func tcpListenerTestCase(t *testing.T, timeoutAccept, timeoutReadWrite time.Dura } func unixListenerTestCase(t *testing.T, timeoutAccept, timeoutReadWrite time.Duration) listenerTestCase { + t.Helper() addr, err := testUnixAddr() if err != nil { t.Fatal(err) @@ -75,6 +77,7 @@ func unixListenerTestCase(t *testing.T, timeoutAccept, timeoutReadWrite time.Dur } func listenerTestCases(t *testing.T, timeoutAccept, timeoutReadWrite time.Duration) []listenerTestCase { + t.Helper() return []listenerTestCase{ tcpListenerTestCase(t, timeoutAccept, timeoutReadWrite), unixListenerTestCase(t, timeoutAccept, timeoutReadWrite), @@ -104,12 +107,16 @@ func TestListenerTimeoutReadWrite(t *testing.T) { // Note: this controls how long this test actually runs. timeoutReadWrite = 10 * time.Millisecond ) + for _, tc := range listenerTestCases(t, timeoutAccept, timeoutReadWrite) { go func(dialer SocketDialer) { - _, err := dialer() + conn, err := dialer() if err != nil { panic(err) } + // Add a delay before closing the connection + time.Sleep(2 * timeoutReadWrite) + conn.Close() }(tc.dialer) c, err := tc.listener.Accept() diff --git a/privval/utils.go b/privval/utils.go index b7d84a9e928..6754a927537 100644 --- a/privval/utils.go +++ b/privval/utils.go @@ -6,8 +6,8 @@ import ( "net" "github.com/cometbft/cometbft/crypto/ed25519" + cmtnet "github.com/cometbft/cometbft/internal/net" "github.com/cometbft/cometbft/libs/log" - cmtnet "github.com/cometbft/cometbft/libs/net" ) // IsConnTimeout returns a boolean indicating whether the error is known to @@ -25,7 +25,7 @@ func IsConnTimeout(err error) bool { } } -// NewSignerListener creates a new SignerListenerEndpoint using the corresponding listen address +// NewSignerListener creates a new SignerListenerEndpoint using the corresponding listen address. func NewSignerListener(listenAddr string, logger log.Logger) (*SignerListenerEndpoint, error) { var listener net.Listener @@ -52,7 +52,7 @@ func NewSignerListener(listenAddr string, logger log.Logger) (*SignerListenerEnd return pve, nil } -// GetFreeLocalhostAddrPort returns a free localhost:port address +// GetFreeLocalhostAddrPort returns a free localhost:port address. func GetFreeLocalhostAddrPort() string { port, err := cmtnet.GetFreePort() if err != nil { diff --git a/proto/README.md b/proto/README.md index fcce452a244..92940bfe9fd 100644 --- a/proto/README.md +++ b/proto/README.md @@ -1,41 +1,84 @@ -# Protocol Buffers - -This sections defines the types and messages shared across implementations. The -definition of the data structures are located in the -[core/data\_structures](../spec/core/data_structures.md) for the core data types -and ABCI definitions are located in the [ABCI](../spec/abci/README.md) section. - -## Process of Updates - -The `.proto` files within this section are core to the protocol and updates must -be treated as such. - -### Steps - -1. Make an issue with the proposed change. Within in the issue members from - both the CometBFT and tendermint-rs team will leave comments. If there is not - consensus on the change an [RFC](../docs/rfc/README.md) may be requested. - 1. Submission of an RFC as a pull request should be made to facilitate - further discussion. - 2. Merge the RFC. -2. Make the necessary changes to the `.proto` file(s), [core data - structures](../spec/core/data_structures.md) and/or [ABCI - protocol](../spec/abci). -3. Open issues within CometBFT and Tendermint-rs repos. This is used to notify - the teams that a change occurred in the spec. - 1. Tag the issue with a spec version label. This will notify the team the - changed has been made on master but has not entered a release. - -### Versioning - -The spec repo aims to be versioned. Once it has been versioned, updates to the -protobuf files will live on master. After a certain amount of time, decided on -by CometBFT and tendermint-rs team leads, a release will be made on the spec -repo. The spec may contain minor releases as well, depending on the -implementation these changes may lead to a breaking change. If so, the -implementation team should open an issue within the spec repo requiring a major -release of the spec. - -If the steps above were followed each implementation should have issues tagged -with a spec change label. Once all issues have been completed the team should -signify their readiness for release. +[NB]: # ( + Ensure that all hyperlinks in this doc are absolute URLs, not relative ones, + as this doc gets published to the Buf registry and relative URLs will fail + to resolve. +) + +# CometBFT Protocol Buffers Definitions + +This is the set of [Protobuf][protobuf] definitions of types used by various +parts of [CometBFT]: + +- The [Application Blockchain Interface][abci] (ABCI), especially in the context + of _remote_ applications. +- The P2P layer, in how CometBFT nodes interact with each other over the + network. +- In interaction with remote signers ("privval"). +- The RPC, in that the native JSON serialization of certain Protobuf types is + used when accepting and responding to RPC requests. +- The storage layer, in how data is serialized to and deserialized from on-disk + storage. + +The canonical Protobuf definitions live in the `proto` folder of the relevant +release branch of CometBFT. These definitions are published to the [Buf +registry][buf] for integrators' convenience. + +The Protobuf files are organized under two domains: `cometbft` and `tendermint`. +The `cometbft.*` packages use version suffixes to let application developers +target versions of the protocols as they have evolved between CometBFT releases. + +## Which CometBFT release does each package belong to? + +By the 1.0.0 release, the entire set of Protobuf definitions used by CometBFT +is published in packages suffixed with `.v1`. Earlier revisions of the +definitions, where they differed, are provided alongside in `.v1beta`_N_ +packages. The correspondence between package suffixes and releases is as follows: + +| Domain | 0.34 | 0.37 | 0.38 | 1.0 | +|-----------------|-----------|-----------|-----------|------| +| `abci` | `v1beta1` | `v1beta2` | `v1beta3` | `v1` | +| `blocksync` | | `v1beta1` | `v1` | `v1` | +| `consensus` | `v1beta1` | `v1beta1` | `v1beta1` | `v1` | +| `crypto` | `v1` | `v1` | `v1` | `v1` | +| `libs/bits` | `v1` | `v1` | `v1` | `v1` | +| `mempool` | `v1` | `v1` | `v1` | `v1` | +| `p2p` | `v1` | `v1` | `v1` | `v1` | +| `privval` | `v1beta1` | `v1beta1` | `v1beta2` | `v1` | +| `rpc/grpc`[^1] | `v1beta1` | `v1beta2` | `v1beta3` | | +| `state` | `v1beta1` | `v1beta2` | `v1beta3` | `v1` | +| `statesync` | `v1` | `v1` | `v1` | `v1` | +| `types` | `v1beta1` | `v1beta2` | `v1` | `v1` | +| `version` | `v1` | `v1` | `v1` | `v1` | + +[^1]: Retired in 1.0 + +## Why does CometBFT provide `tendermint` Protobuf definitions? + +This is as a result of CometBFT being a fork of [Tendermint Core][tmcore] and +wanting to provide integrators with as painless a way as possible of +transitioning from Tendermint Core to CometBFT. + +As of CometBFT v1, however, the project will transition to using and providing a +`cometbft` package of Protobuf definitions (see [\#1330]). + +Protobuf definitions for each respective release are also, for convenience, +published to a corresponding branch in the `tendermint/tendermint` Buf repository. + +| CometBFT version | Canonical Protobufs | Buf registry | +|------------------|---------------------------------------------|-------------------------------------------| +| v0.38.x | [v0.38.x Protobuf definitions][v038-protos] | [Buf repository v0.38.x branch][v038-buf] | +| v0.37.x | [v0.37.x Protobuf definitions][v037-protos] | [Buf repository v0.37.x branch][v037-buf] | +| v0.34.x | [v0.34.x Protobuf definitions][v034-protos] | [Buf repository v0.34.x branch][v034-buf] | + +[protobuf]: https://protobuf.dev/ +[CometBFT]: https://github.com/cometbft/cometbft +[abci]: https://github.com/cometbft/cometbft/tree/main/spec/abci +[buf]: https://buf.build/tendermint/tendermint +[tmcore]: https://github.com/tendermint/tendermint +[\#1330]: https://github.com/cometbft/cometbft/issues/1330 +[v034-protos]: https://github.com/cometbft/cometbft/tree/v0.34.x/proto +[v034-buf]: https://buf.build/tendermint/tendermint/docs/v0.34.x +[v037-protos]: https://github.com/cometbft/cometbft/tree/v0.37.x/proto +[v037-buf]: https://buf.build/tendermint/tendermint/docs/v0.37.x +[v038-protos]: https://github.com/cometbft/cometbft/tree/v0.38.x/proto +[v038-buf]: https://buf.build/tendermint/tendermint/docs/v0.38.x diff --git a/proto/buf.lock b/proto/buf.lock index f2b69369858..6bce5f5fc58 100644 --- a/proto/buf.lock +++ b/proto/buf.lock @@ -4,4 +4,5 @@ deps: - remote: buf.build owner: cosmos repository: gogo-proto - commit: 6652e3443c3b4504bb3bf82e73a7e409 + commit: 88ef6483f90f478fb938c37dde52ece3 + digest: shake256:89c45df2aa11e0cff97b0d695436713db3d993d76792e9f8dc1ae90e6ab9a9bec55503d48ceedd6b86069ab07d3041b32001b2bfe0227fa725dd515ff381e5ba diff --git a/proto/buf.yaml b/proto/buf.yaml index c6e0660f147..75155dc0b9c 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -1,11 +1,51 @@ version: v1 +name: buf.build/cometbft/cometbft deps: - buf.build/cosmos/gogo-proto breaking: use: - FILE +build: + excludes: + - tendermint lint: use: - - BASIC + - DEFAULT + - COMMENTS - FILE_LOWER_SNAKE_CASE - - UNARY_RPC + except: + - COMMENT_FIELD + ignore_only: + ENUM_VALUE_PREFIX: + - cometbft/abci/v1beta1 + - cometbft/abci/v1beta2 + - cometbft/abci/v1beta3 + ENUM_ZERO_VALUE_SUFFIX: + - cometbft/abci/v1beta1 + - cometbft/abci/v1beta2 + - cometbft/abci/v1beta3 + PACKAGE_VERSION_SUFFIX: + - cometbft/abci/v1beta1 + - cometbft/abci/v1beta2 + - cometbft/abci/v1beta3 + RPC_REQUEST_RESPONSE_UNIQUE: + - cometbft/abci/v1beta1 + - cometbft/abci/v1beta2 + - cometbft/abci/v1beta3 + - cometbft/rpc/grpc + RPC_REQUEST_STANDARD_NAME: + - cometbft/abci/v1beta1 + - cometbft/abci/v1beta2 + - cometbft/abci/v1beta3 + - cometbft/rpc/grpc + RPC_RESPONSE_STANDARD_NAME: + - cometbft/abci/v1beta1 + - cometbft/abci/v1beta2 + - cometbft/abci/v1beta3 + - cometbft/rpc/grpc + SERVICE_SUFFIX: + - cometbft/abci/v1beta1 + - cometbft/abci/v1beta2 + - cometbft/abci/v1beta3 + - cometbft/rpc/grpc + enum_zero_value_suffix: _UNKNOWN diff --git a/proto/cometbft/abci/v1/service.proto b/proto/cometbft/abci/v1/service.proto new file mode 100644 index 00000000000..535dbc83586 --- /dev/null +++ b/proto/cometbft/abci/v1/service.proto @@ -0,0 +1,42 @@ +syntax = "proto3"; +package cometbft.abci.v1; + +import "cometbft/abci/v1/types.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/abci/v1"; + +// ABCIService is a service for an ABCI application. +service ABCIService { + // Echo returns back the same message it is sent. + rpc Echo(EchoRequest) returns (EchoResponse); + // Flush flushes the write buffer. + rpc Flush(FlushRequest) returns (FlushResponse); + // Info returns information about the application state. + rpc Info(InfoRequest) returns (InfoResponse); + // CheckTx validates a transaction. + rpc CheckTx(CheckTxRequest) returns (CheckTxResponse); + // Query queries the application state. + rpc Query(QueryRequest) returns (QueryResponse); + // Commit commits a block of transactions. + rpc Commit(CommitRequest) returns (CommitResponse); + // InitChain initializes the blockchain. + rpc InitChain(InitChainRequest) returns (InitChainResponse); + // ListSnapshots lists all the available snapshots. + rpc ListSnapshots(ListSnapshotsRequest) returns (ListSnapshotsResponse); + // OfferSnapshot sends a snapshot offer. + rpc OfferSnapshot(OfferSnapshotRequest) returns (OfferSnapshotResponse); + // LoadSnapshotChunk returns a chunk of snapshot. + rpc LoadSnapshotChunk(LoadSnapshotChunkRequest) returns (LoadSnapshotChunkResponse); + // ApplySnapshotChunk applies a chunk of snapshot. + rpc ApplySnapshotChunk(ApplySnapshotChunkRequest) returns (ApplySnapshotChunkResponse); + // PrepareProposal returns a proposal for the next block. + rpc PrepareProposal(PrepareProposalRequest) returns (PrepareProposalResponse); + // ProcessProposal validates a proposal. + rpc ProcessProposal(ProcessProposalRequest) returns (ProcessProposalResponse); + // ExtendVote extends a vote with application-injected data (vote extensions). + rpc ExtendVote(ExtendVoteRequest) returns (ExtendVoteResponse); + // VerifyVoteExtension verifies a vote extension. + rpc VerifyVoteExtension(VerifyVoteExtensionRequest) returns (VerifyVoteExtensionResponse); + // FinalizeBlock finalizes a block. + rpc FinalizeBlock(FinalizeBlockRequest) returns (FinalizeBlockResponse); +} diff --git a/proto/cometbft/abci/v1/types.proto b/proto/cometbft/abci/v1/types.proto new file mode 100644 index 00000000000..e96cb6a549a --- /dev/null +++ b/proto/cometbft/abci/v1/types.proto @@ -0,0 +1,585 @@ +syntax = "proto3"; +package cometbft.abci.v1; + +import "cometbft/crypto/v1/keys.proto"; +import "cometbft/crypto/v1/proof.proto"; +import "cometbft/types/v1/params.proto"; +import "cometbft/types/v1/validator.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/abci/v1"; + +// ---------------------------------------- +// Request types + +// Request represents a request to the ABCI application. +message Request { + // Sum of all possible messages. + oneof value { + EchoRequest echo = 1; + FlushRequest flush = 2; + InfoRequest info = 3; + InitChainRequest init_chain = 5; + QueryRequest query = 6; + CheckTxRequest check_tx = 8; + CommitRequest commit = 11; + ListSnapshotsRequest list_snapshots = 12; + OfferSnapshotRequest offer_snapshot = 13; + LoadSnapshotChunkRequest load_snapshot_chunk = 14; + ApplySnapshotChunkRequest apply_snapshot_chunk = 15; + PrepareProposalRequest prepare_proposal = 16; + ProcessProposalRequest process_proposal = 17; + ExtendVoteRequest extend_vote = 18; + VerifyVoteExtensionRequest verify_vote_extension = 19; + FinalizeBlockRequest finalize_block = 20; + } + reserved 4, 7, 9, 10; // SetOption, BeginBlock, DeliverTx, EndBlock +} + +// EchoRequest is a request to "echo" the given string. +message EchoRequest { + string message = 1; +} + +// FlushRequest is a request to flush the write buffer. +message FlushRequest {} + +// InfoRequest is a request for the ABCI application version. +message InfoRequest { + string version = 1; + uint64 block_version = 2; + uint64 p2p_version = 3; + string abci_version = 4; +} + +// InitChainRequest is a request to initialize the blockchain. +message InitChainRequest { + google.protobuf.Timestamp time = 1 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + string chain_id = 2; + cometbft.types.v1.ConsensusParams consensus_params = 3; + repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; + int64 initial_height = 6; +} + +// QueryRequest is a request to query the application state. +message QueryRequest { + bytes data = 1; + string path = 2; + int64 height = 3; + bool prove = 4; +} + +// Type of the transaction check request. +// +// This enumeration is incompatible with the CheckTxType definition in +// cometbft.abci.v1beta1 and therefore shall not be used in encoding with the same +// field number. +enum CheckTxType { + option (gogoproto.goproto_enum_prefix) = false; + + // Unknown + CHECK_TX_TYPE_UNKNOWN = 0; + // Recheck (2nd, 3rd, etc.) + CHECK_TX_TYPE_RECHECK = 1; + // Check (1st time) + CHECK_TX_TYPE_CHECK = 2; +} + +// CheckTxRequest is a request to check that the transaction is valid. +message CheckTxRequest { + bytes tx = 1; + CheckTxType type = 3; + reserved 2; // v1beta1.CheckTxType type +} + +// CommitRequest is a request to commit the pending application state. +message CommitRequest {} + +// Request to list available snapshots. +message ListSnapshotsRequest {} + +// Request offering a snapshot to the application. +message OfferSnapshotRequest { + Snapshot snapshot = 1; // snapshot offered by peers + bytes app_hash = 2; // light client-verified app hash for snapshot height +} + +// Request to load a snapshot chunk. +message LoadSnapshotChunkRequest { + uint64 height = 1; + uint32 format = 2; + uint32 chunk = 3; +} + +// Request to apply a snapshot chunk. +message ApplySnapshotChunkRequest { + uint32 index = 1; + bytes chunk = 2; + string sender = 3; +} + +// PrepareProposalRequest is a request for the ABCI application to prepare a new +// block proposal. +message PrepareProposalRequest { + // the modified transactions cannot exceed this size. + int64 max_tx_bytes = 1; + // txs is an array of transactions that will be included in a block, + // sent to the app for possible modifications. + repeated bytes txs = 2; + ExtendedCommitInfo local_last_commit = 3 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 4 [(gogoproto.nullable) = false]; + int64 height = 5; + google.protobuf.Timestamp time = 6 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + bytes next_validators_hash = 7; + // address of the public key of the validator proposing the block. + bytes proposer_address = 8; +} + +// ProcessProposalRequest is a request for the ABCI application to process a proposal +// received from another validator. +message ProcessProposalRequest { + repeated bytes txs = 1; + CommitInfo proposed_last_commit = 2 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 3 [(gogoproto.nullable) = false]; + // Merkle root hash of the fields of the proposed block. + bytes hash = 4; + int64 height = 5; + google.protobuf.Timestamp time = 6 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + bytes next_validators_hash = 7; + // address of the public key of the original proposer of the block. + bytes proposer_address = 8; +} + +// ExtendVoteRequest extends a precommit vote with application-injected data. +message ExtendVoteRequest { + // the hash of the block that this vote may be referring to + bytes hash = 1; + // the height of the extended vote + int64 height = 2; + // info of the block that this vote may be referring to + google.protobuf.Timestamp time = 3 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + repeated bytes txs = 4; + CommitInfo proposed_last_commit = 5 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 6 [(gogoproto.nullable) = false]; + bytes next_validators_hash = 7; + // address of the public key of the original proposer of the block. + bytes proposer_address = 8; +} + +// VerifyVoteExtensionRequest is a request for the application to verify a vote extension +// produced by a different validator. +message VerifyVoteExtensionRequest { + // the hash of the block that this received vote corresponds to + bytes hash = 1; + // the validator that signed the vote extension + bytes validator_address = 2; + int64 height = 3; + bytes vote_extension = 4; +} + +// FinalizeBlockRequest is a request to finalize the block. +message FinalizeBlockRequest { + repeated bytes txs = 1; + CommitInfo decided_last_commit = 2 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 3 [(gogoproto.nullable) = false]; + // Merkle root hash of the fields of the decided block. + bytes hash = 4; + int64 height = 5; + google.protobuf.Timestamp time = 6 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + bytes next_validators_hash = 7; + // address of the public key of the original proposer of the block. + bytes proposer_address = 8; +} + +// ---------------------------------------- +// Response types + +// Response represents a response from the ABCI application. +message Response { + // Sum of all possible messages. + oneof value { + ExceptionResponse exception = 1; + EchoResponse echo = 2; + FlushResponse flush = 3; + InfoResponse info = 4; + InitChainResponse init_chain = 6; + QueryResponse query = 7; + CheckTxResponse check_tx = 9; + CommitResponse commit = 12; + ListSnapshotsResponse list_snapshots = 13; + OfferSnapshotResponse offer_snapshot = 14; + LoadSnapshotChunkResponse load_snapshot_chunk = 15; + ApplySnapshotChunkResponse apply_snapshot_chunk = 16; + PrepareProposalResponse prepare_proposal = 17; + ProcessProposalResponse process_proposal = 18; + ExtendVoteResponse extend_vote = 19; + VerifyVoteExtensionResponse verify_vote_extension = 20; + FinalizeBlockResponse finalize_block = 21; + } + reserved 5, 8, 10, 11; // SetOption, BeginBlock, DeliverTx, EndBlock +} + +// nondeterministic +message ExceptionResponse { + string error = 1; +} + +// EchoResponse indicates that the connection is still alive. +message EchoResponse { + string message = 1; +} + +// FlushResponse indicates that the write buffer was flushed. +message FlushResponse {} + +// InfoResponse contains the ABCI application version information. +message InfoResponse { + string data = 1; + + string version = 2; + uint64 app_version = 3; + + int64 last_block_height = 4; + bytes last_block_app_hash = 5; +} + +// InitChainResponse contains the ABCI application's hash and updates to the +// validator set and/or the consensus params, if any. +message InitChainResponse { + cometbft.types.v1.ConsensusParams consensus_params = 1; + repeated ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; + bytes app_hash = 3; +} + +// QueryResponse contains the ABCI application data along with a proof. +message QueryResponse { + uint32 code = 1; + // bytes data = 2; // use "value" instead. + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 index = 5; + bytes key = 6; + bytes value = 7; + cometbft.crypto.v1.ProofOps proof_ops = 8; + int64 height = 9; + string codespace = 10; +} + +// CheckTxResponse shows if the transaction was deemed valid by the ABCI +// application. +message CheckTxResponse { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated Event events = 7 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; // nondeterministic + string codespace = 8; + + // These reserved fields were used till v0.37 by the priority mempool (now + // removed). + reserved 9 to 11; + reserved "sender", "priority", "mempool_error"; +} + +// CommitResponse indicates how much blocks should CometBFT retain. +message CommitResponse { + reserved 1, 2; // data was previously returned here + int64 retain_height = 3; +} + +// ListSnapshotsResponse contains the list of snapshots. +message ListSnapshotsResponse { + repeated Snapshot snapshots = 1; +} + +// OfferSnapshotResponse indicates the ABCI application decision whenever to +// provide a snapshot to the requester or not. +message OfferSnapshotResponse { + OfferSnapshotResult result = 1; +} + +// The result of offering a snapshot. +enum OfferSnapshotResult { + option (gogoproto.goproto_enum_prefix) = false; + + // Unknown result, abort all snapshot restoration + OFFER_SNAPSHOT_RESULT_UNKNOWN = 0; + // Snapshot accepted, apply chunks + OFFER_SNAPSHOT_RESULT_ACCEPT = 1; + // Abort all snapshot restoration + OFFER_SNAPSHOT_RESULT_ABORT = 2; + // Reject this specific snapshot, try others + OFFER_SNAPSHOT_RESULT_REJECT = 3; + // Reject all snapshots of this format, try others + OFFER_SNAPSHOT_RESULT_REJECT_FORMAT = 4; + // Reject all snapshots from the sender(s), try others + OFFER_SNAPSHOT_RESULT_REJECT_SENDER = 5; +} + +// LoadSnapshotChunkResponse returns a snapshot's chunk. +message LoadSnapshotChunkResponse { + bytes chunk = 1; +} + +// ApplySnapshotChunkResponse returns a result of applying the specified chunk. +message ApplySnapshotChunkResponse { + ApplySnapshotChunkResult result = 1; + repeated uint32 refetch_chunks = 2; // Chunks to refetch and reapply + repeated string reject_senders = 3; // Chunk senders to reject and ban +} + +// The result of applying a snapshot chunk. +enum ApplySnapshotChunkResult { + option (gogoproto.goproto_enum_prefix) = false; + + // Unknown result, abort all snapshot restoration + APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN = 0; + // Chunk successfully accepted + APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT = 1; + // Abort all snapshot restoration + APPLY_SNAPSHOT_CHUNK_RESULT_ABORT = 2; + // Retry chunk (combine with refetch and reject) + APPLY_SNAPSHOT_CHUNK_RESULT_RETRY = 3; + // Retry snapshot (combine with refetch and reject) + APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT = 4; + // Reject this snapshot, try others + APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT = 5; +} + +// PrepareProposalResponse contains a list of transactions, which will form a block. +message PrepareProposalResponse { + repeated bytes txs = 1; +} + +// ProcessProposalResponse indicates the ABCI application's decision whenever +// the given proposal should be accepted or not. +message ProcessProposalResponse { + ProcessProposalStatus status = 1; +} + +// ProcessProposalStatus is the status of the proposal processing. +enum ProcessProposalStatus { + option (gogoproto.goproto_enum_prefix) = false; + + // Unknown + PROCESS_PROPOSAL_STATUS_UNKNOWN = 0; + // Accepted + PROCESS_PROPOSAL_STATUS_ACCEPT = 1; + // Rejected + PROCESS_PROPOSAL_STATUS_REJECT = 2; +} + +// ExtendVoteResponse contains the vote extension that the application would like to +// attach to its next precommit vote. +message ExtendVoteResponse { + bytes vote_extension = 1; +} + +// VerifyVoteExtensionResponse indicates the ABCI application's decision +// whenever the vote extension should be accepted or not. +message VerifyVoteExtensionResponse { + VerifyVoteExtensionStatus status = 1; +} + +// VerifyVoteExtensionStatus is the status of the vote extension verification. +enum VerifyVoteExtensionStatus { + option (gogoproto.goproto_enum_prefix) = false; + + // Unknown + VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN = 0; + // Accepted + VERIFY_VOTE_EXTENSION_STATUS_ACCEPT = 1; + // Rejecting the vote extension will reject the entire precommit by the sender. + // Incorrectly implementing this thus has liveness implications as it may affect + // CometBFT's ability to receive 2/3+ valid votes to finalize the block. + // Honest nodes should never be rejected. + VERIFY_VOTE_EXTENSION_STATUS_REJECT = 2; +} + +// FinalizeBlockResponse contains the result of executing the block. +message FinalizeBlockResponse { + // set of block events emitted as part of executing the block + repeated Event events = 1 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; // nondeterministic + // the result of executing each transaction including the events + // the particular transaction emitted. This should match the order + // of the transactions delivered in the block itself + repeated ExecTxResult tx_results = 2; + // a list of updates to the validator set. These will reflect the validator set at current height + 2. + repeated ValidatorUpdate validator_updates = 3 [(gogoproto.nullable) = false]; + // updates to the consensus params, if any. + cometbft.types.v1.ConsensusParams consensus_param_updates = 4; + // app_hash is the hash of the applications' state which is used to confirm + // that execution of the transactions was deterministic. + // It is up to the application to decide which algorithm to use. + bytes app_hash = 5; +} + +// ---------------------------------------- +// Misc. + +// CommitInfo contains votes for the particular round. +message CommitInfo { + int32 round = 1; + repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + +// ExtendedCommitInfo is similar to CommitInfo except that it is only used in +// the PrepareProposal request such that Tendermint can provide vote extensions +// to the application. +message ExtendedCommitInfo { + // The round at which the block proposer decided in the previous height. + int32 round = 1; + // List of validators' addresses in the last validator set with their voting + // information, including vote extensions. + repeated ExtendedVoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + +// Event allows application developers to attach additional information to +// ResponseFinalizeBlock and ResponseCheckTx. +// Up to 0.37, this could also be used in ResponseBeginBlock, ResponseEndBlock, +// and ResponseDeliverTx. +// Later, transactions may be queried using these events. +message Event { + string type = 1; + repeated EventAttribute attributes = 2 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "attributes,omitempty" + ]; +} + +// EventAttribute is a single key-value pair, associated with an event. +message EventAttribute { + string key = 1; + string value = 2; + bool index = 3; // nondeterministic +} + +// ExecTxResult contains results of executing one individual transaction. +// +// * Its structure is equivalent to #ResponseDeliverTx which will be deprecated/deleted +message ExecTxResult { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; // nondeterministic + string codespace = 8; +} + +// TxResult contains results of executing the transaction. +// +// One usage is indexing transaction results. +message TxResult { + int64 height = 1; + uint32 index = 2; + bytes tx = 3; + ExecTxResult result = 4 [(gogoproto.nullable) = false]; +} + +// ---------------------------------------- +// Blockchain Types + +// Validator in the validator set. +message Validator { + bytes address = 1; // The first 20 bytes of SHA256(public key) + // PubKey pub_key = 2 [(gogoproto.nullable)=false]; + int64 power = 3; // The voting power +} + +// ValidatorUpdate is a singular update to a validator set. +message ValidatorUpdate { + cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + int64 power = 2; +} + +// VoteInfo contains the information about the vote. +message VoteInfo { + Validator validator = 1 [(gogoproto.nullable) = false]; + cometbft.types.v1.BlockIDFlag block_id_flag = 3; + + reserved 2; // signed_last_block +} + +// ExtendedVoteInfo extends VoteInfo with the vote extensions (non-deterministic). +message ExtendedVoteInfo { + // The validator that sent the vote. + Validator validator = 1 [(gogoproto.nullable) = false]; + // Non-deterministic extension provided by the sending validator's application. + bytes vote_extension = 3; + // Vote extension signature created by CometBFT + bytes extension_signature = 4; + // block_id_flag indicates whether the validator voted for a block, nil, or did not vote at all + cometbft.types.v1.BlockIDFlag block_id_flag = 5; + + reserved 2; // signed_last_block +} + +// The type of misbehavior committed by a validator. +enum MisbehaviorType { + option (gogoproto.goproto_enum_prefix) = false; + + // Unknown + MISBEHAVIOR_TYPE_UNKNOWN = 0; + // Duplicate vote + MISBEHAVIOR_TYPE_DUPLICATE_VOTE = 1; + // Light client attack + MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK = 2; +} + +// Misbehavior is a type of misbehavior committed by a validator. +message Misbehavior { + MisbehaviorType type = 1; + // The offending validator + Validator validator = 2 [(gogoproto.nullable) = false]; + // The height when the offense occurred + int64 height = 3; + // The corresponding time where the offense occurred + google.protobuf.Timestamp time = 4 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + // Total voting power of the validator set in case the ABCI application does + // not store historical validators. + // https://github.com/tendermint/tendermint/issues/4581 + int64 total_voting_power = 5; +} + +// ---------------------------------------- +// State Sync Types + +// Snapshot of the ABCI application state. +message Snapshot { + uint64 height = 1; // The height at which the snapshot was taken + uint32 format = 2; // The application-specific snapshot format + uint32 chunks = 3; // Number of chunks in the snapshot + bytes hash = 4; // Arbitrary snapshot hash, equal only if identical + bytes metadata = 5; // Arbitrary application metadata +} diff --git a/proto/cometbft/abci/v1beta1/types.proto b/proto/cometbft/abci/v1beta1/types.proto new file mode 100644 index 00000000000..cd3dd37cafd --- /dev/null +++ b/proto/cometbft/abci/v1beta1/types.proto @@ -0,0 +1,492 @@ +syntax = "proto3"; +package cometbft.abci.v1beta1; + +import "cometbft/crypto/v1/keys.proto"; +// For more information on gogo.proto, see: +// https://github.com/cosmos/gogoproto/blob/master/extensions.md +import "cometbft/crypto/v1/proof.proto"; +import "cometbft/types/v1beta1/params.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/abci/v1beta1"; + +// NOTE: When using custom types, mind the warnings. +// https://github.com/cosmos/gogoproto/blob/master/custom_types.md#warnings-and-issues + +// ---------------------------------------- +// Request types + +// Request represents a request to the ABCI application. +message Request { + // Sum of all possible messages. + oneof value { + RequestEcho echo = 1; + RequestFlush flush = 2; + RequestInfo info = 3; + RequestSetOption set_option = 4; + RequestInitChain init_chain = 5; + RequestQuery query = 6; + RequestBeginBlock begin_block = 7; + RequestCheckTx check_tx = 8; + RequestDeliverTx deliver_tx = 9; + RequestEndBlock end_block = 10; + RequestCommit commit = 11; + RequestListSnapshots list_snapshots = 12; + RequestOfferSnapshot offer_snapshot = 13; + RequestLoadSnapshotChunk load_snapshot_chunk = 14; + RequestApplySnapshotChunk apply_snapshot_chunk = 15; + } +} + +// RequestEcho is a request to "echo" the given string. +message RequestEcho { + string message = 1; +} + +// RequestFlush is a request to flush the write buffer. +message RequestFlush {} + +// RequestInfo is a request for the ABCI application version. +message RequestInfo { + string version = 1; + uint64 block_version = 2; + uint64 p2p_version = 3; +} + +// nondeterministic +message RequestSetOption { + string key = 1; + string value = 2; +} + +// RequestInitChain is a request to initialize the blockchain. +message RequestInitChain { + google.protobuf.Timestamp time = 1 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + string chain_id = 2; + ConsensusParams consensus_params = 3; + repeated ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; + int64 initial_height = 6; +} + +// RequestQuery is a request to query the application state. +message RequestQuery { + bytes data = 1; + string path = 2; + int64 height = 3; + bool prove = 4; +} + +// RequestBeginBlock indicates the beginning of committing the block. +message RequestBeginBlock { + bytes hash = 1; + cometbft.types.v1beta1.Header header = 2 [(gogoproto.nullable) = false]; + LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; + repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; +} + +// Type of the transaction check request. +enum CheckTxType { + // New + NEW = 0 [(gogoproto.enumvalue_customname) = "New"]; + // Recheck (2nd, 3rd, etc.) + RECHECK = 1 [(gogoproto.enumvalue_customname) = "Recheck"]; +} + +// RequestCheckTx is a request to check the transaction. +message RequestCheckTx { + bytes tx = 1; + CheckTxType type = 2; +} + +// RequestDeliverTx is a request to apply the transaction. +message RequestDeliverTx { + bytes tx = 1; +} + +// RequestEndBlock indicates the end of committing the block. +message RequestEndBlock { + int64 height = 1; +} + +// RequestCommit is a request to commit the pending application state. +message RequestCommit {} + +// lists available snapshots +message RequestListSnapshots {} + +// offers a snapshot to the application +message RequestOfferSnapshot { + Snapshot snapshot = 1; // snapshot offered by peers + bytes app_hash = 2; // light client-verified app hash for snapshot height +} + +// loads a snapshot chunk +message RequestLoadSnapshotChunk { + uint64 height = 1; + uint32 format = 2; + uint32 chunk = 3; +} + +// Applies a snapshot chunk +message RequestApplySnapshotChunk { + uint32 index = 1; + bytes chunk = 2; + string sender = 3; +} + +// ---------------------------------------- +// Response types + +// Response represents a response from the ABCI application. +message Response { + // Sum of all possible messages. + oneof value { + ResponseException exception = 1; + ResponseEcho echo = 2; + ResponseFlush flush = 3; + ResponseInfo info = 4; + ResponseSetOption set_option = 5; + ResponseInitChain init_chain = 6; + ResponseQuery query = 7; + ResponseBeginBlock begin_block = 8; + ResponseCheckTx check_tx = 9; + ResponseDeliverTx deliver_tx = 10; + ResponseEndBlock end_block = 11; + ResponseCommit commit = 12; + ResponseListSnapshots list_snapshots = 13; + ResponseOfferSnapshot offer_snapshot = 14; + ResponseLoadSnapshotChunk load_snapshot_chunk = 15; + ResponseApplySnapshotChunk apply_snapshot_chunk = 16; + } +} + +// nondeterministic +message ResponseException { + string error = 1; +} + +// ResponseEcho indicates that the connection is still alive. +message ResponseEcho { + string message = 1; +} + +// ResponseFlush indicates that the ABCI application state was flushed? +message ResponseFlush {} + +// ResponseInfo contains the ABCI application version information. +message ResponseInfo { + string data = 1; + + string version = 2; + uint64 app_version = 3; + + int64 last_block_height = 4; + bytes last_block_app_hash = 5; +} + +// nondeterministic +message ResponseSetOption { + uint32 code = 1; + // bytes data = 2; + string log = 3; + string info = 4; +} + +// ResponseInitChain contains the ABCI application's hash and updates to the +// validator set and/or the consensus params, if any. +message ResponseInitChain { + ConsensusParams consensus_params = 1; + repeated ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; + bytes app_hash = 3; +} + +// ResponseQuery contains the ABCI application data along with a proof. +message ResponseQuery { + uint32 code = 1; + // bytes data = 2; // use "value" instead. + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 index = 5; + bytes key = 6; + bytes value = 7; + cometbft.crypto.v1.ProofOps proof_ops = 8; + int64 height = 9; + string codespace = 10; +} + +// ResponseBeginBlock contains a list of block-level events. +message ResponseBeginBlock { + repeated Event events = 1 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; +} + +// ResponseCheckTx shows if the transaction was deemed valid by the ABCI +// application. +message ResponseCheckTx { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated Event events = 7 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; + string codespace = 8; + string sender = 9; + int64 priority = 10; + + // mempool_error is set by CometBFT. + // ABCI applications creating a ResponseCheckTX should not set mempool_error. + string mempool_error = 11; +} + +// ResponseDeliverTx contains a result of committing the given transaction and a +// list of events. +message ResponseDeliverTx { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated Event events = 7 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; // nondeterministic + string codespace = 8; +} + +// ResponseEndBlock contains updates to consensus params and/or validator set changes, if any. +message ResponseEndBlock { + repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; + ConsensusParams consensus_param_updates = 2; + repeated Event events = 3 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; +} + +// ResponseCommit indicates how much blocks should CometBFT retain. +message ResponseCommit { + // reserve 1 + bytes data = 2; + int64 retain_height = 3; +} + +// ResponseListSnapshots contains the list of snapshots. +message ResponseListSnapshots { + repeated Snapshot snapshots = 1; +} + +// ResponseOfferSnapshot indicates the ABCI application decision whenever to +// provide a snapshot to the requester or not. +message ResponseOfferSnapshot { + Result result = 1; + + // The status code. + enum Result { + // Unknown result, abort all snapshot restoration + UNKNOWN = 0; + // Snapshot accepted, apply chunks + ACCEPT = 1; + // Abort all snapshot restoration + ABORT = 2; + // Reject this specific snapshot, try others + REJECT = 3; + // Reject all snapshots of this format, try others + REJECT_FORMAT = 4; + // Reject all snapshots from the sender(s), try others + REJECT_SENDER = 5; + } +} + +// ResponseLoadSnapshotChunk returns a snapshot's chunk. +message ResponseLoadSnapshotChunk { + bytes chunk = 1; +} + +// ResponseApplySnapshotChunk returns a result of applying the specified chunk. +message ResponseApplySnapshotChunk { + Result result = 1; + repeated uint32 refetch_chunks = 2; // Chunks to refetch and reapply + repeated string reject_senders = 3; // Chunk senders to reject and ban + + // The status code. + enum Result { + // Unknown result, abort all snapshot restoration + UNKNOWN = 0; + // Chunk successfully accepted + ACCEPT = 1; + // Abort all snapshot restoration + ABORT = 2; + // Retry chunk (combine with refetch and reject) + RETRY = 3; + // Retry snapshot (combine with refetch and reject) + RETRY_SNAPSHOT = 4; + // Reject this snapshot, try others + REJECT_SNAPSHOT = 5; + } +} + +// ---------------------------------------- +// Misc. + +// ConsensusParams contains all consensus-relevant parameters +// that can be adjusted by the abci app +message ConsensusParams { + BlockParams block = 1; + cometbft.types.v1beta1.EvidenceParams evidence = 2; + cometbft.types.v1beta1.ValidatorParams validator = 3; + cometbft.types.v1beta1.VersionParams version = 4; +} + +// BlockParams contains limits on the block size. +message BlockParams { + // Note: must be greater than 0 + int64 max_bytes = 1; + // Note: must be greater or equal to -1 + int64 max_gas = 2; +} + +// LastCommitInfo contains votes for the particular round. +message LastCommitInfo { + int32 round = 1; + repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + +// Event allows application developers to attach additional information to +// ResponseBeginBlock, ResponseEndBlock, ResponseCheckTx and ResponseDeliverTx. +// Later, transactions may be queried using these events. +message Event { + string type = 1; + repeated EventAttribute attributes = 2 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "attributes,omitempty" + ]; +} + +// EventAttribute is a single key-value pair, associated with an event. +message EventAttribute { + bytes key = 1; + bytes value = 2; + bool index = 3; // nondeterministic +} + +// TxResult contains results of executing the transaction. +// +// One usage is indexing transaction results. +message TxResult { + int64 height = 1; + uint32 index = 2; + bytes tx = 3; + ResponseDeliverTx result = 4 [(gogoproto.nullable) = false]; +} + +// ---------------------------------------- +// Blockchain Types + +// Validator in the validator set. +message Validator { + bytes address = 1; // The first 20 bytes of SHA256(public key) + // PubKey pub_key = 2 [(gogoproto.nullable)=false]; + int64 power = 3; // The voting power +} + +// ValidatorUpdate is a singular update to a validator set. +message ValidatorUpdate { + cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + int64 power = 2; +} + +// VoteInfo contains the information about the vote. +message VoteInfo { + Validator validator = 1 [(gogoproto.nullable) = false]; + bool signed_last_block = 2; +} + +// The type of evidence. +enum EvidenceType { + // Unknown + UNKNOWN = 0; + // Duplicate vote + DUPLICATE_VOTE = 1; + // Light client attack + LIGHT_CLIENT_ATTACK = 2; +} + +// Evidence of a misbehavior committed by a validator. +message Evidence { + EvidenceType type = 1; + // The offending validator + Validator validator = 2 [(gogoproto.nullable) = false]; + // The height when the offense occurred + int64 height = 3; + // The corresponding time where the offense occurred + google.protobuf.Timestamp time = 4 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + // Total voting power of the validator set in case the ABCI application does + // not store historical validators. + // https://github.com/tendermint/tendermint/issues/4581 + int64 total_voting_power = 5; +} + +// ---------------------------------------- +// State Sync Types + +// Snapshot of the ABCI application state. +message Snapshot { + uint64 height = 1; // The height at which the snapshot was taken + uint32 format = 2; // The application-specific snapshot format + uint32 chunks = 3; // Number of chunks in the snapshot + bytes hash = 4; // Arbitrary snapshot hash, equal only if identical + bytes metadata = 5; // Arbitrary application metadata +} + +// ---------------------------------------- +// Service Definition + +// ABCIApplication is a service for an ABCI application. +service ABCIApplication { + // Echo returns back the same message it is sent. + rpc Echo(RequestEcho) returns (ResponseEcho); + // Flush flushes the write buffer. + rpc Flush(RequestFlush) returns (ResponseFlush); + // Info returns information about the application state. + rpc Info(RequestInfo) returns (ResponseInfo); + // SetOption sets a parameter in the application. + rpc SetOption(RequestSetOption) returns (ResponseSetOption); + // DeliverTx applies a transaction. + rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx); + // CheckTx validates a transaction. + rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx); + // Query queries the application state. + rpc Query(RequestQuery) returns (ResponseQuery); + // Commit commits a block of transactions. + rpc Commit(RequestCommit) returns (ResponseCommit); + // InitChain initializes the blockchain. + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + // BeginBlock signals the beginning of a block. + rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); + // EndBlock signals the end of a block, returns changes to the validator set. + rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); + // ListSnapshots lists all the available snapshots. + rpc ListSnapshots(RequestListSnapshots) returns (ResponseListSnapshots); + // OfferSnapshot sends a snapshot offer. + rpc OfferSnapshot(RequestOfferSnapshot) returns (ResponseOfferSnapshot); + // LoadSnapshotChunk returns a chunk of snapshot. + rpc LoadSnapshotChunk(RequestLoadSnapshotChunk) returns (ResponseLoadSnapshotChunk); + // ApplySnapshotChunk applies a chunk of snapshot. + rpc ApplySnapshotChunk(RequestApplySnapshotChunk) returns (ResponseApplySnapshotChunk); +} diff --git a/proto/cometbft/abci/v1beta2/types.proto b/proto/cometbft/abci/v1beta2/types.proto new file mode 100644 index 00000000000..db6db7d6da0 --- /dev/null +++ b/proto/cometbft/abci/v1beta2/types.proto @@ -0,0 +1,326 @@ +syntax = "proto3"; +package cometbft.abci.v1beta2; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/abci/v1beta2"; + +// For more information on gogo.proto, see: +// https://github.com/cosmos/gogoproto/blob/master/extensions.md +import "gogoproto/gogo.proto"; +import "cometbft/abci/v1beta1/types.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "cometbft/types/v1beta2/params.proto"; +import "google/protobuf/timestamp.proto"; + +// NOTE: When using custom types, mind the warnings. +// https://github.com/cosmos/gogoproto/blob/master/custom_types.md#warnings-and-issues + +// ---------------------------------------- +// Request types + +// Request represents a request to the ABCI application. +message Request { + // Sum of all possible messages. + oneof value { + v1beta1.RequestEcho echo = 1; + v1beta1.RequestFlush flush = 2; + RequestInfo info = 3; + RequestInitChain init_chain = 5; + v1beta1.RequestQuery query = 6; + RequestBeginBlock begin_block = 7; + v1beta1.RequestCheckTx check_tx = 8; + v1beta1.RequestDeliverTx deliver_tx = 9; + v1beta1.RequestEndBlock end_block = 10; + v1beta1.RequestCommit commit = 11; + v1beta1.RequestListSnapshots list_snapshots = 12; + v1beta1.RequestOfferSnapshot offer_snapshot = 13; + v1beta1.RequestLoadSnapshotChunk load_snapshot_chunk = 14; + v1beta1.RequestApplySnapshotChunk apply_snapshot_chunk = 15; + RequestPrepareProposal prepare_proposal = 16; + RequestProcessProposal process_proposal = 17; + } + reserved 4; +} + +// RequestInfo is a request for the ABCI application version. +message RequestInfo { + string version = 1; + uint64 block_version = 2; + uint64 p2p_version = 3; + string abci_version = 4; +} + +// RequestInitChain is a request to initialize the blockchain. +message RequestInitChain { + google.protobuf.Timestamp time = 1 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 2; + cometbft.types.v1beta2.ConsensusParams consensus_params = 3; + repeated v1beta1.ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; + int64 initial_height = 6; +} + +// RequestBeginBlock indicates the beginning of committing the block. +message RequestBeginBlock { + bytes hash = 1; + cometbft.types.v1beta1.Header header = 2 [(gogoproto.nullable) = false]; + CommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; + repeated Misbehavior byzantine_validators = 4 [(gogoproto.nullable) = false]; +} + +// RequestPrepareProposal is a request for the ABCI application to prepare a new +// block proposal. +message RequestPrepareProposal { + // the modified transactions cannot exceed this size. + int64 max_tx_bytes = 1; + // txs is an array of transactions that will be included in a block, + // sent to the app for possible modifications. + repeated bytes txs = 2; + ExtendedCommitInfo local_last_commit = 3 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 4 [(gogoproto.nullable) = false]; + int64 height = 5; + google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes next_validators_hash = 7; + // address of the public key of the validator proposing the block. + bytes proposer_address = 8; +} + +// RequestProcessProposal is a request for the ABCI application to process proposal. +message RequestProcessProposal { + repeated bytes txs = 1; + CommitInfo proposed_last_commit = 2 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 3 [(gogoproto.nullable) = false]; + // hash is the merkle root hash of the fields of the proposed block. + bytes hash = 4; + int64 height = 5; + google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes next_validators_hash = 7; + // address of the public key of the original proposer of the block. + bytes proposer_address = 8; +} + +// ---------------------------------------- +// Response types + +// Response represents a response from the ABCI application. +message Response { + // Sum of all possible messages. + oneof value { + v1beta1.ResponseException exception = 1; + v1beta1.ResponseEcho echo = 2; + v1beta1.ResponseFlush flush = 3; + v1beta1.ResponseInfo info = 4; + ResponseInitChain init_chain = 6; + v1beta1.ResponseQuery query = 7; + ResponseBeginBlock begin_block = 8; + ResponseCheckTx check_tx = 9; + ResponseDeliverTx deliver_tx = 10; + ResponseEndBlock end_block = 11; + v1beta1.ResponseCommit commit = 12; + v1beta1.ResponseListSnapshots list_snapshots = 13; + v1beta1.ResponseOfferSnapshot offer_snapshot = 14; + v1beta1.ResponseLoadSnapshotChunk load_snapshot_chunk = 15; + v1beta1.ResponseApplySnapshotChunk apply_snapshot_chunk = 16; + ResponsePrepareProposal prepare_proposal = 17; + ResponseProcessProposal process_proposal = 18; + } + reserved 5; +} + +// ResponseInitChain contains the ABCI application's hash and updates to the +// validator set and/or the consensus params, if any. +message ResponseInitChain { + cometbft.types.v1beta2.ConsensusParams consensus_params = 1; + repeated v1beta1.ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; + bytes app_hash = 3; +} + +// ResponseBeginBlock contains a list of block-level events. +message ResponseBeginBlock { + repeated Event events = 1 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; +} + +// ResponseCheckTx shows if the transaction was deemed valid by the ABCI +// application. +message ResponseCheckTx { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + string codespace = 8; + string sender = 9; + int64 priority = 10; + + // mempool_error is set by CometBFT. + // ABCI applications creating a ResponseCheckTX should not set mempool_error. + string mempool_error = 11; +} + +// ResponseDeliverTx contains a result of committing the given transaction and a +// list of events. +message ResponseDeliverTx { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated Event events = 7 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; // nondeterministic + string codespace = 8; +} + +// ResponseEndBlock contains updates to consensus params and/or validator set changes, if any. +message ResponseEndBlock { + repeated v1beta1.ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; + cometbft.types.v1beta2.ConsensusParams consensus_param_updates = 2; + repeated Event events = 3 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; +} + +// ResponsePrepareProposal contains the list of transactions that will be included in the proposal. +message ResponsePrepareProposal { + repeated bytes txs = 1; +} + +// ResponseProcessProposal contains the result of processing a proposal. +message ResponseProcessProposal { + ProposalStatus status = 1; + + // The status. + enum ProposalStatus { + // Unknown + UNKNOWN = 0; + // Accepted + ACCEPT = 1; + // Rejected + REJECT = 2; + } +} + +// ---------------------------------------- +// Misc. + +// CommitInfo contains votes for the particular round. +message CommitInfo { + int32 round = 1; + repeated v1beta1.VoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + +// ExtendedCommitInfo is similar to CommitInfo except that it is only used in +// the PrepareProposal request such that Tendermint can provide vote extensions +// to the application. +message ExtendedCommitInfo { + // The round at which the block proposer decided in the previous height. + int32 round = 1; + // List of validators' addresses in the last validator set with their voting + // information, including vote extensions. + repeated ExtendedVoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + +// Event allows application developers to attach additional information to +// ResponseFinalizeBlock (defined in .v1beta3) and ResponseCheckTx. +// Up to 0.37, this could also be used in ResponseBeginBlock, ResponseEndBlock, +// and ResponseDeliverTx. +// Later, transactions may be queried using these events. +message Event { + string type = 1; + repeated EventAttribute attributes = 2 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "attributes,omitempty" + ]; +} + +// EventAttribute is a single key-value pair, associated with an event. +message EventAttribute { + string key = 1; + string value = 2; + bool index = 3; // nondeterministic +} + +// ---------------------------------------- +// Blockchain Types + +// ExtendedVoteInfo extends VoteInfo with the vote extensions (non-deterministic). +message ExtendedVoteInfo { + // The validator that sent the vote. + v1beta1.Validator validator = 1 [(gogoproto.nullable) = false]; + // Indicates whether the validator signed the last block, allowing for rewards based on validator availability. + bool signed_last_block = 2; + // Non-deterministic extension provided by the sending validator's application. + bytes vote_extension = 3; +} + +// The type of misbehavior committed by a validator. +enum MisbehaviorType { + // Unknown + UNKNOWN = 0; + // Duplicate vote + DUPLICATE_VOTE = 1; + // Light client attack + LIGHT_CLIENT_ATTACK = 2; +} + +// Misbehavior is a type of misbehavior committed by a validator. +message Misbehavior { + MisbehaviorType type = 1; + // The offending validator + v1beta1.Validator validator = 2 [(gogoproto.nullable) = false]; + // The height when the offense occurred + int64 height = 3; + // The corresponding time where the offense occurred + google.protobuf.Timestamp time = 4 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + // Total voting power of the validator set in case the ABCI application does + // not store historical validators. + // https://github.com/tendermint/tendermint/issues/4581 + int64 total_voting_power = 5; +} + +// ---------------------------------------- +// Service Definition + +// ABCIApplication is a service for an ABCI application. +service ABCIApplication { + // Echo returns back the same message it is sent. + rpc Echo(v1beta1.RequestEcho) returns (v1beta1.ResponseEcho); + // Flush flushes the write buffer. + rpc Flush(v1beta1.RequestFlush) returns (v1beta1.ResponseFlush); + // Info returns information about the application state. + rpc Info(RequestInfo) returns (v1beta1.ResponseInfo); + // DeliverTx applies a transaction. + rpc DeliverTx(v1beta1.RequestDeliverTx) returns (ResponseDeliverTx); + // CheckTx validates a transaction. + rpc CheckTx(v1beta1.RequestCheckTx) returns (ResponseCheckTx); + // Query queries the application state. + rpc Query(v1beta1.RequestQuery) returns (v1beta1.ResponseQuery); + // Commit commits a block of transactions. + rpc Commit(v1beta1.RequestCommit) returns (v1beta1.ResponseCommit); + // InitChain initializes the blockchain. + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + // BeginBlock signals the beginning of a block. + rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock); + // EndBlock signals the end of a block, returns changes to the validator set. + rpc EndBlock(v1beta1.RequestEndBlock) returns (ResponseEndBlock); + // ListSnapshots lists all the available snapshots. + rpc ListSnapshots(v1beta1.RequestListSnapshots) returns (v1beta1.ResponseListSnapshots); + // OfferSnapshot sends a snapshot offer. + rpc OfferSnapshot(v1beta1.RequestOfferSnapshot) returns (v1beta1.ResponseOfferSnapshot); + // LoadSnapshotChunk returns a chunk of snapshot. + rpc LoadSnapshotChunk(v1beta1.RequestLoadSnapshotChunk) + returns (v1beta1.ResponseLoadSnapshotChunk); + // ApplySnapshotChunk applies a chunk of snapshot. + rpc ApplySnapshotChunk(v1beta1.RequestApplySnapshotChunk) + returns (v1beta1.ResponseApplySnapshotChunk); + // PrepareProposal returns a proposal for the next block. + rpc PrepareProposal(RequestPrepareProposal) returns (ResponsePrepareProposal); + // ProcessProposal validates a proposal. + rpc ProcessProposal(RequestProcessProposal) returns (ResponseProcessProposal); +} diff --git a/proto/cometbft/abci/v1beta3/types.proto b/proto/cometbft/abci/v1beta3/types.proto new file mode 100644 index 00000000000..2b3c7f744df --- /dev/null +++ b/proto/cometbft/abci/v1beta3/types.proto @@ -0,0 +1,336 @@ +syntax = "proto3"; +package cometbft.abci.v1beta3; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/abci/v1beta3"; + +// For more information on gogo.proto, see: +// https://github.com/cosmos/gogoproto/blob/master/extensions.md +import "cometbft/abci/v1beta1/types.proto"; +import "cometbft/abci/v1beta2/types.proto"; +import "cometbft/types/v1/params.proto"; +import "cometbft/types/v1beta1/validator.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +// NOTE: When using custom types, mind the warnings. +// https://github.com/cosmos/gogoproto/blob/master/custom_types.md#warnings-and-issues + +// ABCIService is a service for an ABCI application. +service ABCI { + // Echo returns back the same message it is sent. + rpc Echo(v1beta1.RequestEcho) returns (v1beta1.ResponseEcho); + // Flush flushes the write buffer. + rpc Flush(v1beta1.RequestFlush) returns (v1beta1.ResponseFlush); + // Info returns information about the application state. + rpc Info(v1beta2.RequestInfo) returns (v1beta1.ResponseInfo); + // CheckTx validates a transaction. + rpc CheckTx(v1beta1.RequestCheckTx) returns (ResponseCheckTx); + // Query queries the application state. + rpc Query(v1beta1.RequestQuery) returns (v1beta1.ResponseQuery); + // Commit commits a block of transactions. + rpc Commit(v1beta1.RequestCommit) returns (ResponseCommit); + // InitChain initializes the blockchain. + rpc InitChain(RequestInitChain) returns (ResponseInitChain); + // ListSnapshots lists all the available snapshots. + rpc ListSnapshots(v1beta1.RequestListSnapshots) returns (v1beta1.ResponseListSnapshots); + // OfferSnapshot sends a snapshot offer. + rpc OfferSnapshot(v1beta1.RequestOfferSnapshot) returns (v1beta1.ResponseOfferSnapshot); + // LoadSnapshotChunk returns a chunk of snapshot. + rpc LoadSnapshotChunk(v1beta1.RequestLoadSnapshotChunk) + returns (v1beta1.ResponseLoadSnapshotChunk); + // ApplySnapshotChunk applies a chunk of snapshot. + rpc ApplySnapshotChunk(v1beta1.RequestApplySnapshotChunk) + returns (v1beta1.ResponseApplySnapshotChunk); + // PrepareProposal returns a proposal for the next block. + rpc PrepareProposal(v1beta3.RequestPrepareProposal) returns (v1beta2.ResponsePrepareProposal); + // ProcessProposal validates a proposal. + rpc ProcessProposal(RequestProcessProposal) returns (v1beta2.ResponseProcessProposal); + // ExtendVote extends a vote with application-injected data (vote extensions). + rpc ExtendVote(RequestExtendVote) returns (ResponseExtendVote); + // VerifyVoteExtension verifies a vote extension. + rpc VerifyVoteExtension(RequestVerifyVoteExtension) returns (ResponseVerifyVoteExtension); + // FinalizeBlock finalizes a block. + rpc FinalizeBlock(RequestFinalizeBlock) returns (ResponseFinalizeBlock); +} + +// ---------------------------------------- +// Request types + +// Request represents a request to the ABCI application. +message Request { + // Sum of all possible messages. + oneof value { + v1beta1.RequestEcho echo = 1; + v1beta1.RequestFlush flush = 2; + v1beta2.RequestInfo info = 3; + RequestInitChain init_chain = 5; + v1beta1.RequestQuery query = 6; + v1beta1.RequestCheckTx check_tx = 8; + v1beta1.RequestCommit commit = 11; + v1beta1.RequestListSnapshots list_snapshots = 12; + v1beta1.RequestOfferSnapshot offer_snapshot = 13; + v1beta1.RequestLoadSnapshotChunk load_snapshot_chunk = 14; + v1beta1.RequestApplySnapshotChunk apply_snapshot_chunk = 15; + RequestPrepareProposal prepare_proposal = 16; + RequestProcessProposal process_proposal = 17; + RequestExtendVote extend_vote = 18; + RequestVerifyVoteExtension verify_vote_extension = 19; + RequestFinalizeBlock finalize_block = 20; + } + reserved 4, 7, 9, 10; // SetOption, BeginBlock, DeliverTx, EndBlock +} + +// RequestInitChain is a request to initialize the blockchain. +message RequestInitChain { + google.protobuf.Timestamp time = 1 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 2; + cometbft.types.v1.ConsensusParams consensus_params = 3; + repeated v1beta1.ValidatorUpdate validators = 4 [(gogoproto.nullable) = false]; + bytes app_state_bytes = 5; + int64 initial_height = 6; +} + +// RequestPrepareProposal is a request for the ABCI application to prepare a new +// block proposal. +message RequestPrepareProposal { + // the modified transactions cannot exceed this size. + int64 max_tx_bytes = 1; + // txs is an array of transactions that will be included in a block, + // sent to the app for possible modifications. + repeated bytes txs = 2; + ExtendedCommitInfo local_last_commit = 3 [(gogoproto.nullable) = false]; + repeated v1beta2.Misbehavior misbehavior = 4 [(gogoproto.nullable) = false]; + int64 height = 5; + google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes next_validators_hash = 7; + // address of the public key of the validator proposing the block. + bytes proposer_address = 8; +} + +// RequestProcessProposal is a request for the ABCI application to process proposal. +message RequestProcessProposal { + repeated bytes txs = 1; + CommitInfo proposed_last_commit = 2 [(gogoproto.nullable) = false]; + repeated v1beta2.Misbehavior misbehavior = 3 [(gogoproto.nullable) = false]; + // hash is the merkle root hash of the fields of the proposed block. + bytes hash = 4; + int64 height = 5; + google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes next_validators_hash = 7; + // address of the public key of the original proposer of the block. + bytes proposer_address = 8; +} + +// Extends a vote with application-injected data +message RequestExtendVote { + // the hash of the block that this vote may be referring to + bytes hash = 1; + // the height of the extended vote + int64 height = 2; + // info of the block that this vote may be referring to + google.protobuf.Timestamp time = 3 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + repeated bytes txs = 4; + CommitInfo proposed_last_commit = 5 [(gogoproto.nullable) = false]; + repeated v1beta2.Misbehavior misbehavior = 6 [(gogoproto.nullable) = false]; + bytes next_validators_hash = 7; + // address of the public key of the original proposer of the block. + bytes proposer_address = 8; +} + +// Verify the vote extension +message RequestVerifyVoteExtension { + // the hash of the block that this received vote corresponds to + bytes hash = 1; + // the validator that signed the vote extension + bytes validator_address = 2; + int64 height = 3; + bytes vote_extension = 4; +} + +// RequestFinalizeBlock is a request to finalize the block. +message RequestFinalizeBlock { + repeated bytes txs = 1; + CommitInfo decided_last_commit = 2 [(gogoproto.nullable) = false]; + repeated v1beta2.Misbehavior misbehavior = 3 [(gogoproto.nullable) = false]; + // hash is the merkle root hash of the fields of the decided block. + bytes hash = 4; + int64 height = 5; + google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes next_validators_hash = 7; + // proposer_address is the address of the public key of the original proposer of the block. + bytes proposer_address = 8; +} + +// ---------------------------------------- +// Response types + +// Response represents a response from the ABCI application. +message Response { + // Sum of all possible messages. + oneof value { + v1beta1.ResponseException exception = 1; + v1beta1.ResponseEcho echo = 2; + v1beta1.ResponseFlush flush = 3; + v1beta1.ResponseInfo info = 4; + ResponseInitChain init_chain = 6; + v1beta1.ResponseQuery query = 7; + ResponseCheckTx check_tx = 9; + ResponseCommit commit = 12; + v1beta1.ResponseListSnapshots list_snapshots = 13; + v1beta1.ResponseOfferSnapshot offer_snapshot = 14; + v1beta1.ResponseLoadSnapshotChunk load_snapshot_chunk = 15; + v1beta1.ResponseApplySnapshotChunk apply_snapshot_chunk = 16; + v1beta2.ResponsePrepareProposal prepare_proposal = 17; + v1beta2.ResponseProcessProposal process_proposal = 18; + ResponseExtendVote extend_vote = 19; + ResponseVerifyVoteExtension verify_vote_extension = 20; + ResponseFinalizeBlock finalize_block = 21; + } + reserved 5, 8, 10, 11; // SetOption, BeginBlock, DeliverTx, EndBlock +} + +// ResponseInitChain contains the ABCI application's hash and updates to the +// validator set and/or the consensus params, if any. +message ResponseInitChain { + cometbft.types.v1.ConsensusParams consensus_params = 1; + repeated v1beta1.ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; + bytes app_hash = 3; +} + +// ResponseCheckTx shows if the transaction was deemed valid by the ABCI +// application. +message ResponseCheckTx { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated v1beta2.Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + string codespace = 8; + + // These reserved fields were used till v0.37 by the priority mempool (now + // removed). + reserved 9 to 11; + reserved "sender", "priority", "mempool_error"; +} + +// ResponseCommit indicates how much blocks should CometBFT retain. +message ResponseCommit { + reserved 1, 2; // data was previously returned here + int64 retain_height = 3; +} + +// ResponseExtendVote is the result of extending a vote with application-injected data. +message ResponseExtendVote { + bytes vote_extension = 1; +} + +// ResponseVerifyVoteExtension is the result of verifying a vote extension. +message ResponseVerifyVoteExtension { + VerifyStatus status = 1; + + // Verification status. + enum VerifyStatus { + // Unknown + UNKNOWN = 0; + // Accepted + ACCEPT = 1; + // Rejecting the vote extension will reject the entire precommit by the sender. + // Incorrectly implementing this thus has liveness implications as it may affect + // CometBFT's ability to receive 2/3+ valid votes to finalize the block. + // Honest nodes should never be rejected. + REJECT = 2; + } +} + +// FinalizeBlockResponse contains the result of executing the block. +message ResponseFinalizeBlock { + // set of block events emitted as part of executing the block + repeated v1beta2.Event events = 1 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + // the result of executing each transaction including the events + // the particular transaction emitted. This should match the order + // of the transactions delivered in the block itself + repeated ExecTxResult tx_results = 2; + // a list of updates to the validator set. These will reflect the validator set at current height + 2. + repeated v1beta1.ValidatorUpdate validator_updates = 3 [(gogoproto.nullable) = false]; + // updates to the consensus params, if any. + cometbft.types.v1.ConsensusParams consensus_param_updates = 4; + // app_hash is the hash of the applications' state which is used to confirm + // that execution of the transactions was deterministic. + // It is up to the application to decide which algorithm to use. + bytes app_hash = 5; +} + +// ---------------------------------------- +// Blockchain Types + +// VoteInfo contains the information about the vote. +message VoteInfo { + v1beta1.Validator validator = 1 [(gogoproto.nullable) = false]; + cometbft.types.v1beta1.BlockIDFlag block_id_flag = 3; + + reserved 2; // signed_last_block +} + +// ExtendedVoteInfo extends VoteInfo with the vote extensions (non-deterministic). +message ExtendedVoteInfo { + // The validator that sent the vote. + v1beta1.Validator validator = 1 [(gogoproto.nullable) = false]; + // Non-deterministic extension provided by the sending validator's application. + bytes vote_extension = 3; + // Vote extension signature created by CometBFT + bytes extension_signature = 4; + // block_id_flag indicates whether the validator voted for a block, nil, or did not vote at all + cometbft.types.v1beta1.BlockIDFlag block_id_flag = 5; + + reserved 2; // signed_last_block +} + +// ---------------------------------------- +// Misc. + +// CommitInfo contains votes for the particular round. +message CommitInfo { + int32 round = 1; + repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + +// ExtendedCommitInfo is similar to CommitInfo except that it is only used in +// the PrepareProposal request such that Tendermint can provide vote extensions +// to the application. +message ExtendedCommitInfo { + // The round at which the block proposer decided in the previous height. + int32 round = 1; + // List of validators' addresses in the last validator set with their voting + // information, including vote extensions. + repeated ExtendedVoteInfo votes = 2 [(gogoproto.nullable) = false]; +} + +// ExecTxResult contains results of executing one individual transaction. +// +// * Its structure is equivalent to #ResponseDeliverTx which will be deprecated/deleted +message ExecTxResult { + uint32 code = 1; + bytes data = 2; + string log = 3; // nondeterministic + string info = 4; // nondeterministic + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; + repeated v1beta2.Event events = 7 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; // nondeterministic + string codespace = 8; +} + +// TxResult contains results of executing the transaction. +// +// One usage is indexing transaction results. +message TxResult { + int64 height = 1; + uint32 index = 2; + bytes tx = 3; + ExecTxResult result = 4 [(gogoproto.nullable) = false]; +} diff --git a/proto/cometbft/blocksync/v1/types.proto b/proto/cometbft/blocksync/v1/types.proto new file mode 100644 index 00000000000..b806ed6f76b --- /dev/null +++ b/proto/cometbft/blocksync/v1/types.proto @@ -0,0 +1,45 @@ +syntax = "proto3"; +package cometbft.blocksync.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/blocksync/v1"; + +import "cometbft/types/v1/block.proto"; +import "cometbft/types/v1/types.proto"; + +// BlockRequest requests a block for a specific height +message BlockRequest { + int64 height = 1; +} + +// NoBlockResponse informs the node that the peer does not have block at the requested height +message NoBlockResponse { + int64 height = 1; +} + +// StatusRequest requests the status of a peer. +message StatusRequest { +} + +// StatusResponse is a peer response to inform their status. +message StatusResponse { + int64 height = 1; + int64 base = 2; +} + +// BlockResponse returns block to the requested +message BlockResponse { + cometbft.types.v1.Block block = 1; + cometbft.types.v1.ExtendedCommit ext_commit = 2; +} + +// Message is an abstract blocksync message. +message Message { + // Sum of all possible messages. + oneof sum { + BlockRequest block_request = 1; + NoBlockResponse no_block_response = 2; + BlockResponse block_response = 3; + StatusRequest status_request = 4; + StatusResponse status_response = 5; + } +} diff --git a/proto/cometbft/blocksync/v1beta1/types.proto b/proto/cometbft/blocksync/v1beta1/types.proto new file mode 100644 index 00000000000..a857914cc1d --- /dev/null +++ b/proto/cometbft/blocksync/v1beta1/types.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; +package cometbft.blocksync.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/blocksync/v1beta1"; + +import "cometbft/types/v1beta1/block.proto"; + +// BlockRequest requests a block for a specific height +message BlockRequest { + int64 height = 1; +} + +// NoBlockResponse informs the node that the peer does not have block at the requested height +message NoBlockResponse { + int64 height = 1; +} + +// BlockResponse returns block to the requested +message BlockResponse { + cometbft.types.v1beta1.Block block = 1; +} + +// StatusRequest requests the status of a peer. +message StatusRequest { +} + +// StatusResponse is a peer response to inform their status. +message StatusResponse { + int64 height = 1; + int64 base = 2; +} + +// Message is an abstract blocksync message. +message Message { + // Sum of all possible messages. + oneof sum { + BlockRequest block_request = 1; + NoBlockResponse no_block_response = 2; + BlockResponse block_response = 3; + StatusRequest status_request = 4; + StatusResponse status_response = 5; + } +} diff --git a/proto/cometbft/consensus/v1/types.proto b/proto/cometbft/consensus/v1/types.proto new file mode 100644 index 00000000000..3be71e621e2 --- /dev/null +++ b/proto/cometbft/consensus/v1/types.proto @@ -0,0 +1,102 @@ +syntax = "proto3"; +package cometbft.consensus.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/consensus/v1"; + +import "gogoproto/gogo.proto"; +import "cometbft/libs/bits/v1/types.proto"; +import "cometbft/types/v1/types.proto"; + +// NewRoundStep is sent for every step taken in the ConsensusState. +// For every height/round/step transition +message NewRoundStep { + int64 height = 1; + int32 round = 2; + uint32 step = 3; + int64 seconds_since_start_time = 4; + int32 last_commit_round = 5; +} + +// NewValidBlock is sent when a validator observes a valid block B in some round r, +// i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. +// In case the block is also committed, then IsCommit flag is set to true. +message NewValidBlock { + int64 height = 1; + int32 round = 2; + cometbft.types.v1.PartSetHeader block_part_set_header = 3 [(gogoproto.nullable) = false]; + cometbft.libs.bits.v1.BitArray block_parts = 4; + bool is_commit = 5; +} + +// Proposal is sent when a new block is proposed. +message Proposal { + cometbft.types.v1.Proposal proposal = 1 [(gogoproto.nullable) = false]; +} + +// ProposalPOL is sent when a previous proposal is re-proposed. +message ProposalPOL { + int64 height = 1; + int32 proposal_pol_round = 2; + cometbft.libs.bits.v1.BitArray proposal_pol = 3 [(gogoproto.nullable) = false]; +} + +// BlockPart is sent when gossipping a piece of the proposed block. +message BlockPart { + int64 height = 1; + int32 round = 2; + cometbft.types.v1.Part part = 3 [(gogoproto.nullable) = false]; +} + +// Vote is sent when voting for a proposal (or lack thereof). +message Vote { + cometbft.types.v1.Vote vote = 1; +} + +// HasVote is sent to indicate that a particular vote has been received. +message HasVote { + int64 height = 1; + int32 round = 2; + cometbft.types.v1.SignedMsgType type = 3; + int32 index = 4; +} + +// VoteSetMaj23 is sent to indicate that a given BlockID has seen +2/3 votes. +message VoteSetMaj23 { + int64 height = 1; + int32 round = 2; + cometbft.types.v1.SignedMsgType type = 3; + cometbft.types.v1.BlockID block_id = 4 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; +} + +// VoteSetBits is sent to communicate the bit-array of votes seen for the BlockID. +message VoteSetBits { + int64 height = 1; + int32 round = 2; + cometbft.types.v1.SignedMsgType type = 3; + cometbft.types.v1.BlockID block_id = 4 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; + cometbft.libs.bits.v1.BitArray votes = 5 [(gogoproto.nullable) = false]; +} + +// HasProposalBlockPart is sent to indicate that a particular proposal block part has been received. +message HasProposalBlockPart { + int64 height = 1; + int32 round = 2; + int32 index = 3; +} + +// Message is an abstract consensus message. +message Message { + // Sum of all possible messages. + oneof sum { + NewRoundStep new_round_step = 1; + NewValidBlock new_valid_block = 2; + Proposal proposal = 3; + ProposalPOL proposal_pol = 4; + BlockPart block_part = 5; + Vote vote = 6; + HasVote has_vote = 7; + VoteSetMaj23 vote_set_maj23 = 8; + VoteSetBits vote_set_bits = 9; + HasProposalBlockPart has_proposal_block_part = 10; + } +} diff --git a/proto/cometbft/consensus/v1/wal.proto b/proto/cometbft/consensus/v1/wal.proto new file mode 100644 index 00000000000..ae7f2619667 --- /dev/null +++ b/proto/cometbft/consensus/v1/wal.proto @@ -0,0 +1,50 @@ +syntax = "proto3"; +package cometbft.consensus.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/consensus/v1"; + +import "cometbft/consensus/v1/types.proto"; +import "cometbft/types/v1/events.proto"; + +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +// MsgInfo are msgs from the reactor which may update the state +message MsgInfo { + Message msg = 1 [(gogoproto.nullable) = false]; + string peer_id = 2 [(gogoproto.customname) = "PeerID"]; + google.protobuf.Timestamp receive_time = 3 [(gogoproto.stdtime) = true, (gogoproto.nullable) = true]; +} + +// TimeoutInfo internally generated messages which may update the state +message TimeoutInfo { + google.protobuf.Duration duration = 1 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + int64 height = 2; + int32 round = 3; + uint32 step = 4; +} + +// EndHeight marks the end of the given height inside WAL. +// @internal used by scripts/wal2json util. +message EndHeight { + int64 height = 1; +} + +// WALMessage describes a consensus WAL (Write Ahead Log) entry. +message WALMessage { + // Sum of all possible messages. + oneof sum { + cometbft.types.v1.EventDataRoundState event_data_round_state = 1; + MsgInfo msg_info = 2; + TimeoutInfo timeout_info = 3; + EndHeight end_height = 4; + } +} + +// TimedWALMessage wraps WALMessage and adds Time for debugging purposes. +message TimedWALMessage { + google.protobuf.Timestamp time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + WALMessage msg = 2; +} diff --git a/proto/cometbft/consensus/v1beta1/types.proto b/proto/cometbft/consensus/v1beta1/types.proto new file mode 100644 index 00000000000..be8dc22b669 --- /dev/null +++ b/proto/cometbft/consensus/v1beta1/types.proto @@ -0,0 +1,94 @@ +syntax = "proto3"; +package cometbft.consensus.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/consensus/v1beta1"; + +import "gogoproto/gogo.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "cometbft/libs/bits/v1/types.proto"; + +// NewRoundStep is sent for every step taken in the ConsensusState. +// For every height/round/step transition +message NewRoundStep { + int64 height = 1; + int32 round = 2; + uint32 step = 3; + int64 seconds_since_start_time = 4; + int32 last_commit_round = 5; +} + +// NewValidBlock is sent when a validator observes a valid block B in some round r, +// i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. +// In case the block is also committed, then IsCommit flag is set to true. +message NewValidBlock { + int64 height = 1; + int32 round = 2; + cometbft.types.v1beta1.PartSetHeader block_part_set_header = 3 [(gogoproto.nullable) = false]; + cometbft.libs.bits.v1.BitArray block_parts = 4; + bool is_commit = 5; +} + +// Proposal is sent when a new block is proposed. +message Proposal { + cometbft.types.v1beta1.Proposal proposal = 1 [(gogoproto.nullable) = false]; +} + +// ProposalPOL is sent when a previous proposal is re-proposed. +message ProposalPOL { + int64 height = 1; + int32 proposal_pol_round = 2; + cometbft.libs.bits.v1.BitArray proposal_pol = 3 [(gogoproto.nullable) = false]; +} + +// BlockPart is sent when gossipping a piece of the proposed block. +message BlockPart { + int64 height = 1; + int32 round = 2; + cometbft.types.v1beta1.Part part = 3 [(gogoproto.nullable) = false]; +} + +// Vote is sent when voting for a proposal (or lack thereof). +message Vote { + cometbft.types.v1beta1.Vote vote = 1; +} + +// HasVote is sent to indicate that a particular vote has been received. +message HasVote { + int64 height = 1; + int32 round = 2; + cometbft.types.v1beta1.SignedMsgType type = 3; + int32 index = 4; +} + +// VoteSetMaj23 is sent to indicate that a given BlockID has seen +2/3 votes. +message VoteSetMaj23 { + int64 height = 1; + int32 round = 2; + cometbft.types.v1beta1.SignedMsgType type = 3; + cometbft.types.v1beta1.BlockID block_id = 4 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; +} + +// VoteSetBits is sent to communicate the bit-array of votes seen for the BlockID. +message VoteSetBits { + int64 height = 1; + int32 round = 2; + cometbft.types.v1beta1.SignedMsgType type = 3; + cometbft.types.v1beta1.BlockID block_id = 4 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; + cometbft.libs.bits.v1.BitArray votes = 5 [(gogoproto.nullable) = false]; +} + +// Message is an abstract consensus message. +message Message { + // Sum of all possible messages. + oneof sum { + NewRoundStep new_round_step = 1; + NewValidBlock new_valid_block = 2; + Proposal proposal = 3; + ProposalPOL proposal_pol = 4; + BlockPart block_part = 5; + Vote vote = 6; + HasVote has_vote = 7; + VoteSetMaj23 vote_set_maj23 = 8; + VoteSetBits vote_set_bits = 9; + } +} diff --git a/proto/cometbft/consensus/v1beta1/wal.proto b/proto/cometbft/consensus/v1beta1/wal.proto new file mode 100644 index 00000000000..50a83b67d9b --- /dev/null +++ b/proto/cometbft/consensus/v1beta1/wal.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; +package cometbft.consensus.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/consensus/v1beta1"; + +import "gogoproto/gogo.proto"; +import "cometbft/consensus/v1beta1/types.proto"; +import "cometbft/types/v1beta1/events.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +// MsgInfo are msgs from the reactor which may update the state +message MsgInfo { + Message msg = 1 [(gogoproto.nullable) = false]; + string peer_id = 2 [(gogoproto.customname) = "PeerID"]; +} + +// TimeoutInfo internally generated messages which may update the state +message TimeoutInfo { + google.protobuf.Duration duration = 1 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + int64 height = 2; + int32 round = 3; + uint32 step = 4; +} + +// EndHeight marks the end of the given height inside WAL. +// @internal used by scripts/wal2json util. +message EndHeight { + int64 height = 1; +} + +// WALMessage describes a consensus WAL (Write Ahead Log) entry. +message WALMessage { + // Sum of all possible messages. + oneof sum { + cometbft.types.v1beta1.EventDataRoundState event_data_round_state = 1; + MsgInfo msg_info = 2; + TimeoutInfo timeout_info = 3; + EndHeight end_height = 4; + } +} + +// TimedWALMessage wraps WALMessage and adds Time for debugging purposes. +message TimedWALMessage { + google.protobuf.Timestamp time = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + WALMessage msg = 2; +} diff --git a/proto/cometbft/crypto/v1/keys.proto b/proto/cometbft/crypto/v1/keys.proto new file mode 100644 index 00000000000..83479b73f98 --- /dev/null +++ b/proto/cometbft/crypto/v1/keys.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; +package cometbft.crypto.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/crypto/v1"; + +import "gogoproto/gogo.proto"; + +// PublicKey is a ED25519 or a secp256k1 public key. +message PublicKey { + option (gogoproto.compare) = true; + option (gogoproto.equal) = true; + + // The type of key. + oneof sum { + bytes ed25519 = 1; + bytes secp256k1 = 2; + bytes bls12381 = 3; + } +} diff --git a/proto/cometbft/crypto/v1/proof.proto b/proto/cometbft/crypto/v1/proof.proto new file mode 100644 index 00000000000..2b462166c83 --- /dev/null +++ b/proto/cometbft/crypto/v1/proof.proto @@ -0,0 +1,44 @@ +syntax = "proto3"; +package cometbft.crypto.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/crypto/v1"; + +import "gogoproto/gogo.proto"; + +// Proof is a Merkle proof. +message Proof { + int64 total = 1; + int64 index = 2; + bytes leaf_hash = 3; + repeated bytes aunts = 4; +} + +// ValueOp is a Merkle proof for a single key. +message ValueOp { + // Encoded in ProofOp.Key. + bytes key = 1; + + // To encode in ProofOp.Data + Proof proof = 2; +} + +// DominoOp always returns the given output. +message DominoOp { + string key = 1; + string input = 2; + string output = 3; +} + +// ProofOp defines an operation used for calculating Merkle root +// The data could be arbitrary format, providing necessary data +// for example neighbouring node hash +message ProofOp { + string type = 1; + bytes key = 2; + bytes data = 3; +} + +// ProofOps is Merkle proof defined by the list of ProofOps +message ProofOps { + repeated ProofOp ops = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/cometbft/libs/bits/v1/types.proto b/proto/cometbft/libs/bits/v1/types.proto new file mode 100644 index 00000000000..b735bf88347 --- /dev/null +++ b/proto/cometbft/libs/bits/v1/types.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package cometbft.libs.bits.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/libs/bits/v1"; + +// BitArray is an array of bits. +message BitArray { + int64 bits = 1; + repeated uint64 elems = 2; +} diff --git a/proto/cometbft/mempool/v1/types.proto b/proto/cometbft/mempool/v1/types.proto new file mode 100644 index 00000000000..1ab4e74543c --- /dev/null +++ b/proto/cometbft/mempool/v1/types.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package cometbft.mempool.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/mempool/v1"; + +// Txs contains a list of transaction from the mempool. +message Txs { + repeated bytes txs = 1; +} + +// Message is an abstract mempool message. +message Message { + // Sum of all possible messages. + oneof sum { + Txs txs = 1; + } +} diff --git a/proto/cometbft/p2p/v1/conn.proto b/proto/cometbft/p2p/v1/conn.proto new file mode 100644 index 00000000000..c69b0349303 --- /dev/null +++ b/proto/cometbft/p2p/v1/conn.proto @@ -0,0 +1,38 @@ +syntax = "proto3"; +package cometbft.p2p.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/p2p/v1"; + +import "gogoproto/gogo.proto"; +import "cometbft/crypto/v1/keys.proto"; + +// PacketPing is a request to confirm that the connection is alive. +message PacketPing {} + +// PacketPong is a response to confirm that the connection is alive. +message PacketPong {} + +// PacketMsg contains data for the specified channel ID. EOF means the message +// is fully received. +message PacketMsg { + int32 channel_id = 1 [(gogoproto.customname) = "ChannelID"]; + bool eof = 2 [(gogoproto.customname) = "EOF"]; + bytes data = 3; +} + +// Packet is an abstract p2p message. +message Packet { + // Sum of all possible messages. + oneof sum { + PacketPing packet_ping = 1; + PacketPong packet_pong = 2; + PacketMsg packet_msg = 3; + } +} + +// AuthSigMessage is sent during the authentication and contains our/remote's +// signature along with the public key. +message AuthSigMessage { + cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + bytes sig = 2; +} diff --git a/proto/cometbft/p2p/v1/pex.proto b/proto/cometbft/p2p/v1/pex.proto new file mode 100644 index 00000000000..c7a9144cf52 --- /dev/null +++ b/proto/cometbft/p2p/v1/pex.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package cometbft.p2p.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/p2p/v1"; + +import "cometbft/p2p/v1/types.proto"; +import "gogoproto/gogo.proto"; + +// PexRequest is a request for peer addresses. +message PexRequest {} + +// PexAddrs is a response with peer addresses. +message PexAddrs { + repeated NetAddress addrs = 1 [(gogoproto.nullable) = false]; +} + +// Message is an abstract PEX message. +message Message { + // Sum of all possible messages. + oneof sum { + PexRequest pex_request = 1; + PexAddrs pex_addrs = 2; + } +} diff --git a/proto/cometbft/p2p/v1/types.proto b/proto/cometbft/p2p/v1/types.proto new file mode 100644 index 00000000000..147752aa912 --- /dev/null +++ b/proto/cometbft/p2p/v1/types.proto @@ -0,0 +1,39 @@ +syntax = "proto3"; +package cometbft.p2p.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/p2p/v1"; + +import "gogoproto/gogo.proto"; + +// NetAddress represents a peer's network address. +message NetAddress { + string id = 1 [(gogoproto.customname) = "ID"]; + string ip = 2 [(gogoproto.customname) = "IP"]; + uint32 port = 3; +} + +// ProtocolVersion represents the current p2p protocol version. +message ProtocolVersion { + uint64 p2p = 1 [(gogoproto.customname) = "P2P"]; + uint64 block = 2; + uint64 app = 3; +} + +// DefaultNodeInfo is a basic node's information sent to other peers during the +// p2p handshake. +message DefaultNodeInfo { + ProtocolVersion protocol_version = 1 [(gogoproto.nullable) = false]; + string default_node_id = 2 [(gogoproto.customname) = "DefaultNodeID"]; + string listen_addr = 3; + string network = 4; + string version = 5; + bytes channels = 6; + string moniker = 7; + DefaultNodeInfoOther other = 8 [(gogoproto.nullable) = false]; +} + +// DefaultNodeInfoOther is the misc. application specific data. +message DefaultNodeInfoOther { + string tx_index = 1; + string rpc_address = 2 [(gogoproto.customname) = "RPCAddress"]; +} diff --git a/proto/cometbft/privval/v1/types.proto b/proto/cometbft/privval/v1/types.proto new file mode 100644 index 00000000000..712e13c6144 --- /dev/null +++ b/proto/cometbft/privval/v1/types.proto @@ -0,0 +1,84 @@ +syntax = "proto3"; +package cometbft.privval.v1; + +import "cometbft/crypto/v1/keys.proto"; +import "cometbft/types/v1/types.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/privval/v1"; + +// remotesignererror is returned when the remote signer fails. +message RemoteSignerError { + int32 code = 1; + string description = 2; +} + +// PubKeyRequest requests the consensus public key from the remote signer. +message PubKeyRequest { + string chain_id = 1; +} + +// PubKeyResponse is a response message containing the public key. +message PubKeyResponse { + cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// SignVoteRequest is a request to sign a vote +message SignVoteRequest { + cometbft.types.v1.Vote vote = 1; + string chain_id = 2; + bool skip_extension_signing = 3; // if true, the signer may skip signing the extension bytes. +} + +// SignedVoteResponse is a response containing a signed vote or an error +message SignedVoteResponse { + cometbft.types.v1.Vote vote = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// SignProposalRequest is a request to sign a proposal +message SignProposalRequest { + cometbft.types.v1.Proposal proposal = 1; + string chain_id = 2; +} + +// SignedProposalResponse is response containing a signed proposal or an error +message SignedProposalResponse { + cometbft.types.v1.Proposal proposal = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// SignBytesRequest is a request to sign arbitrary bytes +message SignBytesRequest { + bytes value = 1; +} + +// SignBytesResponse is a response containing a signature or an error +message SignBytesResponse { + bytes signature = 1; + RemoteSignerError error = 2; +} + +// PingRequest is a request to confirm that the connection is alive. +message PingRequest {} + +// PingResponse is a response to confirm that the connection is alive. +message PingResponse {} + +// Message is an abstract message to/from the remote signer. +message Message { + // Sum of all possible messages. + oneof sum { + PubKeyRequest pub_key_request = 1; + PubKeyResponse pub_key_response = 2; + SignVoteRequest sign_vote_request = 3; + SignedVoteResponse signed_vote_response = 4; + SignProposalRequest sign_proposal_request = 5; + SignedProposalResponse signed_proposal_response = 6; + PingRequest ping_request = 7; + PingResponse ping_response = 8; + SignBytesRequest sign_bytes_request = 9; + SignBytesResponse sign_bytes_response = 10; + } +} diff --git a/proto/cometbft/privval/v1beta1/types.proto b/proto/cometbft/privval/v1beta1/types.proto new file mode 100644 index 00000000000..fffde69db96 --- /dev/null +++ b/proto/cometbft/privval/v1beta1/types.proto @@ -0,0 +1,86 @@ +syntax = "proto3"; +package cometbft.privval.v1beta1; + +import "cometbft/crypto/v1/keys.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/privval/v1beta1"; + +// Errors is a list of error codes that can be returned by the remote signer. +enum Errors { + // Unknown error + ERRORS_UNKNOWN = 0; + // Unexpected response + ERRORS_UNEXPECTED_RESPONSE = 1; + // Connection lost + ERRORS_NO_CONNECTION = 2; + // Connection timeout + ERRORS_CONNECTION_TIMEOUT = 3; + // Read timeout + ERRORS_READ_TIMEOUT = 4; + // Write timeout + ERRORS_WRITE_TIMEOUT = 5; +} + +// A service for broadcasting transactions. +message RemoteSignerError { + int32 code = 1; + string description = 2; +} + +// PubKeyRequest requests the consensus public key from the remote signer. +message PubKeyRequest { + string chain_id = 1; +} + +// PubKeyResponse is a response message containing the public key. +message PubKeyResponse { + cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// SignVoteRequest is a request to sign a vote +message SignVoteRequest { + cometbft.types.v1beta1.Vote vote = 1; + string chain_id = 2; +} + +// SignedVoteResponse is a response containing a signed vote or an error +message SignedVoteResponse { + cometbft.types.v1beta1.Vote vote = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// SignProposalRequest is a request to sign a proposal +message SignProposalRequest { + cometbft.types.v1beta1.Proposal proposal = 1; + string chain_id = 2; +} + +// SignedProposalResponse is response containing a signed proposal or an error +message SignedProposalResponse { + cometbft.types.v1beta1.Proposal proposal = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// PingRequest is a request to confirm that the connection is alive. +message PingRequest {} + +// PingResponse is a response to confirm that the connection is alive. +message PingResponse {} + +// Message is an abstract message to/from the remote signer. +message Message { + // Sum of all possible messages. + oneof sum { + PubKeyRequest pub_key_request = 1; + PubKeyResponse pub_key_response = 2; + SignVoteRequest sign_vote_request = 3; + SignedVoteResponse signed_vote_response = 4; + SignProposalRequest sign_proposal_request = 5; + SignedProposalResponse signed_proposal_response = 6; + PingRequest ping_request = 7; + PingResponse ping_response = 8; + } +} diff --git a/proto/cometbft/privval/v1beta2/types.proto b/proto/cometbft/privval/v1beta2/types.proto new file mode 100644 index 00000000000..b2496da545f --- /dev/null +++ b/proto/cometbft/privval/v1beta2/types.proto @@ -0,0 +1,86 @@ +syntax = "proto3"; +package cometbft.privval.v1beta2; + +import "cometbft/crypto/v1/keys.proto"; +import "cometbft/types/v1/types.proto"; +import "gogoproto/gogo.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/privval/v1beta2"; + +// Errors is a list of error codes that can be returned by the remote signer. +enum Errors { + // Unknown error + ERRORS_UNKNOWN = 0; + // Unexpected response + ERRORS_UNEXPECTED_RESPONSE = 1; + // Connection lost + ERRORS_NO_CONNECTION = 2; + // Connection timeout + ERRORS_CONNECTION_TIMEOUT = 3; + // Read timeout + ERRORS_READ_TIMEOUT = 4; + // Write timeout + ERRORS_WRITE_TIMEOUT = 5; +} + +// remotesignererror is returned when the remote signer fails. +message RemoteSignerError { + int32 code = 1; + string description = 2; +} + +// PubKeyRequest requests the consensus public key from the remote signer. +message PubKeyRequest { + string chain_id = 1; +} + +// PubKeyResponse is a response message containing the public key. +message PubKeyResponse { + cometbft.crypto.v1.PublicKey pub_key = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// SignVoteRequest is a request to sign a vote +message SignVoteRequest { + cometbft.types.v1.Vote vote = 1; + string chain_id = 2; +} + +// SignedVoteResponse is a response containing a signed vote or an error +message SignedVoteResponse { + cometbft.types.v1.Vote vote = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// SignProposalRequest is a request to sign a proposal +message SignProposalRequest { + cometbft.types.v1.Proposal proposal = 1; + string chain_id = 2; +} + +// SignedProposalResponse is response containing a signed proposal or an error +message SignedProposalResponse { + cometbft.types.v1.Proposal proposal = 1 [(gogoproto.nullable) = false]; + RemoteSignerError error = 2; +} + +// PingRequest is a request to confirm that the connection is alive. +message PingRequest {} + +// PingResponse is a response to confirm that the connection is alive. +message PingResponse {} + +// Message is an abstract message to/from the remote signer. +message Message { + // Sum of all possible messages. + oneof sum { + PubKeyRequest pub_key_request = 1; + PubKeyResponse pub_key_response = 2; + SignVoteRequest sign_vote_request = 3; + SignedVoteResponse signed_vote_response = 4; + SignProposalRequest sign_proposal_request = 5; + SignedProposalResponse signed_proposal_response = 6; + PingRequest ping_request = 7; + PingResponse ping_response = 8; + } +} diff --git a/proto/cometbft/rpc/grpc/v1beta1/types.proto b/proto/cometbft/rpc/grpc/v1beta1/types.proto new file mode 100644 index 00000000000..035f471810f --- /dev/null +++ b/proto/cometbft/rpc/grpc/v1beta1/types.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; +package cometbft.rpc.grpc.v1beta1; +option go_package = "github.com/cometbft/cometbft/api/cometbft/rpc/grpc/v1beta1"; + +import "cometbft/abci/v1beta1/types.proto"; + +// PingRequest is a request to confirm that the connection is alive. +message RequestPing {} + +// RequestBroadcastTx is a request to broadcast the transaction. +message RequestBroadcastTx { + bytes tx = 1; +} + +// PingResponse is a response to confirm that the connection is alive. +message ResponsePing {} + +// ResponseBroadcastTx is a response of broadcasting the transaction. +message ResponseBroadcastTx { + cometbft.abci.v1beta1.ResponseCheckTx check_tx = 1; + cometbft.abci.v1beta1.ResponseDeliverTx deliver_tx = 2; +} + +// BroadcastAPI is an API for broadcasting transactions. +service BroadcastAPI { + // Ping the connection. + rpc Ping(RequestPing) returns (ResponsePing); + // BroadcastTx broadcasts the transaction. + rpc BroadcastTx(RequestBroadcastTx) returns (ResponseBroadcastTx); +} diff --git a/proto/cometbft/rpc/grpc/v1beta2/types.proto b/proto/cometbft/rpc/grpc/v1beta2/types.proto new file mode 100644 index 00000000000..87b780934d2 --- /dev/null +++ b/proto/cometbft/rpc/grpc/v1beta2/types.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package cometbft.rpc.grpc.v1beta2; +option go_package = "github.com/cometbft/cometbft/api/cometbft/rpc/grpc/v1beta2"; + +import "cometbft/rpc/grpc/v1beta1/types.proto"; +import "cometbft/abci/v1beta2/types.proto"; + +// ResponseBroadcastTx is a response of broadcasting the transaction. +message ResponseBroadcastTx { + cometbft.abci.v1beta2.ResponseCheckTx check_tx = 1; + cometbft.abci.v1beta2.ResponseDeliverTx deliver_tx = 2; +} + +// BroadcastAPI is an API for broadcasting transactions. +service BroadcastAPI { + // Ping the connection. + rpc Ping(v1beta1.RequestPing) returns (v1beta1.ResponsePing); + // BroadcastTx broadcasts the transaction. + rpc BroadcastTx(v1beta1.RequestBroadcastTx) returns (ResponseBroadcastTx); +} diff --git a/proto/cometbft/rpc/grpc/v1beta3/types.proto b/proto/cometbft/rpc/grpc/v1beta3/types.proto new file mode 100644 index 00000000000..2d25cace57a --- /dev/null +++ b/proto/cometbft/rpc/grpc/v1beta3/types.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package cometbft.rpc.grpc.v1beta3; +option go_package = "github.com/cometbft/cometbft/api/cometbft/rpc/grpc/v1beta3"; + +import "cometbft/rpc/grpc/v1beta1/types.proto"; + +import "cometbft/abci/v1beta3/types.proto"; + +// ResponseBroadcastTx is a response of broadcasting the transaction. +message ResponseBroadcastTx { + cometbft.abci.v1beta3.ResponseCheckTx check_tx = 1; + cometbft.abci.v1beta3.ExecTxResult tx_result = 2; +} + +// BroadcastAPI is an API for broadcasting transactions. +// +// Deprecated: This API will be superseded by a more comprehensive gRPC-based +// broadcast API, and is scheduled for removal after v0.38. +service BroadcastAPI { + // Ping the connection. + rpc Ping(v1beta1.RequestPing) returns (v1beta1.ResponsePing); + // BroadcastTx broadcasts a transaction. + rpc BroadcastTx(v1beta1.RequestBroadcastTx) returns (v1beta3.ResponseBroadcastTx); +} diff --git a/proto/cometbft/services/block/v1/block.proto b/proto/cometbft/services/block/v1/block.proto new file mode 100644 index 00000000000..aeac0397c94 --- /dev/null +++ b/proto/cometbft/services/block/v1/block.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; +package cometbft.services.block.v1; + +import "cometbft/types/v1/types.proto"; +import "cometbft/types/v1/block.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/services/block/v1"; + +// GetByHeightRequest is a request for a block at the specified height. +message GetByHeightRequest { + // The height of the block requested. + int64 height = 1; +} + +// GetByHeightResponse contains the block ID and the block at the specified height. +message GetByHeightResponse { + cometbft.types.v1.BlockID block_id = 1; + cometbft.types.v1.Block block = 2; +} + +// GetLatestHeightRequest - empty message since no parameter is required +message GetLatestHeightRequest {} + +// GetLatestHeightResponse provides the height of the latest committed block. +message GetLatestHeightResponse { + // The height of the latest committed block. Will be 0 if no data has been + // committed yet. + int64 height = 1; +} diff --git a/proto/cometbft/services/block/v1/block_service.proto b/proto/cometbft/services/block/v1/block_service.proto new file mode 100644 index 00000000000..4d067e3a36a --- /dev/null +++ b/proto/cometbft/services/block/v1/block_service.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; +package cometbft.services.block.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/services/block/v1"; + +import "cometbft/services/block/v1/block.proto"; + +// BlockService provides information about blocks +service BlockService { + // GetBlock retrieves the block information at a particular height. + rpc GetByHeight(GetByHeightRequest) returns (GetByHeightResponse); + + // GetLatestHeight returns a stream of the latest block heights committed by + // the network. This is a long-lived stream that is only terminated by the + // server if an error occurs. The caller is expected to handle such + // disconnections and automatically reconnect. + rpc GetLatestHeight(GetLatestHeightRequest) returns (stream GetLatestHeightResponse); +} diff --git a/proto/cometbft/services/block_results/v1/block_results.proto b/proto/cometbft/services/block_results/v1/block_results.proto new file mode 100644 index 00000000000..9bcc0244ffb --- /dev/null +++ b/proto/cometbft/services/block_results/v1/block_results.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; +package cometbft.services.block_results.v1; + +import "cometbft/abci/v1/types.proto"; +import "cometbft/types/v1/params.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/services/block_results/v1"; + +// GetBlockResults is a request for the BlockResults of a given height. +message GetBlockResultsRequest { + int64 height = 1; +} + +// GetBlockResultsResponse contains the block results for the given height. +message GetBlockResultsResponse { + int64 height = 1; + repeated cometbft.abci.v1.ExecTxResult tx_results = 2; + repeated cometbft.abci.v1.Event finalize_block_events = 3; + repeated cometbft.abci.v1.ValidatorUpdate validator_updates = 4; + cometbft.types.v1.ConsensusParams consensus_param_updates = 5; + bytes app_hash = 6; +} diff --git a/proto/cometbft/services/block_results/v1/block_results_service.proto b/proto/cometbft/services/block_results/v1/block_results_service.proto new file mode 100644 index 00000000000..e8829eb97a7 --- /dev/null +++ b/proto/cometbft/services/block_results/v1/block_results_service.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; +package cometbft.services.block_results.v1; + +import "cometbft/services/block_results/v1/block_results.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/services/block_results/v1"; + +/* + BlockResultService provides the block results of a given or latestheight. +*/ +service BlockResultsService { + // GetBlockResults returns the BlockResults of the requested height. + rpc GetBlockResults(GetBlockResultsRequest) returns (GetBlockResultsResponse); +} diff --git a/proto/cometbft/services/pruning/v1/pruning.proto b/proto/cometbft/services/pruning/v1/pruning.proto new file mode 100644 index 00000000000..24391b60e9f --- /dev/null +++ b/proto/cometbft/services/pruning/v1/pruning.proto @@ -0,0 +1,74 @@ +syntax = "proto3"; + +package cometbft.services.pruning.v1; + +// SetBlockRetainHeightRequest sets the retain height for blocks. +message SetBlockRetainHeightRequest { + uint64 height = 1; +} + +// SetBlockRetainHeightResponse is empty. +message SetBlockRetainHeightResponse {} + +// GetBlockRetainHeightRequest is a request for the retain height. +message GetBlockRetainHeightRequest {} + +// GetBlockRetainHeightResponse returns the retain height for blocks. +message GetBlockRetainHeightResponse { + // The retain height set by the application. + uint64 app_retain_height = 1; + + // The retain height set via the pruning service (e.g. by the data + // companion) specifically for blocks. + uint64 pruning_service_retain_height = 2; +} + +// SetBlockResultsRetainHeightRequest sets the retain height for block results. +message SetBlockResultsRetainHeightRequest { + uint64 height = 1; +} + +// SetBlockResultsRetainHeightResponse is empty. +message SetBlockResultsRetainHeightResponse {} + +// GetBlockResultsRetainHeightRequest is a request for the retain height. +message GetBlockResultsRetainHeightRequest {} + +// GetBlockResultsRetainHeightResponse returns the retain height for block results. +message GetBlockResultsRetainHeightResponse { + // The retain height set by the pruning service (e.g. by the data + // companion) specifically for block results. + uint64 pruning_service_retain_height = 1; +} + +// SetTxIndexerRetainHeightRequest sets the retain height for the tx indexer. +message SetTxIndexerRetainHeightRequest { + uint64 height = 1; +} + +// SetTxIndexerRetainHeightResponse is empty. +message SetTxIndexerRetainHeightResponse {} + +// GetTxIndexerRetainHeightRequest is a request for the retain height. +message GetTxIndexerRetainHeightRequest {} + +// GetTxIndexerRetainHeightResponse returns the retain height for the tx indexer. +message GetTxIndexerRetainHeightResponse { + uint64 height = 1; +} + +// SetBlockIndexerRetainHeightRequest sets the retain height for the block indexer. +message SetBlockIndexerRetainHeightRequest { + uint64 height = 1; +} + +// SetBlockIndexerRetainHeightResponse is empty. +message SetBlockIndexerRetainHeightResponse {} + +// GetBlockIndexerRetainHeightRequest is a request for the retain height. +message GetBlockIndexerRetainHeightRequest {} + +// GetBlockIndexerRetainHeightResponse returns the retain height for the block indexer. +message GetBlockIndexerRetainHeightResponse { + uint64 height = 1; +} diff --git a/proto/cometbft/services/pruning/v1/service.proto b/proto/cometbft/services/pruning/v1/service.proto new file mode 100644 index 00000000000..f82e3f1a98a --- /dev/null +++ b/proto/cometbft/services/pruning/v1/service.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; + +package cometbft.services.pruning.v1; + +import "cometbft/services/pruning/v1/pruning.proto"; + +// PruningService provides privileged access to specialized pruning +// functionality on the CometBFT node to help control node storage. +service PruningService { + // SetBlockRetainHeightRequest indicates to the node that it can safely + // prune all block data up to the specified retain height. + // + // The lower of this retain height and that set by the application in its + // Commit response will be used by the node to determine which heights' data + // can be pruned. + rpc SetBlockRetainHeight(SetBlockRetainHeightRequest) returns (SetBlockRetainHeightResponse); + + // GetBlockRetainHeight returns information about the retain height + // parameters used by the node to influence block retention/pruning. + rpc GetBlockRetainHeight(GetBlockRetainHeightRequest) returns (GetBlockRetainHeightResponse); + + // SetBlockResultsRetainHeightRequest indicates to the node that it can + // safely prune all block results data up to the specified height. + // + // The node will always store the block results for the latest height to + // help facilitate crash recovery. + rpc SetBlockResultsRetainHeight(SetBlockResultsRetainHeightRequest) returns (SetBlockResultsRetainHeightResponse); + + // GetBlockResultsRetainHeight returns information about the retain height + // parameters used by the node to influence block results retention/pruning. + rpc GetBlockResultsRetainHeight(GetBlockResultsRetainHeightRequest) returns (GetBlockResultsRetainHeightResponse); + + // SetTxIndexerRetainHeightRequest indicates to the node that it can safely + // prune all tx indices up to the specified retain height. + rpc SetTxIndexerRetainHeight(SetTxIndexerRetainHeightRequest) returns (SetTxIndexerRetainHeightResponse); + + // GetTxIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence TxIndexer pruning + rpc GetTxIndexerRetainHeight(GetTxIndexerRetainHeightRequest) returns (GetTxIndexerRetainHeightResponse); + + // SetBlockIndexerRetainHeightRequest indicates to the node that it can safely + // prune all block indices up to the specified retain height. + rpc SetBlockIndexerRetainHeight(SetBlockIndexerRetainHeightRequest) returns (SetBlockIndexerRetainHeightResponse); + + // GetBlockIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence BlockIndexer pruning + rpc GetBlockIndexerRetainHeight(GetBlockIndexerRetainHeightRequest) returns (GetBlockIndexerRetainHeightResponse); +} diff --git a/proto/cometbft/services/version/v1/version.proto b/proto/cometbft/services/version/v1/version.proto new file mode 100644 index 00000000000..ec967527627 --- /dev/null +++ b/proto/cometbft/services/version/v1/version.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; +package cometbft.services.version.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/services/version/v1"; + +// GetVersionRequest is the request for the ABCI version. +message GetVersionRequest {} + +// GetVersionResponse contains the ABCI application version info. +message GetVersionResponse { + string node = 1; // The semantic version of the node software. + string abci = 2; // The version of ABCI used by the node. + uint64 p2p = 3; // The version of the P2P protocol. + uint64 block = 4; // The version of the block protocol. +} diff --git a/proto/cometbft/services/version/v1/version_service.proto b/proto/cometbft/services/version/v1/version_service.proto new file mode 100644 index 00000000000..dbb7c9d40b6 --- /dev/null +++ b/proto/cometbft/services/version/v1/version_service.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; +package cometbft.services.version.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/services/version/v1"; + +import "cometbft/services/version/v1/version.proto"; + +// VersionService simply provides version information about the node and the +// protocols it uses. +// +// The intention with this service is to offer a stable interface through which +// clients can access version information. This means that the version of the +// service should be kept stable at v1, with GetVersionResponse evolving only +// in non-breaking ways. +service VersionService { + // GetVersion retrieves version information about the node and the protocols + // it implements. + rpc GetVersion(GetVersionRequest) returns (GetVersionResponse); +} diff --git a/proto/cometbft/state/v1/types.proto b/proto/cometbft/state/v1/types.proto new file mode 100644 index 00000000000..d184efb6631 --- /dev/null +++ b/proto/cometbft/state/v1/types.proto @@ -0,0 +1,108 @@ +syntax = "proto3"; +package cometbft.state.v1; + +import "cometbft/abci/v1/types.proto"; +import "cometbft/types/v1/params.proto"; +import "cometbft/types/v1/types.proto"; +import "cometbft/types/v1/validator.proto"; +import "cometbft/version/v1/types.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/state/v1"; + +// LegacyABCIResponses retains the responses +// of the legacy ABCI calls during block processing. +// Note ReponseDeliverTx is renamed to ExecTxResult but they are semantically the same +// Kept for backwards compatibility for versions prior to v0.38 +message LegacyABCIResponses { + repeated cometbft.abci.v1.ExecTxResult deliver_txs = 1; + ResponseEndBlock end_block = 2; + ResponseBeginBlock begin_block = 3; +} + +// ResponseBeginBlock is kept for backward compatibility for versions prior to v0.38, +// as it was then defined in the cometbft.abci packages. +message ResponseBeginBlock { + repeated cometbft.abci.v1.Event events = 1 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; +} + +// ResponseEndBlock is kept for backward compatibility for versions prior to v0.38, +// its earlier revisions were defined in the cometbft.abci packages. +// It uses an updated definition for the consensus_param_updates field to keep the +// generated data types interoperable with the latest protocol. +message ResponseEndBlock { + repeated cometbft.abci.v1.ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; + cometbft.types.v1.ConsensusParams consensus_param_updates = 2; + repeated cometbft.abci.v1.Event events = 3 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; +} + +// ValidatorsInfo represents the latest validator set, or the last height it changed +message ValidatorsInfo { + cometbft.types.v1.ValidatorSet validator_set = 1; + int64 last_height_changed = 2; +} + +// ConsensusParamsInfo represents the latest consensus params, or the last height it changed +message ConsensusParamsInfo { + cometbft.types.v1.ConsensusParams consensus_params = 1 [(gogoproto.nullable) = false]; + int64 last_height_changed = 2; +} + +// ABCIResponsesInfo retains the responses of the ABCI calls during block processing. +message ABCIResponsesInfo { + // Retains the responses of the legacy ABCI calls during block processing. + LegacyABCIResponses legacy_abci_responses = 1; + int64 height = 2; + cometbft.abci.v1.FinalizeBlockResponse finalize_block = 3; +} + +// Version is a message for storing versioning information. +message Version { + cometbft.version.v1.Consensus consensus = 1 [(gogoproto.nullable) = false]; + string software = 2; +} + +// State represents the state of the blockchain. +message State { + Version version = 1 [(gogoproto.nullable) = false]; + + // immutable + string chain_id = 2 [(gogoproto.customname) = "ChainID"]; + int64 initial_height = 14; + + // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) + int64 last_block_height = 3; + cometbft.types.v1.BlockID last_block_id = 4 [ + (gogoproto.nullable) = false, + (gogoproto.customname) = "LastBlockID" + ]; + google.protobuf.Timestamp last_block_time = 5 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + + // LastValidators is used to validate block.LastCommit. + // Validators are persisted to the database separately every time they change, + // so we can query for historical validator sets. + // Note that if s.LastBlockHeight causes a valset change, + // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 + // Extra +1 due to nextValSet delay. + cometbft.types.v1.ValidatorSet next_validators = 6; + cometbft.types.v1.ValidatorSet validators = 7; + cometbft.types.v1.ValidatorSet last_validators = 8; + int64 last_height_validators_changed = 9; + + // Consensus parameters used for validating blocks. + // Changes returned by EndBlock and updated after Commit. + cometbft.types.v1.ConsensusParams consensus_params = 10 [(gogoproto.nullable) = false]; + int64 last_height_consensus_params_changed = 11; + + // Merkle root of the results from executing prev block + bytes last_results_hash = 12; + + // the latest AppHash we've received from calling abci.Commit() + bytes app_hash = 13; +} diff --git a/proto/cometbft/state/v1beta1/types.proto b/proto/cometbft/state/v1beta1/types.proto new file mode 100644 index 00000000000..51c86b0414d --- /dev/null +++ b/proto/cometbft/state/v1beta1/types.proto @@ -0,0 +1,83 @@ +syntax = "proto3"; +package cometbft.state.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/state/v1beta1"; + +import "gogoproto/gogo.proto"; +import "cometbft/abci/v1beta1/types.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "cometbft/types/v1beta1/validator.proto"; +import "cometbft/types/v1beta1/params.proto"; +import "cometbft/version/v1/types.proto"; +import "google/protobuf/timestamp.proto"; + +// ABCIResponses retains the responses +// of the various ABCI calls during block processing. +// It is persisted to disk for each height before calling Commit. +message ABCIResponses { + repeated cometbft.abci.v1beta1.ResponseDeliverTx deliver_txs = 1; + cometbft.abci.v1beta1.ResponseEndBlock end_block = 2; + cometbft.abci.v1beta1.ResponseBeginBlock begin_block = 3; +} + +// ValidatorsInfo represents the latest validator set, or the last height it changed +message ValidatorsInfo { + cometbft.types.v1beta1.ValidatorSet validator_set = 1; + int64 last_height_changed = 2; +} + +// ConsensusParamsInfo represents the latest consensus params, or the last height it changed +message ConsensusParamsInfo { + cometbft.types.v1beta1.ConsensusParams consensus_params = 1 [(gogoproto.nullable) = false]; + int64 last_height_changed = 2; +} + +// ABCIResponsesInfo retains the responses of the ABCI calls during block processing. +message ABCIResponsesInfo { + ABCIResponses abci_responses = 1; + int64 height = 2; +} + +// Version is a message for storing versioning information. +message Version { + cometbft.version.v1.Consensus consensus = 1 [(gogoproto.nullable) = false]; + string software = 2; +} + +// State represents the state of the blockchain. +message State { + Version version = 1 [(gogoproto.nullable) = false]; + + // immutable + string chain_id = 2 [(gogoproto.customname) = "ChainID"]; + int64 initial_height = 14; + + // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) + int64 last_block_height = 3; + cometbft.types.v1beta1.BlockID last_block_id = 4 + [(gogoproto.nullable) = false, (gogoproto.customname) = "LastBlockID"]; + google.protobuf.Timestamp last_block_time = 5 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + + // LastValidators is used to validate block.LastCommit. + // Validators are persisted to the database separately every time they change, + // so we can query for historical validator sets. + // Note that if s.LastBlockHeight causes a valset change, + // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 + // Extra +1 due to nextValSet delay. + cometbft.types.v1beta1.ValidatorSet next_validators = 6; + cometbft.types.v1beta1.ValidatorSet validators = 7; + cometbft.types.v1beta1.ValidatorSet last_validators = 8; + int64 last_height_validators_changed = 9; + + // Consensus parameters used for validating blocks. + // Changes returned by EndBlock and updated after Commit. + cometbft.types.v1beta1.ConsensusParams consensus_params = 10 [(gogoproto.nullable) = false]; + int64 last_height_consensus_params_changed = 11; + + // Merkle root of the results from executing prev block + bytes last_results_hash = 12; + + // the latest AppHash we've received from calling abci.Commit() + bytes app_hash = 13; +} diff --git a/proto/cometbft/state/v1beta2/types.proto b/proto/cometbft/state/v1beta2/types.proto new file mode 100644 index 00000000000..fba19839616 --- /dev/null +++ b/proto/cometbft/state/v1beta2/types.proto @@ -0,0 +1,75 @@ +syntax = "proto3"; +package cometbft.state.v1beta2; + +import "cometbft/abci/v1beta2/types.proto"; +import "cometbft/state/v1beta1/types.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "cometbft/types/v1beta1/validator.proto"; +import "cometbft/types/v1beta2/params.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/state/v1beta2"; + +// ABCIResponses retains the responses +// of the various ABCI calls during block processing. +// It is persisted to disk for each height before calling Commit. +message ABCIResponses { + repeated cometbft.abci.v1beta2.ResponseDeliverTx deliver_txs = 1; + cometbft.abci.v1beta2.ResponseEndBlock end_block = 2; + cometbft.abci.v1beta2.ResponseBeginBlock begin_block = 3; +} + +// ConsensusParamsInfo represents the latest consensus params, or the last height it changed +message ConsensusParamsInfo { + cometbft.types.v1beta2.ConsensusParams consensus_params = 1 [(gogoproto.nullable) = false]; + int64 last_height_changed = 2; +} + +// ABCIResponsesInfo retains the responses of the ABCI calls during block processing. +message ABCIResponsesInfo { + ABCIResponses abci_responses = 1; + int64 height = 2; +} + +// State represents the state of the blockchain. +message State { + v1beta1.Version version = 1 [(gogoproto.nullable) = false]; + + // immutable + string chain_id = 2 [(gogoproto.customname) = "ChainID"]; + int64 initial_height = 14; + + // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) + int64 last_block_height = 3; + cometbft.types.v1beta1.BlockID last_block_id = 4 [ + (gogoproto.nullable) = false, + (gogoproto.customname) = "LastBlockID" + ]; + google.protobuf.Timestamp last_block_time = 5 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + + // LastValidators is used to validate block.LastCommit. + // Validators are persisted to the database separately every time they change, + // so we can query for historical validator sets. + // Note that if s.LastBlockHeight causes a valset change, + // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 + // Extra +1 due to nextValSet delay. + cometbft.types.v1beta1.ValidatorSet next_validators = 6; + cometbft.types.v1beta1.ValidatorSet validators = 7; + cometbft.types.v1beta1.ValidatorSet last_validators = 8; + int64 last_height_validators_changed = 9; + + // Consensus parameters used for validating blocks. + // Changes returned by EndBlock and updated after Commit. + cometbft.types.v1beta2.ConsensusParams consensus_params = 10 [(gogoproto.nullable) = false]; + int64 last_height_consensus_params_changed = 11; + + // Merkle root of the results from executing prev block + bytes last_results_hash = 12; + + // the latest AppHash we've received from calling abci.Commit() + bytes app_hash = 13; +} diff --git a/proto/cometbft/state/v1beta3/types.proto b/proto/cometbft/state/v1beta3/types.proto new file mode 100644 index 00000000000..a5d3ff14ba9 --- /dev/null +++ b/proto/cometbft/state/v1beta3/types.proto @@ -0,0 +1,99 @@ +syntax = "proto3"; +package cometbft.state.v1beta3; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/state/v1beta3"; + +import "cometbft/state/v1beta1/types.proto"; + +import "cometbft/abci/v1beta1/types.proto"; +import "cometbft/abci/v1beta2/types.proto"; +import "cometbft/abci/v1beta3/types.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "cometbft/types/v1beta1/validator.proto"; +import "cometbft/types/v1/params.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +// LegacyABCIResponses retains the responses +// of the legacy ABCI calls during block processing. +// Note ReponseDeliverTx is renamed to ExecTxResult but they are semantically the same +// Kept for backwards compatibility for versions prior to v0.38 +message LegacyABCIResponses { + repeated cometbft.abci.v1beta3.ExecTxResult deliver_txs = 1; + ResponseEndBlock end_block = 2; + ResponseBeginBlock begin_block = 3; +} + +// ResponseBeginBlock is kept for backward compatibility for versions prior to v0.38, +// as it was then defined in the cometbft.abci packages. +message ResponseBeginBlock { + repeated cometbft.abci.v1beta2.Event events = 1 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; +} + +// ResponseEndBlock is kept for backward compatibility for versions prior to v0.38, +// its earlier revisions were defined in the cometbft.abci packages. +// It uses an updated definition for the consensus_param_updates field to keep the +// generated data types interoperable with the latest protocol. +message ResponseEndBlock { + repeated cometbft.abci.v1beta1.ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; + cometbft.types.v1.ConsensusParams consensus_param_updates = 2; + repeated cometbft.abci.v1beta2.Event events = 3 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; +} + +// ConsensusParamsInfo represents the latest consensus params, or the last height it changed +message ConsensusParamsInfo { + cometbft.types.v1.ConsensusParams consensus_params = 1 [(gogoproto.nullable) = false]; + int64 last_height_changed = 2; +} + +// ABCIResponsesInfo retains the responses of the ABCI calls during block processing. +message ABCIResponsesInfo { + // Retains the responses of the legacy ABCI calls during block processing. + LegacyABCIResponses legacy_abci_responses = 1; + int64 height = 2; + cometbft.abci.v1beta3.ResponseFinalizeBlock response_finalize_block = 3; +} + +// State represents the state of the blockchain. +message State { + v1beta1.Version version = 1 [(gogoproto.nullable) = false]; + + // immutable + string chain_id = 2 [(gogoproto.customname) = "ChainID"]; + int64 initial_height = 14; + + // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) + int64 last_block_height = 3; + cometbft.types.v1beta1.BlockID last_block_id = 4 [ + (gogoproto.nullable) = false, + (gogoproto.customname) = "LastBlockID" + ]; + google.protobuf.Timestamp last_block_time = 5 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true + ]; + + // LastValidators is used to validate block.LastCommit. + // Validators are persisted to the database separately every time they change, + // so we can query for historical validator sets. + // Note that if s.LastBlockHeight causes a valset change, + // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 + // Extra +1 due to nextValSet delay. + cometbft.types.v1beta1.ValidatorSet next_validators = 6; + cometbft.types.v1beta1.ValidatorSet validators = 7; + cometbft.types.v1beta1.ValidatorSet last_validators = 8; + int64 last_height_validators_changed = 9; + + // Consensus parameters used for validating blocks. + // Changes returned by EndBlock and updated after Commit. + cometbft.types.v1.ConsensusParams consensus_params = 10 [(gogoproto.nullable) = false]; + int64 last_height_consensus_params_changed = 11; + + // Merkle root of the results from executing prev block + bytes last_results_hash = 12; + + // the latest AppHash we've received from calling abci.Commit() + bytes app_hash = 13; +} diff --git a/proto/cometbft/statesync/v1/types.proto b/proto/cometbft/statesync/v1/types.proto new file mode 100644 index 00000000000..02a301dcbb4 --- /dev/null +++ b/proto/cometbft/statesync/v1/types.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; +package cometbft.statesync.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/statesync/v1"; + +// Message is the top-level message type for the statesync service. +message Message { + // The message type. + oneof sum { + SnapshotsRequest snapshots_request = 1; + SnapshotsResponse snapshots_response = 2; + ChunkRequest chunk_request = 3; + ChunkResponse chunk_response = 4; + } +} + +// SnapshotsRequest is sent to request a snapshot. +message SnapshotsRequest {} + +// SnapshotsResponse contains the snapshot metadata. +message SnapshotsResponse { + uint64 height = 1; + uint32 format = 2; + uint32 chunks = 3; + bytes hash = 4; + bytes metadata = 5; +} + +// ChunkRequest is sent to request a chunk. +message ChunkRequest { + uint64 height = 1; + uint32 format = 2; + uint32 index = 3; +} + +// ChunkResponse contains a chunk of the snapshot. +message ChunkResponse { + uint64 height = 1; + uint32 format = 2; + uint32 index = 3; + bytes chunk = 4; + bool missing = 5; +} diff --git a/proto/cometbft/store/v1/types.proto b/proto/cometbft/store/v1/types.proto new file mode 100644 index 00000000000..98f1df43f4b --- /dev/null +++ b/proto/cometbft/store/v1/types.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package cometbft.store.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/store/v1"; + +// BlockStoreState represents the state of the block store. +message BlockStoreState { + int64 base = 1; + int64 height = 2; +} diff --git a/proto/cometbft/types/v1/block.proto b/proto/cometbft/types/v1/block.proto new file mode 100644 index 00000000000..6748263fd01 --- /dev/null +++ b/proto/cometbft/types/v1/block.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; +package cometbft.types.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; + +import "cometbft/types/v1/types.proto"; +import "cometbft/types/v1/evidence.proto"; +import "gogoproto/gogo.proto"; + +// Block defines the structure of a block in the CometBFT blockchain. +message Block { + Header header = 1 [(gogoproto.nullable) = false]; + Data data = 2 [(gogoproto.nullable) = false]; + EvidenceList evidence = 3 [(gogoproto.nullable) = false]; + Commit last_commit = 4; +} diff --git a/proto/cometbft/types/v1/canonical.proto b/proto/cometbft/types/v1/canonical.proto new file mode 100644 index 00000000000..26a07c812b5 --- /dev/null +++ b/proto/cometbft/types/v1/canonical.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; +package cometbft.types.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; + +import "gogoproto/gogo.proto"; +import "cometbft/types/v1/types.proto"; +import "google/protobuf/timestamp.proto"; + +// CanonicalBlockID is a canonical representation of a BlockID, which gets +// serialized and signed. +message CanonicalBlockID { + bytes hash = 1; + CanonicalPartSetHeader part_set_header = 2 [(gogoproto.nullable) = false]; +} + +// CanonicalPartSetHeader is a canonical representation of a PartSetHeader, +// which gets serialized and signed. +message CanonicalPartSetHeader { + uint32 total = 1; + bytes hash = 2; +} + +// CanonicalProposal is a canonical representation of a Proposal, which gets +// serialized and signed. +message CanonicalProposal { + SignedMsgType type = 1; // type alias for byte + sfixed64 height = 2; // canonicalization requires fixed size encoding here + sfixed64 round = 3; // canonicalization requires fixed size encoding here + int64 pol_round = 4 [(gogoproto.customname) = "POLRound"]; + CanonicalBlockID block_id = 5 [(gogoproto.customname) = "BlockID"]; + google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 7 [(gogoproto.customname) = "ChainID"]; +} + +// CanonicalVote is a canonical representation of a Vote, which gets +// serialized and signed. +message CanonicalVote { + SignedMsgType type = 1; // type alias for byte + sfixed64 height = 2; // canonicalization requires fixed size encoding here + sfixed64 round = 3; // canonicalization requires fixed size encoding here + CanonicalBlockID block_id = 4 [(gogoproto.customname) = "BlockID"]; + google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 6 [(gogoproto.customname) = "ChainID"]; +} + +// CanonicalVoteExtension provides us a way to serialize a vote extension from +// a particular validator such that we can sign over those serialized bytes. +message CanonicalVoteExtension { + bytes extension = 1; + sfixed64 height = 2; + sfixed64 round = 3; + string chain_id = 4; +} diff --git a/proto/cometbft/types/v1/events.proto b/proto/cometbft/types/v1/events.proto new file mode 100644 index 00000000000..21e265664b8 --- /dev/null +++ b/proto/cometbft/types/v1/events.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package cometbft.types.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; + +// EventDataRoundState is emitted with each new round step. +message EventDataRoundState { + int64 height = 1; + int32 round = 2; + string step = 3; +} diff --git a/proto/cometbft/types/v1/evidence.proto b/proto/cometbft/types/v1/evidence.proto new file mode 100644 index 00000000000..a77cea8d8f8 --- /dev/null +++ b/proto/cometbft/types/v1/evidence.proto @@ -0,0 +1,41 @@ +syntax = "proto3"; +package cometbft.types.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; + +import "cometbft/types/v1/types.proto"; +import "cometbft/types/v1/validator.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +// Evidence is a generic type for wrapping evidence of misbehavior by a validator. +message Evidence { + // The type of evidence. + oneof sum { + DuplicateVoteEvidence duplicate_vote_evidence = 1; + LightClientAttackEvidence light_client_attack_evidence = 2; + } +} + +// DuplicateVoteEvidence contains evidence of a validator signed two conflicting votes. +message DuplicateVoteEvidence { + Vote vote_a = 1; + Vote vote_b = 2; + int64 total_voting_power = 3; + int64 validator_power = 4; + google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} + +// LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client. +message LightClientAttackEvidence { + LightBlock conflicting_block = 1; + int64 common_height = 2; + repeated Validator byzantine_validators = 3; + int64 total_voting_power = 4; + google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} + +// EvidenceList is a list of evidence. +message EvidenceList { + repeated Evidence evidence = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/cometbft/types/v1/params.proto b/proto/cometbft/types/v1/params.proto new file mode 100644 index 00000000000..4e3b1c21e49 --- /dev/null +++ b/proto/cometbft/types/v1/params.proto @@ -0,0 +1,143 @@ +syntax = "proto3"; +package cometbft.types.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; + +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/wrappers.proto"; + +option (gogoproto.equal_all) = true; + +// ConsensusParams contains consensus critical parameters that determine the +// validity of blocks. +message ConsensusParams { + BlockParams block = 1; + EvidenceParams evidence = 2; + ValidatorParams validator = 3; + VersionParams version = 4; + ABCIParams abci = 5 [deprecated = true]; // Use FeatureParams.vote_extensions_enable_height instead + SynchronyParams synchrony = 6; + FeatureParams feature = 7; +} + +// BlockParams define limits on the block size and gas. +message BlockParams { + // Maximum size of a block, in bytes. + // + // Must be greater or equal to -1 and cannot be greater than the hard-coded + // maximum block size, which is 100MB. + // + // If set to -1, the limit is the hard-coded maximum block size. + int64 max_bytes = 1; + // Maximum gas wanted by transactions included in a block. + // + // Must be greater or equal to -1. If set to -1, no limit is enforced. + int64 max_gas = 2; + + reserved 3; // was TimeIotaMs see https://github.com/tendermint/tendermint/pull/5792 +} + +// EvidenceParams determine the validity of evidences of Byzantine behavior. +message EvidenceParams { + // Maximum age of evidence, in blocks. + // + // The recommended formula for calculating it is max_age_duration / {average + // block time}. + int64 max_age_num_blocks = 1; + + // Maximum age of evidence, in time. + // + // The recommended value of is should correspond to the application's + // "unbonding period" or other similar mechanism for handling + // Nothing-At-Stake attacks. + // See: https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed. + google.protobuf.Duration max_age_duration = 2 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + + // Maximum size in bytes of evidence allowed to be included in a block. + // + // It should fall comfortably under the maximum size of a block. + int64 max_bytes = 3; +} + +// ValidatorParams restrict the public key types validators can use. +// +// NOTE: uses ABCI public keys naming, not Amino names. +message ValidatorParams { + option (gogoproto.populate) = true; + option (gogoproto.equal) = true; + + repeated string pub_key_types = 1; +} + +// VersionParams contain the version of specific components of CometBFT. +message VersionParams { + option (gogoproto.populate) = true; + option (gogoproto.equal) = true; + + // The ABCI application version. + // + // It was named app_version in CometBFT 0.34. + uint64 app = 1; +} + +// HashedParams is a subset of ConsensusParams. +// +// It is hashed into the Header.ConsensusHash. +message HashedParams { + int64 block_max_bytes = 1; + int64 block_max_gas = 2; +} + +// SynchronyParams determine the validity of block timestamps. +// +// These parameters are part of the Proposer-Based Timestamps (PBTS) algorithm. +// For more information on the relationship of the synchrony parameters to +// block timestamps validity, refer to the PBTS specification: +// https://github.com/tendermint/spec/blob/master/spec/consensus/proposer-based-timestamp/README.md +message SynchronyParams { + // Bound for how skewed a proposer's clock may be from any validator on the + // network while still producing valid proposals. + google.protobuf.Duration precision = 1 + [(gogoproto.stdduration) = true]; + // Bound for how long a proposal message may take to reach all validators on + // a network and still be considered valid. + google.protobuf.Duration message_delay = 2 + [(gogoproto.stdduration) = true]; +} + +// FeatureParams configure the height from which features of CometBFT are enabled. +message FeatureParams { + // First height during which vote extensions will be enabled. + // + // During the specified height, and for all subsequent heights, precommit + // messages that do not contain valid extension data will be considered + // invalid. Prior to this height, or when this height is set to 0, vote + // extensions will not be used or accepted by validators on the network. + // + // Once enabled, vote extensions will be created by the application in + // ExtendVote, validated by the application in VerifyVoteExtension, and + // used by the application in PrepareProposal, when proposing the next block. + // + // Cannot be set to heights lower or equal to the current blockchain height. + google.protobuf.Int64Value vote_extensions_enable_height = 1 [(gogoproto.nullable) = true]; + + // Height at which Proposer-Based Timestamps (PBTS) will be enabled. + // + // From the specified height, and for all subsequent heights, the PBTS + // algorithm will be used to produce and validate block timestamps. Prior to + // this height, or when this height is set to 0, the legacy BFT Time + // algorithm is used to produce and validate timestamps. + // + // Cannot be set to heights lower or equal to the current blockchain height. + google.protobuf.Int64Value pbts_enable_height = 2 [(gogoproto.nullable) = true]; +} + +// ABCIParams is deprecated and its contents moved to FeatureParams +message ABCIParams { + option deprecated = true; + // vote_extensions_enable_height has been deprecated. + // Instead, use FeatureParams.vote_extensions_enable_height. + int64 vote_extensions_enable_height = 1; +} diff --git a/proto/cometbft/types/v1/types.proto b/proto/cometbft/types/v1/types.proto new file mode 100644 index 00000000000..0a9555ad2a0 --- /dev/null +++ b/proto/cometbft/types/v1/types.proto @@ -0,0 +1,184 @@ +syntax = "proto3"; +package cometbft.types.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; + +import "cometbft/crypto/v1/proof.proto"; +import "cometbft/types/v1/validator.proto"; +import "cometbft/version/v1/types.proto"; + +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +// SignedMsgType is a type of signed message in the consensus. +enum SignedMsgType { + option (gogoproto.goproto_enum_stringer) = true; + option (gogoproto.goproto_enum_prefix) = false; + + // Unknown + SIGNED_MSG_TYPE_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "UnknownType"]; + // Prevote + SIGNED_MSG_TYPE_PREVOTE = 1 [(gogoproto.enumvalue_customname) = "PrevoteType"]; + // Precommit + SIGNED_MSG_TYPE_PRECOMMIT = 2 [(gogoproto.enumvalue_customname) = "PrecommitType"]; + // Proposal + SIGNED_MSG_TYPE_PROPOSAL = 32 [(gogoproto.enumvalue_customname) = "ProposalType"]; +} + +// Header of the parts set for a block. +message PartSetHeader { + uint32 total = 1; + bytes hash = 2; +} + +// Part of the block. +message Part { + uint32 index = 1; + bytes bytes = 2; + cometbft.crypto.v1.Proof proof = 3 [(gogoproto.nullable) = false]; +} + +// BlockID defines the unique ID of a block as its hash and its `PartSetHeader`. +message BlockID { + bytes hash = 1; + PartSetHeader part_set_header = 2 [(gogoproto.nullable) = false]; +} + +// Header defines the structure of a block header. +message Header { + // basic block info + cometbft.version.v1.Consensus version = 1 [(gogoproto.nullable) = false]; + string chain_id = 2 [(gogoproto.customname) = "ChainID"]; + int64 height = 3; + google.protobuf.Timestamp time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + + // prev block info + BlockID last_block_id = 5 [(gogoproto.nullable) = false]; + + // hashes of block data + bytes last_commit_hash = 6; // commit from validators from the last block + bytes data_hash = 7; // transactions + + // hashes from the app output from the prev block + bytes validators_hash = 8; // validators for the current block + bytes next_validators_hash = 9; // validators for the next block + bytes consensus_hash = 10; // consensus params for current block + bytes app_hash = 11; // state after txs from the previous block + bytes last_results_hash = 12; // root hash of all results from the txs from the previous block + + // consensus info + bytes evidence_hash = 13; // evidence included in the block + bytes proposer_address = 14; // original proposer of the block +} + +// Data contains the set of transactions included in the block +message Data { + // Txs that will be applied by state @ block.Height+1. + // NOTE: not all txs here are valid. We're just agreeing on the order first. + // This means that block.AppHash does not include these txs. + repeated bytes txs = 1; +} + +// Vote represents a prevote or precommit vote from validators for +// consensus. +message Vote { + SignedMsgType type = 1; + int64 height = 2; + int32 round = 3; + BlockID block_id = 4 + [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; // zero if vote is nil. + google.protobuf.Timestamp timestamp = 5 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes validator_address = 6; + int32 validator_index = 7; + // Vote signature by the validator if they participated in consensus for the + // associated block. + bytes signature = 8; + // Vote extension provided by the application. Only valid for precommit + // messages. + bytes extension = 9; + // Vote extension signature by the validator if they participated in + // consensus for the associated block. + // Only valid for precommit messages. + bytes extension_signature = 10; +} + +// Commit contains the evidence that a block was committed by a set of validators. +message Commit { + int64 height = 1; + int32 round = 2; + BlockID block_id = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; + repeated CommitSig signatures = 4 [(gogoproto.nullable) = false]; +} + +// CommitSig is a part of the Vote included in a Commit. +message CommitSig { + BlockIDFlag block_id_flag = 1; + bytes validator_address = 2; + google.protobuf.Timestamp timestamp = 3 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes signature = 4; +} + +// ExtendedCommit is a Commit with ExtendedCommitSig. +message ExtendedCommit { + int64 height = 1; + int32 round = 2; + BlockID block_id = 3 + [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; + repeated ExtendedCommitSig extended_signatures = 4 [(gogoproto.nullable) = false]; +} + +// ExtendedCommitSig retains all the same fields as CommitSig but adds vote +// extension-related fields. We use two signatures to ensure backwards compatibility. +// That is the digest of the original signature is still the same in prior versions +message ExtendedCommitSig { + BlockIDFlag block_id_flag = 1; + bytes validator_address = 2; + google.protobuf.Timestamp timestamp = 3 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes signature = 4; + // Vote extension data + bytes extension = 5; + // Vote extension signature + bytes extension_signature = 6; +} + +// Block proposal. +message Proposal { + SignedMsgType type = 1; + int64 height = 2; + int32 round = 3; + int32 pol_round = 4; + BlockID block_id = 5 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; + google.protobuf.Timestamp timestamp = 6 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes signature = 7; +} + +// SignedHeader contains a Header(H) and Commit(H+1) with signatures of validators who signed it. +message SignedHeader { + Header header = 1; + Commit commit = 2; +} + +// LightBlock is a combination of SignedHeader and ValidatorSet. It is used by light clients. +message LightBlock { + SignedHeader signed_header = 1; + ValidatorSet validator_set = 2; +} + +// BlockMeta contains meta information about a block. +message BlockMeta { + BlockID block_id = 1 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; + int64 block_size = 2; + Header header = 3 [(gogoproto.nullable) = false]; + int64 num_txs = 4; +} + +// TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree. +message TxProof { + bytes root_hash = 1; + bytes data = 2; + cometbft.crypto.v1.Proof proof = 3; +} diff --git a/proto/cometbft/types/v1/validator.proto b/proto/cometbft/types/v1/validator.proto new file mode 100644 index 00000000000..d3c68669789 --- /dev/null +++ b/proto/cometbft/types/v1/validator.proto @@ -0,0 +1,45 @@ +syntax = "proto3"; +package cometbft.types.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1"; + +import "gogoproto/gogo.proto"; +import "cometbft/crypto/v1/keys.proto"; + +// BlockIdFlag indicates which BlockID the signature is for +enum BlockIDFlag { + option (gogoproto.goproto_enum_stringer) = true; + option (gogoproto.goproto_enum_prefix) = false; + + // Indicates an error condition + BLOCK_ID_FLAG_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "BlockIDFlagUnknown"]; + // The vote was not received + BLOCK_ID_FLAG_ABSENT = 1 [(gogoproto.enumvalue_customname) = "BlockIDFlagAbsent"]; + // Voted for the block that received the majority + BLOCK_ID_FLAG_COMMIT = 2 [(gogoproto.enumvalue_customname) = "BlockIDFlagCommit"]; + // Voted for nil + BLOCK_ID_FLAG_NIL = 3 [(gogoproto.enumvalue_customname) = "BlockIDFlagNil"]; +} + +// ValidatorSet defines a set of validators. +message ValidatorSet { + repeated Validator validators = 1; + Validator proposer = 2; + int64 total_voting_power = 3; +} + +// Validator represents a node participating in the consensus protocol. +message Validator { + bytes address = 1; + cometbft.crypto.v1.PublicKey pub_key = 2 [(gogoproto.nullable) = false]; + int64 voting_power = 3; + int64 proposer_priority = 4; +} + +// SimpleValidator is a Validator, which is serialized and hashed in consensus. +// Address is removed because it's redundant with the pubkey. +// Proposer priority is removed because it changes every round. +message SimpleValidator { + cometbft.crypto.v1.PublicKey pub_key = 1; + int64 voting_power = 2; +} diff --git a/proto/cometbft/types/v1beta1/block.proto b/proto/cometbft/types/v1beta1/block.proto new file mode 100644 index 00000000000..8ef9154d394 --- /dev/null +++ b/proto/cometbft/types/v1beta1/block.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; +package cometbft.types.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; + +import "gogoproto/gogo.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "cometbft/types/v1beta1/evidence.proto"; + +// Block defines the structure of a block in the CometBFT blockchain. +message Block { + Header header = 1 [(gogoproto.nullable) = false]; + Data data = 2 [(gogoproto.nullable) = false]; + cometbft.types.v1beta1.EvidenceList evidence = 3 [(gogoproto.nullable) = false]; + Commit last_commit = 4; +} diff --git a/proto/cometbft/types/v1beta1/canonical.proto b/proto/cometbft/types/v1beta1/canonical.proto new file mode 100644 index 00000000000..0176cc5febd --- /dev/null +++ b/proto/cometbft/types/v1beta1/canonical.proto @@ -0,0 +1,45 @@ +syntax = "proto3"; +package cometbft.types.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; + +import "gogoproto/gogo.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "google/protobuf/timestamp.proto"; + +// CanonicalBlockID is a canonical representation of a BlockID, which gets +// serialized and signed. +message CanonicalBlockID { + bytes hash = 1; + CanonicalPartSetHeader part_set_header = 2 [(gogoproto.nullable) = false]; +} + +// CanonicalPartSetHeader is a canonical representation of a PartSetHeader, +// which gets serialized and signed. +message CanonicalPartSetHeader { + uint32 total = 1; + bytes hash = 2; +} + +// CanonicalProposal is a canonical representation of a Proposal, which gets +// serialized and signed. +message CanonicalProposal { + SignedMsgType type = 1; // type alias for byte + sfixed64 height = 2; // canonicalization requires fixed size encoding here + sfixed64 round = 3; // canonicalization requires fixed size encoding here + int64 pol_round = 4 [(gogoproto.customname) = "POLRound"]; + CanonicalBlockID block_id = 5 [(gogoproto.customname) = "BlockID"]; + google.protobuf.Timestamp timestamp = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 7 [(gogoproto.customname) = "ChainID"]; +} + +// CanonicalVote is a canonical representation of a Vote, which gets +// serialized and signed. +message CanonicalVote { + SignedMsgType type = 1; // type alias for byte + sfixed64 height = 2; // canonicalization requires fixed size encoding here + sfixed64 round = 3; // canonicalization requires fixed size encoding here + CanonicalBlockID block_id = 4 [(gogoproto.customname) = "BlockID"]; + google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + string chain_id = 6 [(gogoproto.customname) = "ChainID"]; +} diff --git a/proto/cometbft/types/v1beta1/events.proto b/proto/cometbft/types/v1beta1/events.proto new file mode 100644 index 00000000000..9f09c65ee18 --- /dev/null +++ b/proto/cometbft/types/v1beta1/events.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package cometbft.types.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; + +// EventDataRoundState is emitted with each new round step. +message EventDataRoundState { + int64 height = 1; + int32 round = 2; + string step = 3; +} diff --git a/proto/cometbft/types/v1beta1/evidence.proto b/proto/cometbft/types/v1beta1/evidence.proto new file mode 100644 index 00000000000..d4573f74e87 --- /dev/null +++ b/proto/cometbft/types/v1beta1/evidence.proto @@ -0,0 +1,41 @@ +syntax = "proto3"; +package cometbft.types.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; + +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; +import "cometbft/types/v1beta1/types.proto"; +import "cometbft/types/v1beta1/validator.proto"; + +// Evidence is a generic type for wrapping evidence of misbehavior by a validator. +message Evidence { + // The type of evidence. + oneof sum { + DuplicateVoteEvidence duplicate_vote_evidence = 1; + LightClientAttackEvidence light_client_attack_evidence = 2; + } +} + +// DuplicateVoteEvidence contains evidence of a validator signed two conflicting votes. +message DuplicateVoteEvidence { + cometbft.types.v1beta1.Vote vote_a = 1; + cometbft.types.v1beta1.Vote vote_b = 2; + int64 total_voting_power = 3; + int64 validator_power = 4; + google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} + +// LightClientAttackEvidence contains evidence of a set of validators attempting to mislead a light client. +message LightClientAttackEvidence { + cometbft.types.v1beta1.LightBlock conflicting_block = 1; + int64 common_height = 2; + repeated cometbft.types.v1beta1.Validator byzantine_validators = 3; + int64 total_voting_power = 4; + google.protobuf.Timestamp timestamp = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} + +// EvidenceList is a list of evidence. +message EvidenceList { + repeated Evidence evidence = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/cometbft/types/v1beta1/params.proto b/proto/cometbft/types/v1beta1/params.proto new file mode 100644 index 00000000000..a2545fa082e --- /dev/null +++ b/proto/cometbft/types/v1beta1/params.proto @@ -0,0 +1,81 @@ +syntax = "proto3"; +package cometbft.types.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; + +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; + +option (gogoproto.equal_all) = true; + +// ConsensusParams contains consensus critical parameters that determine the +// validity of blocks. +message ConsensusParams { + BlockParams block = 1 [(gogoproto.nullable) = false]; + EvidenceParams evidence = 2 [(gogoproto.nullable) = false]; + ValidatorParams validator = 3 [(gogoproto.nullable) = false]; + VersionParams version = 4 [(gogoproto.nullable) = false]; +} + +// BlockParams contains limits on the block size. +message BlockParams { + // Max block size, in bytes. + // Note: must be greater than 0 + int64 max_bytes = 1; + // Max gas per block. + // Note: must be greater or equal to -1 + int64 max_gas = 2; + // Minimum time increment between consecutive blocks (in milliseconds) If the + // block header timestamp is ahead of the system clock, decrease this value. + // + // Not exposed to the application. + int64 time_iota_ms = 3; +} + +// EvidenceParams determine how we handle evidence of malfeasance. +message EvidenceParams { + // Max age of evidence, in blocks. + // + // The basic formula for calculating this is: MaxAgeDuration / {average block + // time}. + int64 max_age_num_blocks = 1; + + // Max age of evidence, in time. + // + // It should correspond with an app's "unbonding period" or other similar + // mechanism for handling [Nothing-At-Stake + // attacks](https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed). + google.protobuf.Duration max_age_duration = 2 + [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + + // This sets the maximum size of total evidence in bytes that can be committed in a single block. + // and should fall comfortably under the max block bytes. + // Default is 1048576 or 1MB + int64 max_bytes = 3; +} + +// ValidatorParams restrict the public key types validators can use. +// NOTE: uses ABCI pubkey naming, not Amino names. +message ValidatorParams { + option (gogoproto.populate) = true; + option (gogoproto.equal) = true; + + repeated string pub_key_types = 1; +} + +// VersionParams contains the ABCI application version. +message VersionParams { + option (gogoproto.populate) = true; + option (gogoproto.equal) = true; + + // Was named app_version in Tendermint 0.34 + uint64 app = 1; +} + +// HashedParams is a subset of ConsensusParams. +// +// It is hashed into the Header.ConsensusHash. +message HashedParams { + int64 block_max_bytes = 1; + int64 block_max_gas = 2; +} diff --git a/proto/cometbft/types/v1beta1/types.proto b/proto/cometbft/types/v1beta1/types.proto new file mode 100644 index 00000000000..6b578612402 --- /dev/null +++ b/proto/cometbft/types/v1beta1/types.proto @@ -0,0 +1,152 @@ +syntax = "proto3"; +package cometbft.types.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; + +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; +import "cometbft/crypto/v1/proof.proto"; +import "cometbft/version/v1/types.proto"; +import "cometbft/types/v1beta1/validator.proto"; + +// SignedMsgType is a type of signed message in the consensus. +enum SignedMsgType { + option (gogoproto.goproto_enum_stringer) = true; + option (gogoproto.goproto_enum_prefix) = false; + + // Unknown + SIGNED_MSG_TYPE_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "UnknownType"]; + // Prevote + SIGNED_MSG_TYPE_PREVOTE = 1 [(gogoproto.enumvalue_customname) = "PrevoteType"]; + // Precommit + SIGNED_MSG_TYPE_PRECOMMIT = 2 [(gogoproto.enumvalue_customname) = "PrecommitType"]; + // Proposal + SIGNED_MSG_TYPE_PROPOSAL = 32 [(gogoproto.enumvalue_customname) = "ProposalType"]; +} + +// Header of the parts set for a block. +message PartSetHeader { + uint32 total = 1; + bytes hash = 2; +} + +// Part of the block. +message Part { + uint32 index = 1; + bytes bytes = 2; + cometbft.crypto.v1.Proof proof = 3 [(gogoproto.nullable) = false]; +} + +// BlockID defines the unique ID of a block as its hash and its `PartSetHeader`. +message BlockID { + bytes hash = 1; + PartSetHeader part_set_header = 2 [(gogoproto.nullable) = false]; +} + +// -------------------------------- + +// Header defines the structure of a block header. +message Header { + // basic block info + cometbft.version.v1.Consensus version = 1 [(gogoproto.nullable) = false]; + string chain_id = 2 [(gogoproto.customname) = "ChainID"]; + int64 height = 3; + google.protobuf.Timestamp time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + + // prev block info + BlockID last_block_id = 5 [(gogoproto.nullable) = false]; + + // hashes of block data + bytes last_commit_hash = 6; // commit from validators from the last block + bytes data_hash = 7; // transactions + + // hashes from the app output from the prev block + bytes validators_hash = 8; // validators for the current block + bytes next_validators_hash = 9; // validators for the next block + bytes consensus_hash = 10; // consensus params for current block + bytes app_hash = 11; // state after txs from the previous block + bytes last_results_hash = 12; // root hash of all results from the txs from the previous block + + // consensus info + bytes evidence_hash = 13; // evidence included in the block + bytes proposer_address = 14; // original proposer of the block +} + +// Data contains the set of transactions included in the block +message Data { + // Txs that will be applied by state @ block.Height+1. + // NOTE: not all txs here are valid. We're just agreeing on the order first. + // This means that block.AppHash does not include these txs. + repeated bytes txs = 1; +} + +// Vote represents a prevote or precommit vote from validators for +// consensus. +message Vote { + SignedMsgType type = 1; + int64 height = 2; + int32 round = 3; + BlockID block_id = 4 + [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; // zero if vote is nil. + google.protobuf.Timestamp timestamp = 5 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes validator_address = 6; + int32 validator_index = 7; + bytes signature = 8; +} + +// Commit contains the evidence that a block was committed by a set of validators. +message Commit { + int64 height = 1; + int32 round = 2; + BlockID block_id = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "BlockID"]; + repeated CommitSig signatures = 4 [(gogoproto.nullable) = false]; +} + +// CommitSig is a part of the Vote included in a Commit. +message CommitSig { + BlockIDFlag block_id_flag = 1; + bytes validator_address = 2; + google.protobuf.Timestamp timestamp = 3 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes signature = 4; +} + +// Block proposal. +message Proposal { + SignedMsgType type = 1; + int64 height = 2; + int32 round = 3; + int32 pol_round = 4; + BlockID block_id = 5 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; + google.protobuf.Timestamp timestamp = 6 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + bytes signature = 7; +} + +// SignedHeader contains a Header(H) and Commit(H+1) with signatures of validators who signed it. +message SignedHeader { + Header header = 1; + Commit commit = 2; +} + +// LightBlock is a combination of SignedHeader and ValidatorSet. It is used by light clients. +message LightBlock { + SignedHeader signed_header = 1; + cometbft.types.v1beta1.ValidatorSet validator_set = 2; +} + +// BlockMeta contains meta information about a block. +message BlockMeta { + BlockID block_id = 1 [(gogoproto.customname) = "BlockID", (gogoproto.nullable) = false]; + int64 block_size = 2; + Header header = 3 [(gogoproto.nullable) = false]; + int64 num_txs = 4; +} + +// TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree. +message TxProof { + bytes root_hash = 1; + bytes data = 2; + cometbft.crypto.v1.Proof proof = 3; +} diff --git a/proto/cometbft/types/v1beta1/validator.proto b/proto/cometbft/types/v1beta1/validator.proto new file mode 100644 index 00000000000..90bead1725c --- /dev/null +++ b/proto/cometbft/types/v1beta1/validator.proto @@ -0,0 +1,45 @@ +syntax = "proto3"; +package cometbft.types.v1beta1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta1"; + +import "gogoproto/gogo.proto"; +import "cometbft/crypto/v1/keys.proto"; + +// BlockIdFlag indicates which BlockID the signature is for +enum BlockIDFlag { + option (gogoproto.goproto_enum_stringer) = true; + option (gogoproto.goproto_enum_prefix) = false; + + // Indicates an error condition + BLOCK_ID_FLAG_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "BlockIDFlagUnknown"]; + // The vote was not received + BLOCK_ID_FLAG_ABSENT = 1 [(gogoproto.enumvalue_customname) = "BlockIDFlagAbsent"]; + // Voted for the block that received the majority + BLOCK_ID_FLAG_COMMIT = 2 [(gogoproto.enumvalue_customname) = "BlockIDFlagCommit"]; + // Voted for nil + BLOCK_ID_FLAG_NIL = 3 [(gogoproto.enumvalue_customname) = "BlockIDFlagNil"]; +} + +// ValidatorSet defines a set of validators. +message ValidatorSet { + repeated Validator validators = 1; + Validator proposer = 2; + int64 total_voting_power = 3; +} + +// Validator represents a node participating in the consensus protocol. +message Validator { + bytes address = 1; + cometbft.crypto.v1.PublicKey pub_key = 2 [(gogoproto.nullable) = false]; + int64 voting_power = 3; + int64 proposer_priority = 4; +} + +// SimpleValidator is a Validator, which is serialized and hashed in consensus. +// Address is removed because it's redundant with the pubkey. +// Proposer priority is removed because it changes every round. +message SimpleValidator { + cometbft.crypto.v1.PublicKey pub_key = 1; + int64 voting_power = 2; +} diff --git a/proto/cometbft/types/v1beta2/params.proto b/proto/cometbft/types/v1beta2/params.proto new file mode 100644 index 00000000000..c624eb2f4d3 --- /dev/null +++ b/proto/cometbft/types/v1beta2/params.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; +package cometbft.types.v1beta2; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/types/v1beta2"; + +import "gogoproto/gogo.proto"; +import "cometbft/types/v1beta1/params.proto"; + +option (gogoproto.equal_all) = true; + +// ConsensusParams contains consensus critical parameters that determine the +// validity of blocks. +message ConsensusParams { + BlockParams block = 1; + v1beta1.EvidenceParams evidence = 2; + v1beta1.ValidatorParams validator = 3; + v1beta1.VersionParams version = 4; +} + +// BlockParams contains limits on the block size. +message BlockParams { + // Max block size, in bytes. + // Note: must be greater than 0 + int64 max_bytes = 1; + // Max gas per block. + // Note: must be greater or equal to -1 + int64 max_gas = 2; + + reserved 3; // was TimeIotaMs see https://github.com/tendermint/tendermint/pull/5792 +} diff --git a/proto/cometbft/version/v1/types.proto b/proto/cometbft/version/v1/types.proto new file mode 100644 index 00000000000..243675cdbb8 --- /dev/null +++ b/proto/cometbft/version/v1/types.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package cometbft.version.v1; + +option go_package = "github.com/cometbft/cometbft/api/cometbft/version/v1"; + +import "gogoproto/gogo.proto"; + +// App includes the protocol and software version for the application. +// This information is included in ResponseInfo. The App.Protocol can be +// updated in ResponseEndBlock. +message App { + uint64 protocol = 1; + string software = 2; +} + +// Consensus captures the consensus rules for processing a block in the blockchain, +// including all blockchain data structures and the rules of the application's +// state transition machine. +message Consensus { + option (gogoproto.equal) = true; + + uint64 block = 1; + uint64 app = 2; +} diff --git a/proto/tendermint/abci/types.proto b/proto/tendermint/abci/types.proto index 73151984ff9..5affcc30c5e 100644 --- a/proto/tendermint/abci/types.proto +++ b/proto/tendermint/abci/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.abci; -option go_package = "github.com/cometbft/cometbft/abci/types"; - // For more information on gogo.proto, see: // https://github.com/cosmos/gogoproto/blob/master/extensions.md import "tendermint/crypto/proof.proto"; @@ -36,7 +34,7 @@ service ABCI { rpc FinalizeBlock(RequestFinalizeBlock) returns (ResponseFinalizeBlock); } -//---------------------------------------- +// ---------------------------------------- // Request types message Request { @@ -156,16 +154,24 @@ message RequestProcessProposal { // Extends a vote with application-injected data message RequestExtendVote { - // the hash of the block that this vote may be referring to - bytes hash = 1; + // the hash of the block that this vote may be referring to + bytes hash = 1; // the height of the extended vote int64 height = 2; + // info of the block that this vote may be referring to + google.protobuf.Timestamp time = 3 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + repeated bytes txs = 4; + CommitInfo proposed_last_commit = 5 [(gogoproto.nullable) = false]; + repeated Misbehavior misbehavior = 6 [(gogoproto.nullable) = false]; + bytes next_validators_hash = 7; + // address of the public key of the original proposer of the block. + bytes proposer_address = 8; } // Verify the vote extension message RequestVerifyVoteExtension { // the hash of the block that this received vote corresponds to - bytes hash = 1; + bytes hash = 1; // the validator that signed the vote extension bytes validator_address = 2; int64 height = 3; @@ -185,7 +191,7 @@ message RequestFinalizeBlock { bytes proposer_address = 8; } -//---------------------------------------- +// ---------------------------------------- // Response types message Response { @@ -337,16 +343,16 @@ message ResponseVerifyVoteExtension { // Incorrectly implementing this thus has liveness implications as it may affect // CometBFT's ability to receive 2/3+ valid votes to finalize the block. // Honest nodes should never be rejected. - REJECT = 2; + REJECT = 2; } } message ResponseFinalizeBlock { - // set of block events emmitted as part of executing the block + // set of block events emitted as part of executing the block repeated Event events = 1 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; // the result of executing each transaction including the events - // the particular transction emitted. This should match the order + // the particular transaction emitted. This should match the order // of the transactions delivered in the block itself repeated ExecTxResult tx_results = 2; // a list of updates to the validator set. These will reflect the validator set at current height + 2. @@ -357,7 +363,7 @@ message ResponseFinalizeBlock { bytes app_hash = 5; } -//---------------------------------------- +// ---------------------------------------- // Misc. message CommitInfo { @@ -402,8 +408,8 @@ message ExecTxResult { bytes data = 2; string log = 3; // nondeterministic string info = 4; // nondeterministic - int64 gas_wanted = 5; - int64 gas_used = 6; + int64 gas_wanted = 5 [json_name = "gas_wanted"]; + int64 gas_used = 6 [json_name = "gas_used"]; repeated Event events = 7 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; // nondeterministic string codespace = 8; @@ -419,7 +425,7 @@ message TxResult { ExecTxResult result = 4 [(gogoproto.nullable) = false]; } -//---------------------------------------- +// ---------------------------------------- // Blockchain Types message Validator { @@ -434,10 +440,10 @@ message ValidatorUpdate { } message VoteInfo { - Validator validator = 1 [(gogoproto.nullable) = false]; + Validator validator = 1 [(gogoproto.nullable) = false]; tendermint.types.BlockIDFlag block_id_flag = 3; - reserved 2; // signed_last_block + reserved 2; // signed_last_block } message ExtendedVoteInfo { @@ -450,7 +456,7 @@ message ExtendedVoteInfo { // block_id_flag indicates whether the validator voted for a block, nil, or did not vote at all tendermint.types.BlockIDFlag block_id_flag = 5; - reserved 2; // signed_last_block + reserved 2; // signed_last_block } enum MisbehaviorType { @@ -474,7 +480,7 @@ message Misbehavior { int64 total_voting_power = 5; } -//---------------------------------------- +// ---------------------------------------- // State Sync Types message Snapshot { diff --git a/proto/tendermint/blocksync/types.proto b/proto/tendermint/blocksync/types.proto index 11c39a713bb..e394fb3d675 100644 --- a/proto/tendermint/blocksync/types.proto +++ b/proto/tendermint/blocksync/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.blocksync; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/blocksync"; - import "tendermint/types/block.proto"; import "tendermint/types/types.proto"; diff --git a/proto/tendermint/consensus/types.proto b/proto/tendermint/consensus/types.proto index 542bdc19173..d2a51e2f366 100644 --- a/proto/tendermint/consensus/types.proto +++ b/proto/tendermint/consensus/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.consensus; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/consensus"; - import "gogoproto/gogo.proto"; import "tendermint/types/types.proto"; import "tendermint/libs/bits/types.proto"; @@ -60,6 +58,13 @@ message HasVote { int32 index = 4; } +// HasProposalBlockPart is sent to indicate that a particular proposal block part has been received. +message HasProposalBlockPart { + int64 height = 1; + int32 round = 2; + int32 index = 3; +} + // VoteSetMaj23 is sent to indicate that a given BlockID has seen +2/3 votes. message VoteSetMaj23 { int64 height = 1; @@ -79,14 +84,15 @@ message VoteSetBits { message Message { oneof sum { - NewRoundStep new_round_step = 1; - NewValidBlock new_valid_block = 2; - Proposal proposal = 3; - ProposalPOL proposal_pol = 4; - BlockPart block_part = 5; - Vote vote = 6; - HasVote has_vote = 7; - VoteSetMaj23 vote_set_maj23 = 8; - VoteSetBits vote_set_bits = 9; + NewRoundStep new_round_step = 1; + NewValidBlock new_valid_block = 2; + Proposal proposal = 3; + ProposalPOL proposal_pol = 4; + BlockPart block_part = 5; + Vote vote = 6; + HasVote has_vote = 7; + VoteSetMaj23 vote_set_maj23 = 8; + VoteSetBits vote_set_bits = 9; + HasProposalBlockPart has_proposal_block_part = 10; } } diff --git a/proto/tendermint/consensus/wal.proto b/proto/tendermint/consensus/wal.proto index fafcf11fa92..22531e0d0cf 100644 --- a/proto/tendermint/consensus/wal.proto +++ b/proto/tendermint/consensus/wal.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.consensus; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/consensus"; - import "gogoproto/gogo.proto"; import "tendermint/consensus/types.proto"; import "tendermint/types/events.proto"; diff --git a/proto/tendermint/crypto/keys.proto b/proto/tendermint/crypto/keys.proto index 8fa192fa4bc..b7b50da996d 100644 --- a/proto/tendermint/crypto/keys.proto +++ b/proto/tendermint/crypto/keys.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.crypto; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/crypto"; - import "gogoproto/gogo.proto"; // PublicKey defines the keys available for use with Validators diff --git a/proto/tendermint/crypto/proof.proto b/proto/tendermint/crypto/proof.proto index ae72195e868..4f342c988c0 100644 --- a/proto/tendermint/crypto/proof.proto +++ b/proto/tendermint/crypto/proof.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.crypto; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/crypto"; - import "gogoproto/gogo.proto"; message Proof { @@ -27,7 +25,7 @@ message DominoOp { } // ProofOp defines an operation used for calculating Merkle root -// The data could be arbitrary format, providing nessecary data +// The data could be arbitrary format, providing necessary data // for example neighbouring node hash message ProofOp { string type = 1; diff --git a/proto/tendermint/libs/bits/types.proto b/proto/tendermint/libs/bits/types.proto index e6afc5e8ec2..1ea81d33f80 100644 --- a/proto/tendermint/libs/bits/types.proto +++ b/proto/tendermint/libs/bits/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.libs.bits; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/libs/bits"; - message BitArray { int64 bits = 1; repeated uint64 elems = 2; diff --git a/proto/tendermint/mempool/types.proto b/proto/tendermint/mempool/types.proto index 60bafff03d1..7fa53ef79d8 100644 --- a/proto/tendermint/mempool/types.proto +++ b/proto/tendermint/mempool/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.mempool; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/mempool"; - message Txs { repeated bytes txs = 1; } diff --git a/proto/tendermint/p2p/conn.proto b/proto/tendermint/p2p/conn.proto index a7de695ac8d..62abd4f5f1e 100644 --- a/proto/tendermint/p2p/conn.proto +++ b/proto/tendermint/p2p/conn.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.p2p; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/p2p"; - import "gogoproto/gogo.proto"; import "tendermint/crypto/keys.proto"; diff --git a/proto/tendermint/p2p/pex.proto b/proto/tendermint/p2p/pex.proto index 2191866609b..397efbfb42a 100644 --- a/proto/tendermint/p2p/pex.proto +++ b/proto/tendermint/p2p/pex.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.p2p; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/p2p"; - import "tendermint/p2p/types.proto"; import "gogoproto/gogo.proto"; diff --git a/proto/tendermint/p2p/types.proto b/proto/tendermint/p2p/types.proto index 157d8ba1ca1..5b49c658393 100644 --- a/proto/tendermint/p2p/types.proto +++ b/proto/tendermint/p2p/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.p2p; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/p2p"; - import "gogoproto/gogo.proto"; message NetAddress { diff --git a/proto/tendermint/privval/types.proto b/proto/tendermint/privval/types.proto index 13190ca42fa..ddce7682046 100644 --- a/proto/tendermint/privval/types.proto +++ b/proto/tendermint/privval/types.proto @@ -5,17 +5,6 @@ import "tendermint/crypto/keys.proto"; import "tendermint/types/types.proto"; import "gogoproto/gogo.proto"; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/privval"; - -enum Errors { - ERRORS_UNKNOWN = 0; - ERRORS_UNEXPECTED_RESPONSE = 1; - ERRORS_NO_CONNECTION = 2; - ERRORS_CONNECTION_TIMEOUT = 3; - ERRORS_READ_TIMEOUT = 4; - ERRORS_WRITE_TIMEOUT = 5; -} - message RemoteSignerError { int32 code = 1; string description = 2; @@ -34,8 +23,9 @@ message PubKeyResponse { // SignVoteRequest is a request to sign a vote message SignVoteRequest { - tendermint.types.Vote vote = 1; - string chain_id = 2; + tendermint.types.Vote vote = 1; + string chain_id = 2; + bool skip_extension_signing = 3; // if true, the signer may skip signing the extension bytes. } // SignedVoteResponse is a response containing a signed vote or an error diff --git a/proto/tendermint/rpc/grpc/types.proto b/proto/tendermint/rpc/grpc/types.proto deleted file mode 100644 index b557aad8354..00000000000 --- a/proto/tendermint/rpc/grpc/types.proto +++ /dev/null @@ -1,32 +0,0 @@ -syntax = "proto3"; -package tendermint.rpc.grpc; -option go_package = "github.com/cometbft/cometbft/rpc/grpc;coregrpc"; - -import "tendermint/abci/types.proto"; - -//---------------------------------------- -// Request types - -message RequestPing {} - -message RequestBroadcastTx { - bytes tx = 1; -} - -//---------------------------------------- -// Response types - -message ResponsePing {} - -message ResponseBroadcastTx { - tendermint.abci.ResponseCheckTx check_tx = 1; - tendermint.abci.ExecTxResult tx_result = 2; -} - -//---------------------------------------- -// Service Definition - -service BroadcastAPI { - rpc Ping(RequestPing) returns (ResponsePing); - rpc BroadcastTx(RequestBroadcastTx) returns (ResponseBroadcastTx); -} diff --git a/proto/tendermint/services/block/v1/block.proto b/proto/tendermint/services/block/v1/block.proto new file mode 100644 index 00000000000..78d2c71b92f --- /dev/null +++ b/proto/tendermint/services/block/v1/block.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +package tendermint.services.block.v1; + +import "tendermint/types/block.proto"; +import "tendermint/types/types.proto"; + +message GetByHeightRequest { + // The height of the block requested. + int64 height = 1; +} + +message GetByHeightResponse { + tendermint.types.BlockID block_id = 1; + tendermint.types.Block block = 2; +} + +// GetLatestHeightRequest - empty message since no parameter is required +message GetLatestHeightRequest {} + +// GetLatestHeightResponse provides the height of the latest committed block. +message GetLatestHeightResponse { + // The height of the latest committed block. Will be 0 if no data has been + // committed yet. + int64 height = 1; +} diff --git a/proto/tendermint/services/block/v1/block_service.proto b/proto/tendermint/services/block/v1/block_service.proto new file mode 100644 index 00000000000..11bb421998a --- /dev/null +++ b/proto/tendermint/services/block/v1/block_service.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; +package tendermint.services.block.v1; + +import "tendermint/services/block/v1/block.proto"; + +// BlockService provides information about blocks +service BlockService { + // GetBlock retrieves the block information at a particular height. + rpc GetByHeight(GetByHeightRequest) returns (GetByHeightResponse); + + // GetLatestHeight returns a stream of the latest block heights committed by + // the network. This is a long-lived stream that is only terminated by the + // server if an error occurs. The caller is expected to handle such + // disconnections and automatically reconnect. + rpc GetLatestHeight(GetLatestHeightRequest) returns (stream GetLatestHeightResponse); +} diff --git a/proto/tendermint/services/block_results/v1/block_results.proto b/proto/tendermint/services/block_results/v1/block_results.proto new file mode 100644 index 00000000000..005ec7a9be4 --- /dev/null +++ b/proto/tendermint/services/block_results/v1/block_results.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; +package tendermint.services.block_results.v1; + +import "tendermint/abci/types.proto"; +import "tendermint/types/params.proto"; + +message GetBlockResultsRequest { + int64 height = 1; +} + +message GetBlockResultsResponse { + int64 height = 1; + repeated tendermint.abci.ExecTxResult txs_results = 2; + repeated tendermint.abci.Event finalize_block_events = 3; + repeated tendermint.abci.ValidatorUpdate validator_updates = 4; + tendermint.types.ConsensusParams consensus_param_updates = 5; + bytes app_hash = 6; +} diff --git a/proto/tendermint/services/block_results/v1/block_results_service.proto b/proto/tendermint/services/block_results/v1/block_results_service.proto new file mode 100644 index 00000000000..a0b7c9e1905 --- /dev/null +++ b/proto/tendermint/services/block_results/v1/block_results_service.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +package tendermint.services.block_results.v1; + +import "tendermint/services/block_results/v1/block_results.proto"; + +/* + BlockResultService provides the block results of a given or latestheight. + */ +service BlockResultsService { + // GetBlockResults returns the BlockResults of the requested height. + rpc GetBlockResults(GetBlockResultsRequest) returns (GetBlockResultsResponse); +} diff --git a/proto/tendermint/services/pruning/v1/pruning.proto b/proto/tendermint/services/pruning/v1/pruning.proto new file mode 100644 index 00000000000..16ce3ebdfc8 --- /dev/null +++ b/proto/tendermint/services/pruning/v1/pruning.proto @@ -0,0 +1,58 @@ +syntax = "proto3"; + +package tendermint.services.pruning.v1; + +message SetBlockRetainHeightRequest { + uint64 height = 1; +} + +message SetBlockRetainHeightResponse {} + +message GetBlockRetainHeightRequest {} + +message GetBlockRetainHeightResponse { + // The retain height set by the application. + uint64 app_retain_height = 1; + + // The retain height set via the pruning service (e.g. by the data + // companion) specifically for blocks. + uint64 pruning_service_retain_height = 2; +} + +message SetBlockResultsRetainHeightRequest { + uint64 height = 1; +} + +message SetBlockResultsRetainHeightResponse {} + +message GetBlockResultsRetainHeightRequest {} + +message GetBlockResultsRetainHeightResponse { + // The retain height set by the pruning service (e.g. by the data + // companion) specifically for block results. + uint64 pruning_service_retain_height = 1; +} + +message SetTxIndexerRetainHeightRequest { + uint64 height = 1; +} + +message SetTxIndexerRetainHeightResponse {} + +message GetTxIndexerRetainHeightRequest {} + +message GetTxIndexerRetainHeightResponse { + uint64 height = 1; +} + +message SetBlockIndexerRetainHeightRequest { + uint64 height = 1; +} + +message SetBlockIndexerRetainHeightResponse {} + +message GetBlockIndexerRetainHeightRequest {} + +message GetBlockIndexerRetainHeightResponse { + uint64 height = 1; +} diff --git a/proto/tendermint/services/pruning/v1/service.proto b/proto/tendermint/services/pruning/v1/service.proto new file mode 100644 index 00000000000..2f80d7b4f43 --- /dev/null +++ b/proto/tendermint/services/pruning/v1/service.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; + +package tendermint.services.pruning.v1; + +import "tendermint/services/pruning/v1/pruning.proto"; + +// PruningService provides privileged access to specialized pruning +// functionality on the CometBFT node to help control node storage. +service PruningService { + // SetBlockRetainHeightRequest indicates to the node that it can safely + // prune all block data up to the specified retain height. + // + // The lower of this retain height and that set by the application in its + // Commit response will be used by the node to determine which heights' data + // can be pruned. + rpc SetBlockRetainHeight(SetBlockRetainHeightRequest) returns (SetBlockRetainHeightResponse); + + // GetBlockRetainHeight returns information about the retain height + // parameters used by the node to influence block retention/pruning. + rpc GetBlockRetainHeight(GetBlockRetainHeightRequest) returns (GetBlockRetainHeightResponse); + + // SetBlockResultsRetainHeightRequest indicates to the node that it can + // safely prune all block results data up to the specified height. + // + // The node will always store the block results for the latest height to + // help facilitate crash recovery. + rpc SetBlockResultsRetainHeight(SetBlockResultsRetainHeightRequest) returns (SetBlockResultsRetainHeightResponse); + + // GetBlockResultsRetainHeight returns information about the retain height + // parameters used by the node to influence block results retention/pruning. + rpc GetBlockResultsRetainHeight(GetBlockResultsRetainHeightRequest) returns (GetBlockResultsRetainHeightResponse); + + // SetTxIndexerRetainHeightRequest indicates to the node that it can safely + // prune all tx indices up to the specified retain height. + rpc SetTxIndexerRetainHeight(SetTxIndexerRetainHeightRequest) returns (SetTxIndexerRetainHeightResponse); + + // GetTxIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence TxIndexer pruning + rpc GetTxIndexerRetainHeight(GetTxIndexerRetainHeightRequest) returns (GetTxIndexerRetainHeightResponse); + + // SetBlockIndexerRetainHeightRequest indicates to the node that it can safely + // prune all block indices up to the specified retain height. + rpc SetBlockIndexerRetainHeight(SetBlockIndexerRetainHeightRequest) returns (SetBlockIndexerRetainHeightResponse); + + // GetBlockIndexerRetainHeight returns information about the retain height + // parameters used by the node to influence BlockIndexer pruning + rpc GetBlockIndexerRetainHeight(GetBlockIndexerRetainHeightRequest) returns (GetBlockIndexerRetainHeightResponse); +} diff --git a/proto/tendermint/services/version/v1/version.proto b/proto/tendermint/services/version/v1/version.proto new file mode 100644 index 00000000000..0f82e556d28 --- /dev/null +++ b/proto/tendermint/services/version/v1/version.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package tendermint.services.version.v1; + +message GetVersionRequest {} + +message GetVersionResponse { + string node = 1; // The semantic version of the node software. + string abci = 2; // The version of ABCI used by the node. + uint64 p2p = 3; // The version of the P2P protocol. + uint64 block = 4; // The version of the block protocol. +} diff --git a/proto/tendermint/services/version/v1/version_service.proto b/proto/tendermint/services/version/v1/version_service.proto new file mode 100644 index 00000000000..e0757e618db --- /dev/null +++ b/proto/tendermint/services/version/v1/version_service.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package tendermint.services.version.v1; + +import "tendermint/services/version/v1/version.proto"; + +// VersionService simply provides version information about the node and the +// protocols it uses. +// +// The intention with this service is to offer a stable interface through which +// clients can access version information. This means that the version of the +// service should be kept stable at v1, with GetVersionResponse evolving only +// in non-breaking ways. +service VersionService { + // GetVersion retrieves version information about the node and the protocols + // it implements. + rpc GetVersion(GetVersionRequest) returns (GetVersionResponse); +} diff --git a/proto/tendermint/state/types.proto b/proto/tendermint/state/types.proto index c76c25fa852..57e7083b2df 100644 --- a/proto/tendermint/state/types.proto +++ b/proto/tendermint/state/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.state; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/state"; - import "gogoproto/gogo.proto"; import "tendermint/abci/types.proto"; import "tendermint/types/types.proto"; diff --git a/proto/tendermint/statesync/types.proto b/proto/tendermint/statesync/types.proto index eac36b3dec3..ffca70dc03c 100644 --- a/proto/tendermint/statesync/types.proto +++ b/proto/tendermint/statesync/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.statesync; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/statesync"; - message Message { oneof sum { SnapshotsRequest snapshots_request = 1; diff --git a/proto/tendermint/store/types.proto b/proto/tendermint/store/types.proto index b510169a4c0..36ac35276a4 100644 --- a/proto/tendermint/store/types.proto +++ b/proto/tendermint/store/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.store; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/store"; - message BlockStoreState { int64 base = 1; int64 height = 2; diff --git a/proto/tendermint/types/block.proto b/proto/tendermint/types/block.proto index d531c06a005..8a713b7dcf9 100644 --- a/proto/tendermint/types/block.proto +++ b/proto/tendermint/types/block.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.types; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/types"; - import "gogoproto/gogo.proto"; import "tendermint/types/types.proto"; import "tendermint/types/evidence.proto"; diff --git a/proto/tendermint/types/canonical.proto b/proto/tendermint/types/canonical.proto index bbff09b6605..da5b8e83949 100644 --- a/proto/tendermint/types/canonical.proto +++ b/proto/tendermint/types/canonical.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.types; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/types"; - import "gogoproto/gogo.proto"; import "tendermint/types/types.proto"; import "google/protobuf/timestamp.proto"; diff --git a/proto/tendermint/types/events.proto b/proto/tendermint/types/events.proto index 98ce811be7a..1ef71587283 100644 --- a/proto/tendermint/types/events.proto +++ b/proto/tendermint/types/events.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.types; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/types"; - message EventDataRoundState { int64 height = 1; int32 round = 2; diff --git a/proto/tendermint/types/evidence.proto b/proto/tendermint/types/evidence.proto index 1f35049bdc4..c373b1d8ff6 100644 --- a/proto/tendermint/types/evidence.proto +++ b/proto/tendermint/types/evidence.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.types; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/types"; - import "gogoproto/gogo.proto"; import "google/protobuf/timestamp.proto"; import "tendermint/types/types.proto"; diff --git a/proto/tendermint/types/params.proto b/proto/tendermint/types/params.proto index f96a2e2f572..ad25dde7184 100644 --- a/proto/tendermint/types/params.proto +++ b/proto/tendermint/types/params.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.types; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/types"; - import "gogoproto/gogo.proto"; import "google/protobuf/duration.proto"; diff --git a/proto/tendermint/types/types.proto b/proto/tendermint/types/types.proto index a527e2ffb21..344127cb443 100644 --- a/proto/tendermint/types/types.proto +++ b/proto/tendermint/types/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.types; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/types"; - import "gogoproto/gogo.proto"; import "google/protobuf/timestamp.proto"; import "tendermint/crypto/proof.proto"; @@ -14,12 +12,13 @@ enum SignedMsgType { option (gogoproto.goproto_enum_stringer) = true; option (gogoproto.goproto_enum_prefix) = false; + // Unknown SIGNED_MSG_TYPE_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "UnknownType"]; - // Votes - SIGNED_MSG_TYPE_PREVOTE = 1 [(gogoproto.enumvalue_customname) = "PrevoteType"]; + // Prevote + SIGNED_MSG_TYPE_PREVOTE = 1 [(gogoproto.enumvalue_customname) = "PrevoteType"]; + // Precommit SIGNED_MSG_TYPE_PRECOMMIT = 2 [(gogoproto.enumvalue_customname) = "PrecommitType"]; - - // Proposals + // Proposal SIGNED_MSG_TYPE_PROPOSAL = 32 [(gogoproto.enumvalue_customname) = "ProposalType"]; } diff --git a/proto/tendermint/types/validator.proto b/proto/tendermint/types/validator.proto index 7b55956fcdd..b9bd512a107 100644 --- a/proto/tendermint/types/validator.proto +++ b/proto/tendermint/types/validator.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.types; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/types"; - import "gogoproto/gogo.proto"; import "tendermint/crypto/keys.proto"; @@ -11,13 +9,16 @@ enum BlockIDFlag { option (gogoproto.goproto_enum_stringer) = true; option (gogoproto.goproto_enum_prefix) = false; - BLOCK_ID_FLAG_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "BlockIDFlagUnknown"]; // indicates an error condition - BLOCK_ID_FLAG_ABSENT = 1 [(gogoproto.enumvalue_customname) = "BlockIDFlagAbsent"]; // the vote was not received - BLOCK_ID_FLAG_COMMIT = 2 [(gogoproto.enumvalue_customname) = "BlockIDFlagCommit"]; // voted for the block that received the majority - BLOCK_ID_FLAG_NIL = 3 [(gogoproto.enumvalue_customname) = "BlockIDFlagNil"]; // voted for nil + // Indicates an error condition + BLOCK_ID_FLAG_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "BlockIDFlagUnknown"]; + // The vote was not received + BLOCK_ID_FLAG_ABSENT = 1 [(gogoproto.enumvalue_customname) = "BlockIDFlagAbsent"]; + // Voted for the block that received the majority + BLOCK_ID_FLAG_COMMIT = 2 [(gogoproto.enumvalue_customname) = "BlockIDFlagCommit"]; + // Voted for nil + BLOCK_ID_FLAG_NIL = 3 [(gogoproto.enumvalue_customname) = "BlockIDFlagNil"]; } - message ValidatorSet { repeated Validator validators = 1; Validator proposer = 2; diff --git a/proto/tendermint/version/types.proto b/proto/tendermint/version/types.proto index 3b6ef45479e..ea403ec2e84 100644 --- a/proto/tendermint/version/types.proto +++ b/proto/tendermint/version/types.proto @@ -1,8 +1,6 @@ syntax = "proto3"; package tendermint.version; -option go_package = "github.com/cometbft/cometbft/proto/tendermint/version"; - import "gogoproto/gogo.proto"; // App includes the protocol and software version for the application. diff --git a/proxy/app_conn.go b/proxy/app_conn.go index 064f32891ff..124756a28ad 100644 --- a/proxy/app_conn.go +++ b/proxy/app_conn.go @@ -7,52 +7,52 @@ import ( "github.com/go-kit/kit/metrics" abcicli "github.com/cometbft/cometbft/abci/client" - "github.com/cometbft/cometbft/abci/types" + abcitypes "github.com/cometbft/cometbft/abci/types" ) //go:generate ../scripts/mockery_generate.sh AppConnConsensus|AppConnMempool|AppConnQuery|AppConnSnapshot -//---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- // Enforce which abci msgs can be sent on a connection at the type level type AppConnConsensus interface { Error() error - InitChain(context.Context, *types.RequestInitChain) (*types.ResponseInitChain, error) - PrepareProposal(context.Context, *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) - ProcessProposal(context.Context, *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) - ExtendVote(context.Context, *types.RequestExtendVote) (*types.ResponseExtendVote, error) - VerifyVoteExtension(context.Context, *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) - FinalizeBlock(context.Context, *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) - Commit(context.Context) (*types.ResponseCommit, error) + InitChain(ctx context.Context, req *abcitypes.InitChainRequest) (*abcitypes.InitChainResponse, error) + PrepareProposal(ctx context.Context, req *abcitypes.PrepareProposalRequest) (*abcitypes.PrepareProposalResponse, error) + ProcessProposal(ctx context.Context, req *abcitypes.ProcessProposalRequest) (*abcitypes.ProcessProposalResponse, error) + ExtendVote(ctx context.Context, req *abcitypes.ExtendVoteRequest) (*abcitypes.ExtendVoteResponse, error) + VerifyVoteExtension(ctx context.Context, req *abcitypes.VerifyVoteExtensionRequest) (*abcitypes.VerifyVoteExtensionResponse, error) + FinalizeBlock(ctx context.Context, req *abcitypes.FinalizeBlockRequest) (*abcitypes.FinalizeBlockResponse, error) + Commit(ctx context.Context) (*abcitypes.CommitResponse, error) } type AppConnMempool interface { - SetResponseCallback(abcicli.Callback) + SetResponseCallback(cb abcicli.Callback) Error() error - CheckTx(context.Context, *types.RequestCheckTx) (*types.ResponseCheckTx, error) - CheckTxAsync(context.Context, *types.RequestCheckTx) (*abcicli.ReqRes, error) - Flush(context.Context) error + CheckTx(ctx context.Context, req *abcitypes.CheckTxRequest) (*abcitypes.CheckTxResponse, error) + CheckTxAsync(ctx context.Context, req *abcitypes.CheckTxRequest) (*abcicli.ReqRes, error) + Flush(ctx context.Context) error } type AppConnQuery interface { Error() error - Echo(context.Context, string) (*types.ResponseEcho, error) - Info(context.Context, *types.RequestInfo) (*types.ResponseInfo, error) - Query(context.Context, *types.RequestQuery) (*types.ResponseQuery, error) + Echo(ctx context.Context, echo string) (*abcitypes.EchoResponse, error) + Info(ctx context.Context, req *abcitypes.InfoRequest) (*abcitypes.InfoResponse, error) + Query(ctx context.Context, req *abcitypes.QueryRequest) (*abcitypes.QueryResponse, error) } type AppConnSnapshot interface { Error() error - ListSnapshots(context.Context, *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) - OfferSnapshot(context.Context, *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) - LoadSnapshotChunk(context.Context, *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) - ApplySnapshotChunk(context.Context, *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) + ListSnapshots(ctx context.Context, req *abcitypes.ListSnapshotsRequest) (*abcitypes.ListSnapshotsResponse, error) + OfferSnapshot(ctx context.Context, req *abcitypes.OfferSnapshotRequest) (*abcitypes.OfferSnapshotResponse, error) + LoadSnapshotChunk(ctx context.Context, req *abcitypes.LoadSnapshotChunkRequest) (*abcitypes.LoadSnapshotChunkResponse, error) + ApplySnapshotChunk(ctx context.Context, req *abcitypes.ApplySnapshotChunkRequest) (*abcitypes.ApplySnapshotChunkResponse, error) } -//----------------------------------------------------------------------------------------- +// ----------------------------------------------------------------------------------------- // Implements AppConnConsensus (subset of abcicli.Client) type appConnConsensus struct { @@ -73,43 +73,44 @@ func (app *appConnConsensus) Error() error { return app.appConn.Error() } -func (app *appConnConsensus) InitChain(ctx context.Context, req *types.RequestInitChain) (*types.ResponseInitChain, error) { +func (app *appConnConsensus) InitChain(ctx context.Context, req *abcitypes.InitChainRequest) (*abcitypes.InitChainResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "init_chain", "type", "sync"))() return app.appConn.InitChain(ctx, req) } func (app *appConnConsensus) PrepareProposal(ctx context.Context, - req *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { + req *abcitypes.PrepareProposalRequest, +) (*abcitypes.PrepareProposalResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "prepare_proposal", "type", "sync"))() return app.appConn.PrepareProposal(ctx, req) } -func (app *appConnConsensus) ProcessProposal(ctx context.Context, req *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { +func (app *appConnConsensus) ProcessProposal(ctx context.Context, req *abcitypes.ProcessProposalRequest) (*abcitypes.ProcessProposalResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "process_proposal", "type", "sync"))() return app.appConn.ProcessProposal(ctx, req) } -func (app *appConnConsensus) ExtendVote(ctx context.Context, req *types.RequestExtendVote) (*types.ResponseExtendVote, error) { +func (app *appConnConsensus) ExtendVote(ctx context.Context, req *abcitypes.ExtendVoteRequest) (*abcitypes.ExtendVoteResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "extend_vote", "type", "sync"))() return app.appConn.ExtendVote(ctx, req) } -func (app *appConnConsensus) VerifyVoteExtension(ctx context.Context, req *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) { +func (app *appConnConsensus) VerifyVoteExtension(ctx context.Context, req *abcitypes.VerifyVoteExtensionRequest) (*abcitypes.VerifyVoteExtensionResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "verify_vote_extension", "type", "sync"))() return app.appConn.VerifyVoteExtension(ctx, req) } -func (app *appConnConsensus) FinalizeBlock(ctx context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { +func (app *appConnConsensus) FinalizeBlock(ctx context.Context, req *abcitypes.FinalizeBlockRequest) (*abcitypes.FinalizeBlockResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "finalize_block", "type", "sync"))() return app.appConn.FinalizeBlock(ctx, req) } -func (app *appConnConsensus) Commit(ctx context.Context) (*types.ResponseCommit, error) { +func (app *appConnConsensus) Commit(ctx context.Context) (*abcitypes.CommitResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "commit", "type", "sync"))() - return app.appConn.Commit(ctx, &types.RequestCommit{}) + return app.appConn.Commit(ctx, &abcitypes.CommitRequest{}) } -//------------------------------------------------ +// ------------------------------------------------ // Implements AppConnMempool (subset of abcicli.Client) type appConnMempool struct { @@ -137,17 +138,17 @@ func (app *appConnMempool) Flush(ctx context.Context) error { return app.appConn.Flush(ctx) } -func (app *appConnMempool) CheckTx(ctx context.Context, req *types.RequestCheckTx) (*types.ResponseCheckTx, error) { +func (app *appConnMempool) CheckTx(ctx context.Context, req *abcitypes.CheckTxRequest) (*abcitypes.CheckTxResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "check_tx", "type", "sync"))() return app.appConn.CheckTx(ctx, req) } -func (app *appConnMempool) CheckTxAsync(ctx context.Context, req *types.RequestCheckTx) (*abcicli.ReqRes, error) { +func (app *appConnMempool) CheckTxAsync(ctx context.Context, req *abcitypes.CheckTxRequest) (*abcicli.ReqRes, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "check_tx", "type", "async"))() return app.appConn.CheckTxAsync(ctx, req) } -//------------------------------------------------ +// ------------------------------------------------ // Implements AppConnQuery (subset of abcicli.Client) type appConnQuery struct { @@ -166,22 +167,22 @@ func (app *appConnQuery) Error() error { return app.appConn.Error() } -func (app *appConnQuery) Echo(ctx context.Context, msg string) (*types.ResponseEcho, error) { +func (app *appConnQuery) Echo(ctx context.Context, msg string) (*abcitypes.EchoResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "echo", "type", "sync"))() return app.appConn.Echo(ctx, msg) } -func (app *appConnQuery) Info(ctx context.Context, req *types.RequestInfo) (*types.ResponseInfo, error) { +func (app *appConnQuery) Info(ctx context.Context, req *abcitypes.InfoRequest) (*abcitypes.InfoResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "info", "type", "sync"))() return app.appConn.Info(ctx, req) } -func (app *appConnQuery) Query(ctx context.Context, req *types.RequestQuery) (*types.ResponseQuery, error) { +func (app *appConnQuery) Query(ctx context.Context, req *abcitypes.QueryRequest) (*abcitypes.QueryResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "query", "type", "sync"))() return app.appConn.Query(ctx, req) } -//------------------------------------------------ +// ------------------------------------------------ // Implements AppConnSnapshot (subset of abcicli.Client) type appConnSnapshot struct { @@ -200,28 +201,28 @@ func (app *appConnSnapshot) Error() error { return app.appConn.Error() } -func (app *appConnSnapshot) ListSnapshots(ctx context.Context, req *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) { +func (app *appConnSnapshot) ListSnapshots(ctx context.Context, req *abcitypes.ListSnapshotsRequest) (*abcitypes.ListSnapshotsResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "list_snapshots", "type", "sync"))() return app.appConn.ListSnapshots(ctx, req) } -func (app *appConnSnapshot) OfferSnapshot(ctx context.Context, req *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) { +func (app *appConnSnapshot) OfferSnapshot(ctx context.Context, req *abcitypes.OfferSnapshotRequest) (*abcitypes.OfferSnapshotResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "offer_snapshot", "type", "sync"))() return app.appConn.OfferSnapshot(ctx, req) } -func (app *appConnSnapshot) LoadSnapshotChunk(ctx context.Context, req *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { +func (app *appConnSnapshot) LoadSnapshotChunk(ctx context.Context, req *abcitypes.LoadSnapshotChunkRequest) (*abcitypes.LoadSnapshotChunkResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "load_snapshot_chunk", "type", "sync"))() return app.appConn.LoadSnapshotChunk(ctx, req) } -func (app *appConnSnapshot) ApplySnapshotChunk(ctx context.Context, req *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) { +func (app *appConnSnapshot) ApplySnapshotChunk(ctx context.Context, req *abcitypes.ApplySnapshotChunkRequest) (*abcitypes.ApplySnapshotChunkResponse, error) { defer addTimeSample(app.metrics.MethodTimingSeconds.With("method", "apply_snapshot_chunk", "type", "sync"))() return app.appConn.ApplySnapshotChunk(ctx, req) } // addTimeSample returns a function that, when called, adds an observation to m. -// The observation added to m is the number of seconds ellapsed since addTimeSample +// The observation added to m is the number of seconds elapsed since addTimeSample // was initially called. addTimeSample is meant to be called in a defer to calculate // the amount of time a function takes to complete. func addTimeSample(m metrics.Histogram) func() { diff --git a/proxy/app_conn_test.go b/proxy/app_conn_test.go index cbe73d11b7c..6674afe140f 100644 --- a/proxy/app_conn_test.go +++ b/proxy/app_conn_test.go @@ -8,8 +8,8 @@ import ( "github.com/cometbft/cometbft/abci/example/kvstore" "github.com/cometbft/cometbft/abci/server" abci "github.com/cometbft/cometbft/abci/types" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/libs/log" - cmtrand "github.com/cometbft/cometbft/libs/rand" ) var SOCKET = "socket" @@ -31,7 +31,7 @@ func TestEcho(t *testing.T) { }) // Start client - cli, err := clientCreator.NewABCIClient() + cli, err := clientCreator.NewABCIMempoolClient() if err != nil { t.Fatalf("Error creating ABCI client: %v", err.Error()) } @@ -44,7 +44,10 @@ func TestEcho(t *testing.T) { t.Log("Connected") for i := 0; i < 1000; i++ { - _, err = proxy.CheckTx(context.Background(), &abci.RequestCheckTx{Tx: []byte(fmt.Sprintf("echo-%v", i))}) + _, err = proxy.CheckTx(context.Background(), &abci.CheckTxRequest{ + Tx: []byte(fmt.Sprintf("echo-%v", i)), + Type: abci.CHECK_TX_TYPE_CHECK, + }) if err != nil { t.Fatal(err) } @@ -72,7 +75,7 @@ func BenchmarkEcho(b *testing.B) { }) // Start client - cli, err := clientCreator.NewABCIClient() + cli, err := clientCreator.NewABCIMempoolClient() if err != nil { b.Fatalf("Error creating ABCI client: %v", err.Error()) } @@ -86,7 +89,10 @@ func BenchmarkEcho(b *testing.B) { b.StartTimer() // Start benchmarking tests for i := 0; i < b.N; i++ { - _, err = proxy.CheckTx(context.Background(), &abci.RequestCheckTx{Tx: []byte("hello")}) + _, err = proxy.CheckTx(context.Background(), &abci.CheckTxRequest{ + Tx: []byte("hello"), + Type: abci.CHECK_TX_TYPE_CHECK, + }) if err != nil { b.Error(err) } diff --git a/proxy/client.go b/proxy/client.go index 798a67fe7c2..d6795ca5854 100644 --- a/proxy/client.go +++ b/proxy/client.go @@ -1,24 +1,32 @@ package proxy import ( - "fmt" - abcicli "github.com/cometbft/cometbft/abci/client" "github.com/cometbft/cometbft/abci/example/kvstore" "github.com/cometbft/cometbft/abci/types" - cmtsync "github.com/cometbft/cometbft/libs/sync" + cmtsync "github.com/cometbft/cometbft/internal/sync" e2e "github.com/cometbft/cometbft/test/e2e/app" ) //go:generate ../scripts/mockery_generate.sh ClientCreator -// ClientCreator creates new ABCI clients. +// ClientCreator creates new ABCI clients based on the intended use of the client. type ClientCreator interface { - // NewABCIClient returns a new ABCI client. - NewABCIClient() (abcicli.Client, error) + // NewABCIConsensusClient creates an ABCI client for handling + // consensus-related queries. + NewABCIConsensusClient() (abcicli.Client, error) + // NewABCIMempoolClient creates an ABCI client for handling mempool-related + // queries. + NewABCIMempoolClient() (abcicli.Client, error) + // NewABCIQueryClient creates an ABCI client for handling + // query/info-related queries. + NewABCIQueryClient() (abcicli.Client, error) + // NewABCISnapshotClient creates an ABCI client for handling + // snapshot-related queries. + NewABCISnapshotClient() (abcicli.Client, error) } -//---------------------------------------------------- +// ---------------------------------------------------- // local proxy uses a mutex on an in-proc app type localClientCreator struct { @@ -30,8 +38,6 @@ type localClientCreator struct { // will be running locally. // // Maintains a single mutex over all new clients created with NewABCIClient. -// For a local client creator that uses a single mutex per new client, rather -// use [NewUnsyncLocalClientCreator]. func NewLocalClientCreator(app types.Application) ClientCreator { return &localClientCreator{ mtx: new(cmtsync.Mutex), @@ -39,33 +45,166 @@ func NewLocalClientCreator(app types.Application) ClientCreator { } } -func (l *localClientCreator) NewABCIClient() (abcicli.Client, error) { +// NewABCIConsensusClient implements ClientCreator. +func (l *localClientCreator) NewABCIConsensusClient() (abcicli.Client, error) { + return l.newABCIClient() +} + +// NewABCIMempoolClient implements ClientCreator. +func (l *localClientCreator) NewABCIMempoolClient() (abcicli.Client, error) { + return l.newABCIClient() +} + +// NewABCIQueryClient implements ClientCreator. +func (l *localClientCreator) NewABCIQueryClient() (abcicli.Client, error) { + return l.newABCIClient() +} + +// NewABCISnapshotClient implements ClientCreator. +func (l *localClientCreator) NewABCISnapshotClient() (abcicli.Client, error) { + return l.newABCIClient() +} + +func (l *localClientCreator) newABCIClient() (abcicli.Client, error) { return abcicli.NewLocalClient(l.mtx, l.app), nil } -//---------------------------------------------------- -// local proxy creates a new mutex for each client +// ------------------------------------------------------------------------- +// connection-synchronized local client uses a mutex per "connection" on an +// in-process app + +type connSyncLocalClientCreator struct { + app types.Application +} + +// NewConnSyncLocalClientCreator returns a local [ClientCreator] for the given +// app. +// +// Unlike [NewLocalClientCreator], this is a "connection-synchronized" local +// client creator, meaning each call to NewABCIClient returns an ABCI client +// that maintains its own mutex over the application (i.e. it is +// per-"connection" synchronized). +func NewConnSyncLocalClientCreator(app types.Application) ClientCreator { + return &connSyncLocalClientCreator{ + app: app, + } +} + +// NewABCIConsensusClient implements ClientCreator. +func (c *connSyncLocalClientCreator) NewABCIConsensusClient() (abcicli.Client, error) { + return c.newABCIClient() +} + +// NewABCIMempoolClient implements ClientCreator. +func (c *connSyncLocalClientCreator) NewABCIMempoolClient() (abcicli.Client, error) { + return c.newABCIClient() +} + +// NewABCIQueryClient implements ClientCreator. +func (c *connSyncLocalClientCreator) NewABCIQueryClient() (abcicli.Client, error) { + return c.newABCIClient() +} + +// NewABCISnapshotClient implements ClientCreator. +func (c *connSyncLocalClientCreator) NewABCISnapshotClient() (abcicli.Client, error) { + return c.newABCIClient() +} + +func (c *connSyncLocalClientCreator) newABCIClient() (abcicli.Client, error) { + return abcicli.NewLocalClient(nil, c.app), nil +} + +// ----------------------------------------------------------------------------- +// advanced local client creator with a more complex concurrency model than the +// other local client creators + +type consensusSyncLocalClientCreator struct { + app types.Application +} + +// NewConsensusSyncLocalClientCreator returns a [ClientCreator] with a more +// advanced concurrency model than that provided by [NewLocalClientCreator] or +// [NewConnSyncLocalClientCreator]. +// +// In this model (a "consensus-synchronized" model), only the consensus client +// has a mutex over it to serialize consensus interactions. With all other +// clients (mempool, query, snapshot), enforcing synchronization is left up to +// the app. +func NewConsensusSyncLocalClientCreator(app types.Application) ClientCreator { + return &consensusSyncLocalClientCreator{ + app: app, + } +} + +// NewABCIConsensusClient implements ClientCreator. +func (c *consensusSyncLocalClientCreator) NewABCIConsensusClient() (abcicli.Client, error) { + // A mutex is created by the local client and applied across all + // consensus-related calls. + return abcicli.NewLocalClient(nil, c.app), nil +} + +// NewABCIMempoolClient implements ClientCreator. +func (c *consensusSyncLocalClientCreator) NewABCIMempoolClient() (abcicli.Client, error) { + // It is up to the ABCI app to manage its concurrency when handling + // mempool-related calls. + return abcicli.NewUnsyncLocalClient(c.app), nil +} + +// NewABCIQueryClient implements ClientCreator. +func (c *consensusSyncLocalClientCreator) NewABCIQueryClient() (abcicli.Client, error) { + // It is up to the ABCI app to manage its concurrency when handling + // query-related calls. + return abcicli.NewUnsyncLocalClient(c.app), nil +} + +// NewABCISnapshotClient implements ClientCreator. +func (c *consensusSyncLocalClientCreator) NewABCISnapshotClient() (abcicli.Client, error) { + // It is up to the ABCI app to manage its concurrency when handling + // snapshot-related calls. + return abcicli.NewUnsyncLocalClient(c.app), nil +} + +// ----------------------------------------------------------------------------- +// most advanced local client creator with a more complex concurrency model +// than the other local client creators - all concurrency is assumed to be +// handled by the application type unsyncLocalClientCreator struct { app types.Application } -// NewUnsyncLocalClientCreator returns a [ClientCreator] for the given app. -// Unlike [NewLocalClientCreator], each call to NewABCIClient returns an ABCI -// client that maintains its own mutex over the application. +// NewUnsyncLocalClientCreator returns a [ClientCreator] that is fully +// unsynchronized, meaning that all synchronization must be handled by the +// application. This is an advanced type of client creator, and requires +// special care on the application side to ensure that consensus concurrency is +// not violated. func NewUnsyncLocalClientCreator(app types.Application) ClientCreator { return &unsyncLocalClientCreator{ app: app, } } -func (c *unsyncLocalClientCreator) NewABCIClient() (abcicli.Client, error) { - // Specifying nil for the mutex causes each instance to create its own - // mutex. - return abcicli.NewLocalClient(nil, c.app), nil +// NewABCIConsensusClient implements ClientCreator. +func (c *unsyncLocalClientCreator) NewABCIConsensusClient() (abcicli.Client, error) { + return abcicli.NewUnsyncLocalClient(c.app), nil +} + +// NewABCIMempoolClient implements ClientCreator. +func (c *unsyncLocalClientCreator) NewABCIMempoolClient() (abcicli.Client, error) { + return abcicli.NewUnsyncLocalClient(c.app), nil } -//--------------------------------------------------------------- +// NewABCIQueryClient implements ClientCreator. +func (c *unsyncLocalClientCreator) NewABCIQueryClient() (abcicli.Client, error) { + return abcicli.NewUnsyncLocalClient(c.app), nil +} + +// NewABCISnapshotClient implements ClientCreator. +func (c *unsyncLocalClientCreator) NewABCISnapshotClient() (abcicli.Client, error) { + return abcicli.NewUnsyncLocalClient(c.app), nil +} + +// --------------------------------------------------------------- // remote proxy opens new connections to an external app process type remoteClientCreator struct { @@ -85,10 +224,30 @@ func NewRemoteClientCreator(addr, transport string, mustConnect bool) ClientCrea } } -func (r *remoteClientCreator) NewABCIClient() (abcicli.Client, error) { +// NewABCIConsensusClient implements ClientCreator. +func (r *remoteClientCreator) NewABCIConsensusClient() (abcicli.Client, error) { + return r.newABCIClient() +} + +// NewABCIMempoolClient implements ClientCreator. +func (r *remoteClientCreator) NewABCIMempoolClient() (abcicli.Client, error) { + return r.newABCIClient() +} + +// NewABCIQueryClient implements ClientCreator. +func (r *remoteClientCreator) NewABCIQueryClient() (abcicli.Client, error) { + return r.newABCIClient() +} + +// NewABCISnapshotClient implements ClientCreator. +func (r *remoteClientCreator) NewABCISnapshotClient() (abcicli.Client, error) { + return r.newABCIClient() +} + +func (r *remoteClientCreator) newABCIClient() (abcicli.Client, error) { remoteApp, err := abcicli.NewClient(r.addr, r.transport, r.mustConnect) if err != nil { - return nil, fmt.Errorf("failed to connect to proxy: %w", err) + return nil, ErrUnreachableProxy{Err: err} } return remoteApp, nil @@ -101,16 +260,20 @@ func (r *remoteClientCreator) NewABCIClient() (abcicli.Client, error) { // Otherwise a remote client will be created. // // Each of "kvstore", "persistent_kvstore" and "e2e" also currently have an -// "_unsync" variant (i.e. "kvstore_unsync", etc.), which attempts to replicate -// the same concurrency model as the remote client. +// "_connsync" variant (i.e. "kvstore_connsync", etc.), which attempts to +// replicate the same concurrency model as the remote client. func DefaultClientCreator(addr, transport, dbDir string) ClientCreator { switch addr { case "kvstore": return NewLocalClientCreator(kvstore.NewInMemoryApplication()) + case "kvstore_connsync": + return NewConnSyncLocalClientCreator(kvstore.NewInMemoryApplication()) case "kvstore_unsync": return NewUnsyncLocalClientCreator(kvstore.NewInMemoryApplication()) case "persistent_kvstore": return NewLocalClientCreator(kvstore.NewPersistentApplication(dbDir)) + case "persistent_kvstore_connsync": + return NewConnSyncLocalClientCreator(kvstore.NewPersistentApplication(dbDir)) case "persistent_kvstore_unsync": return NewUnsyncLocalClientCreator(kvstore.NewPersistentApplication(dbDir)) case "e2e": @@ -119,6 +282,12 @@ func DefaultClientCreator(addr, transport, dbDir string) ClientCreator { panic(err) } return NewLocalClientCreator(app) + case "e2e_connsync": + app, err := e2e.NewApplication(e2e.DefaultConfig(dbDir)) + if err != nil { + panic(err) + } + return NewConnSyncLocalClientCreator(app) case "e2e_unsync": app, err := e2e.NewApplication(e2e.DefaultConfig(dbDir)) if err != nil { diff --git a/proxy/errors.go b/proxy/errors.go new file mode 100644 index 00000000000..85e5da85b0d --- /dev/null +++ b/proxy/errors.go @@ -0,0 +1,43 @@ +package proxy + +import ( + "fmt" +) + +type ErrUnreachableProxy struct { + Err error +} + +func (e ErrUnreachableProxy) Error() string { + return fmt.Sprintf("failed to connect to proxy: %v", e.Err) +} + +func (e ErrUnreachableProxy) Unwrap() error { + return e.Err +} + +type ErrABCIClientCreate struct { + ClientName string + Err error +} + +func (e ErrABCIClientCreate) Error() string { + return fmt.Sprintf("error creating ABCI client (%s client): %v", e.ClientName, e.Err) +} + +func (e ErrABCIClientCreate) Unwrap() error { + return e.Err +} + +type ErrABCIClientStart struct { + CliType string + Err error +} + +func (e ErrABCIClientStart) Error() string { + return fmt.Sprintf("error starting ABCI client (%s client): %v", e.CliType, e.Err) +} + +func (e ErrABCIClientStart) Unwrap() error { + return e.Err +} diff --git a/proxy/mocks/app_conn_consensus.go b/proxy/mocks/app_conn_consensus.go index 7dee0b1c5ce..2ae515c9bab 100644 --- a/proxy/mocks/app_conn_consensus.go +++ b/proxy/mocks/app_conn_consensus.go @@ -7,7 +7,7 @@ import ( mock "github.com/stretchr/testify/mock" - types "github.com/cometbft/cometbft/abci/types" + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" ) // AppConnConsensus is an autogenerated mock type for the AppConnConsensus type @@ -15,25 +15,29 @@ type AppConnConsensus struct { mock.Mock } -// Commit provides a mock function with given fields: _a0 -func (_m *AppConnConsensus) Commit(_a0 context.Context) (*types.ResponseCommit, error) { - ret := _m.Called(_a0) +// Commit provides a mock function with given fields: ctx +func (_m *AppConnConsensus) Commit(ctx context.Context) (*v1.CommitResponse, error) { + ret := _m.Called(ctx) - var r0 *types.ResponseCommit + if len(ret) == 0 { + panic("no return value specified for Commit") + } + + var r0 *v1.CommitResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*types.ResponseCommit, error)); ok { - return rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context) (*v1.CommitResponse, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func(context.Context) *types.ResponseCommit); ok { - r0 = rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context) *v1.CommitResponse); ok { + r0 = rf(ctx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseCommit) + r0 = ret.Get(0).(*v1.CommitResponse) } } if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(_a0) + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -45,6 +49,10 @@ func (_m *AppConnConsensus) Commit(_a0 context.Context) (*types.ResponseCommit, func (_m *AppConnConsensus) Error() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Error") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -55,25 +63,29 @@ func (_m *AppConnConsensus) Error() error { return r0 } -// ExtendVote provides a mock function with given fields: _a0, _a1 -func (_m *AppConnConsensus) ExtendVote(_a0 context.Context, _a1 *types.RequestExtendVote) (*types.ResponseExtendVote, error) { - ret := _m.Called(_a0, _a1) +// ExtendVote provides a mock function with given fields: ctx, req +func (_m *AppConnConsensus) ExtendVote(ctx context.Context, req *v1.ExtendVoteRequest) (*v1.ExtendVoteResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for ExtendVote") + } - var r0 *types.ResponseExtendVote + var r0 *v1.ExtendVoteResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestExtendVote) (*types.ResponseExtendVote, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExtendVoteRequest) (*v1.ExtendVoteResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestExtendVote) *types.ResponseExtendVote); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ExtendVoteRequest) *v1.ExtendVoteResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseExtendVote) + r0 = ret.Get(0).(*v1.ExtendVoteResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestExtendVote) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ExtendVoteRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -81,25 +93,29 @@ func (_m *AppConnConsensus) ExtendVote(_a0 context.Context, _a1 *types.RequestEx return r0, r1 } -// FinalizeBlock provides a mock function with given fields: _a0, _a1 -func (_m *AppConnConsensus) FinalizeBlock(_a0 context.Context, _a1 *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { - ret := _m.Called(_a0, _a1) +// FinalizeBlock provides a mock function with given fields: ctx, req +func (_m *AppConnConsensus) FinalizeBlock(ctx context.Context, req *v1.FinalizeBlockRequest) (*v1.FinalizeBlockResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for FinalizeBlock") + } - var r0 *types.ResponseFinalizeBlock + var r0 *v1.FinalizeBlockResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.FinalizeBlockRequest) (*v1.FinalizeBlockResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestFinalizeBlock) *types.ResponseFinalizeBlock); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.FinalizeBlockRequest) *v1.FinalizeBlockResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseFinalizeBlock) + r0 = ret.Get(0).(*v1.FinalizeBlockResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestFinalizeBlock) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.FinalizeBlockRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -107,25 +123,29 @@ func (_m *AppConnConsensus) FinalizeBlock(_a0 context.Context, _a1 *types.Reques return r0, r1 } -// InitChain provides a mock function with given fields: _a0, _a1 -func (_m *AppConnConsensus) InitChain(_a0 context.Context, _a1 *types.RequestInitChain) (*types.ResponseInitChain, error) { - ret := _m.Called(_a0, _a1) +// InitChain provides a mock function with given fields: ctx, req +func (_m *AppConnConsensus) InitChain(ctx context.Context, req *v1.InitChainRequest) (*v1.InitChainResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for InitChain") + } - var r0 *types.ResponseInitChain + var r0 *v1.InitChainResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInitChain) (*types.ResponseInitChain, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InitChainRequest) (*v1.InitChainResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInitChain) *types.ResponseInitChain); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InitChainRequest) *v1.InitChainResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseInitChain) + r0 = ret.Get(0).(*v1.InitChainResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestInitChain) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.InitChainRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -133,25 +153,29 @@ func (_m *AppConnConsensus) InitChain(_a0 context.Context, _a1 *types.RequestIni return r0, r1 } -// PrepareProposal provides a mock function with given fields: _a0, _a1 -func (_m *AppConnConsensus) PrepareProposal(_a0 context.Context, _a1 *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) { - ret := _m.Called(_a0, _a1) +// PrepareProposal provides a mock function with given fields: ctx, req +func (_m *AppConnConsensus) PrepareProposal(ctx context.Context, req *v1.PrepareProposalRequest) (*v1.PrepareProposalResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponsePrepareProposal + if len(ret) == 0 { + panic("no return value specified for PrepareProposal") + } + + var r0 *v1.PrepareProposalResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.PrepareProposalRequest) (*v1.PrepareProposalResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestPrepareProposal) *types.ResponsePrepareProposal); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.PrepareProposalRequest) *v1.PrepareProposalResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponsePrepareProposal) + r0 = ret.Get(0).(*v1.PrepareProposalResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestPrepareProposal) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.PrepareProposalRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -159,25 +183,29 @@ func (_m *AppConnConsensus) PrepareProposal(_a0 context.Context, _a1 *types.Requ return r0, r1 } -// ProcessProposal provides a mock function with given fields: _a0, _a1 -func (_m *AppConnConsensus) ProcessProposal(_a0 context.Context, _a1 *types.RequestProcessProposal) (*types.ResponseProcessProposal, error) { - ret := _m.Called(_a0, _a1) +// ProcessProposal provides a mock function with given fields: ctx, req +func (_m *AppConnConsensus) ProcessProposal(ctx context.Context, req *v1.ProcessProposalRequest) (*v1.ProcessProposalResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseProcessProposal + if len(ret) == 0 { + panic("no return value specified for ProcessProposal") + } + + var r0 *v1.ProcessProposalResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestProcessProposal) (*types.ResponseProcessProposal, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ProcessProposalRequest) (*v1.ProcessProposalResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestProcessProposal) *types.ResponseProcessProposal); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ProcessProposalRequest) *v1.ProcessProposalResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseProcessProposal) + r0 = ret.Get(0).(*v1.ProcessProposalResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestProcessProposal) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ProcessProposalRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -185,25 +213,29 @@ func (_m *AppConnConsensus) ProcessProposal(_a0 context.Context, _a1 *types.Requ return r0, r1 } -// VerifyVoteExtension provides a mock function with given fields: _a0, _a1 -func (_m *AppConnConsensus) VerifyVoteExtension(_a0 context.Context, _a1 *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error) { - ret := _m.Called(_a0, _a1) +// VerifyVoteExtension provides a mock function with given fields: ctx, req +func (_m *AppConnConsensus) VerifyVoteExtension(ctx context.Context, req *v1.VerifyVoteExtensionRequest) (*v1.VerifyVoteExtensionResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for VerifyVoteExtension") + } - var r0 *types.ResponseVerifyVoteExtension + var r0 *v1.VerifyVoteExtensionResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestVerifyVoteExtension) (*types.ResponseVerifyVoteExtension, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.VerifyVoteExtensionRequest) (*v1.VerifyVoteExtensionResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestVerifyVoteExtension) *types.ResponseVerifyVoteExtension); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.VerifyVoteExtensionRequest) *v1.VerifyVoteExtensionResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseVerifyVoteExtension) + r0 = ret.Get(0).(*v1.VerifyVoteExtensionResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestVerifyVoteExtension) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.VerifyVoteExtensionRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -211,13 +243,12 @@ func (_m *AppConnConsensus) VerifyVoteExtension(_a0 context.Context, _a1 *types. return r0, r1 } -type mockConstructorTestingTNewAppConnConsensus interface { +// NewAppConnConsensus creates a new instance of AppConnConsensus. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAppConnConsensus(t interface { mock.TestingT Cleanup(func()) -} - -// NewAppConnConsensus creates a new instance of AppConnConsensus. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAppConnConsensus(t mockConstructorTestingTNewAppConnConsensus) *AppConnConsensus { +}) *AppConnConsensus { mock := &AppConnConsensus{} mock.Mock.Test(t) diff --git a/proxy/mocks/app_conn_mempool.go b/proxy/mocks/app_conn_mempool.go index 281ff21c9f9..224cfd296bb 100644 --- a/proxy/mocks/app_conn_mempool.go +++ b/proxy/mocks/app_conn_mempool.go @@ -9,7 +9,7 @@ import ( mock "github.com/stretchr/testify/mock" - types "github.com/cometbft/cometbft/abci/types" + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" ) // AppConnMempool is an autogenerated mock type for the AppConnMempool type @@ -17,25 +17,29 @@ type AppConnMempool struct { mock.Mock } -// CheckTx provides a mock function with given fields: _a0, _a1 -func (_m *AppConnMempool) CheckTx(_a0 context.Context, _a1 *types.RequestCheckTx) (*types.ResponseCheckTx, error) { - ret := _m.Called(_a0, _a1) +// CheckTx provides a mock function with given fields: ctx, req +func (_m *AppConnMempool) CheckTx(ctx context.Context, req *v1.CheckTxRequest) (*v1.CheckTxResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseCheckTx + if len(ret) == 0 { + panic("no return value specified for CheckTx") + } + + var r0 *v1.CheckTxResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) (*types.ResponseCheckTx, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) (*v1.CheckTxResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) *types.ResponseCheckTx); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) *v1.CheckTxResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseCheckTx) + r0 = ret.Get(0).(*v1.CheckTxResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestCheckTx) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.CheckTxRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -43,25 +47,29 @@ func (_m *AppConnMempool) CheckTx(_a0 context.Context, _a1 *types.RequestCheckTx return r0, r1 } -// CheckTxAsync provides a mock function with given fields: _a0, _a1 -func (_m *AppConnMempool) CheckTxAsync(_a0 context.Context, _a1 *types.RequestCheckTx) (*abcicli.ReqRes, error) { - ret := _m.Called(_a0, _a1) +// CheckTxAsync provides a mock function with given fields: ctx, req +func (_m *AppConnMempool) CheckTxAsync(ctx context.Context, req *v1.CheckTxRequest) (*abcicli.ReqRes, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for CheckTxAsync") + } var r0 *abcicli.ReqRes var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) (*abcicli.ReqRes, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) (*abcicli.ReqRes, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestCheckTx) *abcicli.ReqRes); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.CheckTxRequest) *abcicli.ReqRes); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*abcicli.ReqRes) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestCheckTx) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.CheckTxRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -73,6 +81,10 @@ func (_m *AppConnMempool) CheckTxAsync(_a0 context.Context, _a1 *types.RequestCh func (_m *AppConnMempool) Error() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Error") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -83,13 +95,17 @@ func (_m *AppConnMempool) Error() error { return r0 } -// Flush provides a mock function with given fields: _a0 -func (_m *AppConnMempool) Flush(_a0 context.Context) error { - ret := _m.Called(_a0) +// Flush provides a mock function with given fields: ctx +func (_m *AppConnMempool) Flush(ctx context.Context) error { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for Flush") + } var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -97,18 +113,17 @@ func (_m *AppConnMempool) Flush(_a0 context.Context) error { return r0 } -// SetResponseCallback provides a mock function with given fields: _a0 -func (_m *AppConnMempool) SetResponseCallback(_a0 abcicli.Callback) { - _m.Called(_a0) +// SetResponseCallback provides a mock function with given fields: cb +func (_m *AppConnMempool) SetResponseCallback(cb abcicli.Callback) { + _m.Called(cb) } -type mockConstructorTestingTNewAppConnMempool interface { +// NewAppConnMempool creates a new instance of AppConnMempool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAppConnMempool(t interface { mock.TestingT Cleanup(func()) -} - -// NewAppConnMempool creates a new instance of AppConnMempool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAppConnMempool(t mockConstructorTestingTNewAppConnMempool) *AppConnMempool { +}) *AppConnMempool { mock := &AppConnMempool{} mock.Mock.Test(t) diff --git a/proxy/mocks/app_conn_query.go b/proxy/mocks/app_conn_query.go index b10838ac01e..fdc2a50920a 100644 --- a/proxy/mocks/app_conn_query.go +++ b/proxy/mocks/app_conn_query.go @@ -7,7 +7,7 @@ import ( mock "github.com/stretchr/testify/mock" - types "github.com/cometbft/cometbft/abci/types" + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" ) // AppConnQuery is an autogenerated mock type for the AppConnQuery type @@ -15,25 +15,29 @@ type AppConnQuery struct { mock.Mock } -// Echo provides a mock function with given fields: _a0, _a1 -func (_m *AppConnQuery) Echo(_a0 context.Context, _a1 string) (*types.ResponseEcho, error) { - ret := _m.Called(_a0, _a1) +// Echo provides a mock function with given fields: ctx, echo +func (_m *AppConnQuery) Echo(ctx context.Context, echo string) (*v1.EchoResponse, error) { + ret := _m.Called(ctx, echo) - var r0 *types.ResponseEcho + if len(ret) == 0 { + panic("no return value specified for Echo") + } + + var r0 *v1.EchoResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (*types.ResponseEcho, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, string) (*v1.EchoResponse, error)); ok { + return rf(ctx, echo) } - if rf, ok := ret.Get(0).(func(context.Context, string) *types.ResponseEcho); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, string) *v1.EchoResponse); ok { + r0 = rf(ctx, echo) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseEcho) + r0 = ret.Get(0).(*v1.EchoResponse) } } if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(_a0, _a1) + r1 = rf(ctx, echo) } else { r1 = ret.Error(1) } @@ -45,6 +49,10 @@ func (_m *AppConnQuery) Echo(_a0 context.Context, _a1 string) (*types.ResponseEc func (_m *AppConnQuery) Error() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Error") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -55,25 +63,29 @@ func (_m *AppConnQuery) Error() error { return r0 } -// Info provides a mock function with given fields: _a0, _a1 -func (_m *AppConnQuery) Info(_a0 context.Context, _a1 *types.RequestInfo) (*types.ResponseInfo, error) { - ret := _m.Called(_a0, _a1) +// Info provides a mock function with given fields: ctx, req +func (_m *AppConnQuery) Info(ctx context.Context, req *v1.InfoRequest) (*v1.InfoResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for Info") + } - var r0 *types.ResponseInfo + var r0 *v1.InfoResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInfo) (*types.ResponseInfo, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InfoRequest) (*v1.InfoResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestInfo) *types.ResponseInfo); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.InfoRequest) *v1.InfoResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseInfo) + r0 = ret.Get(0).(*v1.InfoResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestInfo) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.InfoRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -81,25 +93,29 @@ func (_m *AppConnQuery) Info(_a0 context.Context, _a1 *types.RequestInfo) (*type return r0, r1 } -// Query provides a mock function with given fields: _a0, _a1 -func (_m *AppConnQuery) Query(_a0 context.Context, _a1 *types.RequestQuery) (*types.ResponseQuery, error) { - ret := _m.Called(_a0, _a1) +// Query provides a mock function with given fields: ctx, req +func (_m *AppConnQuery) Query(ctx context.Context, req *v1.QueryRequest) (*v1.QueryResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseQuery + if len(ret) == 0 { + panic("no return value specified for Query") + } + + var r0 *v1.QueryResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestQuery) (*types.ResponseQuery, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.QueryRequest) (*v1.QueryResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestQuery) *types.ResponseQuery); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.QueryRequest) *v1.QueryResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseQuery) + r0 = ret.Get(0).(*v1.QueryResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestQuery) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.QueryRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -107,13 +123,12 @@ func (_m *AppConnQuery) Query(_a0 context.Context, _a1 *types.RequestQuery) (*ty return r0, r1 } -type mockConstructorTestingTNewAppConnQuery interface { +// NewAppConnQuery creates a new instance of AppConnQuery. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAppConnQuery(t interface { mock.TestingT Cleanup(func()) -} - -// NewAppConnQuery creates a new instance of AppConnQuery. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAppConnQuery(t mockConstructorTestingTNewAppConnQuery) *AppConnQuery { +}) *AppConnQuery { mock := &AppConnQuery{} mock.Mock.Test(t) diff --git a/proxy/mocks/app_conn_snapshot.go b/proxy/mocks/app_conn_snapshot.go index cb313d522d5..75094e34b26 100644 --- a/proxy/mocks/app_conn_snapshot.go +++ b/proxy/mocks/app_conn_snapshot.go @@ -7,7 +7,7 @@ import ( mock "github.com/stretchr/testify/mock" - types "github.com/cometbft/cometbft/abci/types" + v1 "github.com/cometbft/cometbft/api/cometbft/abci/v1" ) // AppConnSnapshot is an autogenerated mock type for the AppConnSnapshot type @@ -15,25 +15,29 @@ type AppConnSnapshot struct { mock.Mock } -// ApplySnapshotChunk provides a mock function with given fields: _a0, _a1 -func (_m *AppConnSnapshot) ApplySnapshotChunk(_a0 context.Context, _a1 *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) { - ret := _m.Called(_a0, _a1) +// ApplySnapshotChunk provides a mock function with given fields: ctx, req +func (_m *AppConnSnapshot) ApplySnapshotChunk(ctx context.Context, req *v1.ApplySnapshotChunkRequest) (*v1.ApplySnapshotChunkResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseApplySnapshotChunk + if len(ret) == 0 { + panic("no return value specified for ApplySnapshotChunk") + } + + var r0 *v1.ApplySnapshotChunkResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ApplySnapshotChunkRequest) (*v1.ApplySnapshotChunkResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestApplySnapshotChunk) *types.ResponseApplySnapshotChunk); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ApplySnapshotChunkRequest) *v1.ApplySnapshotChunkResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseApplySnapshotChunk) + r0 = ret.Get(0).(*v1.ApplySnapshotChunkResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestApplySnapshotChunk) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ApplySnapshotChunkRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -45,6 +49,10 @@ func (_m *AppConnSnapshot) ApplySnapshotChunk(_a0 context.Context, _a1 *types.Re func (_m *AppConnSnapshot) Error() error { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Error") + } + var r0 error if rf, ok := ret.Get(0).(func() error); ok { r0 = rf() @@ -55,25 +63,29 @@ func (_m *AppConnSnapshot) Error() error { return r0 } -// ListSnapshots provides a mock function with given fields: _a0, _a1 -func (_m *AppConnSnapshot) ListSnapshots(_a0 context.Context, _a1 *types.RequestListSnapshots) (*types.ResponseListSnapshots, error) { - ret := _m.Called(_a0, _a1) +// ListSnapshots provides a mock function with given fields: ctx, req +func (_m *AppConnSnapshot) ListSnapshots(ctx context.Context, req *v1.ListSnapshotsRequest) (*v1.ListSnapshotsResponse, error) { + ret := _m.Called(ctx, req) - var r0 *types.ResponseListSnapshots + if len(ret) == 0 { + panic("no return value specified for ListSnapshots") + } + + var r0 *v1.ListSnapshotsResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestListSnapshots) (*types.ResponseListSnapshots, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ListSnapshotsRequest) (*v1.ListSnapshotsResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestListSnapshots) *types.ResponseListSnapshots); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.ListSnapshotsRequest) *v1.ListSnapshotsResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseListSnapshots) + r0 = ret.Get(0).(*v1.ListSnapshotsResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestListSnapshots) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.ListSnapshotsRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -81,25 +93,29 @@ func (_m *AppConnSnapshot) ListSnapshots(_a0 context.Context, _a1 *types.Request return r0, r1 } -// LoadSnapshotChunk provides a mock function with given fields: _a0, _a1 -func (_m *AppConnSnapshot) LoadSnapshotChunk(_a0 context.Context, _a1 *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) { - ret := _m.Called(_a0, _a1) +// LoadSnapshotChunk provides a mock function with given fields: ctx, req +func (_m *AppConnSnapshot) LoadSnapshotChunk(ctx context.Context, req *v1.LoadSnapshotChunkRequest) (*v1.LoadSnapshotChunkResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for LoadSnapshotChunk") + } - var r0 *types.ResponseLoadSnapshotChunk + var r0 *v1.LoadSnapshotChunkResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.LoadSnapshotChunkRequest) (*v1.LoadSnapshotChunkResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestLoadSnapshotChunk) *types.ResponseLoadSnapshotChunk); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.LoadSnapshotChunkRequest) *v1.LoadSnapshotChunkResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseLoadSnapshotChunk) + r0 = ret.Get(0).(*v1.LoadSnapshotChunkResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestLoadSnapshotChunk) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.LoadSnapshotChunkRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -107,25 +123,29 @@ func (_m *AppConnSnapshot) LoadSnapshotChunk(_a0 context.Context, _a1 *types.Req return r0, r1 } -// OfferSnapshot provides a mock function with given fields: _a0, _a1 -func (_m *AppConnSnapshot) OfferSnapshot(_a0 context.Context, _a1 *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error) { - ret := _m.Called(_a0, _a1) +// OfferSnapshot provides a mock function with given fields: ctx, req +func (_m *AppConnSnapshot) OfferSnapshot(ctx context.Context, req *v1.OfferSnapshotRequest) (*v1.OfferSnapshotResponse, error) { + ret := _m.Called(ctx, req) + + if len(ret) == 0 { + panic("no return value specified for OfferSnapshot") + } - var r0 *types.ResponseOfferSnapshot + var r0 *v1.OfferSnapshotResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error)); ok { - return rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.OfferSnapshotRequest) (*v1.OfferSnapshotResponse, error)); ok { + return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *types.RequestOfferSnapshot) *types.ResponseOfferSnapshot); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(context.Context, *v1.OfferSnapshotRequest) *v1.OfferSnapshotResponse); ok { + r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ResponseOfferSnapshot) + r0 = ret.Get(0).(*v1.OfferSnapshotResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *types.RequestOfferSnapshot) error); ok { - r1 = rf(_a0, _a1) + if rf, ok := ret.Get(1).(func(context.Context, *v1.OfferSnapshotRequest) error); ok { + r1 = rf(ctx, req) } else { r1 = ret.Error(1) } @@ -133,13 +153,12 @@ func (_m *AppConnSnapshot) OfferSnapshot(_a0 context.Context, _a1 *types.Request return r0, r1 } -type mockConstructorTestingTNewAppConnSnapshot interface { +// NewAppConnSnapshot creates a new instance of AppConnSnapshot. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAppConnSnapshot(t interface { mock.TestingT Cleanup(func()) -} - -// NewAppConnSnapshot creates a new instance of AppConnSnapshot. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAppConnSnapshot(t mockConstructorTestingTNewAppConnSnapshot) *AppConnSnapshot { +}) *AppConnSnapshot { mock := &AppConnSnapshot{} mock.Mock.Test(t) diff --git a/proxy/mocks/client_creator.go b/proxy/mocks/client_creator.go index 798afe88fb2..bc9f7eac86e 100644 --- a/proxy/mocks/client_creator.go +++ b/proxy/mocks/client_creator.go @@ -12,10 +12,14 @@ type ClientCreator struct { mock.Mock } -// NewABCIClient provides a mock function with given fields: -func (_m *ClientCreator) NewABCIClient() (abcicli.Client, error) { +// NewABCIConsensusClient provides a mock function with given fields: +func (_m *ClientCreator) NewABCIConsensusClient() (abcicli.Client, error) { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for NewABCIConsensusClient") + } + var r0 abcicli.Client var r1 error if rf, ok := ret.Get(0).(func() (abcicli.Client, error)); ok { @@ -38,13 +42,102 @@ func (_m *ClientCreator) NewABCIClient() (abcicli.Client, error) { return r0, r1 } -type mockConstructorTestingTNewClientCreator interface { - mock.TestingT - Cleanup(func()) +// NewABCIMempoolClient provides a mock function with given fields: +func (_m *ClientCreator) NewABCIMempoolClient() (abcicli.Client, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for NewABCIMempoolClient") + } + + var r0 abcicli.Client + var r1 error + if rf, ok := ret.Get(0).(func() (abcicli.Client, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() abcicli.Client); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(abcicli.Client) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewABCIQueryClient provides a mock function with given fields: +func (_m *ClientCreator) NewABCIQueryClient() (abcicli.Client, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for NewABCIQueryClient") + } + + var r0 abcicli.Client + var r1 error + if rf, ok := ret.Get(0).(func() (abcicli.Client, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() abcicli.Client); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(abcicli.Client) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewABCISnapshotClient provides a mock function with given fields: +func (_m *ClientCreator) NewABCISnapshotClient() (abcicli.Client, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for NewABCISnapshotClient") + } + + var r0 abcicli.Client + var r1 error + if rf, ok := ret.Get(0).(func() (abcicli.Client, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() abcicli.Client); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(abcicli.Client) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // NewClientCreator creates a new instance of ClientCreator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClientCreator(t mockConstructorTestingTNewClientCreator) *ClientCreator { +// The first argument is typically a *testing.T value. +func NewClientCreator(t interface { + mock.TestingT + Cleanup(func()) +}) *ClientCreator { mock := &ClientCreator{} mock.Mock.Test(t) diff --git a/proxy/multi_app_conn.go b/proxy/multi_app_conn.go index 9117c304664..3012f4a5d1d 100644 --- a/proxy/multi_app_conn.go +++ b/proxy/multi_app_conn.go @@ -1,12 +1,10 @@ package proxy import ( - "fmt" - abcicli "github.com/cometbft/cometbft/abci/client" + cmtos "github.com/cometbft/cometbft/internal/os" + "github.com/cometbft/cometbft/internal/service" cmtlog "github.com/cometbft/cometbft/libs/log" - cmtos "github.com/cometbft/cometbft/libs/os" - "github.com/cometbft/cometbft/libs/service" ) const ( @@ -40,7 +38,7 @@ func NewAppConns(clientCreator ClientCreator, metrics *Metrics) AppConns { // // A multiAppConn is made of a few appConns and manages their underlying abci // clients. -// TODO: on app restart, clients must reboot together +// TODO: on app restart, clients must reboot together. type multiAppConn struct { service.BaseService @@ -85,40 +83,74 @@ func (app *multiAppConn) Snapshot() AppConnSnapshot { } func (app *multiAppConn) OnStart() error { - c, err := app.abciClientFor(connQuery) - if err != nil { + if err := app.startQueryClient(); err != nil { + return err + } + if err := app.startSnapshotClient(); err != nil { + app.stopAllClients() + return err + } + if err := app.startMempoolClient(); err != nil { + app.stopAllClients() + return err + } + if err := app.startConsensusClient(); err != nil { + app.stopAllClients() return err } + + // Kill CometBFT if the ABCI application crashes. + go app.killTMOnClientError() + + return nil +} + +func (app *multiAppConn) startQueryClient() error { + c, err := app.clientCreator.NewABCIQueryClient() + if err != nil { + return ErrABCIClientCreate{ClientName: "query", Err: err} + } app.queryConnClient = c app.queryConn = NewAppConnQuery(c, app.metrics) + return app.startClient(c, "query") +} - c, err = app.abciClientFor(connSnapshot) +func (app *multiAppConn) startSnapshotClient() error { + c, err := app.clientCreator.NewABCISnapshotClient() if err != nil { - app.stopAllClients() - return err + return ErrABCIClientCreate{ClientName: "snapshot", Err: err} } app.snapshotConnClient = c app.snapshotConn = NewAppConnSnapshot(c, app.metrics) + return app.startClient(c, "snapshot") +} - c, err = app.abciClientFor(connMempool) +func (app *multiAppConn) startMempoolClient() error { + c, err := app.clientCreator.NewABCIMempoolClient() if err != nil { - app.stopAllClients() - return err + return ErrABCIClientCreate{ClientName: "mempool", Err: err} } app.mempoolConnClient = c app.mempoolConn = NewAppConnMempool(c, app.metrics) + return app.startClient(c, "mempool") +} - c, err = app.abciClientFor(connConsensus) +func (app *multiAppConn) startConsensusClient() error { + c, err := app.clientCreator.NewABCIConsensusClient() if err != nil { app.stopAllClients() - return err + return ErrABCIClientCreate{ClientName: "consensus", Err: err} } app.consensusConnClient = c app.consensusConn = NewAppConnConsensus(c, app.metrics) + return app.startClient(c, "consensus") +} - // Kill CometBFT if the ABCI application crashes. - go app.killTMOnClientError() - +func (app *multiAppConn) startClient(c abcicli.Client, conn string) error { + c.SetLogger(app.Logger.With("module", "abci-client", "connection", conn)) + if err := c.Start(); err != nil { + return ErrABCIClientStart{CliType: conn, Err: err} + } return nil } @@ -129,7 +161,7 @@ func (app *multiAppConn) OnStop() { func (app *multiAppConn) killTMOnClientError() { killFn := func(conn string, err error, logger cmtlog.Logger) { logger.Error( - fmt.Sprintf("%s connection terminated. Did the application crash? Please restart CometBFT", conn), + conn+" connection terminated. Did the application crash? Please restart CometBFT", "err", err) killErr := cmtos.Kill() if killErr != nil { @@ -179,15 +211,3 @@ func (app *multiAppConn) stopAllClients() { } } } - -func (app *multiAppConn) abciClientFor(conn string) (abcicli.Client, error) { - c, err := app.clientCreator.NewABCIClient() - if err != nil { - return nil, fmt.Errorf("error creating ABCI client (%s connection): %w", conn, err) - } - c.SetLogger(app.Logger.With("module", "abci-client", "connection", conn)) - if err := c.Start(); err != nil { - return nil, fmt.Errorf("error starting ABCI client (%s connection): %w", conn, err) - } - return c, nil -} diff --git a/proxy/multi_app_conn_test.go b/proxy/multi_app_conn_test.go index 2c6e3e51ef0..a3c5a1cd055 100644 --- a/proxy/multi_app_conn_test.go +++ b/proxy/multi_app_conn_test.go @@ -26,7 +26,10 @@ func TestAppConns_Start_Stop(t *testing.T) { clientMock.On("Stop").Return(nil).Times(4) clientMock.On("Quit").Return(quitCh).Times(4) - clientCreatorMock.On("NewABCIClient").Return(clientMock, nil).Times(4) + clientCreatorMock.On("NewABCIQueryClient").Return(clientMock, nil).Times(4) + clientCreatorMock.On("NewABCIMempoolClient").Return(clientMock, nil).Times(4) + clientCreatorMock.On("NewABCISnapshotClient").Return(clientMock, nil).Times(4) + clientCreatorMock.On("NewABCIConsensusClient").Return(clientMock, nil).Times(4) appConns := NewAppConns(clientCreatorMock, NopMetrics()) @@ -41,7 +44,7 @@ func TestAppConns_Start_Stop(t *testing.T) { clientMock.AssertExpectations(t) } -// Upon failure, we call cmtos.Kill +// Upon failure, we call cmtos.Kill. func TestAppConns_Failure(t *testing.T) { ok := make(chan struct{}) c := make(chan os.Signal, 1) @@ -66,7 +69,10 @@ func TestAppConns_Failure(t *testing.T) { clientMock.On("Quit").Return(recvQuitCh) clientMock.On("Error").Return(errors.New("EOF")).Once() - clientCreatorMock.On("NewABCIClient").Return(clientMock, nil) + clientCreatorMock.On("NewABCIQueryClient").Return(clientMock, nil) + clientCreatorMock.On("NewABCIMempoolClient").Return(clientMock, nil) + clientCreatorMock.On("NewABCISnapshotClient").Return(clientMock, nil) + clientCreatorMock.On("NewABCIConsensusClient").Return(clientMock, nil) appConns := NewAppConns(clientCreatorMock, NopMetrics()) diff --git a/proxy/version.go b/proxy/version.go index 134dfc4aea0..4681bfe1125 100644 --- a/proxy/version.go +++ b/proxy/version.go @@ -5,11 +5,11 @@ import ( "github.com/cometbft/cometbft/version" ) -// RequestInfo contains all the information for sending -// the abci.RequestInfo message during handshake with the app. +// InfoRequest contains all the information for sending +// the abci.InfoRequest message during handshake with the app. // It contains only compile-time version information. -var RequestInfo = &abci.RequestInfo{ - Version: version.TMCoreSemVer, +var InfoRequest = &abci.InfoRequest{ + Version: version.CMTSemVer, BlockVersion: version.BlockProtocol, P2PVersion: version.P2PProtocol, AbciVersion: version.ABCIVersion, diff --git a/rpc/client/errors.go b/rpc/client/errors.go new file mode 100644 index 00000000000..987a8a11970 --- /dev/null +++ b/rpc/client/errors.go @@ -0,0 +1,29 @@ +package client + +import ( + "errors" + "fmt" +) + +var ErrEventTimeout = errors.New("event timeout") + +type ErrWaitThreshold struct { + Got int64 + Expected int64 +} + +func (e ErrWaitThreshold) Error() string { + return fmt.Sprintf("waiting for %d blocks exceeded the threshold %d", e.Got, e.Expected) +} + +type ErrSubscribe struct { + Source error +} + +func (e ErrSubscribe) Error() string { + return fmt.Sprintf("failed to subscribe: %v", e.Source) +} + +func (e ErrSubscribe) Unwrap() error { + return e.Source +} diff --git a/rpc/client/event_test.go b/rpc/client/event_test.go index ca38b8e0e46..3e341c72d83 100644 --- a/rpc/client/event_test.go +++ b/rpc/client/event_test.go @@ -2,7 +2,6 @@ package client_test import ( "context" - "fmt" "reflect" "testing" "time" @@ -11,7 +10,7 @@ import ( "github.com/stretchr/testify/require" abci "github.com/cometbft/cometbft/abci/types" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/rpc/client" ctypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cometbft/cometbft/types" @@ -19,7 +18,7 @@ import ( var waitForEventTimeout = 8 * time.Second -// MakeTxKV returns a text transaction, allong with expected key, value pair +// MakeTxKV returns a text transaction, along with expected key, value pair. func MakeTxKV() ([]byte, []byte, []byte) { k := []byte(cmtrand.Str(8)) v := []byte(cmtrand.Str(8)) @@ -34,7 +33,7 @@ func TestHeaderEvents(t *testing.T) { if !c.IsRunning() { // if so, then we start it, listen, and stop it. err := c.Start() - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) t.Cleanup(func() { if err := c.Stop(); err != nil { t.Error(err) @@ -44,7 +43,8 @@ func TestHeaderEvents(t *testing.T) { evtTyp := types.EventNewBlockHeader evt, err := client.WaitForOneEvent(c, evtTyp, waitForEventTimeout) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err) + require.NoError(t, err, "%d: %+v", i, err) _, ok := evt.(types.EventDataNewBlockHeader) require.True(t, ok, "%d: %#v", i, evt) // TODO: more checks... @@ -52,17 +52,16 @@ func TestHeaderEvents(t *testing.T) { } } -// subscribe to new blocks and make sure height increments by 1 +// subscribe to new blocks and make sure height increments by 1. func TestBlockEvents(t *testing.T) { for _, c := range GetClients() { c := c t.Run(reflect.TypeOf(c).String(), func(t *testing.T) { - // start for this test it if it wasn't already running if !c.IsRunning() { // if so, then we start it, listen, and stop it. err := c.Start() - require.Nil(t, err) + require.NoError(t, err) t.Cleanup(func() { if err := c.Stop(); err != nil { t.Error(err) @@ -102,15 +101,15 @@ func TestTxEventsSentWithBroadcastTxAsync(t *testing.T) { testTxEventsSent(t, "a func TestTxEventsSentWithBroadcastTxSync(t *testing.T) { testTxEventsSent(t, "sync") } func testTxEventsSent(t *testing.T, broadcastMethod string) { + t.Helper() for _, c := range GetClients() { c := c t.Run(reflect.TypeOf(c).String(), func(t *testing.T) { - // start for this test it if it wasn't already running if !c.IsRunning() { // if so, then we start it, listen, and stop it. err := c.Start() - require.Nil(t, err) + require.NoError(t, err) t.Cleanup(func() { if err := c.Stop(); err != nil { t.Error(err) @@ -134,16 +133,16 @@ func testTxEventsSent(t *testing.T, broadcastMethod string) { case "sync": txres, err = c.BroadcastTxSync(ctx, tx) default: - panic(fmt.Sprintf("Unknown broadcastMethod %s", broadcastMethod)) + panic("Unknown broadcastMethod " + broadcastMethod) } - if assert.NoError(t, err) { - assert.Equal(t, txres.Code, abci.CodeTypeOK) + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here + require.Equal(t, abci.CodeTypeOK, txres.Code) } }() // and wait for confirmation evt, err := client.WaitForOneEvent(c, types.EventTx, waitForEventTimeout) - require.Nil(t, err) + require.NoError(t, err) // and make sure it has the proper info txe, ok := evt.(types.EventDataTx) @@ -162,14 +161,14 @@ func TestHTTPReturnsErrorIfClientIsNotRunning(t *testing.T) { // on Subscribe _, err := c.Subscribe(context.Background(), "TestHeaderEvents", types.QueryForEvent(types.EventNewBlockHeader).String()) - assert.Error(t, err) + require.Error(t, err) // on Unsubscribe err = c.Unsubscribe(context.Background(), "TestHeaderEvents", types.QueryForEvent(types.EventNewBlockHeader).String()) - assert.Error(t, err) + require.Error(t, err) // on UnsubscribeAll err = c.UnsubscribeAll(context.Background(), "TestHeaderEvents") - assert.Error(t, err) + require.Error(t, err) } diff --git a/rpc/client/evidence_test.go b/rpc/client/evidence_test.go index 432f0868844..f0cfab5d1bc 100644 --- a/rpc/client/evidence_test.go +++ b/rpc/client/evidence_test.go @@ -13,25 +13,20 @@ import ( "github.com/cometbft/cometbft/crypto/ed25519" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" "github.com/cometbft/cometbft/crypto/tmhash" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/internal/test" - cmtrand "github.com/cometbft/cometbft/libs/rand" "github.com/cometbft/cometbft/privval" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/rpc/client" rpctest "github.com/cometbft/cometbft/rpc/test" "github.com/cometbft/cometbft/types" ) -// For some reason the empty node used in tests has a time of -// 2018-10-10 08:20:13.695936996 +0000 UTC -// this is because the test genesis time is set here -// so in order to validate evidence we need evidence to be the same time -var defaultTestTime = time.Date(2018, 10, 10, 8, 20, 13, 695936996, time.UTC) - func newEvidence(t *testing.T, val *privval.FilePV, vote *types.Vote, vote2 *types.Vote, - chainID string) *types.DuplicateVoteEvidence { - + chainID string, + timestamp time.Time, +) *types.DuplicateVoteEvidence { + t.Helper() var err error v := vote.ToProto() @@ -46,7 +41,7 @@ func newEvidence(t *testing.T, val *privval.FilePV, validator := types.NewValidator(val.Key.PubKey, 10) valSet := types.NewValidatorSet([]*types.Validator{validator}) - ev, err := types.NewDuplicateVoteEvidence(vote, vote2, defaultTestTime, valSet) + ev, err := types.NewDuplicateVoteEvidence(vote, vote2, timestamp, valSet) require.NoError(t, err) return ev } @@ -55,14 +50,16 @@ func makeEvidences( t *testing.T, val *privval.FilePV, chainID string, + timestamp time.Time, ) (correct *types.DuplicateVoteEvidence, fakes []*types.DuplicateVoteEvidence) { + t.Helper() vote := types.Vote{ ValidatorAddress: val.Key.Address, ValidatorIndex: 0, Height: 1, Round: 0, - Type: cmtproto.PrevoteType, - Timestamp: defaultTestTime, + Type: types.PrevoteType, + Timestamp: timestamp, BlockID: types.BlockID{ Hash: tmhash.Sum(cmtrand.Bytes(tmhash.Size)), PartSetHeader: types.PartSetHeader{ @@ -74,7 +71,7 @@ func makeEvidences( vote2 := vote vote2.BlockID.Hash = tmhash.Sum([]byte("blockhash2")) - correct = newEvidence(t, val, &vote, &vote2, chainID) + correct = newEvidence(t, val, &vote, &vote2, chainID, timestamp) fakes = make([]*types.DuplicateVoteEvidence, 0) @@ -82,34 +79,34 @@ func makeEvidences( { v := vote2 v.ValidatorAddress = []byte("some_address") - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } // different height { v := vote2 v.Height = vote.Height + 1 - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } // different round { v := vote2 v.Round = vote.Round + 1 - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } // different type { v := vote2 - v.Type = cmtproto.PrecommitType - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + v.Type = types.PrecommitType + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } // exactly same vote { v := vote - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } return correct, fakes @@ -123,7 +120,13 @@ func TestBroadcastEvidence_DuplicateVoteEvidence(t *testing.T) { ) for i, c := range GetClients() { - correct, fakes := makeEvidences(t, pv, chainID) + evidenceHeight := int64(1) + err := client.WaitForHeight(c, evidenceHeight, nil) + require.NoError(t, err) + block, err := c.Block(ctx, &evidenceHeight) + require.NoError(t, err) + ts := block.Block.Time + correct, fakes := makeEvidences(t, pv, chainID, ts) t.Logf("client %d", i) result, err := c.BroadcastEvidence(context.Background(), correct) @@ -162,6 +165,6 @@ func TestBroadcastEvidence_DuplicateVoteEvidence(t *testing.T) { func TestBroadcastEmptyEvidence(t *testing.T) { for _, c := range GetClients() { _, err := c.BroadcastEvidence(context.Background(), nil) - assert.Error(t, err) + require.Error(t, err) } } diff --git a/rpc/client/examples_test.go b/rpc/client/examples_test.go index 4c8d8eed656..b8d942040bf 100644 --- a/rpc/client/examples_test.go +++ b/rpc/client/examples_test.go @@ -15,14 +15,14 @@ import ( func ExampleHTTP_simple() { // Start a CometBFT node (and kvstore) in the background to test against app := kvstore.NewInMemoryApplication() - node := rpctest.StartTendermint(app, rpctest.SuppressStdout, rpctest.RecreateConfig) - defer rpctest.StopTendermint(node) + node := rpctest.StartCometBFT(app, rpctest.SuppressStdout, rpctest.RecreateConfig) + defer rpctest.StopCometBFT(node) // Create our RPC client rpcAddr := rpctest.GetConfig().RPC.ListenAddress - c, err := rpchttp.New(rpcAddr, "/websocket") + c, err := rpchttp.New(rpcAddr) if err != nil { - log.Fatal(err) //nolint:gocritic + log.Fatal(err) } // Create a transaction @@ -68,16 +68,16 @@ func ExampleHTTP_simple() { func ExampleHTTP_batching() { // Start a CometBFT node (and kvstore) in the background to test against app := kvstore.NewInMemoryApplication() - node := rpctest.StartTendermint(app, rpctest.SuppressStdout, rpctest.RecreateConfig) + node := rpctest.StartCometBFT(app, rpctest.SuppressStdout, rpctest.RecreateConfig) // Create our RPC client rpcAddr := rpctest.GetConfig().RPC.ListenAddress - c, err := rpchttp.New(rpcAddr, "/websocket") + c, err := rpchttp.New(rpcAddr) if err != nil { log.Fatal(err) } - defer rpctest.StopTendermint(node) + defer rpctest.StopCometBFT(node) // Create our two transactions k1 := []byte("firstName") @@ -98,7 +98,7 @@ func ExampleHTTP_batching() { // Broadcast the transaction and wait for it to commit (rather use // c.BroadcastTxSync though in production). if _, err := batch.BroadcastTxCommit(context.Background(), tx); err != nil { - log.Fatal(err) //nolint:gocritic + log.Fatal(err) } } diff --git a/rpc/client/helpers.go b/rpc/client/helpers.go index fe34d0480b1..9b115a10c00 100644 --- a/rpc/client/helpers.go +++ b/rpc/client/helpers.go @@ -2,21 +2,21 @@ package client import ( "context" - "errors" - "fmt" "time" "github.com/cometbft/cometbft/types" ) -// Waiter is informed of current height, decided whether to quit early +const WaitThreshold = 10 + +// Waiter is informed of current height, decided whether to quit early. type Waiter func(delta int64) (abort error) // DefaultWaitStrategy is the standard backoff algorithm, -// but you can plug in another one +// but you can plug in another one. func DefaultWaitStrategy(delta int64) (abort error) { - if delta > 10 { - return fmt.Errorf("waiting for %d blocks... aborting", delta) + if delta > WaitThreshold { + return ErrWaitThreshold{Got: delta, Expected: WaitThreshold} } else if delta > 0 { // estimate of wait time.... // wait half a second for the next block (in progress) @@ -31,7 +31,7 @@ func DefaultWaitStrategy(delta int64) (abort error) { // the block at the given height is available. // // If waiter is nil, we use DefaultWaitStrategy, but you can also -// provide your own implementation +// provide your own implementation. func WaitForHeight(c StatusClient, h int64, waiter Waiter) error { if waiter == nil { waiter = DefaultWaitStrategy @@ -42,6 +42,9 @@ func WaitForHeight(c StatusClient, h int64, waiter Waiter) error { if err != nil { return err } + // delta might be negative (if h is less than LatestBlockHeight + // but this should not cause an error when calling the waiter with + // a negative value delta = h - s.SyncInfo.LatestBlockHeight // wait for the time, or abort early if err := waiter(delta); err != nil { @@ -56,7 +59,7 @@ func WaitForHeight(c StatusClient, h int64, waiter Waiter) error { // event time and returns upon receiving it one time, or // when the timeout duration has expired. // -// This handles subscribing and unsubscribing under the hood +// This handles subscribing and unsubscribing under the hood. func WaitForOneEvent(c EventsClient, evtTyp string, timeout time.Duration) (types.TMEventData, error) { const subscriber = "helpers" ctx, cancel := context.WithTimeout(context.Background(), timeout) @@ -65,7 +68,7 @@ func WaitForOneEvent(c EventsClient, evtTyp string, timeout time.Duration) (type // register for the next event of this type eventCh, err := c.Subscribe(ctx, subscriber, types.QueryForEvent(evtTyp).String()) if err != nil { - return nil, fmt.Errorf("failed to subscribe: %w", err) + return nil, ErrSubscribe{Source: err} } // make sure to unregister after the test is over defer func() { @@ -78,6 +81,6 @@ func WaitForOneEvent(c EventsClient, evtTyp string, timeout time.Duration) (type case event := <-eventCh: return event.Data, nil case <-ctx.Done(): - return nil, errors.New("timed out waiting for event") + return nil, ErrEventTimeout } } diff --git a/rpc/client/helpers_test.go b/rpc/client/helpers_test.go index 65f55a4c32a..11c7910450d 100644 --- a/rpc/client/helpers_test.go +++ b/rpc/client/helpers_test.go @@ -2,7 +2,6 @@ package client_test import ( "errors" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -26,10 +25,10 @@ func TestWaitForHeight(t *testing.T) { // connection failure always leads to error err := client.WaitForHeight(r, 8, nil) - require.NotNil(err) + require.Error(err) require.Equal("bye", err.Error()) // we called status once to check - require.Equal(1, len(r.Calls)) + require.Len(r.Calls, 1) // now set current block height to 10 m.Call = mock.Call{ @@ -38,16 +37,17 @@ func TestWaitForHeight(t *testing.T) { // we will not wait for more than 10 blocks err = client.WaitForHeight(r, 40, nil) - require.NotNil(err) - require.True(strings.Contains(err.Error(), "aborting")) + require.Error(err) + require.ErrorAs(err, &client.ErrWaitThreshold{}) + // we called status once more to check - require.Equal(2, len(r.Calls)) + require.Len(r.Calls, 2) // waiting for the past returns immediately err = client.WaitForHeight(r, 5, nil) - require.Nil(err) + require.NoError(err) // we called status once more to check - require.Equal(3, len(r.Calls)) + require.Len(r.Calls, 3) // since we can't update in a background goroutine (test --race) // we use the callback to update the status height @@ -59,18 +59,18 @@ func TestWaitForHeight(t *testing.T) { // we wait for a few blocks err = client.WaitForHeight(r, 12, myWaiter) - require.Nil(err) + require.NoError(err) // we called status once to check - require.Equal(5, len(r.Calls)) + require.Len(r.Calls, 5) pre := r.Calls[3] - require.Nil(pre.Error) + require.NoError(pre.Error) prer, ok := pre.Response.(*ctypes.ResultStatus) require.True(ok) assert.Equal(int64(10), prer.SyncInfo.LatestBlockHeight) post := r.Calls[4] - require.Nil(post.Error) + require.NoError(post.Error) postr, ok := post.Response.(*ctypes.ResultStatus) require.True(ok) assert.Equal(int64(15), postr.SyncInfo.LatestBlockHeight) diff --git a/rpc/client/http/http.go b/rpc/client/http/http.go index 30a31f77b6f..becc3d6f5f6 100644 --- a/rpc/client/http/http.go +++ b/rpc/client/http/http.go @@ -7,12 +7,12 @@ import ( "strings" "time" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + "github.com/cometbft/cometbft/internal/service" + cmtsync "github.com/cometbft/cometbft/internal/sync" "github.com/cometbft/cometbft/libs/bytes" cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - "github.com/cometbft/cometbft/libs/service" - cmtsync "github.com/cometbft/cometbft/libs/sync" rpcclient "github.com/cometbft/cometbft/rpc/client" ctypes "github.com/cometbft/cometbft/rpc/core/types" jsonrpcclient "github.com/cometbft/cometbft/rpc/jsonrpc/client" @@ -39,7 +39,7 @@ the example for more details. Example: - c, err := New("http://192.168.1.10:26657", "/websocket") + c, err := New("http://192.168.1.10:26657/v1") if err != nil { // handle error } @@ -104,33 +104,32 @@ var ( _ rpcClient = (*baseRPCClient)(nil) ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // HTTP -// New takes a remote endpoint in the form ://: and -// the websocket path (which always seems to be "/websocket") -// An error is returned on invalid remote. The function panics when remote is nil. -func New(remote, wsEndpoint string) (*HTTP, error) { +// New takes a remote endpoint in the form ://:. An error +// is returned on invalid remote. The function panics when remote is nil. +func New(remote string) (*HTTP, error) { httpClient, err := jsonrpcclient.DefaultHTTPClient(remote) if err != nil { return nil, err } - return NewWithClient(remote, wsEndpoint, httpClient) + return NewWithClient(remote, httpClient) } -// Create timeout enabled http client -func NewWithTimeout(remote, wsEndpoint string, timeout uint) (*HTTP, error) { +// Create timeout enabled http client. +func NewWithTimeout(remote string, timeout uint) (*HTTP, error) { httpClient, err := jsonrpcclient.DefaultHTTPClient(remote) if err != nil { return nil, err } httpClient.Timeout = time.Duration(timeout) * time.Second - return NewWithClient(remote, wsEndpoint, httpClient) + return NewWithClient(remote, httpClient) } -// NewWithClient allows for setting a custom http client (See New). -// An error is returned on invalid remote. The function panics when remote is nil. -func NewWithClient(remote, wsEndpoint string, client *http.Client) (*HTTP, error) { +// NewWithClient allows for setting a custom http client (See New). An error is +// returned on invalid remote. The function panics when remote is nil. +func NewWithClient(remote string, client *http.Client) (*HTTP, error) { if client == nil { panic("nil http.Client provided") } @@ -140,7 +139,7 @@ func NewWithClient(remote, wsEndpoint string, client *http.Client) (*HTTP, error return nil, err } - wsEvents, err := newWSEvents(remote, wsEndpoint) + wsEvents, err := newWSEvents(remote, "/websocket") if err != nil { return nil, err } @@ -178,14 +177,14 @@ func (c *HTTP) NewBatch() *BatchHTTP { } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // BatchHTTP // Send is a convenience function for an HTTP batch that will trigger the // compilation of the batched requests and send them off using the client as a // single request. On success, this returns a list of the deserialized results // from each request in the sent batch. -func (b *BatchHTTP) Send(ctx context.Context) ([]interface{}, error) { +func (b *BatchHTTP) Send(ctx context.Context) ([]any, error) { return b.rpcBatch.Send(ctx) } @@ -200,12 +199,12 @@ func (b *BatchHTTP) Count() int { return b.rpcBatch.Count() } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // baseRPCClient func (c *baseRPCClient) Status(ctx context.Context) (*ctypes.ResultStatus, error) { result := new(ctypes.ResultStatus) - _, err := c.caller.Call(ctx, "status", map[string]interface{}{}, result) + _, err := c.caller.Call(ctx, "status", map[string]any{}, result) if err != nil { return nil, err } @@ -215,7 +214,7 @@ func (c *baseRPCClient) Status(ctx context.Context) (*ctypes.ResultStatus, error func (c *baseRPCClient) ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) { result := new(ctypes.ResultABCIInfo) - _, err := c.caller.Call(ctx, "abci_info", map[string]interface{}{}, result) + _, err := c.caller.Call(ctx, "abci_info", map[string]any{}, result) if err != nil { return nil, err } @@ -235,10 +234,11 @@ func (c *baseRPCClient) ABCIQueryWithOptions( ctx context.Context, path string, data bytes.HexBytes, - opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { + opts rpcclient.ABCIQueryOptions, +) (*ctypes.ResultABCIQuery, error) { result := new(ctypes.ResultABCIQuery) _, err := c.caller.Call(ctx, "abci_query", - map[string]interface{}{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove}, + map[string]any{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove}, result) if err != nil { return nil, err @@ -252,7 +252,7 @@ func (c *baseRPCClient) BroadcastTxCommit( tx types.Tx, ) (*ctypes.ResultBroadcastTxCommit, error) { result := new(ctypes.ResultBroadcastTxCommit) - _, err := c.caller.Call(ctx, "broadcast_tx_commit", map[string]interface{}{"tx": tx}, result) + _, err := c.caller.Call(ctx, "broadcast_tx_commit", map[string]any{"tx": tx}, result) if err != nil { return nil, err } @@ -279,7 +279,7 @@ func (c *baseRPCClient) broadcastTX( tx types.Tx, ) (*ctypes.ResultBroadcastTx, error) { result := new(ctypes.ResultBroadcastTx) - _, err := c.caller.Call(ctx, route, map[string]interface{}{"tx": tx}, result) + _, err := c.caller.Call(ctx, route, map[string]any{"tx": tx}, result) if err != nil { return nil, err } @@ -291,7 +291,7 @@ func (c *baseRPCClient) UnconfirmedTxs( limit *int, ) (*ctypes.ResultUnconfirmedTxs, error) { result := new(ctypes.ResultUnconfirmedTxs) - params := make(map[string]interface{}) + params := make(map[string]any) if limit != nil { params["limit"] = limit } @@ -304,7 +304,7 @@ func (c *baseRPCClient) UnconfirmedTxs( func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUnconfirmedTxs, error) { result := new(ctypes.ResultUnconfirmedTxs) - _, err := c.caller.Call(ctx, "num_unconfirmed_txs", map[string]interface{}{}, result) + _, err := c.caller.Call(ctx, "num_unconfirmed_txs", map[string]any{}, result) if err != nil { return nil, err } @@ -313,7 +313,7 @@ func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUn func (c *baseRPCClient) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { result := new(ctypes.ResultCheckTx) - _, err := c.caller.Call(ctx, "check_tx", map[string]interface{}{"tx": tx}, result) + _, err := c.caller.Call(ctx, "check_tx", map[string]any{"tx": tx}, result) if err != nil { return nil, err } @@ -322,7 +322,7 @@ func (c *baseRPCClient) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.Resul func (c *baseRPCClient) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) { result := new(ctypes.ResultNetInfo) - _, err := c.caller.Call(ctx, "net_info", map[string]interface{}{}, result) + _, err := c.caller.Call(ctx, "net_info", map[string]any{}, result) if err != nil { return nil, err } @@ -331,7 +331,7 @@ func (c *baseRPCClient) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, err func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) { result := new(ctypes.ResultDumpConsensusState) - _, err := c.caller.Call(ctx, "dump_consensus_state", map[string]interface{}{}, result) + _, err := c.caller.Call(ctx, "dump_consensus_state", map[string]any{}, result) if err != nil { return nil, err } @@ -340,7 +340,7 @@ func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*ctypes.ResultD func (c *baseRPCClient) ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) { result := new(ctypes.ResultConsensusState) - _, err := c.caller.Call(ctx, "consensus_state", map[string]interface{}{}, result) + _, err := c.caller.Call(ctx, "consensus_state", map[string]any{}, result) if err != nil { return nil, err } @@ -352,7 +352,7 @@ func (c *baseRPCClient) ConsensusParams( height *int64, ) (*ctypes.ResultConsensusParams, error) { result := new(ctypes.ResultConsensusParams) - params := make(map[string]interface{}) + params := make(map[string]any) if height != nil { params["height"] = height } @@ -365,7 +365,7 @@ func (c *baseRPCClient) ConsensusParams( func (c *baseRPCClient) Health(ctx context.Context) (*ctypes.ResultHealth, error) { result := new(ctypes.ResultHealth) - _, err := c.caller.Call(ctx, "health", map[string]interface{}{}, result) + _, err := c.caller.Call(ctx, "health", map[string]any{}, result) if err != nil { return nil, err } @@ -379,7 +379,7 @@ func (c *baseRPCClient) BlockchainInfo( ) (*ctypes.ResultBlockchainInfo, error) { result := new(ctypes.ResultBlockchainInfo) _, err := c.caller.Call(ctx, "blockchain", - map[string]interface{}{"minHeight": minHeight, "maxHeight": maxHeight}, + map[string]any{"minHeight": minHeight, "maxHeight": maxHeight}, result) if err != nil { return nil, err @@ -389,7 +389,7 @@ func (c *baseRPCClient) BlockchainInfo( func (c *baseRPCClient) Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) { result := new(ctypes.ResultGenesis) - _, err := c.caller.Call(ctx, "genesis", map[string]interface{}{}, result) + _, err := c.caller.Call(ctx, "genesis", map[string]any{}, result) if err != nil { return nil, err } @@ -398,7 +398,7 @@ func (c *baseRPCClient) Genesis(ctx context.Context) (*ctypes.ResultGenesis, err func (c *baseRPCClient) GenesisChunked(ctx context.Context, id uint) (*ctypes.ResultGenesisChunk, error) { result := new(ctypes.ResultGenesisChunk) - _, err := c.caller.Call(ctx, "genesis_chunked", map[string]interface{}{"chunk": id}, result) + _, err := c.caller.Call(ctx, "genesis_chunked", map[string]any{"chunk": id}, result) if err != nil { return nil, err } @@ -407,7 +407,7 @@ func (c *baseRPCClient) GenesisChunked(ctx context.Context, id uint) (*ctypes.Re func (c *baseRPCClient) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) { result := new(ctypes.ResultBlock) - params := make(map[string]interface{}) + params := make(map[string]any) if height != nil { params["height"] = height } @@ -420,7 +420,7 @@ func (c *baseRPCClient) Block(ctx context.Context, height *int64) (*ctypes.Resul func (c *baseRPCClient) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBlock, error) { result := new(ctypes.ResultBlock) - params := map[string]interface{}{ + params := map[string]any{ "hash": hash, } _, err := c.caller.Call(ctx, "block_by_hash", params, result) @@ -435,7 +435,7 @@ func (c *baseRPCClient) BlockResults( height *int64, ) (*ctypes.ResultBlockResults, error) { result := new(ctypes.ResultBlockResults) - params := make(map[string]interface{}) + params := make(map[string]any) if height != nil { params["height"] = height } @@ -448,7 +448,7 @@ func (c *baseRPCClient) BlockResults( func (c *baseRPCClient) Header(ctx context.Context, height *int64) (*ctypes.ResultHeader, error) { result := new(ctypes.ResultHeader) - params := make(map[string]interface{}) + params := make(map[string]any) if height != nil { params["height"] = height } @@ -461,7 +461,7 @@ func (c *baseRPCClient) Header(ctx context.Context, height *int64) (*ctypes.Resu func (c *baseRPCClient) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*ctypes.ResultHeader, error) { result := new(ctypes.ResultHeader) - params := map[string]interface{}{ + params := map[string]any{ "hash": hash, } _, err := c.caller.Call(ctx, "header_by_hash", params, result) @@ -473,7 +473,7 @@ func (c *baseRPCClient) HeaderByHash(ctx context.Context, hash bytes.HexBytes) ( func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) { result := new(ctypes.ResultCommit) - params := make(map[string]interface{}) + params := make(map[string]any) if height != nil { params["height"] = height } @@ -486,7 +486,7 @@ func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*ctypes.Resu func (c *baseRPCClient) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { result := new(ctypes.ResultTx) - params := map[string]interface{}{ + params := map[string]any{ "hash": hash, "prove": prove, } @@ -505,9 +505,8 @@ func (c *baseRPCClient) TxSearch( perPage *int, orderBy string, ) (*ctypes.ResultTxSearch, error) { - result := new(ctypes.ResultTxSearch) - params := map[string]interface{}{ + params := map[string]any{ "query": query, "prove": prove, "order_by": orderBy, @@ -534,9 +533,8 @@ func (c *baseRPCClient) BlockSearch( page, perPage *int, orderBy string, ) (*ctypes.ResultBlockSearch, error) { - result := new(ctypes.ResultBlockSearch) - params := map[string]interface{}{ + params := map[string]any{ "query": query, "order_by": orderBy, } @@ -563,7 +561,7 @@ func (c *baseRPCClient) Validators( perPage *int, ) (*ctypes.ResultValidators, error) { result := new(ctypes.ResultValidators) - params := make(map[string]interface{}) + params := make(map[string]any) if page != nil { params["page"] = page } @@ -585,14 +583,14 @@ func (c *baseRPCClient) BroadcastEvidence( ev types.Evidence, ) (*ctypes.ResultBroadcastEvidence, error) { result := new(ctypes.ResultBroadcastEvidence) - _, err := c.caller.Call(ctx, "broadcast_evidence", map[string]interface{}{"evidence": ev}, result) + _, err := c.caller.Call(ctx, "broadcast_evidence", map[string]any{"evidence": ev}, result) if err != nil { return nil, err } return result, nil } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // WSEvents var errNotRunning = errors.New("client is not running. Use .Start() method to start") @@ -654,9 +652,9 @@ func (w *WSEvents) OnStop() { // Channel is never closed to prevent clients from seeing an erroneous event. // // It returns an error if WSEvents is not running. -func (w *WSEvents) Subscribe(ctx context.Context, subscriber, query string, - outCapacity ...int) (out <-chan ctypes.ResultEvent, err error) { - +func (w *WSEvents) Subscribe(ctx context.Context, _, query string, + outCapacity ...int, +) (out <-chan ctypes.ResultEvent, err error) { if !w.IsRunning() { return nil, errNotRunning } @@ -684,7 +682,7 @@ func (w *WSEvents) Subscribe(ctx context.Context, subscriber, query string, // subscriber from query. // // It returns an error if WSEvents is not running. -func (w *WSEvents) Unsubscribe(ctx context.Context, subscriber, query string) error { +func (w *WSEvents) Unsubscribe(ctx context.Context, _, query string) error { if !w.IsRunning() { return errNotRunning } @@ -707,7 +705,7 @@ func (w *WSEvents) Unsubscribe(ctx context.Context, subscriber, query string) er // given subscriber from all the queries. // // It returns an error if WSEvents is not running. -func (w *WSEvents) UnsubscribeAll(ctx context.Context, subscriber string) error { +func (w *WSEvents) UnsubscribeAll(ctx context.Context, _ string) error { if !w.IsRunning() { return errNotRunning } diff --git a/rpc/client/interface.go b/rpc/client/interface.go index 285ac74e533..8229cb91a95 100644 --- a/rpc/client/interface.go +++ b/rpc/client/interface.go @@ -23,8 +23,8 @@ implementation. import ( "context" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/libs/bytes" - "github.com/cometbft/cometbft/libs/service" ctypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cometbft/cometbft/types" ) @@ -50,15 +50,15 @@ type Client interface { // is easier to mock. type ABCIClient interface { // Reading from abci app - ABCIInfo(context.Context) (*ctypes.ResultABCIInfo, error) + ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) ABCIQuery(ctx context.Context, path string, data bytes.HexBytes) (*ctypes.ResultABCIQuery, error) ABCIQueryWithOptions(ctx context.Context, path string, data bytes.HexBytes, opts ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) // Writing to abci app - BroadcastTxCommit(context.Context, types.Tx) (*ctypes.ResultBroadcastTxCommit, error) - BroadcastTxAsync(context.Context, types.Tx) (*ctypes.ResultBroadcastTx, error) - BroadcastTxSync(context.Context, types.Tx) (*ctypes.ResultBroadcastTx, error) + BroadcastTxCommit(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) + BroadcastTxAsync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) + BroadcastTxSync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) } // SignClient groups together the functionality needed to get valid signatures @@ -95,28 +95,28 @@ type SignClient interface { // HistoryClient provides access to data from genesis to now in large chunks. type HistoryClient interface { - Genesis(context.Context) (*ctypes.ResultGenesis, error) - GenesisChunked(context.Context, uint) (*ctypes.ResultGenesisChunk, error) + Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) + GenesisChunked(ctx context.Context, id uint) (*ctypes.ResultGenesisChunk, error) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) } // StatusClient provides access to general chain info. type StatusClient interface { - Status(context.Context) (*ctypes.ResultStatus, error) + Status(ctx context.Context) (*ctypes.ResultStatus, error) } // NetworkClient is general info about the network state. May not be needed // usually. type NetworkClient interface { - NetInfo(context.Context) (*ctypes.ResultNetInfo, error) - DumpConsensusState(context.Context) (*ctypes.ResultDumpConsensusState, error) - ConsensusState(context.Context) (*ctypes.ResultConsensusState, error) + NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) + DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) + ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) ConsensusParams(ctx context.Context, height *int64) (*ctypes.ResultConsensusParams, error) - Health(context.Context) (*ctypes.ResultHealth, error) + Health(ctx context.Context) (*ctypes.ResultHealth, error) } // EventsClient is reactive, you can subscribe to any message, given the proper -// string. see cometbft/types/events.go +// string. see cometbft/types/events.go. type EventsClient interface { // Subscribe subscribes given subscriber to query. Returns a channel with // cap=1 onto which events are published. An error is returned if it fails to @@ -135,14 +135,14 @@ type EventsClient interface { // MempoolClient shows us data about current mempool state. type MempoolClient interface { UnconfirmedTxs(ctx context.Context, limit *int) (*ctypes.ResultUnconfirmedTxs, error) - NumUnconfirmedTxs(context.Context) (*ctypes.ResultUnconfirmedTxs, error) - CheckTx(context.Context, types.Tx) (*ctypes.ResultCheckTx, error) + NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUnconfirmedTxs, error) + CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) } // EvidenceClient is used for submitting an evidence of the malicious // behavior. type EvidenceClient interface { - BroadcastEvidence(context.Context, types.Evidence) (*ctypes.ResultBroadcastEvidence, error) + BroadcastEvidence(ctx context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) } // RemoteClient is a Client, which can also return the remote network address. diff --git a/rpc/client/local/local.go b/rpc/client/local/local.go index 39f98b6f060..1c3520f37a3 100644 --- a/rpc/client/local/local.go +++ b/rpc/client/local/local.go @@ -5,10 +5,10 @@ import ( "fmt" "time" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + cmtquery "github.com/cometbft/cometbft/internal/pubsub/query" "github.com/cometbft/cometbft/libs/bytes" "github.com/cometbft/cometbft/libs/log" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - cmtquery "github.com/cometbft/cometbft/libs/pubsub/query" nm "github.com/cometbft/cometbft/node" rpcclient "github.com/cometbft/cometbft/rpc/client" "github.com/cometbft/cometbft/rpc/core" @@ -18,15 +18,15 @@ import ( ) /* -Local is a Client implementation that directly executes the rpc -functions on a given node, without going through HTTP or GRPC. +Local is a Client implementation that directly executes the RPC +functions on a given node, without going through HTTP. This implementation is useful for: -* Running tests against a node in-process without the overhead -of going through an http server -* Communication between an ABCI app and CometBFT when they -are compiled in process. + - Running tests against a node in-process without the overhead + of going through an HTTP server + - Communication between an ABCI app and CometBFT when they + are compiled in process. For real clients, you probably want to use client.HTTP. For more powerful control during testing, you probably want the "client/mock" package. @@ -60,16 +60,28 @@ func New(node *nm.Node) *Local { var _ rpcclient.Client = (*Local)(nil) +type ErrParseQuery struct { + Source error +} + +func (e ErrParseQuery) Error() string { + return fmt.Sprintf("failed to parse query: %v", e.Source) +} + +func (e ErrParseQuery) Unwrap() error { + return e.Source +} + // SetLogger allows to set a logger on the client. func (c *Local) SetLogger(l log.Logger) { c.Logger = l } -func (c *Local) Status(ctx context.Context) (*ctypes.ResultStatus, error) { +func (c *Local) Status(context.Context) (*ctypes.ResultStatus, error) { return c.env.Status(c.ctx) } -func (c *Local) ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) { +func (c *Local) ABCIInfo(context.Context) (*ctypes.ResultABCIInfo, error) { return c.env.ABCIInfo(c.ctx) } @@ -78,63 +90,64 @@ func (c *Local) ABCIQuery(ctx context.Context, path string, data bytes.HexBytes) } func (c *Local) ABCIQueryWithOptions( - ctx context.Context, + _ context.Context, path string, data bytes.HexBytes, - opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { + opts rpcclient.ABCIQueryOptions, +) (*ctypes.ResultABCIQuery, error) { return c.env.ABCIQuery(c.ctx, path, data, opts.Height, opts.Prove) } -func (c *Local) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { +func (c *Local) BroadcastTxCommit(_ context.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { return c.env.BroadcastTxCommit(c.ctx, tx) } -func (c *Local) BroadcastTxAsync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { +func (c *Local) BroadcastTxAsync(_ context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { return c.env.BroadcastTxAsync(c.ctx, tx) } -func (c *Local) BroadcastTxSync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { +func (c *Local) BroadcastTxSync(_ context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { return c.env.BroadcastTxSync(c.ctx, tx) } -func (c *Local) UnconfirmedTxs(ctx context.Context, limit *int) (*ctypes.ResultUnconfirmedTxs, error) { +func (c *Local) UnconfirmedTxs(_ context.Context, limit *int) (*ctypes.ResultUnconfirmedTxs, error) { return c.env.UnconfirmedTxs(c.ctx, limit) } -func (c *Local) NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUnconfirmedTxs, error) { +func (c *Local) NumUnconfirmedTxs(context.Context) (*ctypes.ResultUnconfirmedTxs, error) { return c.env.NumUnconfirmedTxs(c.ctx) } -func (c *Local) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { +func (c *Local) CheckTx(_ context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { return c.env.CheckTx(c.ctx, tx) } -func (c *Local) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) { +func (c *Local) NetInfo(context.Context) (*ctypes.ResultNetInfo, error) { return c.env.NetInfo(c.ctx) } -func (c *Local) DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) { +func (c *Local) DumpConsensusState(context.Context) (*ctypes.ResultDumpConsensusState, error) { return c.env.DumpConsensusState(c.ctx) } -func (c *Local) ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) { +func (c *Local) ConsensusState(context.Context) (*ctypes.ResultConsensusState, error) { return c.env.GetConsensusState(c.ctx) } -func (c *Local) ConsensusParams(ctx context.Context, height *int64) (*ctypes.ResultConsensusParams, error) { +func (c *Local) ConsensusParams(_ context.Context, height *int64) (*ctypes.ResultConsensusParams, error) { return c.env.ConsensusParams(c.ctx, height) } -func (c *Local) Health(ctx context.Context) (*ctypes.ResultHealth, error) { +func (c *Local) Health(context.Context) (*ctypes.ResultHealth, error) { return c.env.Health(c.ctx) } -func (c *Local) DialSeeds(ctx context.Context, seeds []string) (*ctypes.ResultDialSeeds, error) { +func (c *Local) DialSeeds(_ context.Context, seeds []string) (*ctypes.ResultDialSeeds, error) { return c.env.UnsafeDialSeeds(c.ctx, seeds) } func (c *Local) DialPeers( - ctx context.Context, + _ context.Context, peers []string, persistent, unconditional, @@ -143,47 +156,47 @@ func (c *Local) DialPeers( return c.env.UnsafeDialPeers(c.ctx, peers, persistent, unconditional, private) } -func (c *Local) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { +func (c *Local) BlockchainInfo(_ context.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { return c.env.BlockchainInfo(c.ctx, minHeight, maxHeight) } -func (c *Local) Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) { +func (c *Local) Genesis(context.Context) (*ctypes.ResultGenesis, error) { return c.env.Genesis(c.ctx) } -func (c *Local) GenesisChunked(ctx context.Context, id uint) (*ctypes.ResultGenesisChunk, error) { +func (c *Local) GenesisChunked(_ context.Context, id uint) (*ctypes.ResultGenesisChunk, error) { return c.env.GenesisChunked(c.ctx, id) } -func (c *Local) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) { +func (c *Local) Block(_ context.Context, height *int64) (*ctypes.ResultBlock, error) { return c.env.Block(c.ctx, height) } -func (c *Local) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBlock, error) { +func (c *Local) BlockByHash(_ context.Context, hash []byte) (*ctypes.ResultBlock, error) { return c.env.BlockByHash(c.ctx, hash) } -func (c *Local) BlockResults(ctx context.Context, height *int64) (*ctypes.ResultBlockResults, error) { +func (c *Local) BlockResults(_ context.Context, height *int64) (*ctypes.ResultBlockResults, error) { return c.env.BlockResults(c.ctx, height) } -func (c *Local) Header(ctx context.Context, height *int64) (*ctypes.ResultHeader, error) { +func (c *Local) Header(_ context.Context, height *int64) (*ctypes.ResultHeader, error) { return c.env.Header(c.ctx, height) } -func (c *Local) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*ctypes.ResultHeader, error) { +func (c *Local) HeaderByHash(_ context.Context, hash bytes.HexBytes) (*ctypes.ResultHeader, error) { return c.env.HeaderByHash(c.ctx, hash) } -func (c *Local) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) { +func (c *Local) Commit(_ context.Context, height *int64) (*ctypes.ResultCommit, error) { return c.env.Commit(c.ctx, height) } -func (c *Local) Validators(ctx context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) { +func (c *Local) Validators(_ context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) { return c.env.Validators(c.ctx, height, page, perPage) } -func (c *Local) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { +func (c *Local) Tx(_ context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { return c.env.Tx(c.ctx, hash, prove) } @@ -207,7 +220,7 @@ func (c *Local) BlockSearch( return c.env.BlockSearch(c.ctx, query, page, perPage, orderBy) } -func (c *Local) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { +func (c *Local) BroadcastEvidence(_ context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { return c.env.BroadcastEvidence(c.ctx, ev) } @@ -215,10 +228,11 @@ func (c *Local) Subscribe( ctx context.Context, subscriber, query string, - outCapacity ...int) (out <-chan ctypes.ResultEvent, err error) { + outCapacity ...int, +) (out <-chan ctypes.ResultEvent, err error) { q, err := cmtquery.New(query) if err != nil { - return nil, fmt.Errorf("failed to parse query: %w", err) + return nil, ErrParseQuery{Source: err} } outCap := 1 @@ -233,7 +247,7 @@ func (c *Local) Subscribe( sub, err = c.EventBus.SubscribeUnbuffered(ctx, subscriber, q) } if err != nil { - return nil, fmt.Errorf("failed to subscribe: %w", err) + return nil, rpcclient.ErrSubscribe{Source: err} } outc := make(chan ctypes.ResultEvent, outCap) @@ -246,7 +260,8 @@ func (c *Local) eventsRoutine( sub types.Subscription, subscriber string, q cmtpubsub.Query, - outc chan<- ctypes.ResultEvent) { + outc chan<- ctypes.ResultEvent, +) { for { select { case msg := <-sub.Out(): @@ -297,7 +312,7 @@ func (c *Local) resubscribe(subscriber string, q cmtpubsub.Query) types.Subscrip func (c *Local) Unsubscribe(ctx context.Context, subscriber, query string) error { q, err := cmtquery.New(query) if err != nil { - return fmt.Errorf("failed to parse query: %w", err) + return ErrParseQuery{Source: err} } return c.EventBus.Unsubscribe(ctx, subscriber, q) } diff --git a/rpc/client/main_test.go b/rpc/client/main_test.go index 290ebf35e31..12fdfeee474 100644 --- a/rpc/client/main_test.go +++ b/rpc/client/main_test.go @@ -20,13 +20,13 @@ 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) + // app.SetGenBlockEvents() // needs to be called here (see TestBlockSearch in rpc_test.go) + node = rpctest.StartCometBFT(app) code := m.Run() // and shut down proper at the end - rpctest.StopTendermint(node) + rpctest.StopCometBFT(node) _ = os.RemoveAll(dir) os.Exit(code) } diff --git a/rpc/client/mock/client.go b/rpc/client/mock/client.go index 447ae9c694e..b4e9dc82d27 100644 --- a/rpc/client/mock/client.go +++ b/rpc/client/mock/client.go @@ -18,8 +18,8 @@ import ( "context" "reflect" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/libs/bytes" - "github.com/cometbft/cometbft/libs/service" "github.com/cometbft/cometbft/rpc/client" "github.com/cometbft/cometbft/rpc/core" ctypes "github.com/cometbft/cometbft/rpc/core/types" @@ -53,18 +53,18 @@ var _ client.Client = Client{} // It can also be used to configure mock responses. type Call struct { Name string - Args interface{} - Response interface{} + Args any + Response any Error error } -// GetResponse will generate the apporiate response for us, when +// GetResponse will generate the appropriate response for us, when // using the Call struct to configure a Mock handler. // // When configuring a response, if only one of Response or Error is // set then that will always be returned. If both are set, then // we return Response if the Args match the set args, Error otherwise. -func (c Call) GetResponse(args interface{}) (interface{}, error) { +func (c Call) GetResponse(args any) (any, error) { // handle the case with no response if c.Response == nil { if c.Error == nil { @@ -83,11 +83,11 @@ func (c Call) GetResponse(args interface{}) (interface{}, error) { return nil, c.Error } -func (c Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) { +func (c Client) Status(context.Context) (*ctypes.ResultStatus, error) { return c.env.Status(&rpctypes.Context{}) } -func (c Client) ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) { +func (c Client) ABCIInfo(context.Context) (*ctypes.ResultABCIInfo, error) { return c.env.ABCIInfo(&rpctypes.Context{}) } @@ -96,55 +96,56 @@ func (c Client) ABCIQuery(ctx context.Context, path string, data bytes.HexBytes) } func (c Client) ABCIQueryWithOptions( - ctx context.Context, + _ context.Context, path string, data bytes.HexBytes, - opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { + opts client.ABCIQueryOptions, +) (*ctypes.ResultABCIQuery, error) { return c.env.ABCIQuery(&rpctypes.Context{}, path, data, opts.Height, opts.Prove) } -func (c Client) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { +func (c Client) BroadcastTxCommit(_ context.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { return c.env.BroadcastTxCommit(&rpctypes.Context{}, tx) } -func (c Client) BroadcastTxAsync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { +func (c Client) BroadcastTxAsync(_ context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { return c.env.BroadcastTxAsync(&rpctypes.Context{}, tx) } -func (c Client) BroadcastTxSync(ctx context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { +func (c Client) BroadcastTxSync(_ context.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { return c.env.BroadcastTxSync(&rpctypes.Context{}, tx) } -func (c Client) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { +func (c Client) CheckTx(_ context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { return c.env.CheckTx(&rpctypes.Context{}, tx) } -func (c Client) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) { +func (c Client) NetInfo(_ context.Context) (*ctypes.ResultNetInfo, error) { return c.env.NetInfo(&rpctypes.Context{}) } -func (c Client) ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) { +func (c Client) ConsensusState(_ context.Context) (*ctypes.ResultConsensusState, error) { return c.env.GetConsensusState(&rpctypes.Context{}) } -func (c Client) DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) { +func (c Client) DumpConsensusState(_ context.Context) (*ctypes.ResultDumpConsensusState, error) { return c.env.DumpConsensusState(&rpctypes.Context{}) } -func (c Client) ConsensusParams(ctx context.Context, height *int64) (*ctypes.ResultConsensusParams, error) { +func (c Client) ConsensusParams(_ context.Context, height *int64) (*ctypes.ResultConsensusParams, error) { return c.env.ConsensusParams(&rpctypes.Context{}, height) } -func (c Client) Health(ctx context.Context) (*ctypes.ResultHealth, error) { +func (c Client) Health(_ context.Context) (*ctypes.ResultHealth, error) { return c.env.Health(&rpctypes.Context{}) } -func (c Client) DialSeeds(ctx context.Context, seeds []string) (*ctypes.ResultDialSeeds, error) { +func (c Client) DialSeeds(_ context.Context, seeds []string) (*ctypes.ResultDialSeeds, error) { return c.env.UnsafeDialSeeds(&rpctypes.Context{}, seeds) } func (c Client) DialPeers( - ctx context.Context, + _ context.Context, peers []string, persistent, unconditional, @@ -153,30 +154,30 @@ func (c Client) DialPeers( return c.env.UnsafeDialPeers(&rpctypes.Context{}, peers, persistent, unconditional, private) } -func (c Client) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { +func (c Client) BlockchainInfo(_ context.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { return c.env.BlockchainInfo(&rpctypes.Context{}, minHeight, maxHeight) } -func (c Client) Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) { +func (c Client) Genesis(context.Context) (*ctypes.ResultGenesis, error) { return c.env.Genesis(&rpctypes.Context{}) } -func (c Client) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) { +func (c Client) Block(_ context.Context, height *int64) (*ctypes.ResultBlock, error) { return c.env.Block(&rpctypes.Context{}, height) } -func (c Client) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBlock, error) { +func (c Client) BlockByHash(_ context.Context, hash []byte) (*ctypes.ResultBlock, error) { return c.env.BlockByHash(&rpctypes.Context{}, hash) } -func (c Client) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) { +func (c Client) Commit(_ context.Context, height *int64) (*ctypes.ResultCommit, error) { return c.env.Commit(&rpctypes.Context{}, height) } -func (c Client) Validators(ctx context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) { +func (c Client) Validators(_ context.Context, height *int64, page, perPage *int) (*ctypes.ResultValidators, error) { return c.env.Validators(&rpctypes.Context{}, height, page, perPage) } -func (c Client) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { +func (c Client) BroadcastEvidence(_ context.Context, ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { return c.env.BroadcastEvidence(&rpctypes.Context{}, ev) } diff --git a/rpc/client/mock/status.go b/rpc/client/mock/status.go index a68bcf0d7aa..9d57e54ed8a 100644 --- a/rpc/client/mock/status.go +++ b/rpc/client/mock/status.go @@ -7,7 +7,7 @@ import ( ctypes "github.com/cometbft/cometbft/rpc/core/types" ) -// StatusMock returns the result specified by the Call +// StatusMock returns the result specified by the Call. type StatusMock struct { Call } @@ -17,7 +17,7 @@ var ( _ client.StatusClient = (*StatusRecorder)(nil) ) -func (m *StatusMock) Status(ctx context.Context) (*ctypes.ResultStatus, error) { +func (m *StatusMock) Status(context.Context) (*ctypes.ResultStatus, error) { res, err := m.GetResponse(nil) if err != nil { return nil, err @@ -26,7 +26,7 @@ func (m *StatusMock) Status(ctx context.Context) (*ctypes.ResultStatus, error) { } // StatusRecorder can wrap another type (StatusMock, full client) -// and record the status calls +// and record the status calls. type StatusRecorder struct { Client client.StatusClient Calls []Call diff --git a/rpc/client/mock/status_test.go b/rpc/client/mock/status_test.go index 26bb33caa80..5bc00177eef 100644 --- a/rpc/client/mock/status_test.go +++ b/rpc/client/mock/status_test.go @@ -23,24 +23,25 @@ func TestStatus(t *testing.T) { LatestAppHash: bytes.HexBytes("app"), LatestBlockHeight: 10, }, - }}, + }, + }, } r := mock.NewStatusRecorder(m) - require.Equal(0, len(r.Calls)) + require.Empty(r.Calls) // make sure response works proper status, err := r.Status(context.Background()) - require.Nil(err, "%+v", err) + require.NoError(err, "%+v", err) assert.EqualValues("block", status.SyncInfo.LatestBlockHash) assert.EqualValues(10, status.SyncInfo.LatestBlockHeight) // make sure recorder works properly - require.Equal(1, len(r.Calls)) + require.Len(r.Calls, 1) rs := r.Calls[0] assert.Equal("status", rs.Name) assert.Nil(rs.Args) - assert.Nil(rs.Error) + require.NoError(rs.Error) require.NotNil(rs.Response) st, ok := rs.Response.(*ctypes.ResultStatus) require.True(ok) diff --git a/rpc/client/mocks/client.go b/rpc/client/mocks/client.go index aa612af26cb..b8cb7816008 100644 --- a/rpc/client/mocks/client.go +++ b/rpc/client/mocks/client.go @@ -723,11 +723,11 @@ func (_m *Client) String() string { // Subscribe provides a mock function with given fields: ctx, subscriber, query, outCapacity func (_m *Client) Subscribe(ctx context.Context, subscriber string, query string, outCapacity ...int) (<-chan coretypes.ResultEvent, error) { - _va := make([]interface{}, len(outCapacity)) + _va := make([]any, len(outCapacity)) for _i := range outCapacity { _va[_i] = outCapacity[_i] } - var _ca []interface{} + var _ca []any _ca = append(_ca, ctx, subscriber, query) _ca = append(_ca, _va...) ret := _m.Called(_ca...) diff --git a/rpc/client/rpc_test.go b/rpc/client/rpc_test.go index f9cc2f3d19c..9d6e17bf872 100644 --- a/rpc/client/rpc_test.go +++ b/rpc/client/rpc_test.go @@ -18,7 +18,6 @@ import ( cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" cmtmath "github.com/cometbft/cometbft/libs/math" - mempl "github.com/cometbft/cometbft/mempool" "github.com/cometbft/cometbft/rpc/client" rpchttp "github.com/cometbft/cometbft/rpc/client/http" rpclocal "github.com/cometbft/cometbft/rpc/client/local" @@ -28,13 +27,11 @@ import ( "github.com/cometbft/cometbft/types" ) -var ( - ctx = context.Background() -) +var ctx = context.Background() func getHTTPClient() *rpchttp.HTTP { - rpcAddr := rpctest.GetConfig().RPC.ListenAddress - c, err := rpchttp.New(rpcAddr, "/websocket") + rpcAddr := strings.Replace(rpctest.GetConfig().RPC.ListenAddress, "tcp://", "http://", 1) + c, err := rpchttp.New(rpcAddr + "/v1") if err != nil { panic(err) } @@ -44,7 +41,7 @@ func getHTTPClient() *rpchttp.HTTP { func getHTTPClientWithTimeout(timeout uint) *rpchttp.HTTP { rpcAddr := rpctest.GetConfig().RPC.ListenAddress - c, err := rpchttp.NewWithTimeout(rpcAddr, "/websocket", timeout) + c, err := rpchttp.NewWithTimeout(rpcAddr, timeout) if err != nil { panic(err) } @@ -56,7 +53,7 @@ func getLocalClient() *rpclocal.Local { return rpclocal.New(node) } -// GetClients returns a slice of clients for table-driven tests +// GetClients returns a slice of clients for table-driven tests. func GetClients() []client.Client { return []client.Client{ getHTTPClient(), @@ -66,7 +63,7 @@ func GetClients() []client.Client { func TestNilCustomHTTPClient(t *testing.T) { require.Panics(t, func() { - _, _ = rpchttp.NewWithClient("http://example.com", "/websocket", nil) + _, _ = rpchttp.NewWithClient("http://example.com", nil) }) require.Panics(t, func() { _, _ = rpcclient.NewWithHTTPClient("http://example.com", nil) @@ -75,8 +72,8 @@ func TestNilCustomHTTPClient(t *testing.T) { func TestCustomHTTPClient(t *testing.T) { remote := rpctest.GetConfig().RPC.ListenAddress - c, err := rpchttp.NewWithClient(remote, "/websocket", http.DefaultClient) - require.Nil(t, err) + c, err := rpchttp.NewWithClient(remote, http.DefaultClient) + require.NoError(t, err) status, err := c.Status(context.Background()) require.NoError(t, err) require.NotNil(t, status) @@ -86,34 +83,34 @@ func TestCorsEnabled(t *testing.T) { origin := rpctest.GetConfig().RPC.CORSAllowedOrigins[0] remote := strings.ReplaceAll(rpctest.GetConfig().RPC.ListenAddress, "tcp", "http") - req, err := http.NewRequest("GET", remote, nil) - require.Nil(t, err, "%+v", err) + req, err := http.NewRequest(http.MethodGet, remote, nil) + require.NoError(t, err, "%+v", err) req.Header.Set("Origin", origin) c := &http.Client{} resp, err := c.Do(req) - require.Nil(t, err, "%+v", err) + require.NoError(t, err, "%+v", err) defer resp.Body.Close() assert.Equal(t, resp.Header.Get("Access-Control-Allow-Origin"), origin) } -// Make sure status is correct (we connect properly) +// Make sure status is correct (we connect properly). func TestStatus(t *testing.T) { for i, c := range GetClients() { moniker := rpctest.GetConfig().Moniker status, err := c.Status(context.Background()) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) assert.Equal(t, moniker, status.NodeInfo.Moniker) } } -// Make sure info is correct (we connect properly) +// Make sure info is correct (we connect properly). func TestInfo(t *testing.T) { for i, c := range GetClients() { // status, err := c.Status() // require.Nil(t, err, "%+v", err) info, err := c.ABCIInfo(context.Background()) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) // TODO: this is not correct - fix merkleeyes! // assert.EqualValues(t, status.SyncInfo.LatestBlockHeight, info.Response.LastBlockHeight) assert.True(t, strings.Contains(info.Response.Data, "size")) @@ -125,9 +122,9 @@ func TestNetInfo(t *testing.T) { nc, ok := c.(client.NetworkClient) require.True(t, ok, "%d", i) netinfo, err := nc.NetInfo(context.Background()) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) assert.True(t, netinfo.Listening) - assert.Equal(t, 0, len(netinfo.Peers)) + assert.Empty(t, netinfo.Peers) } } @@ -137,7 +134,7 @@ func TestDumpConsensusState(t *testing.T) { nc, ok := c.(client.NetworkClient) require.True(t, ok, "%d", i) cons, err := nc.DumpConsensusState(context.Background()) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) assert.NotEmpty(t, cons.RoundState) assert.Empty(t, cons.Peers) } @@ -149,7 +146,7 @@ func TestConsensusState(t *testing.T) { nc, ok := c.(client.NetworkClient) require.True(t, ok, "%d", i) cons, err := nc.ConsensusState(context.Background()) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) assert.NotEmpty(t, cons.RoundState) } } @@ -159,25 +156,24 @@ func TestHealth(t *testing.T) { nc, ok := c.(client.NetworkClient) require.True(t, ok, "%d", i) _, err := nc.Health(context.Background()) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) } } func TestGenesisAndValidators(t *testing.T) { for i, c := range GetClients() { - // make sure this is the right genesis file gen, err := c.Genesis(context.Background()) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) // get the genesis validator - require.Equal(t, 1, len(gen.Genesis.Validators)) + require.Len(t, gen.Genesis.Validators, 1) gval := gen.Genesis.Validators[0] // get the current validators h := int64(1) vals, err := c.Validators(context.Background(), &h, nil, nil) - require.Nil(t, err, "%d: %+v", i, err) - require.Equal(t, 1, len(vals.Validators)) + require.NoError(t, err, "%d: %+v", i, err) + require.Len(t, vals.Validators, 1) require.Equal(t, 1, vals.Count) require.Equal(t, 1, vals.Total) val := vals.Validators[0] @@ -203,7 +199,6 @@ func TestGenesisChunked(t *testing.T) { data, err := base64.StdEncoding.DecodeString(chunk.Data) require.NoError(t, err) decoded = append(decoded, string(data)) - } doc := []byte(strings.Join(decoded, "")) @@ -218,7 +213,7 @@ func TestABCIQuery(t *testing.T) { // write something k, v, tx := MakeTxKV() bres, err := c.BroadcastTxCommit(context.Background(), tx) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) apph := bres.Height + 1 // this is where the tx will be applied to the state // wait before querying @@ -226,17 +221,16 @@ func TestABCIQuery(t *testing.T) { require.NoError(t, err) res, err := c.ABCIQuery(context.Background(), "/key", k) qres := res.Response - if assert.Nil(t, err) && assert.True(t, qres.IsOK()) { + if assert.NoError(t, err) && assert.True(t, qres.IsOK()) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.EqualValues(t, v, qres.Value) } } } -// Make some app checks +// Make some app checks. func TestAppCalls(t *testing.T) { assert, require := assert.New(t), require.New(t) for i, c := range GetClients() { - // get an offset of height to avoid racing and guessing s, err := c.Status(context.Background()) require.NoError(err) @@ -278,7 +272,7 @@ func TestAppCalls(t *testing.T) { block, err := c.Block(context.Background(), &apph) require.NoError(err) appHash := block.Block.Header.AppHash - assert.True(len(appHash) > 0) + assert.NotEmpty(appHash) assert.EqualValues(apph, block.Block.Header.Height) blockByHash, err := c.BlockByHash(context.Background(), block.BlockID.Hash) @@ -296,18 +290,18 @@ func TestAppCalls(t *testing.T) { // now check the results blockResults, err := c.BlockResults(context.Background(), &txh) - require.Nil(err, "%d: %+v", i, err) + require.NoError(err, "%d: %+v", i, err) assert.Equal(txh, blockResults.Height) - if assert.Equal(1, len(blockResults.TxsResults)) { + if assert.Len(blockResults.TxResults, 1) { // check success code - assert.EqualValues(0, blockResults.TxsResults[0].Code) + assert.EqualValues(0, blockResults.TxResults[0].Code) } // check blockchain info, now that we know there is info info, err := c.BlockchainInfo(context.Background(), apph, apph) require.NoError(err) - assert.True(info.LastHeight >= apph) - if assert.Equal(1, len(info.BlockMetas)) { + assert.GreaterOrEqual(info.LastHeight, apph) + if assert.Len(info.BlockMetas, 1) { lastMeta := info.BlockMetas[0] assert.EqualValues(apph, lastMeta.Header.Height) blockData := block.Block @@ -329,10 +323,10 @@ func TestAppCalls(t *testing.T) { assert.Equal(block.Block.LastCommitHash, commit2.Commit.Hash()) // and we got a proof that works! - _pres, err := c.ABCIQueryWithOptions(context.Background(), "/key", k, client.ABCIQueryOptions{Prove: true}) + _proofResp, err := c.ABCIQueryWithOptions(context.Background(), "/key", k, client.ABCIQueryOptions{Prove: true}) require.NoError(err) - pres := _pres.Response - assert.True(pres.IsOK()) + proofResp := _proofResp.Response + assert.True(proofResp.IsOK()) // XXX Test proof } @@ -348,8 +342,8 @@ func TestBroadcastTxSync(t *testing.T) { for i, c := range GetClients() { _, _, tx := MakeTxKV() bres, err := c.BroadcastTxSync(context.Background(), tx) - require.Nil(err, "%d: %+v", i, err) - require.Equal(bres.Code, abci.CodeTypeOK) // FIXME + require.NoError(err, "%d: %+v", i, err) + require.Equal(abci.CodeTypeOK, bres.Code) // FIXME require.Equal(initMempoolSize+1, mempool.Size()) @@ -366,7 +360,7 @@ func TestBroadcastTxCommit(t *testing.T) { for i, c := range GetClients() { _, _, tx := MakeTxKV() bres, err := c.BroadcastTxCommit(context.Background(), tx) - require.Nil(err, "%d: %+v", i, err) + require.NoError(err, "%d: %+v", i, err) require.True(bres.CheckTx.IsOK()) require.True(bres.TxResult.IsOK()) @@ -377,10 +371,11 @@ func TestBroadcastTxCommit(t *testing.T) { func TestUnconfirmedTxs(t *testing.T) { _, _, tx := MakeTxKV() - ch := make(chan *abci.ResponseCheckTx, 1) + ch := make(chan *abci.CheckTxResponse, 1) mempool := node.Mempool() - err := mempool.CheckTx(tx, func(resp *abci.ResponseCheckTx) { ch <- resp }, mempl.TxInfo{}) + reqRes, err := mempool.CheckTx(tx) require.NoError(t, err) + ch <- reqRes.Response.GetCheckTx() // wait for tx to arrive in mempoool. select { @@ -407,10 +402,11 @@ func TestUnconfirmedTxs(t *testing.T) { func TestNumUnconfirmedTxs(t *testing.T) { _, _, tx := MakeTxKV() - ch := make(chan *abci.ResponseCheckTx, 1) + ch := make(chan *abci.CheckTxResponse, 1) mempool := node.Mempool() - err := mempool.CheckTx(tx, func(resp *abci.ResponseCheckTx) { ch <- resp }, mempl.TxInfo{}) + reqRes, err := mempool.CheckTx(tx) require.NoError(t, err) + ch <- reqRes.Response.GetCheckTx() // wait for tx to arrive in mempoool. select { @@ -424,7 +420,7 @@ func TestNumUnconfirmedTxs(t *testing.T) { mc, ok := c.(client.MempoolClient) require.True(t, ok, "%d", i) res, err := mc.NumUnconfirmedTxs(context.Background()) - require.Nil(t, err, "%d: %+v", i, err) + require.NoError(t, err, "%d: %+v", i, err) assert.Equal(t, mempoolSize, res.Count) assert.Equal(t, mempoolSize, res.Total) @@ -453,7 +449,7 @@ func TestTx(t *testing.T) { c := getHTTPClient() _, _, tx := MakeTxKV() bres, err := c.BroadcastTxCommit(context.Background(), tx) - require.Nil(t, err, "%+v", err) + require.NoError(t, err, "%+v", err) txHeight := bres.Height txHash := bres.Hash @@ -483,9 +479,9 @@ func TestTx(t *testing.T) { ptx, err := c.Tx(context.Background(), tc.hash, tc.prove) if !tc.valid { - require.NotNil(t, err) + require.Error(t, err) } else { - require.Nil(t, err, "%+v", err) + require.NoError(t, err, "%+v", err) assert.EqualValues(t, txHeight, ptx.Height) assert.EqualValues(t, tx, ptx.Tx) assert.Zero(t, ptx.Index) @@ -495,7 +491,7 @@ func TestTx(t *testing.T) { // time to verify the proof proof := ptx.Proof if tc.prove && assert.EqualValues(t, tx, proof.Data) { - assert.NoError(t, proof.Proof.Verify(proof.RootHash, txHash)) + require.NoError(t, proof.Proof.Verify(proof.RootHash, txHash)) } } } @@ -512,8 +508,8 @@ func TestTxSearchWithTimeout(t *testing.T) { // query using a compositeKey (see kvstore application) result, err := timeoutClient.TxSearch(context.Background(), "app.creator='Cosmoshi Netowoko'", false, nil, nil, "asc") - require.Nil(t, err) - require.Greater(t, len(result.Txs), 0, "expected a lot of transactions") + require.NoError(t, err) + require.NotEmpty(t, result.Txs, "expected a lot of transactions") } // This test does nothing if we do not call app.SetGenBlockEvents() within main_test.go @@ -529,14 +525,18 @@ func TestBlockSearch(t *testing.T) { 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") + result, err := c.BlockSearch(context.Background(), "begin_event.foo = 100", nil, nil, "asc") require.NoError(t, err) blockCount := len(result.Blocks) - require.Equal(t, blockCount, 0) + // if we generate block events within the test (by uncommenting + // the code in line main_test.go:L23) then we expect len(result.Blocks) + // to be at least 5 + // require.GreaterOrEqual(t, blockCount, 5) + // otherwise it is 0 + require.Equal(t, 0, blockCount) } + func TestTxSearch(t *testing.T) { c := getHTTPClient() @@ -558,10 +558,9 @@ func TestTxSearch(t *testing.T) { anotherTxHash := types.Tx("a different tx").Hash() 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") - require.Nil(t, err) + require.NoError(t, err) require.Len(t, result.Txs, 1) require.Equal(t, find.Hash, result.Txs[0].Hash) @@ -574,56 +573,56 @@ func TestTxSearch(t *testing.T) { // time to verify the proof if assert.EqualValues(t, find.Tx, ptx.Proof.Data) { - assert.NoError(t, ptx.Proof.Proof.Verify(ptx.Proof.RootHash, find.Hash)) + require.NoError(t, ptx.Proof.Proof.Verify(ptx.Proof.RootHash, find.Hash)) } // query by height result, err = c.TxSearch(context.Background(), fmt.Sprintf("tx.height=%d", find.Height), true, nil, nil, "asc") - require.Nil(t, err) + require.NoError(t, err) require.Len(t, result.Txs, 1) // query for non existing tx result, err = c.TxSearch(context.Background(), fmt.Sprintf("tx.hash='%X'", anotherTxHash), false, nil, nil, "asc") - require.Nil(t, err) - require.Len(t, result.Txs, 0) + require.NoError(t, err) + require.Empty(t, result.Txs) // query using a compositeKey (see kvstore application) result, err = c.TxSearch(context.Background(), "app.creator='Cosmoshi Netowoko'", false, nil, nil, "asc") - require.Nil(t, err) - require.Greater(t, len(result.Txs), 0, "expected a lot of transactions") + require.NoError(t, err) + require.NotEmpty(t, result.Txs, "expected a lot of transactions") // query using an index key result, err = c.TxSearch(context.Background(), "app.index_key='index is working'", false, nil, nil, "asc") - require.Nil(t, err) - require.Greater(t, len(result.Txs), 0, "expected a lot of transactions") + require.NoError(t, err) + require.NotEmpty(t, len(result.Txs), "expected a lot of transactions") // query using an noindex key result, err = c.TxSearch(context.Background(), "app.noindex_key='index is working'", false, nil, nil, "asc") - require.Nil(t, err) - require.Equal(t, len(result.Txs), 0, "expected a lot of transactions") + require.NoError(t, err) + require.Empty(t, result.Txs) // query using a compositeKey (see kvstore application) and height result, err = c.TxSearch(context.Background(), "app.creator='Cosmoshi Netowoko' AND tx.height<10000", true, nil, nil, "asc") - require.Nil(t, err) - require.Greater(t, len(result.Txs), 0, "expected a lot of transactions") + require.NoError(t, err) + require.NotEmpty(t, result.Txs, "expected a lot of transactions") // query a non existing tx with page 1 and txsPerPage 1 perPage := 1 result, err = c.TxSearch(context.Background(), "app.creator='Cosmoshi Neetowoko'", true, nil, &perPage, "asc") - require.Nil(t, err) - require.Len(t, result.Txs, 0) + require.NoError(t, err) + require.Empty(t, result.Txs) // check sorting result, err = c.TxSearch(context.Background(), "tx.height >= 1", false, nil, nil, "asc") - require.Nil(t, err) + require.NoError(t, err) for k := 0; k < len(result.Txs)-1; k++ { require.LessOrEqual(t, result.Txs[k].Height, result.Txs[k+1].Height) require.LessOrEqual(t, result.Txs[k].Index, result.Txs[k+1].Index) } result, err = c.TxSearch(context.Background(), "tx.height >= 1", false, nil, nil, "desc") - require.Nil(t, err) + require.NoError(t, err) for k := 0; k < len(result.Txs)-1; k++ { require.GreaterOrEqual(t, result.Txs[k].Height, result.Txs[k+1].Height) require.GreaterOrEqual(t, result.Txs[k].Index, result.Txs[k+1].Index) @@ -667,6 +666,7 @@ func TestBatchedJSONRPCCalls(t *testing.T) { } func testBatchedJSONRPCCalls(t *testing.T, c *rpchttp.HTTP) { + t.Helper() k1, v1, tx1 := MakeTxKV() k2, v2, tx2 := MakeTxKV() diff --git a/rpc/core/abci.go b/rpc/core/abci.go index 3152c080df7..84e1d35a9f2 100644 --- a/rpc/core/abci.go +++ b/rpc/core/abci.go @@ -13,13 +13,13 @@ import ( // ABCIQuery queries the application for some information. // More: https://docs.cometbft.com/main/rpc/#/ABCI/abci_query func (env *Environment) ABCIQuery( - ctx *rpctypes.Context, + _ *rpctypes.Context, path string, data bytes.HexBytes, height int64, prove bool, ) (*ctypes.ResultABCIQuery, error) { - resQuery, err := env.ProxyAppQuery.Query(context.TODO(), &abci.RequestQuery{ + resQuery, err := env.ProxyAppQuery.Query(context.TODO(), &abci.QueryRequest{ Path: path, Data: data, Height: height, @@ -34,8 +34,8 @@ func (env *Environment) ABCIQuery( // ABCIInfo gets some info about the application. // More: https://docs.cometbft.com/main/rpc/#/ABCI/abci_info -func (env *Environment) ABCIInfo(ctx *rpctypes.Context) (*ctypes.ResultABCIInfo, error) { - resInfo, err := env.ProxyAppQuery.Info(context.TODO(), proxy.RequestInfo) +func (env *Environment) ABCIInfo(_ *rpctypes.Context) (*ctypes.ResultABCIInfo, error) { + resInfo, err := env.ProxyAppQuery.Info(context.TODO(), proxy.InfoRequest) if err != nil { return nil, err } diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index ce8b1871b5b..d69a59bef11 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -1,16 +1,14 @@ package core import ( - "errors" - "fmt" "sort" + cmtquery "github.com/cometbft/cometbft/internal/pubsub/query" + blockidxnull "github.com/cometbft/cometbft/internal/state/indexer/block/null" "github.com/cometbft/cometbft/libs/bytes" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtquery "github.com/cometbft/cometbft/libs/pubsub/query" ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" - blockidxnull "github.com/cometbft/cometbft/state/indexer/block/null" "github.com/cometbft/cometbft/types" ) @@ -25,9 +23,9 @@ import ( // // More: https://docs.cometbft.com/main/rpc/#/Info/blockchain func (env *Environment) BlockchainInfo( - ctx *rpctypes.Context, - minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { - + _ *rpctypes.Context, + minHeight, maxHeight int64, +) (*ctypes.ResultBlockchainInfo, error) { const limit int64 = 20 var err error minHeight, maxHeight, err = filterMinMax( @@ -49,16 +47,17 @@ func (env *Environment) BlockchainInfo( return &ctypes.ResultBlockchainInfo{ LastHeight: env.BlockStore.Height(), - BlockMetas: blockMetas}, nil + BlockMetas: blockMetas, + }, nil } // error if either min or max are negative or min > max // if 0, use blockstore base for min, latest block height for max // enforce limit. -func filterMinMax(base, height, min, max, limit int64) (int64, int64, error) { +func filterMinMax(base, height, min, max, limit int64) (minHeight, maxHeight int64, err error) { // filter negatives if min < 0 || max < 0 { - return min, max, fmt.Errorf("heights must be non-negative") + return min, max, ErrNegativeHeight } // adjust for default values @@ -80,7 +79,7 @@ func filterMinMax(base, height, min, max, limit int64) (int64, int64, error) { min = cmtmath.MaxInt64(min, max-limit+1) if min > max { - return min, max, fmt.Errorf("min height %d can't be greater than max height %d", min, max) + return min, max, ErrHeightMinGTMax{Min: min, Max: max} } return min, max, nil } @@ -88,7 +87,7 @@ func filterMinMax(base, height, min, max, limit int64) (int64, int64, error) { // Header gets block header at a given height. // If no height is provided, it will fetch the latest header. // More: https://docs.cometbft.com/main/rpc/#/Info/header -func (env *Environment) Header(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultHeader, error) { +func (env *Environment) Header(_ *rpctypes.Context, heightPtr *int64) (*ctypes.ResultHeader, error) { height, err := env.getHeight(env.BlockStore.Height(), heightPtr) if err != nil { return nil, err @@ -104,7 +103,7 @@ func (env *Environment) Header(ctx *rpctypes.Context, heightPtr *int64) (*ctypes // HeaderByHash gets header by hash. // More: https://docs.cometbft.com/main/rpc/#/Info/header_by_hash -func (env *Environment) HeaderByHash(ctx *rpctypes.Context, hash bytes.HexBytes) (*ctypes.ResultHeader, error) { +func (env *Environment) HeaderByHash(_ *rpctypes.Context, hash bytes.HexBytes) (*ctypes.ResultHeader, error) { // N.B. The hash parameter is HexBytes so that the reflective parameter // decoding logic in the HTTP service will correctly translate from JSON. // See https://github.com/tendermint/tendermint/issues/6802 for context. @@ -120,14 +119,13 @@ func (env *Environment) HeaderByHash(ctx *rpctypes.Context, hash bytes.HexBytes) // Block gets block at a given height. // If no height is provided, it will fetch the latest block. // More: https://docs.cometbft.com/main/rpc/#/Info/block -func (env *Environment) Block(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlock, error) { +func (env *Environment) Block(_ *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlock, error) { height, err := env.getHeight(env.BlockStore.Height(), heightPtr) if err != nil { return nil, err } - block := env.BlockStore.LoadBlock(height) - blockMeta := env.BlockStore.LoadBlockMeta(height) + block, blockMeta := env.BlockStore.LoadBlock(height) if blockMeta == nil { return &ctypes.ResultBlock{BlockID: types.BlockID{}, Block: block}, nil } @@ -136,20 +134,18 @@ func (env *Environment) Block(ctx *rpctypes.Context, heightPtr *int64) (*ctypes. // BlockByHash gets block by hash. // More: https://docs.cometbft.com/main/rpc/#/Info/block_by_hash -func (env *Environment) BlockByHash(ctx *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error) { - block := env.BlockStore.LoadBlockByHash(hash) - if block == nil { +func (env *Environment) BlockByHash(_ *rpctypes.Context, hash []byte) (*ctypes.ResultBlock, error) { + block, blockMeta := env.BlockStore.LoadBlockByHash(hash) + if blockMeta == nil { return &ctypes.ResultBlock{BlockID: types.BlockID{}, Block: nil}, nil } - // If block is not nil, then blockMeta can't be nil. - blockMeta := env.BlockStore.LoadBlockMeta(block.Height) return &ctypes.ResultBlock{BlockID: blockMeta.BlockID, Block: block}, nil } // Commit gets block commit at a given height. // If no height is provided, it will fetch the commit for the latest block. // More: https://docs.cometbft.com/main/rpc/#/Info/commit -func (env *Environment) Commit(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCommit, error) { +func (env *Environment) Commit(_ *rpctypes.Context, heightPtr *int64) (*ctypes.ResultCommit, error) { height, err := env.getHeight(env.BlockStore.Height(), heightPtr) if err != nil { return nil, err @@ -180,7 +176,7 @@ func (env *Environment) Commit(ctx *rpctypes.Context, heightPtr *int64) (*ctypes // Thus response.results.deliver_tx[5] is the results of executing // getBlock(h).Txs[5] // More: https://docs.cometbft.com/main/rpc/#/Info/block_results -func (env *Environment) BlockResults(ctx *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlockResults, error) { +func (env *Environment) BlockResults(_ *rpctypes.Context, heightPtr *int64) (*ctypes.ResultBlockResults, error) { height, err := env.getHeight(env.BlockStore.Height(), heightPtr) if err != nil { return nil, err @@ -193,7 +189,7 @@ func (env *Environment) BlockResults(ctx *rpctypes.Context, heightPtr *int64) (* return &ctypes.ResultBlockResults{ Height: height, - TxsResults: results.TxResults, + TxResults: results.TxResults, FinalizeBlockEvents: results.Events, ValidatorUpdates: results.ValidatorUpdates, ConsensusParamUpdates: results.ConsensusParamUpdates, @@ -208,10 +204,9 @@ func (env *Environment) BlockSearch( pagePtr, perPagePtr *int, orderBy string, ) (*ctypes.ResultBlockSearch, error) { - // skip if block indexing is disabled if _, ok := env.BlockIndexer.(*blockidxnull.BlockerIndexer); ok { - return nil, errors.New("block indexing is disabled") + return nil, ErrBlockIndexing } q, err := cmtquery.New(query) @@ -233,7 +228,7 @@ func (env *Environment) BlockSearch( sort.Slice(results, func(i, j int) bool { return results[i] < results[j] }) default: - return nil, errors.New("expected order_by to be either `asc` or `desc` or empty") + return nil, ErrInvalidOrderBy{orderBy} } // paginate results @@ -250,15 +245,12 @@ func (env *Environment) BlockSearch( apiResults := make([]*ctypes.ResultBlock, 0, pageSize) for i := skipCount; i < skipCount+pageSize; i++ { - block := env.BlockStore.LoadBlock(results[i]) - if block != nil { - blockMeta := env.BlockStore.LoadBlockMeta(block.Height) - if blockMeta != nil { - apiResults = append(apiResults, &ctypes.ResultBlock{ - Block: block, - BlockID: blockMeta.BlockID, - }) - } + block, blockMeta := env.BlockStore.LoadBlock(results[i]) + if blockMeta != nil { + apiResults = append(apiResults, &ctypes.ResultBlock{ + Block: block, + BlockID: blockMeta.BlockID, + }) } } diff --git a/rpc/core/blocks_test.go b/rpc/core/blocks_test.go index 88bf57ceb4d..bc4e0bdb469 100644 --- a/rpc/core/blocks_test.go +++ b/rpc/core/blocks_test.go @@ -8,12 +8,11 @@ import ( "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" - abci "github.com/cometbft/cometbft/abci/types" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/mocks" ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/mocks" ) func TestBlockchainInfo(t *testing.T) { @@ -68,7 +67,7 @@ func TestBlockchainInfo(t *testing.T) { } func TestBlockResults(t *testing.T) { - results := &abci.ResponseFinalizeBlock{ + results := &abci.FinalizeBlockResponse{ TxResults: []*abci.ExecTxResult{ {Code: 0, Data: []byte{0x01}, Log: "ok"}, {Code: 0, Data: []byte{0x02}, Log: "ok"}, @@ -97,7 +96,7 @@ func TestBlockResults(t *testing.T) { {101, true, nil}, {100, false, &ctypes.ResultBlockResults{ Height: 100, - TxsResults: results.TxResults, + TxResults: results.TxResults, FinalizeBlockEvents: results.Events, ValidatorUpdates: results.ValidatorUpdates, ConsensusParamUpdates: results.ConsensusParamUpdates, @@ -107,9 +106,9 @@ func TestBlockResults(t *testing.T) { for _, tc := range testCases { res, err := env.BlockResults(&rpctypes.Context{}, &tc.height) if tc.wantErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tc.wantRes, res) } } diff --git a/rpc/core/consensus.go b/rpc/core/consensus.go index b39c090ff3e..a33a4919c74 100644 --- a/rpc/core/consensus.go +++ b/rpc/core/consensus.go @@ -1,8 +1,11 @@ package core import ( - cm "github.com/cometbft/cometbft/consensus" + "fmt" + + cm "github.com/cometbft/cometbft/internal/consensus" cmtmath "github.com/cometbft/cometbft/libs/math" + "github.com/cometbft/cometbft/p2p" ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" "github.com/cometbft/cometbft/types" @@ -16,10 +19,10 @@ import ( // // More: https://docs.cometbft.com/main/rpc/#/Info/validators func (env *Environment) Validators( - ctx *rpctypes.Context, + _ *rpctypes.Context, heightPtr *int64, - pagePtr, perPagePtr *int) (*ctypes.ResultValidators, error) { - + pagePtr, perPagePtr *int, +) (*ctypes.ResultValidators, error) { // The latest validator that we know is the NextValidator of the last block. height, err := env.getHeight(env.latestUncommittedHeight(), heightPtr) if err != nil { @@ -46,32 +49,38 @@ func (env *Environment) Validators( BlockHeight: height, Validators: v, Count: len(v), - Total: totalCount}, nil + Total: totalCount, + }, nil } // DumpConsensusState dumps consensus state. // UNSTABLE // More: https://docs.cometbft.com/main/rpc/#/Info/dump_consensus_state -func (env *Environment) DumpConsensusState(ctx *rpctypes.Context) (*ctypes.ResultDumpConsensusState, error) { +func (env *Environment) DumpConsensusState(*rpctypes.Context) (*ctypes.ResultDumpConsensusState, error) { // Get Peer consensus states. - peers := env.P2PPeers.Peers().List() - peerStates := make([]ctypes.PeerStateInfo, len(peers)) - for i, peer := range peers { + peerStates := make([]ctypes.PeerStateInfo, 0) + var err error + env.P2PPeers.Peers().ForEach(func(peer p2p.Peer) { peerState, ok := peer.Get(types.PeerStateKey).(*cm.PeerState) if !ok { // peer does not have a state yet - continue + return } - peerStateJSON, err := peerState.MarshalJSON() - if err != nil { - return nil, err + peerStateJSON, marshalErr := peerState.MarshalJSON() + if marshalErr != nil { + err = fmt.Errorf("failed to marshal peer %v state: %w", peer.ID(), marshalErr) + return } - peerStates[i] = ctypes.PeerStateInfo{ + peerStates = append(peerStates, ctypes.PeerStateInfo{ // Peer basic info. NodeAddress: peer.SocketAddr().String(), // Peer consensus state. PeerState: peerStateJSON, - } + }) + }) + if err != nil { + return nil, err } + // Get self round state. roundState, err := env.ConsensusState.GetRoundStateJSON() if err != nil { @@ -79,13 +88,14 @@ func (env *Environment) DumpConsensusState(ctx *rpctypes.Context) (*ctypes.Resul } return &ctypes.ResultDumpConsensusState{ RoundState: roundState, - Peers: peerStates}, nil + Peers: peerStates, + }, nil } // ConsensusState returns a concise summary of the consensus state. // UNSTABLE // More: https://docs.cometbft.com/main/rpc/#/Info/consensus_state -func (env *Environment) GetConsensusState(ctx *rpctypes.Context) (*ctypes.ResultConsensusState, error) { +func (env *Environment) GetConsensusState(*rpctypes.Context) (*ctypes.ResultConsensusState, error) { // Get self round state. bz, err := env.ConsensusState.GetRoundStateSimpleJSON() return &ctypes.ResultConsensusState{RoundState: bz}, err @@ -95,9 +105,9 @@ func (env *Environment) GetConsensusState(ctx *rpctypes.Context) (*ctypes.Result // If no height is provided, it will fetch the latest consensus params. // More: https://docs.cometbft.com/main/rpc/#/Info/consensus_params func (env *Environment) ConsensusParams( - ctx *rpctypes.Context, - heightPtr *int64) (*ctypes.ResultConsensusParams, error) { - + _ *rpctypes.Context, + heightPtr *int64, +) (*ctypes.ResultConsensusParams, error) { // The latest consensus params that we know is the consensus params after the // last block. height, err := env.getHeight(env.latestUncommittedHeight(), heightPtr) @@ -111,5 +121,6 @@ func (env *Environment) ConsensusParams( } return &ctypes.ResultConsensusParams{ BlockHeight: height, - ConsensusParams: consensusParams}, nil + ConsensusParams: consensusParams, + }, nil } diff --git a/rpc/core/dev.go b/rpc/core/dev.go index 90f035531f8..389c96ee03c 100644 --- a/rpc/core/dev.go +++ b/rpc/core/dev.go @@ -6,7 +6,7 @@ import ( ) // UnsafeFlushMempool removes all transactions from the mempool. -func (env *Environment) UnsafeFlushMempool(ctx *rpctypes.Context) (*ctypes.ResultUnsafeFlushMempool, error) { +func (env *Environment) UnsafeFlushMempool(*rpctypes.Context) (*ctypes.ResultUnsafeFlushMempool, error) { env.Mempool.Flush() return &ctypes.ResultUnsafeFlushMempool{}, nil } diff --git a/rpc/core/doc.go b/rpc/core/doc.go index dbd76ac69ca..6427a7d32ed 100644 --- a/rpc/core/doc.go +++ b/rpc/core/doc.go @@ -9,7 +9,7 @@ https://github.com/cometbft/cometbft/tree/main/rpc/jsonrpc. An HTTP Get request to the root RPC endpoint shows a list of available endpoints. ```bash -curl 'localhost:26657' +curl "http://localhost:26657" | textutil -stdin -convert txt -stdout | sed 's/\/\/localhost:26657//g' ``` > Response: @@ -19,27 +19,37 @@ Available endpoints: /abci_info /dump_consensus_state /genesis +/health /net_info /num_unconfirmed_txs /status -/health -/unconfirmed_txs /unsafe_flush_mempool -/validators +/unsubscribe_all? Endpoints that require arguments: -/abci_query?path=_&data=_&prove=_ +/abci_query?path=_&data=_&height=_&prove=_ /block?height=_ +/block_by_hash?hash=_ +/block_results?height=_ +/block_search?query=_&page=_&per_page=_&order_by=_ /blockchain?minHeight=_&maxHeight=_ +/broadcast_evidence?evidence=_ /broadcast_tx_async?tx=_ /broadcast_tx_commit?tx=_ /broadcast_tx_sync?tx=_ +/check_tx?tx=_ /commit?height=_ -/dial_seeds?seeds=_ -/dial_persistent_peers?persistent_peers=_ -/subscribe?event=_ +/consensus_params?height=_ +/consensus_state? +/genesis_chunked?chunk=_ +/header?height=_ +/header_by_hash?hash=_ +/subscribe?query=_ /tx?hash=_&prove=_ -/unsubscribe?event=_ +/tx_search?query=_&prove=_&page=_&per_page=_&order_by=_ +/unconfirmed_txs?limit=_ +/unsubscribe?query=_ +/validators?height=_&page=_&per_page=_ ``` */ package core diff --git a/rpc/core/env.go b/rpc/core/env.go index 9dc27b7c131..4682e15493c 100644 --- a/rpc/core/env.go +++ b/rpc/core/env.go @@ -7,32 +7,31 @@ import ( cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/state/indexer" + "github.com/cometbft/cometbft/internal/state/txindex" cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" mempl "github.com/cometbft/cometbft/mempool" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/proxy" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/state/txindex" "github.com/cometbft/cometbft/types" ) const ( - // see README + // see README. defaultPerPage = 30 maxPerPage = 100 // SubscribeTimeout is the maximum time we wait to subscribe for an event. - // must be less than the server's write timeout (see rpcserver.DefaultConfig) + // must be less than the server's write timeout (see rpcserver.DefaultConfig). SubscribeTimeout = 5 * time.Second // genesisChunkSize is the maximum size, in bytes, of each - // chunk in the genesis structure for the chunked API + // chunk in the genesis structure for the chunked API. genesisChunkSize = 16 * 1024 * 1024 // 16 ) -//---------------------------------------------- // These interfaces are used by RPC and must be thread safe type Consensus interface { @@ -50,18 +49,18 @@ type transport interface { } type peers interface { - AddPersistentPeers([]string) error - AddUnconditionalPeerIDs([]string) error - AddPrivatePeerIDs([]string) error - DialPeersAsync([]string) error + AddPersistentPeers(peers []string) error + AddUnconditionalPeerIDs(peerIDs []string) error + AddPrivatePeerIDs(peerIDs []string) error + DialPeersAsync(peers []string) error Peers() p2p.IPeerSet } -type consensusReactor interface { +// A reactor that transitions from block sync or state sync to consensus mode. +type syncReactor interface { WaitSync() bool } -// ---------------------------------------------- // Environment contains objects and interfaces used by the RPC. It is expected // to be setup once during startup. type Environment struct { @@ -74,7 +73,8 @@ type Environment struct { BlockStore sm.BlockStore EvidencePool sm.EvidencePool ConsensusState Consensus - ConsensusReactor consensusReactor + ConsensusReactor syncReactor + MempoolReactor syncReactor P2PPeers peers P2PTransport transport @@ -94,8 +94,6 @@ type Environment struct { genChunks []string } -//---------------------------------------------- - func validatePage(pagePtr *int, perPage, totalCount int) (int, error) { if perPage < 1 { panic(fmt.Sprintf("zero or negative perPage: %d", perPage)) @@ -117,7 +115,7 @@ func validatePage(pagePtr *int, perPage, totalCount int) (int, error) { return page, nil } -func (env *Environment) validatePerPage(perPagePtr *int) int { +func (*Environment) validatePerPage(perPagePtr *int) int { if perPagePtr == nil { // no per_page parameter return defaultPerPage } diff --git a/rpc/core/env_test.go b/rpc/core/env_test.go index dc64db1d6ae..19909dc4562 100644 --- a/rpc/core/env_test.go +++ b/rpc/core/env_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestPaginationPage(t *testing.T) { @@ -42,7 +43,7 @@ func TestPaginationPage(t *testing.T) { for _, c := range cases { p, err := validatePage(&c.page, c.perPage, c.totalCount) if c.expErr { - assert.Error(t, err) + require.Error(t, err) continue } @@ -51,7 +52,7 @@ func TestPaginationPage(t *testing.T) { // nil case p, err := validatePage(nil, 1, 1) - if assert.NoError(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, 1, p) } } diff --git a/rpc/core/errors.go b/rpc/core/errors.go new file mode 100644 index 00000000000..b79b0dc5f40 --- /dev/null +++ b/rpc/core/errors.go @@ -0,0 +1,161 @@ +package core + +import ( + "errors" + "fmt" +) + +var ( + ErrNegativeHeight = errors.New("negative height") + ErrBlockIndexing = errors.New("block indexing is disabled") + ErrTxIndexingDisabled = errors.New("transaction indexing is disabled") + ErrNoEvidence = errors.New("no evidence was provided") + ErrSlowClient = errors.New("slow client") + ErrCometBFTExited = errors.New("cometBFT exited") + ErrConfirmationNotReceived = errors.New("broadcast confirmation not received") + ErrCheckTxFailed = errors.New("transaction failed to pass CheckTx") + ErrTimedOutWaitingForTx = errors.New("timed out waiting for tx to be included in a block") + ErrGenesisRespSize = errors.New("genesis response is too large, please use the genesis_chunked API instead") + ErrChunkNotInitialized = errors.New("genesis chunks are not initialized") + ErrNoChunks = errors.New("no chunks") +) + +type ErrMaxSubscription struct { + Max int +} + +func (e ErrMaxSubscription) Error() string { + return fmt.Sprintf("maximum number of subscriptions reached: %d", e.Max) +} + +type ErrMaxPerClientSubscription struct { + Max int +} + +func (e ErrMaxPerClientSubscription) Error() string { + return fmt.Sprintf("maximum number of subscriptions per client reached: %d", e.Max) +} + +type ErrHeightMinGTMax struct { + Min int64 + Max int64 +} + +func (e ErrHeightMinGTMax) Error() string { + return fmt.Sprintf("min height %d can't be greater than max height %d", e.Min, e.Max) +} + +type ErrQueryLength struct { + length int + maxLength int +} + +func (e ErrQueryLength) Error() string { + return fmt.Sprintf("maximum query length exceeded: length %d, max_length %d", e.length, e.maxLength) +} + +type ErrValidation struct { + Source error + ValType string +} + +func (e ErrValidation) Error() string { + return fmt.Sprintf("%s validation failed: %s", e.ValType, e.Source) +} + +func (e ErrValidation) Unwrap() error { return e.Source } + +type ErrAddEvidence struct { + Source error +} + +func (e ErrAddEvidence) Error() string { + return fmt.Sprintf("failed to add evidence: %s", e.Source) +} + +func (e ErrAddEvidence) Unwrap() error { + return e.Source +} + +type ErrSubCanceled struct { + Reason string +} + +func (e ErrSubCanceled) Error() string { + return fmt.Sprintf("subscription canceled: (reason: %s)", e.Reason) +} + +type ErrTxSubFailed struct { + Source error + TxHash []byte +} + +func (e ErrTxSubFailed) Error() string { + return fmt.Sprintf("failed to subscribe to tx %X: %s", e.TxHash, e.Source) +} + +func (e ErrTxSubFailed) Unwrap() error { + return e.Source +} + +type ErrTxBroadcast struct { + Source error + ErrReason error +} + +func (e ErrTxBroadcast) Error() string { + return fmt.Sprintf("failed to broadcast tx: %v: %v", e.ErrReason, e.Source) +} + +func (e ErrTxBroadcast) Unwrap() error { + return e.Source +} + +func (e ErrTxBroadcast) Reason() error { + return e.ErrReason +} + +type ErrServiceConfig struct { + Source error +} + +func (e ErrServiceConfig) Error() string { + return fmt.Sprintf("service configuration error: %s", e.Source) +} + +func (e ErrServiceConfig) Unwrap() error { return e.Source } + +type ErrInvalidChunkID struct { + RequestedID int + MaxID int +} + +func (e ErrInvalidChunkID) Error() string { + return fmt.Sprintf("invalid chunk ID: length %d but maximum available is %d", e.RequestedID, e.MaxID) +} + +type ErrTxNotFound struct { + Hash []byte +} + +func (e ErrTxNotFound) Error() string { + return fmt.Sprintf("tx not found: %X", e.Hash) +} + +type ErrInvalidOrderBy struct { + OrderBy string +} + +func (e ErrInvalidOrderBy) Error() string { + return "invalid order_by: maxLength either `asc` or `desc` or an empty value but got " + e.OrderBy +} + +type ErrInvalidNodeType struct { + PeerID string + Expected string + Actual string +} + +func (e ErrInvalidNodeType) Error() string { + return fmt.Sprintf("peer %s has an invalid node type: maxLength %s but got %s", e.PeerID, e.Expected, e.Actual) +} diff --git a/rpc/core/events.go b/rpc/core/events.go index a4da11a1b73..2bec271aa1f 100644 --- a/rpc/core/events.go +++ b/rpc/core/events.go @@ -6,8 +6,8 @@ import ( "fmt" "time" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - cmtquery "github.com/cometbft/cometbft/libs/pubsub/query" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + cmtquery "github.com/cometbft/cometbft/internal/pubsub/query" ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) @@ -18,24 +18,37 @@ const ( maxQueryLength = 512 ) +type ErrParseQuery struct { + Source error +} + +func (e ErrParseQuery) Error() string { + return fmt.Sprintf("failed to parse query: %v", e.Source) +} + +func (e ErrParseQuery) Unwrap() error { + return e.Source +} + // Subscribe for events via WebSocket. // More: https://docs.cometbft.com/main/rpc/#/Websocket/subscribe func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, error) { addr := ctx.RemoteAddr() - if env.EventBus.NumClients() >= env.Config.MaxSubscriptionClients { - return nil, fmt.Errorf("max_subscription_clients %d reached", env.Config.MaxSubscriptionClients) - } else if env.EventBus.NumClientSubscriptions(addr) >= env.Config.MaxSubscriptionsPerClient { - return nil, fmt.Errorf("max_subscriptions_per_client %d reached", env.Config.MaxSubscriptionsPerClient) - } else if len(query) > maxQueryLength { - return nil, errors.New("maximum query length exceeded") + switch { + case env.EventBus.NumClients() >= env.Config.MaxSubscriptionClients: + return nil, ErrMaxSubscription{env.Config.MaxSubscriptionClients} + case env.EventBus.NumClientSubscriptions(addr) >= env.Config.MaxSubscriptionsPerClient: + return nil, ErrMaxPerClientSubscription{env.Config.MaxSubscriptionsPerClient} + case len(query) > maxQueryLength: + return nil, ErrQueryLength{len(query), maxQueryLength} } env.Logger.Info("Subscribe to query", "remote", addr, "query", query) q, err := cmtquery.New(query) if err != nil { - return nil, fmt.Errorf("failed to parse query: %w", err) + return nil, ErrParseQuery{Source: err} } subCtx, cancel := context.WithTimeout(ctx.Context(), SubscribeTimeout) @@ -66,7 +79,7 @@ func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*ctypes. if closeIfSlow { var ( - err = errors.New("subscription was canceled (reason: slow client)") + err = ErrSubCanceled{ErrSlowClient.Error()} resp = rpctypes.RPCServerError(subscriptionID, err) ) if !ctx.WSConn.TryWriteRPCResponse(resp) { @@ -77,15 +90,15 @@ func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*ctypes. } } case <-sub.Canceled(): - if sub.Err() != cmtpubsub.ErrUnsubscribed { + if !errors.Is(sub.Err(), cmtpubsub.ErrUnsubscribed) { var reason string if sub.Err() == nil { - reason = "CometBFT exited" + reason = ErrCometBFTExited.Error() } else { reason = sub.Err().Error() } var ( - err = fmt.Errorf("subscription was canceled (reason: %s)", reason) + err = ErrSubCanceled{reason} resp = rpctypes.RPCServerError(subscriptionID, err) ) if !ctx.WSConn.TryWriteRPCResponse(resp) { @@ -108,12 +121,14 @@ func (env *Environment) Unsubscribe(ctx *rpctypes.Context, query string) (*ctype env.Logger.Info("Unsubscribe from query", "remote", addr, "query", query) q, err := cmtquery.New(query) if err != nil { - return nil, fmt.Errorf("failed to parse query: %w", err) + return nil, ErrParseQuery{Source: err} } + err = env.EventBus.Unsubscribe(context.Background(), addr, q) if err != nil { return nil, err } + return &ctypes.ResultUnsubscribe{}, nil } diff --git a/rpc/core/evidence.go b/rpc/core/evidence.go index 38bb862562e..ecf01f98823 100644 --- a/rpc/core/evidence.go +++ b/rpc/core/evidence.go @@ -1,8 +1,7 @@ package core import ( - "errors" - "fmt" + "reflect" ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" @@ -12,19 +11,23 @@ import ( // BroadcastEvidence broadcasts evidence of the misbehavior. // More: https://docs.cometbft.com/main/rpc/#/Evidence/broadcast_evidence func (env *Environment) BroadcastEvidence( - ctx *rpctypes.Context, - ev types.Evidence) (*ctypes.ResultBroadcastEvidence, error) { - + _ *rpctypes.Context, + ev types.Evidence, +) (*ctypes.ResultBroadcastEvidence, error) { if ev == nil { - return nil, errors.New("no evidence was provided") + return nil, ErrNoEvidence } if err := ev.ValidateBasic(); err != nil { - return nil, fmt.Errorf("evidence.ValidateBasic failed: %w", err) + return nil, ErrValidation{ + Source: err, + ValType: reflect.TypeOf(ev).String(), + } } if err := env.EvidencePool.AddEvidence(ev); err != nil { - return nil, fmt.Errorf("failed to add evidence: %w", err) + return nil, ErrAddEvidence{err} } + return &ctypes.ResultBroadcastEvidence{Hash: ev.Hash()}, nil } diff --git a/rpc/core/health.go b/rpc/core/health.go index 322e6af7aa9..628d6ed4dec 100644 --- a/rpc/core/health.go +++ b/rpc/core/health.go @@ -8,6 +8,6 @@ import ( // Health gets node health. Returns empty result (200 OK) on success, no // response - in case of an error. // More: https://docs.cometbft.com/main/rpc/#/Info/health -func (env *Environment) Health(ctx *rpctypes.Context) (*ctypes.ResultHealth, error) { +func (*Environment) Health(*rpctypes.Context) (*ctypes.ResultHealth, error) { return &ctypes.ResultHealth{}, nil } diff --git a/rpc/core/mempool.go b/rpc/core/mempool.go index 17e2c323910..2bb7ca1c73d 100644 --- a/rpc/core/mempool.go +++ b/rpc/core/mempool.go @@ -3,25 +3,27 @@ package core import ( "context" "errors" - "fmt" "time" abci "github.com/cometbft/cometbft/abci/types" - mempl "github.com/cometbft/cometbft/mempool" ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" "github.com/cometbft/cometbft/types" ) -//----------------------------------------------------------------------------- +var ErrEndpointClosedCatchingUp = errors.New("endpoint is closed while node is catching up") + +// ----------------------------------------------------------------------------- // NOTE: tx should be signed, but this is only checked at the app level (not by CometBFT!) // BroadcastTxAsync returns right away, with no response. Does not wait for // CheckTx nor transaction results. // More: https://docs.cometbft.com/main/rpc/#/Tx/broadcast_tx_async -func (env *Environment) BroadcastTxAsync(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { - err := env.Mempool.CheckTx(tx, nil, mempl.TxInfo{}) - +func (env *Environment) BroadcastTxAsync(_ *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { + if env.MempoolReactor.WaitSync() { + return nil, ErrEndpointClosedCatchingUp + } + _, err := env.Mempool.CheckTx(tx) if err != nil { return nil, err } @@ -32,21 +34,24 @@ func (env *Environment) BroadcastTxAsync(ctx *rpctypes.Context, tx types.Tx) (*c // the transaction result. // More: https://docs.cometbft.com/main/rpc/#/Tx/broadcast_tx_sync func (env *Environment) BroadcastTxSync(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { - resCh := make(chan *abci.ResponseCheckTx, 1) - err := env.Mempool.CheckTx(tx, func(res *abci.ResponseCheckTx) { - select { - case <-ctx.Context().Done(): - case resCh <- res: - } + if env.MempoolReactor.WaitSync() { + return nil, ErrEndpointClosedCatchingUp + } - }, mempl.TxInfo{}) + resCh := make(chan *abci.CheckTxResponse, 1) + reqRes, err := env.Mempool.CheckTx(tx) if err != nil { return nil, err } - + reqRes.SetCallback(func(_ *abci.Response) { + select { + case <-ctx.Context().Done(): + case resCh <- reqRes.Response.GetCheckTx(): + } + }) select { case <-ctx.Context().Done(): - return nil, fmt.Errorf("broadcast confirmation not received: %w", ctx.Context().Err()) + return nil, ErrTxBroadcast{Source: ctx.Context().Err(), ErrReason: ErrConfirmationNotReceived} case res := <-resCh: return &ctypes.ResultBroadcastTx{ Code: res.Code, @@ -61,12 +66,16 @@ func (env *Environment) BroadcastTxSync(ctx *rpctypes.Context, tx types.Tx) (*ct // BroadcastTxCommit returns with the responses from CheckTx and ExecTxResult. // More: https://docs.cometbft.com/main/rpc/#/Tx/broadcast_tx_commit func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { + if env.MempoolReactor.WaitSync() { + return nil, ErrEndpointClosedCatchingUp + } + subscriber := ctx.RemoteAddr() if env.EventBus.NumClients() >= env.Config.MaxSubscriptionClients { - return nil, fmt.Errorf("max_subscription_clients %d reached", env.Config.MaxSubscriptionClients) + return nil, ErrMaxSubscription{env.Config.MaxSubscriptionClients} } else if env.EventBus.NumClientSubscriptions(subscriber) >= env.Config.MaxSubscriptionsPerClient { - return nil, fmt.Errorf("max_subscriptions_per_client %d reached", env.Config.MaxSubscriptionsPerClient) + return nil, ErrMaxPerClientSubscription{env.Config.MaxSubscriptionsPerClient} } // Subscribe to tx being committed in block. @@ -75,7 +84,7 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (* q := types.EventQueryTxFor(tx) txSub, err := env.EventBus.Subscribe(subCtx, subscriber, q) if err != nil { - err = fmt.Errorf("failed to subscribe to tx: %w", err) + err = ErrTxSubFailed{Source: err, TxHash: tx.Hash()} env.Logger.Error("Error on broadcast_tx_commit", "err", err) return nil, err } @@ -86,20 +95,21 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (* }() // Broadcast tx and wait for CheckTx result - checkTxResCh := make(chan *abci.ResponseCheckTx, 1) - err = env.Mempool.CheckTx(tx, func(res *abci.ResponseCheckTx) { - select { - case <-ctx.Context().Done(): - case checkTxResCh <- res: - } - }, mempl.TxInfo{}) + checkTxResCh := make(chan *abci.CheckTxResponse, 1) + reqRes, err := env.Mempool.CheckTx(tx) if err != nil { env.Logger.Error("Error on broadcastTxCommit", "err", err) - return nil, fmt.Errorf("error on broadcastTxCommit: %v", err) + return nil, ErrTxBroadcast{Source: err, ErrReason: ErrCheckTxFailed} } + reqRes.SetCallback(func(_ *abci.Response) { + select { + case <-ctx.Context().Done(): + case checkTxResCh <- reqRes.Response.GetCheckTx(): + } + }) select { case <-ctx.Context().Done(): - return nil, fmt.Errorf("broadcast confirmation not received: %w", ctx.Context().Err()) + return nil, ErrTxBroadcast{Source: ctx.Context().Err(), ErrReason: ErrConfirmationNotReceived} case checkTxRes := <-checkTxResCh: if checkTxRes.Code != abci.CodeTypeOK { return &ctypes.ResultBroadcastTxCommit{ @@ -122,11 +132,11 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (* case <-txSub.Canceled(): var reason string if txSub.Err() == nil { - reason = "CometBFT exited" + reason = ErrCometBFTExited.Error() } else { reason = txSub.Err().Error() } - err = fmt.Errorf("txSub was canceled (reason: %s)", reason) + err = ErrSubCanceled{reason} env.Logger.Error("Error on broadcastTxCommit", "err", err) return &ctypes.ResultBroadcastTxCommit{ CheckTx: *checkTxRes, @@ -134,7 +144,7 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (* Hash: tx.Hash(), }, err case <-time.After(env.Config.TimeoutBroadcastTxCommit): - err = errors.New("timed out waiting for tx to be included in a block") + err = ErrTimedOutWaitingForTx env.Logger.Error("Error on broadcastTxCommit", "err", err) return &ctypes.ResultBroadcastTxCommit{ CheckTx: *checkTxRes, @@ -148,7 +158,7 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (* // UnconfirmedTxs gets unconfirmed transactions (maximum ?limit entries) // including their number. // More: https://docs.cometbft.com/main/rpc/#/Info/unconfirmed_txs -func (env *Environment) UnconfirmedTxs(ctx *rpctypes.Context, limitPtr *int) (*ctypes.ResultUnconfirmedTxs, error) { +func (env *Environment) UnconfirmedTxs(_ *rpctypes.Context, limitPtr *int) (*ctypes.ResultUnconfirmedTxs, error) { // reuse per_page validator limit := env.validatePerPage(limitPtr) @@ -157,25 +167,27 @@ func (env *Environment) UnconfirmedTxs(ctx *rpctypes.Context, limitPtr *int) (*c Count: len(txs), Total: env.Mempool.Size(), TotalBytes: env.Mempool.SizeBytes(), - Txs: txs}, nil + Txs: txs, + }, nil } // NumUnconfirmedTxs gets number of unconfirmed transactions. // More: https://docs.cometbft.com/main/rpc/#/Info/num_unconfirmed_txs -func (env *Environment) NumUnconfirmedTxs(ctx *rpctypes.Context) (*ctypes.ResultUnconfirmedTxs, error) { +func (env *Environment) NumUnconfirmedTxs(*rpctypes.Context) (*ctypes.ResultUnconfirmedTxs, error) { return &ctypes.ResultUnconfirmedTxs{ Count: env.Mempool.Size(), Total: env.Mempool.Size(), - TotalBytes: env.Mempool.SizeBytes()}, nil + TotalBytes: env.Mempool.SizeBytes(), + }, nil } // CheckTx checks the transaction without executing it. The transaction won't // be added to the mempool either. // More: https://docs.cometbft.com/main/rpc/#/Tx/check_tx -func (env *Environment) CheckTx(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { - res, err := env.ProxyAppMempool.CheckTx(context.TODO(), &abci.RequestCheckTx{Tx: tx}) +func (env *Environment) CheckTx(_ *rpctypes.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { + res, err := env.ProxyAppMempool.CheckTx(context.TODO(), &abci.CheckTxRequest{Tx: tx, Type: abci.CHECK_TX_TYPE_CHECK}) if err != nil { return nil, err } - return &ctypes.ResultCheckTx{ResponseCheckTx: *res}, nil + return &ctypes.ResultCheckTx{CheckTxResponse: *res}, nil } diff --git a/rpc/core/net.go b/rpc/core/net.go index 0a619910e61..3f73e0908e3 100644 --- a/rpc/core/net.go +++ b/rpc/core/net.go @@ -12,13 +12,18 @@ import ( // NetInfo returns network info. // More: https://docs.cometbft.com/main/rpc/#/Info/net_info -func (env *Environment) NetInfo(ctx *rpctypes.Context) (*ctypes.ResultNetInfo, error) { - peersList := env.P2PPeers.Peers().List() - peers := make([]ctypes.Peer, 0, len(peersList)) - for _, peer := range peersList { +func (env *Environment) NetInfo(*rpctypes.Context) (*ctypes.ResultNetInfo, error) { + peers := make([]ctypes.Peer, 0) + var err error + env.P2PPeers.Peers().ForEach(func(peer p2p.Peer) { nodeInfo, ok := peer.NodeInfo().(p2p.DefaultNodeInfo) if !ok { - return nil, fmt.Errorf("peer.NodeInfo() is not DefaultNodeInfo") + err = ErrInvalidNodeType{ + PeerID: string(peer.ID()), + Expected: fmt.Sprintf("%T", p2p.DefaultNodeInfo{}), + Actual: fmt.Sprintf("%T", peer.NodeInfo()), + } + return } peers = append(peers, ctypes.Peer{ NodeInfo: nodeInfo, @@ -26,6 +31,9 @@ func (env *Environment) NetInfo(ctx *rpctypes.Context) (*ctypes.ResultNetInfo, e ConnectionStatus: peer.Status(), RemoteIP: peer.RemoteIP().String(), }) + }) + if err != nil { + return nil, err } // TODO: Should we include PersistentPeers and Seeds in here? // PRO: useful info @@ -39,7 +47,7 @@ func (env *Environment) NetInfo(ctx *rpctypes.Context) (*ctypes.ResultNetInfo, e } // UnsafeDialSeeds dials the given seeds (comma-separated id@IP:PORT). -func (env *Environment) UnsafeDialSeeds(ctx *rpctypes.Context, seeds []string) (*ctypes.ResultDialSeeds, error) { +func (env *Environment) UnsafeDialSeeds(_ *rpctypes.Context, seeds []string) (*ctypes.ResultDialSeeds, error) { if len(seeds) == 0 { return &ctypes.ResultDialSeeds{}, errors.New("no seeds provided") } @@ -53,10 +61,10 @@ func (env *Environment) UnsafeDialSeeds(ctx *rpctypes.Context, seeds []string) ( // UnsafeDialPeers dials the given peers (comma-separated id@IP:PORT), // optionally making them persistent. func (env *Environment) UnsafeDialPeers( - ctx *rpctypes.Context, + _ *rpctypes.Context, peers []string, - persistent, unconditional, private bool) (*ctypes.ResultDialPeers, error) { - + persistent, unconditional, private bool, +) (*ctypes.ResultDialPeers, error) { if len(peers) == 0 { return &ctypes.ResultDialPeers{}, errors.New("no peers provided") } @@ -96,27 +104,27 @@ func (env *Environment) UnsafeDialPeers( // Genesis returns genesis file. // More: https://docs.cometbft.com/main/rpc/#/Info/genesis -func (env *Environment) Genesis(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) { +func (env *Environment) Genesis(*rpctypes.Context) (*ctypes.ResultGenesis, error) { if len(env.genChunks) > 1 { - return nil, errors.New("genesis response is large, please use the genesis_chunked API instead") + return nil, ErrGenesisRespSize } return &ctypes.ResultGenesis{Genesis: env.GenDoc}, nil } -func (env *Environment) GenesisChunked(ctx *rpctypes.Context, chunk uint) (*ctypes.ResultGenesisChunk, error) { +func (env *Environment) GenesisChunked(_ *rpctypes.Context, chunk uint) (*ctypes.ResultGenesisChunk, error) { if env.genChunks == nil { - return nil, fmt.Errorf("service configuration error, genesis chunks are not initialized") + return nil, ErrServiceConfig{ErrChunkNotInitialized} } if len(env.genChunks) == 0 { - return nil, fmt.Errorf("service configuration error, there are no chunks") + return nil, ErrServiceConfig{ErrNoChunks} } id := int(chunk) if id > len(env.genChunks)-1 { - return nil, fmt.Errorf("there are %d chunks, %d is invalid", len(env.genChunks)-1, id) + return nil, ErrInvalidChunkID{id, len(env.genChunks) - 1} } return &ctypes.ResultGenesisChunk{ @@ -130,13 +138,11 @@ func getIDs(peers []string) ([]string, error) { ids := make([]string, 0, len(peers)) for _, peer := range peers { - spl := strings.Split(peer, "@") if len(spl) != 2 { return nil, p2p.ErrNetAddressNoID{Addr: peer} } ids = append(ids, spl[0]) - } return ids, nil } diff --git a/rpc/core/net_test.go b/rpc/core/net_test.go index 29feccecb7a..d1b58b3497f 100644 --- a/rpc/core/net_test.go +++ b/rpc/core/net_test.go @@ -13,8 +13,8 @@ import ( ) func TestUnsafeDialSeeds(t *testing.T) { - sw := p2p.MakeSwitch(cfg.DefaultP2PConfig(), 1, "testing", "123.123.123", - func(n int, sw *p2p.Switch) *p2p.Switch { return sw }) + sw := p2p.MakeSwitch(cfg.DefaultP2PConfig(), 1, + func(_ int, sw *p2p.Switch) *p2p.Switch { return sw }) err := sw.Start() require.NoError(t, err) t.Cleanup(func() { @@ -39,17 +39,17 @@ func TestUnsafeDialSeeds(t *testing.T) { for _, tc := range testCases { res, err := env.UnsafeDialSeeds(&rpctypes.Context{}, tc.seeds) if tc.isErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, res) } } } func TestUnsafeDialPeers(t *testing.T) { - sw := p2p.MakeSwitch(cfg.DefaultP2PConfig(), 1, "testing", "123.123.123", - func(n int, sw *p2p.Switch) *p2p.Switch { return sw }) + sw := p2p.MakeSwitch(cfg.DefaultP2PConfig(), 1, + func(_ int, sw *p2p.Switch) *p2p.Switch { return sw }) sw.SetAddrBook(&p2p.AddrBookMock{ Addrs: make(map[string]struct{}), OurAddrs: make(map[string]struct{}), @@ -80,9 +80,9 @@ func TestUnsafeDialPeers(t *testing.T) { for _, tc := range testCases { res, err := env.UnsafeDialPeers(&rpctypes.Context{}, tc.peers, tc.persistence, tc.unconditional, tc.private) if tc.isErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, res) } } diff --git a/rpc/core/status.go b/rpc/core/status.go index 29cba7cbeed..6f56d1a9cdc 100644 --- a/rpc/core/status.go +++ b/rpc/core/status.go @@ -13,7 +13,7 @@ import ( // Status returns CometBFT status including node info, pubkey, latest block // hash, app hash, block height and time. // More: https://docs.cometbft.com/main/rpc/#/Info/status -func (env *Environment) Status(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) { +func (env *Environment) Status(*rpctypes.Context) (*ctypes.ResultStatus, error) { var ( earliestBlockHeight int64 earliestBlockHash cmtbytes.HexBytes diff --git a/rpc/core/tx.go b/rpc/core/tx.go index d84ed3a955a..9dc7eb6edc5 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -1,15 +1,13 @@ package core import ( - "errors" - "fmt" "sort" + cmtquery "github.com/cometbft/cometbft/internal/pubsub/query" + "github.com/cometbft/cometbft/internal/state/txindex/null" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtquery "github.com/cometbft/cometbft/libs/pubsub/query" ctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" - "github.com/cometbft/cometbft/state/txindex/null" "github.com/cometbft/cometbft/types" ) @@ -17,10 +15,10 @@ import ( // transaction is in the mempool, invalidated, or was not sent in the first // place. // More: https://docs.cometbft.com/main/rpc/#/Info/tx -func (env *Environment) Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { +func (env *Environment) Tx(_ *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { // if index is disabled, return error if _, ok := env.TxIndexer.(*null.TxIndex); ok { - return nil, fmt.Errorf("transaction indexing is disabled") + return nil, ErrTxIndexingDisabled } r, err := env.TxIndexer.Get(hash) @@ -29,12 +27,12 @@ func (env *Environment) Tx(ctx *rpctypes.Context, hash []byte, prove bool) (*cty } if r == nil { - return nil, fmt.Errorf("tx (%X) not found", hash) + return nil, ErrTxNotFound{hash} } var proof types.TxProof if prove { - block := env.BlockStore.LoadBlock(r.Height) + block, _ := env.BlockStore.LoadBlock(r.Height) proof = block.Data.Txs.Proof(int(r.Index)) } @@ -58,12 +56,11 @@ func (env *Environment) TxSearch( pagePtr, perPagePtr *int, orderBy string, ) (*ctypes.ResultTxSearch, error) { - // if index is disabled, return error if _, ok := env.TxIndexer.(*null.TxIndex); ok { - return nil, errors.New("transaction indexing is disabled") + return nil, ErrTxIndexingDisabled } else if len(query) > maxQueryLength { - return nil, errors.New("maximum query length exceeded") + return nil, ErrQueryLength{len(query), maxQueryLength} } q, err := cmtquery.New(query) @@ -93,7 +90,7 @@ func (env *Environment) TxSearch( return results[i].Height < results[j].Height }) default: - return nil, errors.New("expected order_by to be either `asc` or `desc` or empty") + return nil, ErrInvalidOrderBy{orderBy} } // paginate results @@ -114,7 +111,7 @@ func (env *Environment) TxSearch( var proof types.TxProof if prove { - block := env.BlockStore.LoadBlock(r.Height) + block, _ := env.BlockStore.LoadBlock(r.Height) proof = block.Data.Txs.Proof(int(r.Index)) } diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go index 36d3ef87306..c2a0aed91cc 100644 --- a/rpc/core/types/responses.go +++ b/rpc/core/types/responses.go @@ -4,21 +4,21 @@ import ( "encoding/json" "time" - abci "github.com/cometbft/cometbft/abci/types" + abcitypes "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/libs/bytes" "github.com/cometbft/cometbft/p2p" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cometbft/cometbft/types" ) -// List of blocks +// List of blocks. type ResultBlockchainInfo struct { LastHeight int64 `json:"last_height"` BlockMetas []*types.BlockMeta `json:"block_metas"` } -// Genesis file +// Genesis file. type ResultGenesis struct { Genesis *types.GenesisDoc `json:"genesis"` } @@ -33,38 +33,38 @@ type ResultGenesisChunk struct { Data string `json:"data"` } -// Single block (with meta) +// Single block (with meta). type ResultBlock struct { BlockID types.BlockID `json:"block_id"` Block *types.Block `json:"block"` } -// ResultHeader represents the response for a Header RPC Client query +// ResultHeader represents the response for a Header RPC Client query. type ResultHeader struct { Header *types.Header `json:"header"` } -// Commit and Header +// Commit and Header. type ResultCommit struct { types.SignedHeader `json:"signed_header"` CanonicalCommit bool `json:"canonical"` } -// ABCI results from a block +// ABCI results from a block. type ResultBlockResults struct { - Height int64 `json:"height"` - TxsResults []*abci.ExecTxResult `json:"txs_results"` - FinalizeBlockEvents []abci.Event `json:"finalize_block_events"` - ValidatorUpdates []abci.ValidatorUpdate `json:"validator_updates"` - ConsensusParamUpdates *cmtproto.ConsensusParams `json:"consensus_param_updates"` - AppHash []byte `json:"app_hash"` + Height int64 `json:"height"` + TxResults []*abcitypes.ExecTxResult `json:"txs_results"` + FinalizeBlockEvents []abcitypes.Event `json:"finalize_block_events"` + ValidatorUpdates []abcitypes.ValidatorUpdate `json:"validator_updates"` + ConsensusParamUpdates *cmtproto.ConsensusParams `json:"consensus_param_updates"` + AppHash []byte `json:"app_hash"` } // NewResultCommit is a helper to initialize the ResultCommit with -// the embedded struct +// the embedded struct. func NewResultCommit(header *types.Header, commit *types.Commit, - canonical bool) *ResultCommit { - + canonical bool, +) *ResultCommit { return &ResultCommit{ SignedHeader: types.SignedHeader{ Header: header, @@ -74,7 +74,7 @@ func NewResultCommit(header *types.Header, commit *types.Commit, } } -// Info about the node's syncing state +// Info about the node's syncing state. type SyncInfo struct { LatestBlockHash bytes.HexBytes `json:"latest_block_hash"` LatestAppHash bytes.HexBytes `json:"latest_app_hash"` @@ -89,21 +89,21 @@ type SyncInfo struct { CatchingUp bool `json:"catching_up"` } -// Info about the node's validator +// Info about the node's validator. type ValidatorInfo struct { Address bytes.HexBytes `json:"address"` PubKey crypto.PubKey `json:"pub_key"` VotingPower int64 `json:"voting_power"` } -// Node Status +// Node Status. type ResultStatus struct { NodeInfo p2p.DefaultNodeInfo `json:"node_info"` SyncInfo SyncInfo `json:"sync_info"` ValidatorInfo ValidatorInfo `json:"validator_info"` } -// Is TxIndexing enabled +// Is TxIndexing enabled. func (s *ResultStatus) TxIndexEnabled() bool { if s == nil { return false @@ -111,7 +111,7 @@ func (s *ResultStatus) TxIndexEnabled() bool { return s.NodeInfo.Other.TxIndex == "on" } -// Info about peer connections +// Info about peer connections. type ResultNetInfo struct { Listening bool `json:"listening"` Listeners []string `json:"listeners"` @@ -119,17 +119,17 @@ type ResultNetInfo struct { Peers []Peer `json:"peers"` } -// Log from dialing seeds +// Log from dialing seeds. type ResultDialSeeds struct { Log string `json:"log"` } -// Log from dialing peers +// Log from dialing peers. type ResultDialPeers struct { Log string `json:"log"` } -// A peer +// A peer. type Peer struct { NodeInfo p2p.DefaultNodeInfo `json:"node_info"` IsOutbound bool `json:"is_outbound"` @@ -147,31 +147,31 @@ type ResultValidators struct { Total int `json:"total"` } -// ConsensusParams for given height +// ConsensusParams for given height. type ResultConsensusParams struct { BlockHeight int64 `json:"block_height"` ConsensusParams types.ConsensusParams `json:"consensus_params"` } // Info about the consensus state. -// UNSTABLE +// UNSTABLE. type ResultDumpConsensusState struct { RoundState json.RawMessage `json:"round_state"` Peers []PeerStateInfo `json:"peers"` } -// UNSTABLE +// UNSTABLE. type PeerStateInfo struct { NodeAddress string `json:"node_address"` PeerState json.RawMessage `json:"peer_state"` } -// UNSTABLE +// UNSTABLE. type ResultConsensusState struct { RoundState json.RawMessage `json:"round_state"` } -// CheckTx result +// CheckTx result. type ResultBroadcastTx struct { Code uint32 `json:"code"` Data bytes.HexBytes `json:"data"` @@ -181,30 +181,30 @@ type ResultBroadcastTx struct { Hash bytes.HexBytes `json:"hash"` } -// CheckTx and ExecTx results +// CheckTx and ExecTx results. type ResultBroadcastTxCommit struct { - CheckTx abci.ResponseCheckTx `json:"check_tx"` - TxResult abci.ExecTxResult `json:"tx_result"` - Hash bytes.HexBytes `json:"hash"` - Height int64 `json:"height"` + CheckTx abcitypes.CheckTxResponse `json:"check_tx"` + TxResult abcitypes.ExecTxResult `json:"tx_result"` + Hash bytes.HexBytes `json:"hash"` + Height int64 `json:"height"` } -// ResultCheckTx wraps abci.ResponseCheckTx. +// ResultCheckTx wraps abci.CheckTxResponse. type ResultCheckTx struct { - abci.ResponseCheckTx + abcitypes.CheckTxResponse } -// Result of querying for a tx +// Result of querying for a tx. type ResultTx struct { - Hash bytes.HexBytes `json:"hash"` - Height int64 `json:"height"` - Index uint32 `json:"index"` - TxResult abci.ExecTxResult `json:"tx_result"` - Tx types.Tx `json:"tx"` - Proof types.TxProof `json:"proof,omitempty"` + Hash bytes.HexBytes `json:"hash"` + Height int64 `json:"height"` + Index uint32 `json:"index"` + TxResult abcitypes.ExecTxResult `json:"tx_result"` + Tx types.Tx `json:"tx"` + Proof types.TxProof `json:"proof,omitempty"` } -// Result of searching for txs +// Result of searching for txs. type ResultTxSearch struct { Txs []*ResultTx `json:"txs"` TotalCount int `json:"total_count"` @@ -216,7 +216,7 @@ type ResultBlockSearch struct { TotalCount int `json:"total_count"` } -// List of mempool txs +// List of mempool txs. type ResultUnconfirmedTxs struct { Count int `json:"n_txs"` Total int `json:"total"` @@ -224,22 +224,22 @@ type ResultUnconfirmedTxs struct { Txs []types.Tx `json:"txs"` } -// Info abci msg +// Info abci msg. type ResultABCIInfo struct { - Response abci.ResponseInfo `json:"response"` + Response abcitypes.InfoResponse `json:"response"` } -// Query abci msg +// Query abci msg. type ResultABCIQuery struct { - Response abci.ResponseQuery `json:"response"` + Response abcitypes.QueryResponse `json:"response"` } -// Result of broadcasting evidence +// Result of broadcasting evidence. type ResultBroadcastEvidence struct { Hash []byte `json:"hash"` } -// empty results +// empty results. type ( ResultUnsafeFlushMempool struct{} ResultUnsafeProfile struct{} @@ -248,7 +248,7 @@ type ( ResultHealth struct{} ) -// Event data from a subscription +// Event data from a subscription. type ResultEvent struct { Query string `json:"query"` Data types.TMEventData `json:"data"` diff --git a/rpc/grpc/api.go b/rpc/grpc/api.go deleted file mode 100644 index 08031991dc4..00000000000 --- a/rpc/grpc/api.go +++ /dev/null @@ -1,40 +0,0 @@ -package coregrpc - -import ( - "context" - - abci "github.com/cometbft/cometbft/abci/types" - core "github.com/cometbft/cometbft/rpc/core" - rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" -) - -type broadcastAPI struct { - env *core.Environment -} - -func (bapi *broadcastAPI) Ping(ctx context.Context, req *RequestPing) (*ResponsePing, error) { - // kvstore so we can check if the server is up - return &ResponsePing{}, nil -} - -func (bapi *broadcastAPI) BroadcastTx(ctx context.Context, req *RequestBroadcastTx) (*ResponseBroadcastTx, error) { - // NOTE: there's no way to get client's remote address - // see https://stackoverflow.com/questions/33684570/session-and-remote-ip-address-in-grpc-go - res, err := bapi.env.BroadcastTxCommit(&rpctypes.Context{}, req.Tx) - if err != nil { - return nil, err - } - - return &ResponseBroadcastTx{ - CheckTx: &abci.ResponseCheckTx{ - Code: res.CheckTx.Code, - Data: res.CheckTx.Data, - Log: res.CheckTx.Log, - }, - TxResult: &abci.ExecTxResult{ - Code: res.TxResult.Code, - Data: res.TxResult.Data, - Log: res.TxResult.Log, - }, - }, nil -} diff --git a/rpc/grpc/client/block_results_service.go b/rpc/grpc/client/block_results_service.go new file mode 100644 index 00000000000..fb88acb00e2 --- /dev/null +++ b/rpc/grpc/client/block_results_service.go @@ -0,0 +1,62 @@ +package client + +import ( + "context" + + "github.com/cosmos/gogoproto/grpc" + + abci "github.com/cometbft/cometbft/abci/types" + brs "github.com/cometbft/cometbft/api/cometbft/services/block_results/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" +) + +type BlockResults struct { + Height int64 `json:"height"` + TxResults []*abci.ExecTxResult `json:"txs_results"` + FinalizeBlockEvents []*abci.Event `json:"finalize_block_events"` + ValidatorUpdates []*abci.ValidatorUpdate `json:"validator_updates"` + ConsensusParamUpdates *cmtproto.ConsensusParams `json:"consensus_param_updates"` + AppHash []byte `json:"app_hash"` +} + +// BlockResultsServiceClient provides the block results of a given height (or latest if none provided). +type BlockResultsServiceClient interface { + GetBlockResults(ctx context.Context, height int64) (*BlockResults, error) +} + +type blockResultServiceClient struct { + client brs.BlockResultsServiceClient +} + +func (b blockResultServiceClient) GetBlockResults(ctx context.Context, height int64) (*BlockResults, error) { + res, err := b.client.GetBlockResults(ctx, &brs.GetBlockResultsRequest{Height: height}) + if err != nil { + return nil, ErrBlockResults{Height: height, Source: err} + } + + return &BlockResults{ + Height: res.Height, + TxResults: res.TxResults, + FinalizeBlockEvents: res.FinalizeBlockEvents, + ValidatorUpdates: res.ValidatorUpdates, + ConsensusParamUpdates: res.ConsensusParamUpdates, + AppHash: res.AppHash, + }, nil +} + +func newBlockResultsServiceClient(conn grpc.ClientConn) BlockResultsServiceClient { + return &blockResultServiceClient{ + client: brs.NewBlockResultsServiceClient(conn), + } +} + +type disabledBlockResultsServiceClient struct{} + +func newDisabledBlockResultsServiceClient() BlockResultsServiceClient { + return &disabledBlockResultsServiceClient{} +} + +// GetBlockResults implements BlockResultsServiceClient. +func (*disabledBlockResultsServiceClient) GetBlockResults(_ context.Context, _ int64) (*BlockResults, error) { + panic("block results service client is disabled") +} diff --git a/rpc/grpc/client/block_service.go b/rpc/grpc/client/block_service.go new file mode 100644 index 00000000000..73c4765b35e --- /dev/null +++ b/rpc/grpc/client/block_service.go @@ -0,0 +1,151 @@ +package client + +import ( + "context" + + "github.com/cosmos/gogoproto/grpc" + + blocksvc "github.com/cometbft/cometbft/api/cometbft/services/block/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/types" +) + +// Block data returned by the CometBFT BlockService gRPC API. +type Block struct { + BlockID *types.BlockID `json:"block_id"` + Block *types.Block `json:"block"` +} + +func blockFromProto(pblockID *cmtproto.BlockID, pblock *cmtproto.Block) (*Block, error) { + blockID, err := types.BlockIDFromProto(pblockID) + if err != nil { + return nil, err + } + + block, err := types.BlockFromProto(pblock) + if err != nil { + return nil, err + } + + return &Block{ + BlockID: blockID, + Block: block, + }, nil +} + +// LatestHeightResult type used in GetLatestResult and send to the client +// via a channel. +type LatestHeightResult struct { + Height int64 + Error error +} + +type getLatestHeightConfig struct { + chSize uint +} + +type GetLatestHeightOption func(*getLatestHeightConfig) + +// GetLatestHeightChannelSize allows control over the channel size. If not used +// or the channel size is set to 0, an unbuffered channel will be created. +func GetLatestHeightChannelSize(sz uint) GetLatestHeightOption { + return func(opts *getLatestHeightConfig) { + opts.chSize = sz + } +} + +// BlockServiceClient provides block information. +type BlockServiceClient interface { + // GetBlockByHeight attempts to retrieve the block associated with the + // given height. + GetBlockByHeight(ctx context.Context, height int64) (*Block, error) + + // GetLatestHeight provides sends the latest committed block height to the + // resulting output channel as blocks are committed. + GetLatestHeight(ctx context.Context, opts ...GetLatestHeightOption) (<-chan LatestHeightResult, error) +} + +type blockServiceClient struct { + client blocksvc.BlockServiceClient +} + +func newBlockServiceClient(conn grpc.ClientConn) BlockServiceClient { + return &blockServiceClient{ + client: blocksvc.NewBlockServiceClient(conn), + } +} + +// GetBlockByHeight implements BlockServiceClient GetBlockByHeight. +func (c *blockServiceClient) GetBlockByHeight(ctx context.Context, height int64) (*Block, error) { + res, err := c.client.GetByHeight(ctx, &blocksvc.GetByHeightRequest{ + Height: height, + }) + if err != nil { + return nil, err + } + + return blockFromProto(res.BlockId, res.Block) +} + +// GetLatestHeight implements BlockServiceClient GetLatestHeight. +func (c *blockServiceClient) GetLatestHeight(ctx context.Context, opts ...GetLatestHeightOption) (<-chan LatestHeightResult, error) { + req := blocksvc.GetLatestHeightRequest{} + + latestHeightClient, err := c.client.GetLatestHeight(ctx, &req) + if err != nil { + return nil, ErrStreamSetup{Source: err} + } + + cfg := &getLatestHeightConfig{} + for _, opt := range opts { + opt(cfg) + } + resultCh := make(chan LatestHeightResult, cfg.chSize) + + go func(client blocksvc.BlockService_GetLatestHeightClient) { + defer close(resultCh) + for { + response, err := client.Recv() + if err != nil { + res := LatestHeightResult{Error: ErrStreamReceive{Source: err}} + select { + case <-ctx.Done(): + case resultCh <- res: + } + return + } + res := LatestHeightResult{Height: response.Height} + select { + case <-ctx.Done(): + return + case resultCh <- res: + default: + // Skip sending this result because the channel is full - the + // client will get the next one once the channel opens up again + } + } + }(latestHeightClient) + + return resultCh, nil +} + +type disabledBlockServiceClient struct{} + +func newDisabledBlockServiceClient() BlockServiceClient { + return &disabledBlockServiceClient{} +} + +// GetBlockByHeight implements BlockServiceClient GetBlockByHeight - disabled client. +func (*disabledBlockServiceClient) GetBlockByHeight(context.Context, int64) (*Block, error) { + panic("block service client is disabled") +} + +// GetLatestBlock implements BlockServiceClient. +func (*disabledBlockServiceClient) GetLatestBlock(context.Context) (*Block, error) { + panic("block service client is disabled") +} + +// GetLatestHeight implements BlockServiceClient GetLatestHeight - disabled client. +func (*disabledBlockServiceClient) GetLatestHeight(context.Context, ...GetLatestHeightOption) (<-chan LatestHeightResult, error) { + panic("block service client is disabled") +} diff --git a/rpc/grpc/client/client.go b/rpc/grpc/client/client.go new file mode 100644 index 00000000000..1f2f94654bc --- /dev/null +++ b/rpc/grpc/client/client.go @@ -0,0 +1,142 @@ +// Note that no auto-generated gRPC code is directly exposed via the client +// interface. This is on purpose to minimize the potential impact on users of +// switching to Google's Go code generator in future. See +// https://github.com/cometbft/cometbft/issues/731 for more details. +package client + +import ( + "context" + "net" + + ggrpc "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + cmtnet "github.com/cometbft/cometbft/internal/net" +) + +type Option func(*clientBuilder) + +// Client defines the full client interface for interacting with a CometBFT +// node via gRPC. +type Client interface { + VersionServiceClient + BlockServiceClient + BlockResultsServiceClient + + // Close the connection to the server. Any subsequent requests will fail. + Close() error +} + +type clientBuilder struct { + dialerFunc func(context.Context, string) (net.Conn, error) + grpcOpts []ggrpc.DialOption + + versionServiceEnabled bool + blockServiceEnabled bool + blockResultsServiceEnabled bool +} + +func newClientBuilder() *clientBuilder { + return &clientBuilder{ + dialerFunc: defaultDialerFunc, + grpcOpts: make([]ggrpc.DialOption, 0), + versionServiceEnabled: true, + blockServiceEnabled: true, + blockResultsServiceEnabled: true, + } +} + +func defaultDialerFunc(ctx context.Context, addr string) (net.Conn, error) { + return cmtnet.ConnectContext(ctx, addr) +} + +type client struct { + conn *ggrpc.ClientConn + + VersionServiceClient + BlockServiceClient + BlockResultsServiceClient +} + +// Close implements Client. +func (c *client) Close() error { + return c.conn.Close() +} + +// WithInsecure disables transport security for the underlying client +// connection. +// +// A shortcut for using grpc.WithTransportCredentials and +// insecure.NewCredentials from google.golang.org/grpc. +func WithInsecure() Option { + return WithGRPCDialOption(ggrpc.WithTransportCredentials(insecure.NewCredentials())) +} + +// WithVersionServiceEnabled allows control of whether or not to create a +// client for interacting with the version service of a CometBFT node. +// +// If disabled and the client attempts to access the version service API, the +// client will panic. +func WithVersionServiceEnabled(enabled bool) Option { + return func(b *clientBuilder) { + b.versionServiceEnabled = enabled + } +} + +// WithBlockServiceEnabled allows control of whether or not to create a +// client for interacting with the block service of a CometBFT node. +// +// If disabled and the client attempts to access the block service API, the +// client will panic. +func WithBlockServiceEnabled(enabled bool) Option { + return func(b *clientBuilder) { + b.blockServiceEnabled = enabled + } +} + +// WithGRPCDialOption allows passing lower-level gRPC dial options through to +// the gRPC dialer when creating the client. +func WithGRPCDialOption(opt ggrpc.DialOption) Option { + return func(b *clientBuilder) { + b.grpcOpts = append(b.grpcOpts, opt) + } +} + +// New constructs a client for interacting with a CometBFT node via gRPC. +// +// Makes no assumptions about whether or not to use TLS to connect to the given +// address. To connect to a gRPC server without using TLS, use the WithInsecure +// option. +// +// To connect to a gRPC server with TLS, use the WithGRPCDialOption option with +// the appropriate gRPC credentials configuration. See +// https://pkg.go.dev/google.golang.org/grpc#WithTransportCredentials +func New(ctx context.Context, addr string, opts ...Option) (Client, error) { + builder := newClientBuilder() + for _, opt := range opts { + opt(builder) + } + conn, err := ggrpc.DialContext(ctx, addr, builder.grpcOpts...) + if err != nil { + return nil, ErrDial{addr, err} + } + + versionServiceClient := newDisabledVersionServiceClient() + if builder.versionServiceEnabled { + versionServiceClient = newVersionServiceClient(conn) + } + blockServiceClient := newDisabledBlockServiceClient() + if builder.blockServiceEnabled { + blockServiceClient = newBlockServiceClient(conn) + } + blockResultServiceClient := newDisabledBlockResultsServiceClient() + if builder.blockResultsServiceEnabled { + blockResultServiceClient = newBlockResultsServiceClient(conn) + } + return &client{ + conn: conn, + VersionServiceClient: versionServiceClient, + BlockServiceClient: blockServiceClient, + BlockResultsServiceClient: blockResultServiceClient, + }, nil +} diff --git a/rpc/grpc/client/errors.go b/rpc/grpc/client/errors.go new file mode 100644 index 00000000000..f5c4377635d --- /dev/null +++ b/rpc/grpc/client/errors.go @@ -0,0 +1,49 @@ +package client + +import "fmt" + +type ErrBlockResults struct { + Height int64 + Source error +} + +func (e ErrBlockResults) Error() string { + return fmt.Sprintf("error fetching BlockResults for height %d: %s", e.Height, e.Source.Error()) +} + +type ErrStreamSetup struct { + Source error +} + +func (e ErrStreamSetup) Error() string { + return "error getting a stream for the latest height: " + e.Source.Error() +} + +func (e ErrStreamSetup) Unwrap() error { + return e.Source +} + +type ErrStreamReceive struct { + Source error +} + +func (e ErrStreamReceive) Error() string { + return "error receiving the latest height from a stream: " + e.Source.Error() +} + +func (e ErrStreamReceive) Unwrap() error { + return e.Source +} + +type ErrDial struct { + Addr string + Source error +} + +func (e ErrDial) Error() string { + return fmt.Sprintf("failed to dial: address %s: %v", e.Addr, e.Source) +} + +func (e ErrDial) Unwrap() error { + return e.Source +} diff --git a/rpc/grpc/client/privileged/privileged.go b/rpc/grpc/client/privileged/privileged.go new file mode 100644 index 00000000000..2030f0e34bf --- /dev/null +++ b/rpc/grpc/client/privileged/privileged.go @@ -0,0 +1,111 @@ +package privileged + +import ( + "context" + "net" + + ggrpc "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + cmtnet "github.com/cometbft/cometbft/internal/net" + grpcclient "github.com/cometbft/cometbft/rpc/grpc/client" +) + +type Option func(*clientBuilder) + +// Client defines the full client interface for interacting with +// a CometBFT node via the privileged gRPC server. +type Client interface { + PruningServiceClient + + // Close the connection to the server. Any subsequent requests will fail. + Close() error +} + +type clientBuilder struct { + dialerFunc func(context.Context, string) (net.Conn, error) + grpcOpts []ggrpc.DialOption + + pruningServiceEnabled bool +} + +func newClientBuilder() *clientBuilder { + return &clientBuilder{ + dialerFunc: defaultDialerFunc, + grpcOpts: make([]ggrpc.DialOption, 0), + pruningServiceEnabled: true, + } +} + +func defaultDialerFunc(ctx context.Context, addr string) (net.Conn, error) { + return cmtnet.ConnectContext(ctx, addr) +} + +type client struct { + conn *ggrpc.ClientConn + + PruningServiceClient +} + +// Close implements Client. +func (c *client) Close() error { + return c.conn.Close() +} + +// WithInsecure disables transport security for the underlying client +// connection. +// +// A shortcut for using grpc.WithTransportCredentials and +// insecure.NewCredentials from google.golang.org/grpc. +func WithInsecure() Option { + return WithGRPCDialOption(ggrpc.WithTransportCredentials(insecure.NewCredentials())) +} + +// WithPruningServiceEnabled allows control of whether or not to create a +// client for interacting with the pruning service of a CometBFT node. +// +// If disabled and the client attempts to access the pruning service API, the +// client will panic. +func WithPruningServiceEnabled(enabled bool) Option { + return func(b *clientBuilder) { + b.pruningServiceEnabled = enabled + } +} + +// WithGRPCDialOption allows passing lower-level gRPC dial options through to +// the gRPC dialer when creating the client. +func WithGRPCDialOption(opt ggrpc.DialOption) Option { + return func(b *clientBuilder) { + b.grpcOpts = append(b.grpcOpts, opt) + } +} + +// New constructs a client for interacting with a CometBFT node via its +// privileged gRPC server. +// +// Makes no assumptions about whether or not to use TLS to connect to the given +// address. To connect to a gRPC server without using TLS, use the WithInsecure +// option. +// +// To connect to a gRPC server with TLS, use the WithGRPCDialOption option with +// the appropriate gRPC credentials configuration. See +// https://pkg.go.dev/google.golang.org/grpc#WithTransportCredentials +func New(ctx context.Context, addr string, opts ...Option) (Client, error) { + builder := newClientBuilder() + for _, opt := range opts { + opt(builder) + } + conn, err := ggrpc.DialContext(ctx, addr, builder.grpcOpts...) + if err != nil { + return nil, grpcclient.ErrDial{Addr: addr, Source: err} + } + + pruningServiceClient := newDisabledPruningServiceClient() + if builder.pruningServiceEnabled { + pruningServiceClient = newPruningServiceClient(conn) + } + return &client{ + conn: conn, + PruningServiceClient: pruningServiceClient, + }, nil +} diff --git a/rpc/grpc/client/privileged/pruning_service.go b/rpc/grpc/client/privileged/pruning_service.go new file mode 100644 index 00000000000..8eb63d048f9 --- /dev/null +++ b/rpc/grpc/client/privileged/pruning_service.go @@ -0,0 +1,149 @@ +package privileged + +import ( + "context" + + "github.com/cosmos/gogoproto/grpc" + + pbsvc "github.com/cometbft/cometbft/api/cometbft/services/pruning/v1" +) + +// RetainHeights provides information on which block height limits have been +// set for block information to be retained by the ABCI application and the +// pruning service. +type RetainHeights struct { + App uint64 + PruningService uint64 +} + +type PruningServiceClient interface { + SetBlockRetainHeight(ctx context.Context, height uint64) error + GetBlockRetainHeight(ctx context.Context) (RetainHeights, error) + SetBlockResultsRetainHeight(ctx context.Context, height uint64) error + GetBlockResultsRetainHeight(ctx context.Context) (uint64, error) + SetTxIndexerRetainHeight(ctx context.Context, height uint64) error + GetTxIndexerRetainHeight(ctx context.Context) (uint64, error) + SetBlockIndexerRetainHeight(ctx context.Context, height uint64) error + GetBlockIndexerRetainHeight(ctx context.Context) (uint64, error) +} + +type pruningServiceClient struct { + inner pbsvc.PruningServiceClient +} + +func newPruningServiceClient(conn grpc.ClientConn) PruningServiceClient { + return &pruningServiceClient{ + inner: pbsvc.NewPruningServiceClient(conn), + } +} + +func (c *pruningServiceClient) SetBlockIndexerRetainHeight(ctx context.Context, height uint64) error { + _, err := c.inner.SetBlockIndexerRetainHeight(ctx, &pbsvc.SetBlockIndexerRetainHeightRequest{ + Height: height, + }) + return err +} + +func (c *pruningServiceClient) GetBlockIndexerRetainHeight(ctx context.Context) (uint64, error) { + res, err := c.inner.GetBlockIndexerRetainHeight(ctx, &pbsvc.GetBlockIndexerRetainHeightRequest{}) + if err != nil { + return 0, err + } + return res.Height, nil +} + +// SetTxIndexerRetainHeight implements PruningServiceClient. +func (c *pruningServiceClient) SetTxIndexerRetainHeight(ctx context.Context, height uint64) error { + _, err := c.inner.SetTxIndexerRetainHeight(ctx, &pbsvc.SetTxIndexerRetainHeightRequest{ + Height: height, + }) + return err +} + +// GetTxIndexerRetainHeight implements PruningServiceClient. +func (c *pruningServiceClient) GetTxIndexerRetainHeight(ctx context.Context) (uint64, error) { + res, err := c.inner.GetTxIndexerRetainHeight(ctx, &pbsvc.GetTxIndexerRetainHeightRequest{}) + if err != nil { + return 0, err + } + return res.Height, nil +} + +// SetBlockRetainHeight implements PruningServiceClient. +func (c *pruningServiceClient) SetBlockRetainHeight(ctx context.Context, height uint64) error { + _, err := c.inner.SetBlockRetainHeight(ctx, &pbsvc.SetBlockRetainHeightRequest{ + Height: height, + }) + return err +} + +// GetBlockRetainHeight implements PruningServiceClient. +func (c *pruningServiceClient) GetBlockRetainHeight(ctx context.Context) (RetainHeights, error) { + res, err := c.inner.GetBlockRetainHeight(ctx, &pbsvc.GetBlockRetainHeightRequest{}) + if err != nil { + return RetainHeights{}, err + } + return RetainHeights{ + App: res.AppRetainHeight, + PruningService: res.PruningServiceRetainHeight, + }, nil +} + +// SetBlockResultsRetainHeight implements PruningServiceClient. +func (c *pruningServiceClient) SetBlockResultsRetainHeight(ctx context.Context, height uint64) error { + _, err := c.inner.SetBlockResultsRetainHeight(ctx, &pbsvc.SetBlockResultsRetainHeightRequest{ + Height: height, + }) + return err +} + +// GetBlockResultsRetainHeight implements PruningServiceClient. +func (c *pruningServiceClient) GetBlockResultsRetainHeight(ctx context.Context) (uint64, error) { + res, err := c.inner.GetBlockResultsRetainHeight(ctx, &pbsvc.GetBlockResultsRetainHeightRequest{}) + if err != nil { + return 0, err + } + return res.PruningServiceRetainHeight, nil +} + +type disabledPruningServiceClient struct{} + +func newDisabledPruningServiceClient() PruningServiceClient { + return &disabledPruningServiceClient{} +} + +// SetBlockRetainHeight implements PruningServiceClient. +func (*disabledPruningServiceClient) SetBlockRetainHeight(context.Context, uint64) error { + panic("pruning service client is disabled") +} + +// GetBlockRetainHeight implements PruningServiceClient. +func (*disabledPruningServiceClient) GetBlockRetainHeight(context.Context) (RetainHeights, error) { + panic("pruning service client is disabled") +} + +// SetBlockResultsRetainHeight implements PruningServiceClient. +func (*disabledPruningServiceClient) SetBlockResultsRetainHeight(context.Context, uint64) error { + panic("pruning service client is disabled") +} + +// GetBlockResultsRetainHeight implements PruningServiceClient. +func (*disabledPruningServiceClient) GetBlockResultsRetainHeight(context.Context) (uint64, error) { + panic("pruning service client is disabled") +} + +func (*disabledPruningServiceClient) SetTxIndexerRetainHeight(context.Context, uint64) error { + panic("pruning service client is disabled") +} + +func (*disabledPruningServiceClient) GetTxIndexerRetainHeight(context.Context) (uint64, error) { + panic("pruning service client is disabled") +} + +func (*disabledPruningServiceClient) SetBlockIndexerRetainHeight(context.Context, uint64) error { + panic("pruning service client is disabled") +} + +func (*disabledPruningServiceClient) GetBlockIndexerRetainHeight(context.Context) (uint64, error) { + panic("pruning service client is disabled") +} diff --git a/rpc/grpc/client/version_service.go b/rpc/grpc/client/version_service.go new file mode 100644 index 00000000000..bef0fa445eb --- /dev/null +++ b/rpc/grpc/client/version_service.go @@ -0,0 +1,57 @@ +package client + +import ( + "context" + + "github.com/cosmos/gogoproto/grpc" + + pbsvc "github.com/cometbft/cometbft/api/cometbft/services/version/v1" +) + +// Version provides version information about a particular CometBFT node. +type Version struct { + Node string // The semantic version of the node software (i.e. the version of CometBFT). + ABCI string // The version of the ABCI protocol used by the node. + P2P uint64 // The version of the P2P protocol used by the node. + Block uint64 // The version of the block protocol used by the node. +} + +// VersionServiceClient provides version information about a CometBFT node. +type VersionServiceClient interface { + GetVersion(ctx context.Context) (*Version, error) +} + +type versionServiceClient struct { + client pbsvc.VersionServiceClient +} + +func newVersionServiceClient(conn grpc.ClientConn) VersionServiceClient { + return &versionServiceClient{ + client: pbsvc.NewVersionServiceClient(conn), + } +} + +// GetVersion implements VersionServiceClient. +func (c *versionServiceClient) GetVersion(ctx context.Context) (*Version, error) { + res, err := c.client.GetVersion(ctx, &pbsvc.GetVersionRequest{}) + if err != nil { + return nil, err + } + return &Version{ + Node: res.Node, + ABCI: res.Abci, + P2P: res.P2P, + Block: res.Block, + }, nil +} + +type disabledVersionServiceClient struct{} + +func newDisabledVersionServiceClient() VersionServiceClient { + return &disabledVersionServiceClient{} +} + +// GetVersion implements VersionServiceClient. +func (*disabledVersionServiceClient) GetVersion(context.Context) (*Version, error) { + panic("version service client is disabled") +} diff --git a/rpc/grpc/client_server.go b/rpc/grpc/client_server.go deleted file mode 100644 index 3856d3ecca1..00000000000 --- a/rpc/grpc/client_server.go +++ /dev/null @@ -1,40 +0,0 @@ -package coregrpc - -import ( - "net" - - "golang.org/x/net/context" - "google.golang.org/grpc" - - cmtnet "github.com/cometbft/cometbft/libs/net" - "github.com/cometbft/cometbft/rpc/core" -) - -// Config is an gRPC server configuration. -type Config struct { - MaxOpenConnections int -} - -// StartGRPCServer starts a new gRPC BroadcastAPIServer using the given -// net.Listener. -// NOTE: This function blocks - you may want to call it in a go-routine. -func StartGRPCServer(env *core.Environment, ln net.Listener) error { - grpcServer := grpc.NewServer() - RegisterBroadcastAPIServer(grpcServer, &broadcastAPI{env: env}) - return grpcServer.Serve(ln) -} - -// StartGRPCClient dials the gRPC server using protoAddr and returns a new -// BroadcastAPIClient. -func StartGRPCClient(protoAddr string) BroadcastAPIClient { - //nolint: staticcheck // SA1019 Existing use of deprecated but supported dial option. - conn, err := grpc.Dial(protoAddr, grpc.WithInsecure(), grpc.WithContextDialer(dialerFunc)) - if err != nil { - panic(err) - } - return NewBroadcastAPIClient(conn) -} - -func dialerFunc(ctx context.Context, addr string) (net.Conn, error) { - return cmtnet.Connect(addr) -} diff --git a/rpc/grpc/errors/errors.go b/rpc/grpc/errors/errors.go new file mode 100644 index 00000000000..e799c942d11 --- /dev/null +++ b/rpc/grpc/errors/errors.go @@ -0,0 +1,11 @@ +package errors + +import "fmt" + +type ErrInvalidRemoteAddress struct { + Addr string +} + +func (e ErrInvalidRemoteAddress) Error() string { + return fmt.Sprintf("invalid listening address %s (use fully formed addresses, including the tcp:// or unix:// prefix)", e.Addr) +} diff --git a/rpc/grpc/grpc_test.go b/rpc/grpc/grpc_test.go deleted file mode 100644 index ed06eeb9646..00000000000 --- a/rpc/grpc/grpc_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package coregrpc_test - -import ( - "context" - "os" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cometbft/cometbft/abci/example/kvstore" - core_grpc "github.com/cometbft/cometbft/rpc/grpc" - rpctest "github.com/cometbft/cometbft/rpc/test" -) - -func TestMain(m *testing.M) { - // start a CometBFT node in the background to test against - app := kvstore.NewInMemoryApplication() - node := rpctest.StartTendermint(app) - - code := m.Run() - - // and shut down proper at the end - rpctest.StopTendermint(node) - os.Exit(code) -} - -func TestBroadcastTx(t *testing.T) { - res, err := rpctest.GetGRPCClient().BroadcastTx( - context.Background(), - &core_grpc.RequestBroadcastTx{Tx: kvstore.NewTx("hello", "world")}, - ) - require.NoError(t, err) - require.EqualValues(t, 0, res.CheckTx.Code) - require.EqualValues(t, 0, res.TxResult.Code) -} diff --git a/rpc/grpc/server/privileged/privileged.go b/rpc/grpc/server/privileged/privileged.go new file mode 100644 index 00000000000..bde0ce28a30 --- /dev/null +++ b/rpc/grpc/server/privileged/privileged.go @@ -0,0 +1,74 @@ +package privileged + +import ( + "fmt" + "net" + + "google.golang.org/grpc" + + pbpruningsvc "github.com/cometbft/cometbft/api/cometbft/services/pruning/v1" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/libs/log" + "github.com/cometbft/cometbft/rpc/grpc/server/services/pruningservice" +) + +// Option is any function that allows for configuration of the gRPC server +// during its creation. +type Option func(*serverBuilder) + +type serverBuilder struct { + listener net.Listener + pruningService pbpruningsvc.PruningServiceServer + logger log.Logger + grpcOpts []grpc.ServerOption +} + +func newServerBuilder(listener net.Listener) *serverBuilder { + return &serverBuilder{ + listener: listener, + logger: log.NewNopLogger(), + grpcOpts: make([]grpc.ServerOption, 0), + } +} + +// WithVersionService enables the version service on the CometBFT server. +func WithPruningService(pruner *sm.Pruner, logger log.Logger) Option { + return func(b *serverBuilder) { + b.pruningService = pruningservice.New(pruner, logger) + } +} + +// WithLogger enables logging using the given logger. If not specified, the +// gRPC server does not log anything. +func WithLogger(logger log.Logger) Option { + return func(b *serverBuilder) { + b.logger = logger.With("module", "privileged-grpc-server") + } +} + +// WithGRPCOption allows one to specify Google gRPC server options during the +// construction of the CometBFT gRPC server. +func WithGRPCOption(opt grpc.ServerOption) Option { + return func(b *serverBuilder) { + b.grpcOpts = append(b.grpcOpts, opt) + } +} + +// Serve constructs and runs a CometBFT privileged gRPC server using the given +// listener and options. +// +// This function only returns upon error, otherwise it blocks the current +// goroutine. +func Serve(listener net.Listener, opts ...Option) error { + b := newServerBuilder(listener) + for _, opt := range opts { + opt(b) + } + server := grpc.NewServer(b.grpcOpts...) + if b.pruningService != nil { + pbpruningsvc.RegisterPruningServiceServer(server, b.pruningService) + b.logger.Debug("Registered pruning service") + } + b.logger.Info("serve", "msg", fmt.Sprintf("Starting privileged gRPC server on %s", listener.Addr())) + return server.Serve(b.listener) +} diff --git a/rpc/grpc/server/server.go b/rpc/grpc/server/server.go new file mode 100644 index 00000000000..7b79bf8005b --- /dev/null +++ b/rpc/grpc/server/server.go @@ -0,0 +1,118 @@ +package server + +import ( + "fmt" + "net" + "strings" + + "google.golang.org/grpc" + + pbblocksvc "github.com/cometbft/cometbft/api/cometbft/services/block/v1" + brs "github.com/cometbft/cometbft/api/cometbft/services/block_results/v1" + pbversionsvc "github.com/cometbft/cometbft/api/cometbft/services/version/v1" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" + "github.com/cometbft/cometbft/libs/log" + grpcerr "github.com/cometbft/cometbft/rpc/grpc/errors" + "github.com/cometbft/cometbft/rpc/grpc/server/services/blockresultservice" + "github.com/cometbft/cometbft/rpc/grpc/server/services/blockservice" + "github.com/cometbft/cometbft/rpc/grpc/server/services/versionservice" + "github.com/cometbft/cometbft/types" +) + +// Option is any function that allows for configuration of the gRPC server +// during its creation. +type Option func(*serverBuilder) + +type serverBuilder struct { + listener net.Listener + versionService pbversionsvc.VersionServiceServer + blockService pbblocksvc.BlockServiceServer + blockResultsService brs.BlockResultsServiceServer + logger log.Logger + grpcOpts []grpc.ServerOption +} + +func newServerBuilder(listener net.Listener) *serverBuilder { + return &serverBuilder{ + listener: listener, + logger: log.NewNopLogger(), + grpcOpts: make([]grpc.ServerOption, 0), + } +} + +// Listen starts a new net.Listener on the given address. +// +// The address must conform to the standard listener address format used by +// CometBFT, i.e. "://
". For example, +// "tcp://127.0.0.1:26670". +func Listen(addr string) (net.Listener, error) { + parts := strings.SplitN(addr, "://", 2) + if len(parts) != 2 { + return nil, grpcerr.ErrInvalidRemoteAddress{Addr: addr} + } + return net.Listen(parts[0], parts[1]) +} + +// WithVersionService enables the version service on the CometBFT server. +func WithVersionService() Option { + return func(b *serverBuilder) { + b.versionService = versionservice.New() + } +} + +// WithBlockService enables the block service on the CometBFT server. +func WithBlockService(store *store.BlockStore, eventBus *types.EventBus, logger log.Logger) Option { + return func(b *serverBuilder) { + b.blockService = blockservice.New(store, eventBus, logger) + } +} + +func WithBlockResultsService(bs *store.BlockStore, ss sm.Store, logger log.Logger) Option { + return func(b *serverBuilder) { + b.blockResultsService = blockresultservice.New(bs, ss, logger) + } +} + +// WithLogger enables logging using the given logger. If not specified, the +// gRPC server does not log anything. +func WithLogger(logger log.Logger) Option { + return func(b *serverBuilder) { + b.logger = logger.With("module", "grpc-server") + } +} + +// WithGRPCOption allows one to specify Google gRPC server options during the +// construction of the CometBFT gRPC server. +func WithGRPCOption(opt grpc.ServerOption) Option { + return func(b *serverBuilder) { + b.grpcOpts = append(b.grpcOpts, opt) + } +} + +// Serve constructs and runs a CometBFT gRPC server using the given listener +// and options. +// +// This function only returns upon error, otherwise it blocks the current +// goroutine. +func Serve(listener net.Listener, opts ...Option) error { + b := newServerBuilder(listener) + for _, opt := range opts { + opt(b) + } + server := grpc.NewServer(b.grpcOpts...) + if b.versionService != nil { + pbversionsvc.RegisterVersionServiceServer(server, b.versionService) + b.logger.Debug("Registered version service") + } + if b.blockService != nil { + pbblocksvc.RegisterBlockServiceServer(server, b.blockService) + b.logger.Debug("Registered block service") + } + if b.blockResultsService != nil { + brs.RegisterBlockResultsServiceServer(server, b.blockResultsService) + b.logger.Debug("Registered block results service") + } + b.logger.Info("serve", "msg", fmt.Sprintf("Starting gRPC server on %s", listener.Addr())) + return server.Serve(b.listener) +} diff --git a/rpc/grpc/server/services/blockresultservice/service.go b/rpc/grpc/server/services/blockresultservice/service.go new file mode 100644 index 00000000000..4181d98c614 --- /dev/null +++ b/rpc/grpc/server/services/blockresultservice/service.go @@ -0,0 +1,63 @@ +package blockresultservice + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + brs "github.com/cometbft/cometbft/api/cometbft/services/block_results/v1" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/internal/store" + "github.com/cometbft/cometbft/libs/log" +) + +type blockResultsService struct { + stateStore sm.Store + blockStore *store.BlockStore + logger log.Logger +} + +// New creates a new CometBFT block results service server. +func New(bs *store.BlockStore, ss sm.Store, logger log.Logger) brs.BlockResultsServiceServer { + return &blockResultsService{ + stateStore: ss, + blockStore: bs, + logger: logger.With("service", "BlockResultsService"), + } +} + +// GetBlockResults returns the block results of the requested height. +func (s *blockResultsService) GetBlockResults(_ context.Context, req *brs.GetBlockResultsRequest) (*brs.GetBlockResultsResponse, error) { + logger := s.logger.With("endpoint", "GetBlockResults") + ss, err := s.stateStore.Load() + if err != nil { + logger.Error("Error loading store", "err", err) + return nil, status.Error(codes.Internal, "Internal server error") + } + if req.Height > ss.LastBlockHeight || req.Height < 0 { + return nil, status.Errorf(codes.InvalidArgument, "Height must be between 0 and the last effective height (%d)", ss.LastBlockHeight) + } + + res, err := s.stateStore.LoadFinalizeBlockResponse(req.Height) + if err != nil { + logger.Error("Error fetching BlockResults", "height", req.Height, "err", err) + return nil, status.Error(codes.Internal, "Internal server error") + } + + return &brs.GetBlockResultsResponse{ + Height: req.Height, + TxResults: res.TxResults, + FinalizeBlockEvents: formatProtoToRef(res.Events), + ValidatorUpdates: formatProtoToRef(res.ValidatorUpdates), + AppHash: res.AppHash, + }, nil +} + +func formatProtoToRef[T any](collection []T) []*T { + res := []*T{} + for i := range collection { + res = append(res, &collection[i]) + } + return res +} diff --git a/rpc/grpc/server/services/blockservice/service.go b/rpc/grpc/server/services/blockservice/service.go new file mode 100644 index 00000000000..f7d283d87fd --- /dev/null +++ b/rpc/grpc/server/services/blockservice/service.go @@ -0,0 +1,146 @@ +package blockservice + +import ( + "context" + "fmt" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + blocksvc "github.com/cometbft/cometbft/api/cometbft/services/block/v1" + ptypes "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + "github.com/cometbft/cometbft/internal/rpctrace" + "github.com/cometbft/cometbft/internal/store" + "github.com/cometbft/cometbft/libs/log" + "github.com/cometbft/cometbft/types" +) + +type blockServiceServer struct { + store *store.BlockStore + eventBus *types.EventBus + logger log.Logger +} + +// New creates a new CometBFT version service server. +func New(store *store.BlockStore, eventBus *types.EventBus, logger log.Logger) blocksvc.BlockServiceServer { + return &blockServiceServer{ + store: store, + eventBus: eventBus, + logger: logger.With("service", "BlockService"), + } +} + +// GetByHeight implements v1.BlockServiceServer GetByHeight method. +func (s *blockServiceServer) GetByHeight(_ context.Context, req *blocksvc.GetByHeightRequest) (*blocksvc.GetByHeightResponse, error) { + logger := s.logger.With("endpoint", "GetByHeight") + if err := validateBlockHeight(req.Height, s.store.Base(), s.store.Height()); err != nil { + return nil, err + } + + blockID, block, err := s.getBlock(req.Height, logger) + if err != nil { + return nil, err + } + + return &blocksvc.GetByHeightResponse{ + BlockId: blockID, + Block: block, + }, nil +} + +func (s *blockServiceServer) getBlock(height int64, logger log.Logger) (*ptypes.BlockID, *ptypes.Block, error) { + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + + block, blockMeta := s.store.LoadBlock(height) + if block == nil { + return nil, nil, status.Errorf(codes.NotFound, fmt.Sprintf("Block not found for height %d", height)) + } + bp, err := block.ToProto() + if err != nil { + logger.Error("Error attempting to convert block to its Protobuf representation", "err", err, "traceID", traceID) + return nil, nil, status.Errorf(codes.Internal, fmt.Sprintf("Failed to load block from store (see logs for trace ID: %s)", traceID)) + } + + if blockMeta == nil { + logger.Error("Failed to load block meta when block was successfully loaded", "height", height) + return nil, nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + + blockIDProto := blockMeta.BlockID.ToProto() + return &blockIDProto, bp, nil +} + +// GetLatestHeight implements v1.BlockServiceServer GetLatestHeight method. +func (s *blockServiceServer) GetLatestHeight(_ *blocksvc.GetLatestHeightRequest, stream blocksvc.BlockService_GetLatestHeightServer) error { + logger := s.logger.With("endpoint", "GetLatestHeight") + + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return status.Error(codes.Internal, "Internal server error") + } + + // The trace ID is reused as a unique subscriber ID + sub, err := s.eventBus.Subscribe(context.Background(), traceID, types.QueryForEvent(types.EventNewBlock), 1) + if err != nil { + logger.Error("Cannot subscribe to new block events", "err", err, "traceID", traceID) + return status.Errorf(codes.Internal, "Cannot subscribe to new block events (see logs for trace ID: %s)", traceID) + } + + for { + select { + case msg := <-sub.Out(): + height, err := getHeightFromMsg(msg) + if err != nil { + logger.Error("Failed to extract height from subscription message", "err", err, "traceID", traceID) + return status.Errorf(codes.Internal, "Internal server error (see logs for trace ID: %s)", traceID) + } + if err := stream.Send(&blocksvc.GetLatestHeightResponse{Height: height}); err != nil { + logger.Error("Failed to stream new block", "err", err, "height", height, "traceID", traceID) + return status.Errorf(codes.Unavailable, "Cannot send stream response (see logs for trace ID: %s)", traceID) + } + case <-sub.Canceled(): + switch sub.Err() { + case cmtpubsub.ErrUnsubscribed: + return status.Error(codes.Canceled, "Subscription terminated") + case nil: + return status.Error(codes.Canceled, "Subscription canceled without errors") + default: + logger.Info("Subscription canceled with errors", "err", sub.Err(), "traceID", traceID) + return status.Errorf(codes.Canceled, "Subscription canceled with errors (see logs for trace ID: %s)", traceID) + } + default: + continue + } + if sub.Err() != nil { + logger.Error("New block subscription error", "err", sub.Err(), "traceID", traceID) + return status.Errorf(codes.Internal, "New block subscription error (see logs for trace ID: %s)", traceID) + } + } +} + +func validateBlockHeight(height, baseHeight, latestHeight int64) error { + switch { + case height <= 0: + return status.Error(codes.InvalidArgument, "Height cannot be zero or negative") + case height < baseHeight: + return status.Errorf(codes.InvalidArgument, "Requested height %d is below base height %d", height, baseHeight) + case height > latestHeight: + return status.Errorf(codes.InvalidArgument, "Requested height %d is higher than latest height %d", height, latestHeight) + } + return nil +} + +func getHeightFromMsg(msg cmtpubsub.Message) (int64, error) { + switch eventType := msg.Data().(type) { + case types.EventDataNewBlock: + return eventType.Block.Height, nil + default: + return -1, fmt.Errorf("unexpected event type: %v", eventType) + } +} diff --git a/rpc/grpc/server/services/pruningservice/service.go b/rpc/grpc/server/services/pruningservice/service.go new file mode 100644 index 00000000000..d3699f5e654 --- /dev/null +++ b/rpc/grpc/server/services/pruningservice/service.go @@ -0,0 +1,176 @@ +package pruningservice + +import ( + "context" + "fmt" + "math" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + pbsvc "github.com/cometbft/cometbft/api/cometbft/services/pruning/v1" + "github.com/cometbft/cometbft/internal/rpctrace" + sm "github.com/cometbft/cometbft/internal/state" + "github.com/cometbft/cometbft/libs/log" +) + +type pruningServiceServer struct { + pruner *sm.Pruner + logger log.Logger +} + +// New creates a new CometBFT pruning service server. +func New(pruner *sm.Pruner, logger log.Logger) pbsvc.PruningServiceServer { + return &pruningServiceServer{ + pruner: pruner, + logger: logger.With("service", "PruningService"), + } +} + +func (s *pruningServiceServer) SetBlockIndexerRetainHeight(_ context.Context, request *pbsvc.SetBlockIndexerRetainHeightRequest) (*pbsvc.SetBlockIndexerRetainHeightResponse, error) { + height := request.Height + // Because we can't agree on a single type to represent tx indexer height. + if height > uint64(math.MaxInt64) { + return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Invalid height %d", height)) + } + logger := s.logger.With("endpoint", "SetBlockIndexerRetainHeight") + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + if err := s.pruner.SetBlockIndexerRetainHeight(int64(height)); err != nil { + logger.Error("Cannot set block indexer retain height", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to set block indexer retain height (see logs for trace ID: %s)", traceID) + } + return &pbsvc.SetBlockIndexerRetainHeightResponse{}, nil +} + +func (s *pruningServiceServer) GetBlockIndexerRetainHeight(_ context.Context, _ *pbsvc.GetBlockIndexerRetainHeightRequest) (*pbsvc.GetBlockIndexerRetainHeightResponse, error) { + logger := s.logger.With("endpoint", "GetBLockIndexerRetainHeight") + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + height, err := s.pruner.GetBlockIndexerRetainHeight() + if err != nil { + logger.Error("Cannot get block indexer retain height", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to get block indexer retain height (see logs for trace ID: %s)", traceID) + } + return &pbsvc.GetBlockIndexerRetainHeightResponse{Height: uint64(height)}, nil +} + +func (s *pruningServiceServer) SetTxIndexerRetainHeight(_ context.Context, request *pbsvc.SetTxIndexerRetainHeightRequest) (*pbsvc.SetTxIndexerRetainHeightResponse, error) { + height := request.Height + // Because we can't agree on a single type to represent tx indexer height. + if height > uint64(math.MaxInt64) { + return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Invalid height %d", height)) + } + logger := s.logger.With("endpoint", "SetTxIndexerRetainHeight") + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + if err := s.pruner.SetTxIndexerRetainHeight(int64(height)); err != nil { + logger.Error("Cannot set tx indexer retain height", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to set tx indexer retain height (see logs for trace ID: %s)", traceID) + } + return &pbsvc.SetTxIndexerRetainHeightResponse{}, nil +} + +func (s *pruningServiceServer) GetTxIndexerRetainHeight(_ context.Context, _ *pbsvc.GetTxIndexerRetainHeightRequest) (*pbsvc.GetTxIndexerRetainHeightResponse, error) { + logger := s.logger.With("endpoint", "GetTxIndexerRetainHeight") + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + height, err := s.pruner.GetTxIndexerRetainHeight() + if err != nil { + logger.Error("Cannot get tx indexer retain height", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to get tx indexer retain height (see logs for trace ID: %s)", traceID) + } + return &pbsvc.GetTxIndexerRetainHeightResponse{Height: uint64(height)}, nil +} + +// SetBlockRetainHeight implements v1.PruningServiceServer. +func (s *pruningServiceServer) SetBlockRetainHeight(_ context.Context, req *pbsvc.SetBlockRetainHeightRequest) (*pbsvc.SetBlockRetainHeightResponse, error) { + height := req.Height + // Because we can't agree on a single type to represent block height. + if height > uint64(math.MaxInt64) { + return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Invalid height %d", height)) + } + logger := s.logger.With("endpoint", "SetBlockRetainHeight") + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + if err := s.pruner.SetCompanionBlockRetainHeight(int64(height)); err != nil { + logger.Error("Cannot set block retain height", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to set block retain height (see logs for trace ID: %s)", traceID) + } + return &pbsvc.SetBlockRetainHeightResponse{}, nil +} + +// GetBlockRetainHeight implements v1.PruningServiceServer. +func (s *pruningServiceServer) GetBlockRetainHeight(_ context.Context, _ *pbsvc.GetBlockRetainHeightRequest) (*pbsvc.GetBlockRetainHeightResponse, error) { + logger := s.logger.With("endpoint", "GetBlockRetainHeight") + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + svcHeight, err := s.pruner.GetCompanionBlockRetainHeight() + if err != nil { + logger.Error("Cannot get block retain height stored by companion", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to get companion block retain height (see logs for trace ID: %s)", traceID) + } + appHeight, err := s.pruner.GetApplicationRetainHeight() + if err != nil { + logger.Error("Cannot get block retain height specified by application", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to get app block retain height (see logs for trace ID: %s)", traceID) + } + return &pbsvc.GetBlockRetainHeightResponse{ + PruningServiceRetainHeight: uint64(svcHeight), + AppRetainHeight: uint64(appHeight), + }, nil +} + +// SetBlockResultsRetainHeight implements v1.PruningServiceServer. +func (s *pruningServiceServer) SetBlockResultsRetainHeight(_ context.Context, req *pbsvc.SetBlockResultsRetainHeightRequest) (*pbsvc.SetBlockResultsRetainHeightResponse, error) { + height := req.Height + // Because we can't agree on a single type to represent block height. + if height > uint64(math.MaxInt64) { + return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Invalid height %d", height)) + } + logger := s.logger.With("endpoint", "SetBlockResultsRetainHeight") + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + if err := s.pruner.SetABCIResRetainHeight(int64(height)); err != nil { + logger.Error("Cannot set block results retain height", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to set block results retain height (see logs for trace ID: %s)", traceID) + } + return &pbsvc.SetBlockResultsRetainHeightResponse{}, nil +} + +// GetBlockResultsRetainHeight implements v1.PruningServiceServer. +func (s *pruningServiceServer) GetBlockResultsRetainHeight(_ context.Context, _ *pbsvc.GetBlockResultsRetainHeightRequest) (*pbsvc.GetBlockResultsRetainHeightResponse, error) { + logger := s.logger.With("endpoint", "GetBlockResultsRetainHeight") + traceID, err := rpctrace.New() + if err != nil { + logger.Error("Error generating RPC trace ID", "err", err) + return nil, status.Error(codes.Internal, "Internal server error - see logs for details") + } + height, err := s.pruner.GetABCIResRetainHeight() + if err != nil { + logger.Error("Cannot get block results retain height", "err", err, "traceID", traceID) + return nil, status.Errorf(codes.Internal, "Failed to get block results retain height (see logs for trace ID: %s)", traceID) + } + return &pbsvc.GetBlockResultsRetainHeightResponse{PruningServiceRetainHeight: uint64(height)}, nil +} diff --git a/rpc/grpc/server/services/versionservice/service.go b/rpc/grpc/server/services/versionservice/service.go new file mode 100644 index 00000000000..fc2feba7f30 --- /dev/null +++ b/rpc/grpc/server/services/versionservice/service.go @@ -0,0 +1,25 @@ +package versionservice + +import ( + "context" + + pbsvc "github.com/cometbft/cometbft/api/cometbft/services/version/v1" + "github.com/cometbft/cometbft/version" +) + +type versionServiceServer struct{} + +// New creates a new CometBFT version service server. +func New() pbsvc.VersionServiceServer { + return &versionServiceServer{} +} + +// GetVersion implements v1.VersionServiceServer. +func (*versionServiceServer) GetVersion(context.Context, *pbsvc.GetVersionRequest) (*pbsvc.GetVersionResponse, error) { + return &pbsvc.GetVersionResponse{ + Node: version.CMTSemVer, + Abci: version.ABCIVersion, + P2P: version.P2PProtocol, + Block: version.BlockProtocol, + }, nil +} diff --git a/rpc/grpc/types.pb.go b/rpc/grpc/types.pb.go deleted file mode 100644 index 393c7394764..00000000000 --- a/rpc/grpc/types.pb.go +++ /dev/null @@ -1,926 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: tendermint/rpc/grpc/types.proto - -package coregrpc - -import ( - context "context" - fmt "fmt" - types "github.com/cometbft/cometbft/abci/types" - grpc1 "github.com/cosmos/gogoproto/grpc" - proto "github.com/cosmos/gogoproto/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -type RequestPing struct { -} - -func (m *RequestPing) Reset() { *m = RequestPing{} } -func (m *RequestPing) String() string { return proto.CompactTextString(m) } -func (*RequestPing) ProtoMessage() {} -func (*RequestPing) Descriptor() ([]byte, []int) { - return fileDescriptor_0ffff5682c662b95, []int{0} -} -func (m *RequestPing) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *RequestPing) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_RequestPing.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *RequestPing) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestPing.Merge(m, src) -} -func (m *RequestPing) XXX_Size() int { - return m.Size() -} -func (m *RequestPing) XXX_DiscardUnknown() { - xxx_messageInfo_RequestPing.DiscardUnknown(m) -} - -var xxx_messageInfo_RequestPing proto.InternalMessageInfo - -type RequestBroadcastTx struct { - Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` -} - -func (m *RequestBroadcastTx) Reset() { *m = RequestBroadcastTx{} } -func (m *RequestBroadcastTx) String() string { return proto.CompactTextString(m) } -func (*RequestBroadcastTx) ProtoMessage() {} -func (*RequestBroadcastTx) Descriptor() ([]byte, []int) { - return fileDescriptor_0ffff5682c662b95, []int{1} -} -func (m *RequestBroadcastTx) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *RequestBroadcastTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_RequestBroadcastTx.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *RequestBroadcastTx) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestBroadcastTx.Merge(m, src) -} -func (m *RequestBroadcastTx) XXX_Size() int { - return m.Size() -} -func (m *RequestBroadcastTx) XXX_DiscardUnknown() { - xxx_messageInfo_RequestBroadcastTx.DiscardUnknown(m) -} - -var xxx_messageInfo_RequestBroadcastTx proto.InternalMessageInfo - -func (m *RequestBroadcastTx) GetTx() []byte { - if m != nil { - return m.Tx - } - return nil -} - -type ResponsePing struct { -} - -func (m *ResponsePing) Reset() { *m = ResponsePing{} } -func (m *ResponsePing) String() string { return proto.CompactTextString(m) } -func (*ResponsePing) ProtoMessage() {} -func (*ResponsePing) Descriptor() ([]byte, []int) { - return fileDescriptor_0ffff5682c662b95, []int{2} -} -func (m *ResponsePing) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ResponsePing) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ResponsePing.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ResponsePing) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponsePing.Merge(m, src) -} -func (m *ResponsePing) XXX_Size() int { - return m.Size() -} -func (m *ResponsePing) XXX_DiscardUnknown() { - xxx_messageInfo_ResponsePing.DiscardUnknown(m) -} - -var xxx_messageInfo_ResponsePing proto.InternalMessageInfo - -type ResponseBroadcastTx struct { - CheckTx *types.ResponseCheckTx `protobuf:"bytes,1,opt,name=check_tx,json=checkTx,proto3" json:"check_tx,omitempty"` - TxResult *types.ExecTxResult `protobuf:"bytes,2,opt,name=tx_result,json=txResult,proto3" json:"tx_result,omitempty"` -} - -func (m *ResponseBroadcastTx) Reset() { *m = ResponseBroadcastTx{} } -func (m *ResponseBroadcastTx) String() string { return proto.CompactTextString(m) } -func (*ResponseBroadcastTx) ProtoMessage() {} -func (*ResponseBroadcastTx) Descriptor() ([]byte, []int) { - return fileDescriptor_0ffff5682c662b95, []int{3} -} -func (m *ResponseBroadcastTx) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ResponseBroadcastTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ResponseBroadcastTx.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ResponseBroadcastTx) XXX_Merge(src proto.Message) { - xxx_messageInfo_ResponseBroadcastTx.Merge(m, src) -} -func (m *ResponseBroadcastTx) XXX_Size() int { - return m.Size() -} -func (m *ResponseBroadcastTx) XXX_DiscardUnknown() { - xxx_messageInfo_ResponseBroadcastTx.DiscardUnknown(m) -} - -var xxx_messageInfo_ResponseBroadcastTx proto.InternalMessageInfo - -func (m *ResponseBroadcastTx) GetCheckTx() *types.ResponseCheckTx { - if m != nil { - return m.CheckTx - } - return nil -} - -func (m *ResponseBroadcastTx) GetTxResult() *types.ExecTxResult { - if m != nil { - return m.TxResult - } - return nil -} - -func init() { - proto.RegisterType((*RequestPing)(nil), "tendermint.rpc.grpc.RequestPing") - proto.RegisterType((*RequestBroadcastTx)(nil), "tendermint.rpc.grpc.RequestBroadcastTx") - proto.RegisterType((*ResponsePing)(nil), "tendermint.rpc.grpc.ResponsePing") - proto.RegisterType((*ResponseBroadcastTx)(nil), "tendermint.rpc.grpc.ResponseBroadcastTx") -} - -func init() { proto.RegisterFile("tendermint/rpc/grpc/types.proto", fileDescriptor_0ffff5682c662b95) } - -var fileDescriptor_0ffff5682c662b95 = []byte{ - // 324 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x31, 0x4f, 0x02, 0x31, - 0x14, 0xc7, 0x29, 0x31, 0x8a, 0x05, 0x19, 0xca, 0x42, 0x30, 0x9e, 0x48, 0x4c, 0x64, 0x2a, 0x09, - 0x6e, 0x32, 0x89, 0x31, 0xd1, 0xb8, 0x90, 0x86, 0xc9, 0x05, 0xb9, 0xf2, 0x84, 0x8b, 0x72, 0x3d, - 0xdb, 0x47, 0x52, 0xbf, 0x84, 0xf1, 0x0b, 0xb9, 0x3b, 0x32, 0x3a, 0x1a, 0xf8, 0x22, 0xa6, 0x27, - 0x27, 0x35, 0x46, 0x96, 0xe6, 0xdf, 0xe6, 0xff, 0x7b, 0xfd, 0xbf, 0xd7, 0xd2, 0x43, 0x84, 0x78, - 0x04, 0x7a, 0x1a, 0xc5, 0xd8, 0xd2, 0x89, 0x6c, 0x8d, 0xdd, 0x82, 0xcf, 0x09, 0x18, 0x9e, 0x68, - 0x85, 0x8a, 0x55, 0xd6, 0x06, 0xae, 0x13, 0xc9, 0x9d, 0xa1, 0xb6, 0xef, 0x51, 0xc3, 0x50, 0x46, - 0x3e, 0xd1, 0xd8, 0xa3, 0x45, 0x01, 0x4f, 0x33, 0x30, 0xd8, 0x8b, 0xe2, 0x71, 0xe3, 0x98, 0xb2, - 0xd5, 0xb6, 0xab, 0xd5, 0x70, 0x24, 0x87, 0x06, 0xfb, 0x96, 0x95, 0x69, 0x1e, 0x6d, 0x95, 0xd4, - 0x49, 0xb3, 0x24, 0xf2, 0x68, 0x1b, 0x65, 0x5a, 0x12, 0x60, 0x12, 0x15, 0x1b, 0x48, 0xa9, 0x17, - 0x42, 0x2b, 0xd9, 0x81, 0xcf, 0x75, 0x68, 0x41, 0x4e, 0x40, 0x3e, 0x0c, 0x56, 0x74, 0xb1, 0x5d, - 0xe7, 0x5e, 0x42, 0x17, 0x86, 0x67, 0xdc, 0x85, 0x33, 0xf6, 0xad, 0xd8, 0x91, 0xdf, 0x82, 0x9d, - 0xd1, 0x5d, 0xb4, 0x03, 0x0d, 0x66, 0xf6, 0x88, 0xd5, 0x7c, 0x4a, 0x1f, 0xfc, 0xa1, 0x2f, 0x2d, - 0xc8, 0xbe, 0x15, 0xa9, 0x49, 0x14, 0x70, 0xa5, 0xda, 0x6f, 0x84, 0x96, 0x7e, 0x82, 0x9c, 0xf7, - 0xae, 0xd9, 0x0d, 0xdd, 0x72, 0x49, 0xd9, 0xaf, 0xfb, 0xb3, 0x09, 0x71, 0x6f, 0x02, 0xb5, 0xa3, - 0x7f, 0x1c, 0xeb, 0x76, 0xd9, 0x1d, 0x2d, 0xfa, 0x5d, 0x9e, 0x6c, 0xaa, 0xe9, 0x19, 0x6b, 0xcd, - 0x8d, 0xa5, 0x3d, 0x67, 0xf7, 0xea, 0x7d, 0x11, 0x90, 0xf9, 0x22, 0x20, 0x9f, 0x8b, 0x80, 0xbc, - 0x2e, 0x83, 0xdc, 0x7c, 0x19, 0xe4, 0x3e, 0x96, 0x41, 0xee, 0x96, 0x8f, 0x23, 0x9c, 0xcc, 0x42, - 0x2e, 0xd5, 0xb4, 0x25, 0xd5, 0x14, 0x30, 0xbc, 0xc7, 0xb5, 0xc8, 0x3e, 0x45, 0x47, 0x2a, 0x0d, - 0x4e, 0x84, 0xdb, 0xe9, 0x33, 0x9f, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x0c, 0xca, 0xdb, 0xe7, - 0x3b, 0x02, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// BroadcastAPIClient is the client API for BroadcastAPI service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type BroadcastAPIClient interface { - Ping(ctx context.Context, in *RequestPing, opts ...grpc.CallOption) (*ResponsePing, error) - BroadcastTx(ctx context.Context, in *RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) -} - -type broadcastAPIClient struct { - cc grpc1.ClientConn -} - -func NewBroadcastAPIClient(cc grpc1.ClientConn) BroadcastAPIClient { - return &broadcastAPIClient{cc} -} - -func (c *broadcastAPIClient) Ping(ctx context.Context, in *RequestPing, opts ...grpc.CallOption) (*ResponsePing, error) { - out := new(ResponsePing) - err := c.cc.Invoke(ctx, "/tendermint.rpc.grpc.BroadcastAPI/Ping", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *broadcastAPIClient) BroadcastTx(ctx context.Context, in *RequestBroadcastTx, opts ...grpc.CallOption) (*ResponseBroadcastTx, error) { - out := new(ResponseBroadcastTx) - err := c.cc.Invoke(ctx, "/tendermint.rpc.grpc.BroadcastAPI/BroadcastTx", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// BroadcastAPIServer is the server API for BroadcastAPI service. -type BroadcastAPIServer interface { - Ping(context.Context, *RequestPing) (*ResponsePing, error) - BroadcastTx(context.Context, *RequestBroadcastTx) (*ResponseBroadcastTx, error) -} - -// UnimplementedBroadcastAPIServer can be embedded to have forward compatible implementations. -type UnimplementedBroadcastAPIServer struct { -} - -func (*UnimplementedBroadcastAPIServer) Ping(ctx context.Context, req *RequestPing) (*ResponsePing, error) { - return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") -} -func (*UnimplementedBroadcastAPIServer) BroadcastTx(ctx context.Context, req *RequestBroadcastTx) (*ResponseBroadcastTx, error) { - return nil, status.Errorf(codes.Unimplemented, "method BroadcastTx not implemented") -} - -func RegisterBroadcastAPIServer(s grpc1.Server, srv BroadcastAPIServer) { - s.RegisterService(&_BroadcastAPI_serviceDesc, srv) -} - -func _BroadcastAPI_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestPing) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BroadcastAPIServer).Ping(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.rpc.grpc.BroadcastAPI/Ping", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BroadcastAPIServer).Ping(ctx, req.(*RequestPing)) - } - return interceptor(ctx, in, info, handler) -} - -func _BroadcastAPI_BroadcastTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestBroadcastTx) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BroadcastAPIServer).BroadcastTx(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/tendermint.rpc.grpc.BroadcastAPI/BroadcastTx", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BroadcastAPIServer).BroadcastTx(ctx, req.(*RequestBroadcastTx)) - } - return interceptor(ctx, in, info, handler) -} - -var _BroadcastAPI_serviceDesc = grpc.ServiceDesc{ - ServiceName: "tendermint.rpc.grpc.BroadcastAPI", - HandlerType: (*BroadcastAPIServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Ping", - Handler: _BroadcastAPI_Ping_Handler, - }, - { - MethodName: "BroadcastTx", - Handler: _BroadcastAPI_BroadcastTx_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "tendermint/rpc/grpc/types.proto", -} - -func (m *RequestPing) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *RequestPing) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *RequestPing) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *RequestBroadcastTx) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *RequestBroadcastTx) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *RequestBroadcastTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Tx) > 0 { - i -= len(m.Tx) - copy(dAtA[i:], m.Tx) - i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ResponsePing) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ResponsePing) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ResponsePing) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *ResponseBroadcastTx) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ResponseBroadcastTx) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ResponseBroadcastTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.TxResult != nil { - { - size, err := m.TxResult.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if m.CheckTx != nil { - { - size, err := m.CheckTx.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTypes(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { - offset -= sovTypes(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *RequestPing) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *RequestBroadcastTx) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Tx) - if l > 0 { - n += 1 + l + sovTypes(uint64(l)) - } - return n -} - -func (m *ResponsePing) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *ResponseBroadcastTx) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.CheckTx != nil { - l = m.CheckTx.Size() - n += 1 + l + sovTypes(uint64(l)) - } - if m.TxResult != nil { - l = m.TxResult.Size() - n += 1 + l + sovTypes(uint64(l)) - } - return n -} - -func sovTypes(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozTypes(x uint64) (n int) { - return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *RequestPing) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: RequestPing: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: RequestPing: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *RequestBroadcastTx) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: RequestBroadcastTx: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: RequestBroadcastTx: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tx", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) - if m.Tx == nil { - m.Tx = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ResponsePing) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ResponsePing: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ResponsePing: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ResponseBroadcastTx) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ResponseBroadcastTx: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ResponseBroadcastTx: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.CheckTx == nil { - m.CheckTx = &types.ResponseCheckTx{} - } - if err := m.CheckTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TxResult", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTypes - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTypes - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.TxResult == nil { - m.TxResult = &types.ExecTxResult{} - } - if err := m.TxResult.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipTypes(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTypes - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTypes - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTypes - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthTypes - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupTypes - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthTypes - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") -) diff --git a/rpc/jsonrpc/client/args_test.go b/rpc/jsonrpc/client/args_test.go index 2506f307349..eba2b2862b8 100644 --- a/rpc/jsonrpc/client/args_test.go +++ b/rpc/jsonrpc/client/args_test.go @@ -19,7 +19,7 @@ func TestArgToJSON(t *testing.T) { require := require.New(t) cases := []struct { - input interface{} + input any expected string }{ {[]byte("1234"), "0x31323334"}, @@ -28,10 +28,10 @@ func TestArgToJSON(t *testing.T) { } for i, tc := range cases { - args := map[string]interface{}{"data": tc.input} + args := map[string]any{"data": tc.input} err := argsToJSON(args) - require.Nil(err, "%d: %+v", i, err) - require.Equal(1, len(args), "%d", i) + require.NoError(err, "%d: %+v", i, err) + require.Len(args, 1, "%d", i) data, ok := args["data"].(string) require.True(ok, "%d: %#v", i, args["data"]) assert.Equal(tc.expected, data, "%d", i) diff --git a/rpc/jsonrpc/client/decode.go b/rpc/jsonrpc/client/decode.go index 2ae917d97d1..7b60a99b553 100644 --- a/rpc/jsonrpc/client/decode.go +++ b/rpc/jsonrpc/client/decode.go @@ -6,15 +6,14 @@ import ( "fmt" cmtjson "github.com/cometbft/cometbft/libs/json" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) func unmarshalResponseBytes( responseBytes []byte, expectedID types.JSONRPCIntID, - result interface{}, -) (interface{}, error) { - + result any, +) (any, error) { // Read response. If rpc/core/types is imported, the result will unmarshal // into the correct type. response := &types.RPCResponse{} @@ -41,12 +40,9 @@ func unmarshalResponseBytes( func unmarshalResponseBytesArray( responseBytes []byte, expectedIDs []types.JSONRPCIntID, - results []interface{}, -) ([]interface{}, error) { - - var ( - responses []types.RPCResponse - ) + results []any, +) ([]any, error) { + var responses []types.RPCResponse if err := json.Unmarshal(responseBytes, &responses); err != nil { return nil, fmt.Errorf("error unmarshalling: %w", err) @@ -92,11 +88,10 @@ func validateResponseIDs(ids, expectedIDs []types.JSONRPCIntID) error { } for i, id := range ids { - if m[id] { - delete(m, id) - } else { + if !m[id] { return fmt.Errorf("unsolicited ID #%d: %v", i, id) } + delete(m, id) } return nil @@ -114,7 +109,7 @@ func validateAndVerifyID(res *types.RPCResponse, expectedID types.JSONRPCIntID) return nil } -func validateResponseID(id interface{}) error { +func validateResponseID(id any) error { if id == nil { return errors.New("no ID") } diff --git a/rpc/jsonrpc/client/encode.go b/rpc/jsonrpc/client/encode.go index 42d997be478..e024abb8901 100644 --- a/rpc/jsonrpc/client/encode.go +++ b/rpc/jsonrpc/client/encode.go @@ -8,7 +8,7 @@ import ( cmtjson "github.com/cometbft/cometbft/libs/json" ) -func argsToURLValues(args map[string]interface{}) (url.Values, error) { +func argsToURLValues(args map[string]any) (url.Values, error) { values := make(url.Values) if len(args) == 0 { return values, nil @@ -26,7 +26,7 @@ func argsToURLValues(args map[string]interface{}) (url.Values, error) { return values, nil } -func argsToJSON(args map[string]interface{}) error { +func argsToJSON(args map[string]any) error { for k, v := range args { rt := reflect.TypeOf(v) isByteSlice := rt.Kind() == reflect.Slice && rt.Elem().Kind() == reflect.Uint8 diff --git a/rpc/jsonrpc/client/errors.go b/rpc/jsonrpc/client/errors.go new file mode 100644 index 00000000000..86e7008acd2 --- /dev/null +++ b/rpc/jsonrpc/client/errors.go @@ -0,0 +1,94 @@ +package client + +import "fmt" + +type ErrInvalidAddress struct { + Addr string + Source error +} + +func (e ErrInvalidAddress) Error() string { + return fmt.Sprintf("invalid address: %s: %v ", e.Addr, e.Source) +} + +func (e ErrInvalidAddress) Unwrap() error { + return e.Source +} + +type ErrEncodingParams struct { + Source error +} + +func (e ErrEncodingParams) Error() string { + return fmt.Sprintf("failed to encode params: %v", e.Source) +} + +func (e ErrEncodingParams) Unwrap() error { + return e.Source +} + +type ErrMarshalRequest struct { + Source error +} + +func (e ErrMarshalRequest) Error() string { + return fmt.Sprintf("failed to marshal request: %v", e.Source) +} + +func (e ErrMarshalRequest) Unwrap() error { + return e.Source +} + +type ErrCreateRequest struct { + Source error +} + +func (e ErrCreateRequest) Error() string { + return fmt.Sprintf("failed to create request: %v", e.Source) +} + +func (e ErrCreateRequest) Unwrap() error { + return e.Source +} + +type ErrFailedRequest struct { + Source error +} + +func (e ErrFailedRequest) Error() string { + return fmt.Sprintf("failed request: %v", e.Source) +} + +func (e ErrFailedRequest) Unwrap() error { + return e.Source +} + +type ErrReadResponse struct { + Source error + Description string +} + +func (e ErrReadResponse) Error() string { + if e.Description == "" { + return fmt.Sprintf("failed to read response: %s : %v", e.Source.Error(), e.Source) + } + + return fmt.Sprintf("failed to read response: %s : %v", e.Description, e.Source) +} + +func (e ErrReadResponse) Unwrap() error { + return e.Source +} + +type ErrUnmarshalResponse struct { + Source error + Description string +} + +func (e ErrUnmarshalResponse) Error() string { + if e.Description == "" { + return fmt.Sprintf("failed to unmarshal response: %s : %v", e.Source.Error(), e.Source) + } + + return fmt.Sprintf("failed to unmarshal response: %s : %v", e.Description, e.Source) +} diff --git a/rpc/jsonrpc/client/http_json_client.go b/rpc/jsonrpc/client/http_json_client.go index 0e64242ea08..d893b6bb8d4 100644 --- a/rpc/jsonrpc/client/http_json_client.go +++ b/rpc/jsonrpc/client/http_json_client.go @@ -9,10 +9,11 @@ import ( "net" "net/http" "net/url" + "regexp" "strings" - cmtsync "github.com/cometbft/cometbft/libs/sync" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + cmtsync "github.com/cometbft/cometbft/internal/sync" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) const ( @@ -24,16 +25,18 @@ const ( protoUNIX = "unix" ) -//------------------------------------------------------------- +var endsWithPortPattern = regexp.MustCompile(`:[0-9]+$`) -// Parsed URL structure +// ------------------------------------------------------------- + +// Parsed URL structure. type parsedURL struct { url.URL isUnixSocket bool } -// Parse URL and set defaults +// Parse URL and set defaults. func newParsedURL(remoteAddr string) (*parsedURL, error) { u, err := url.Parse(remoteAddr) if err != nil { @@ -57,7 +60,7 @@ func newParsedURL(remoteAddr string) (*parsedURL, error) { return pu, nil } -// Change protocol to HTTP for unknown protocols and TCP protocol - useful for RPC connections +// Change protocol to HTTP for unknown protocols and TCP protocol - useful for RPC connections. func (u *parsedURL) SetDefaultSchemeHTTP() { // protocol to use for http operations, to support both http and https switch u.Scheme { @@ -69,13 +72,13 @@ func (u *parsedURL) SetDefaultSchemeHTTP() { } } -// Get full address without the protocol - useful for Dialer connections +// Get full address without the protocol - useful for Dialer connections. func (u parsedURL) GetHostWithPath() string { // Remove protocol, userinfo and # fragment, assume opaque is empty return u.Host + u.EscapedPath() } -// Get a trimmed address - useful for WS connections +// Get a trimmed address - useful for WS connections. func (u parsedURL) GetTrimmedHostWithPath() string { // if it's not an unix socket we return the normal URL if !u.isUnixSocket { @@ -87,35 +90,46 @@ func (u parsedURL) GetTrimmedHostWithPath() string { return strings.ReplaceAll(u.GetHostWithPath(), "/", ".") } -// GetDialAddress returns the endpoint to dial for the parsed URL +// GetDialAddress returns the endpoint to dial for the parsed URL. func (u parsedURL) GetDialAddress() string { - // if it's not a unix socket we return the host, example: localhost:443 + // if it's not a unix socket we return the host with port, example: localhost:443 if !u.isUnixSocket { + hasPort := endsWithPortPattern.MatchString(u.Host) + if !hasPort { + // http and ws default to port 80, https and wss default to port 443 + // https://www.rfc-editor.org/rfc/rfc9110#section-4.2 + // https://www.rfc-editor.org/rfc/rfc6455.html#section-3 + if u.Scheme == protoHTTP || u.Scheme == protoWS { + return u.Host + `:80` + } else if u.Scheme == protoHTTPS || u.Scheme == protoWSS { + return u.Host + `:443` + } + } return u.Host } // otherwise we return the path of the unix socket, ex /tmp/socket return u.GetHostWithPath() } -// Get a trimmed address with protocol - useful as address in RPC connections +// Get a trimmed address with protocol - useful as address in RPC connections. func (u parsedURL) GetTrimmedURL() string { return u.Scheme + "://" + u.GetTrimmedHostWithPath() } -//------------------------------------------------------------- +// ------------------------------------------------------------- // HTTPClient is a common interface for JSON-RPC HTTP clients. type HTTPClient interface { // Call calls the given method with the params and returns a result. - Call(ctx context.Context, method string, params map[string]interface{}, result interface{}) (interface{}, error) + Call(ctx context.Context, method string, params map[string]any, result any) (any, error) } // Caller implementers can facilitate calling the JSON-RPC endpoint. type Caller interface { - Call(ctx context.Context, method string, params map[string]interface{}, result interface{}) (interface{}, error) + Call(ctx context.Context, method string, params map[string]any, result any) (any, error) } -//------------------------------------------------------------- +// ------------------------------------------------------------- // Client is a JSON-RPC client, which sends POST HTTP requests to the // remote server. @@ -136,8 +150,12 @@ var _ HTTPClient = (*Client)(nil) // Both Client and RequestBatch can facilitate calls to the JSON // RPC endpoint. -var _ Caller = (*Client)(nil) -var _ Caller = (*RequestBatch)(nil) +var ( + _ Caller = (*Client)(nil) + _ Caller = (*RequestBatch)(nil) +) + +var _ fmt.Stringer = (*Client)(nil) // New returns a Client pointed at the given address. // An error is returned on invalid remote. The function panics when remote is nil. @@ -159,7 +177,7 @@ func NewWithHTTPClient(remote string, client *http.Client) (*Client, error) { parsedURL, err := newParsedURL(remote) if err != nil { - return nil, fmt.Errorf("invalid remote %s: %s", remote, err) + return nil, ErrInvalidAddress{Addr: remote, Source: err} } parsedURL.SetDefaultSchemeHTTP() @@ -183,25 +201,25 @@ func NewWithHTTPClient(remote string, client *http.Client) (*Client, error) { func (c *Client) Call( ctx context.Context, method string, - params map[string]interface{}, - result interface{}, -) (interface{}, error) { + params map[string]any, + result any, +) (any, error) { id := c.nextRequestID() request, err := types.MapToRequest(id, method, params) if err != nil { - return nil, fmt.Errorf("failed to encode params: %w", err) + return nil, ErrEncodingParams{Source: err} } requestBytes, err := json.Marshal(request) if err != nil { - return nil, fmt.Errorf("failed to marshal request: %w", err) + return nil, ErrMarshalRequest{Source: err} } requestBuf := bytes.NewBuffer(requestBytes) httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, c.address, requestBuf) if err != nil { - return nil, fmt.Errorf("request failed: %w", err) + return nil, ErrCreateRequest{Source: err} } httpRequest.Header.Set("Content-Type", "application/json") @@ -212,17 +230,28 @@ func (c *Client) Call( httpResponse, err := c.client.Do(httpRequest) if err != nil { - return nil, fmt.Errorf("post failed: %w", err) + return nil, ErrFailedRequest{Source: err} } - defer httpResponse.Body.Close() responseBytes, err := io.ReadAll(httpResponse.Body) if err != nil { - return nil, fmt.Errorf("failed to read response body: %w", err) + return nil, ErrReadResponse{Source: err, Description: getHTTPRespErrPrefix(httpResponse)} + } + + res, err := unmarshalResponseBytes(responseBytes, id, result) + if err != nil { + return nil, ErrUnmarshalResponse{Source: err, Description: getHTTPRespErrPrefix(httpResponse)} } + return res, nil +} + +func getHTTPRespErrPrefix(resp *http.Response) string { + return fmt.Sprintf("error in json rpc client, with http response metadata: (Status: %s, Protocol %s)", resp.Status, resp.Proto) +} - return unmarshalResponseBytes(responseBytes, id, result) +func (c *Client) String() string { + return fmt.Sprintf("&Client{user=%v, addr=%v, client=%v, nextReqID=%v}", c.username, c.address, c.client, c.nextReqID) } // NewRequestBatch starts a batch of requests for this client. @@ -233,9 +262,9 @@ func (c *Client) NewRequestBatch() *RequestBatch { } } -func (c *Client) sendBatch(ctx context.Context, requests []*jsonRPCBufferedRequest) ([]interface{}, error) { +func (c *Client) sendBatch(ctx context.Context, requests []*jsonRPCBufferedRequest) ([]any, error) { reqs := make([]types.RPCRequest, 0, len(requests)) - results := make([]interface{}, 0, len(requests)) + results := make([]any, 0, len(requests)) for _, req := range requests { reqs = append(reqs, req.request) results = append(results, req.result) @@ -287,13 +316,13 @@ func (c *Client) nextRequestID() types.JSONRPCIntID { return types.JSONRPCIntID(id) } -//------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------ // jsonRPCBufferedRequest encapsulates a single buffered request, as well as its // anticipated response structure. type jsonRPCBufferedRequest struct { request types.RPCRequest - result interface{} // The result will be deserialized into this object. + result any // The result will be deserialized into this object. } // RequestBatch allows us to buffer multiple request/response structures @@ -335,7 +364,7 @@ func (b *RequestBatch) clear() int { // Send will attempt to send the current batch of enqueued requests, and then // will clear out the requests once done. On success, this returns the // deserialized list of results from each of the enqueued requests. -func (b *RequestBatch) Send(ctx context.Context) ([]interface{}, error) { +func (b *RequestBatch) Send(ctx context.Context) ([]any, error) { b.mtx.Lock() defer func() { b.clear() @@ -349,9 +378,9 @@ func (b *RequestBatch) Send(ctx context.Context) ([]interface{}, error) { func (b *RequestBatch) Call( _ context.Context, method string, - params map[string]interface{}, - result interface{}, -) (interface{}, error) { + params map[string]any, + result any, +) (any, error) { id := b.client.nextRequestID() request, err := types.MapToRequest(id, method, params) if err != nil { @@ -361,9 +390,10 @@ func (b *RequestBatch) Call( return result, nil } -//------------------------------------------------------------- +// ------------------------------------------------------------- -func makeHTTPDialer(remoteAddr string) (func(string, string) (net.Conn, error), error) { +// MakeHTTPDialer creates an HTTP client dialer based on the given URL. +func MakeHTTPDialer(remoteAddr string) (func(string, string) (net.Conn, error), error) { u, err := newParsedURL(remoteAddr) if err != nil { return nil, err @@ -377,7 +407,7 @@ func makeHTTPDialer(remoteAddr string) (func(string, string) (net.Conn, error), protocol = protoTCP } - dialFn := func(proto, addr string) (net.Conn, error) { + dialFn := func(_, _ string) (net.Conn, error) { return net.Dial(protocol, u.GetDialAddress()) } @@ -389,7 +419,7 @@ func makeHTTPDialer(remoteAddr string) (func(string, string) (net.Conn, error), // remoteAddr should be fully featured (eg. with tcp:// or unix://). // An error will be returned in case of invalid remoteAddr. func DefaultHTTPClient(remoteAddr string) (*http.Client, error) { - dialFn, err := makeHTTPDialer(remoteAddr) + dialFn, err := MakeHTTPDialer(remoteAddr) if err != nil { return nil, err } @@ -399,6 +429,7 @@ func DefaultHTTPClient(remoteAddr string) (*http.Client, error) { // Set to true to prevent GZIP-bomb DoS attacks DisableCompression: true, Dial: dialFn, + Proxy: http.ProxyFromEnvironment, }, } diff --git a/rpc/jsonrpc/client/http_json_client_test.go b/rpc/jsonrpc/client/http_json_client_test.go index 03134dff583..d773c6b344a 100644 --- a/rpc/jsonrpc/client/http_json_client_test.go +++ b/rpc/jsonrpc/client/http_json_client_test.go @@ -11,7 +11,7 @@ import ( ) func TestHTTPClientMakeHTTPDialer(t *testing.T) { - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { _, _ = w.Write([]byte("Hi!\n")) }) ts := httptest.NewServer(handler) @@ -26,8 +26,8 @@ func TestHTTPClientMakeHTTPDialer(t *testing.T) { for _, testURL := range []string{ts.URL, tsTLS.URL} { u, err := newParsedURL(testURL) require.NoError(t, err) - dialFn, err := makeHTTPDialer(testURL) - require.Nil(t, err) + dialFn, err := MakeHTTPDialer(testURL) + require.NoError(t, err) addr, err := dialFn(u.Scheme, u.GetHostWithPath()) require.NoError(t, err) @@ -52,25 +52,45 @@ func Test_parsedURL(t *testing.T) { }, "http endpoint": { + url: "http://example.com", + expectedURL: "http://example.com", + expectedHostWithPath: "example.com", + expectedDialAddress: "example.com:80", + }, + + "http endpoint with port": { + url: "http://example.com:8080", + expectedURL: "http://example.com:8080", + expectedHostWithPath: "example.com:8080", + expectedDialAddress: "example.com:8080", + }, + + "https endpoint": { url: "https://example.com", expectedURL: "https://example.com", expectedHostWithPath: "example.com", - expectedDialAddress: "example.com", + expectedDialAddress: "example.com:443", }, - "http endpoint with port": { + "https endpoint with port": { url: "https://example.com:8080", expectedURL: "https://example.com:8080", expectedHostWithPath: "example.com:8080", expectedDialAddress: "example.com:8080", }, - "http path routed endpoint": { + "https path routed endpoint": { url: "https://example.com:8080/rpc", expectedURL: "https://example.com:8080/rpc", expectedHostWithPath: "example.com:8080/rpc", expectedDialAddress: "example.com:8080", }, + "https path routed endpoint with version": { + url: "https://example.com:8080/rpc/v1", + expectedURL: "https://example.com:8080/rpc/v1", + expectedHostWithPath: "example.com:8080/rpc/v1", + expectedDialAddress: "example.com:8080", + }, } for name, tt := range tests { diff --git a/rpc/jsonrpc/client/http_uri_client.go b/rpc/jsonrpc/client/http_uri_client.go index b8bce3cfc09..a10c12f94d1 100644 --- a/rpc/jsonrpc/client/http_uri_client.go +++ b/rpc/jsonrpc/client/http_uri_client.go @@ -2,16 +2,15 @@ package client import ( "context" - "fmt" "io" "net/http" "strings" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) const ( - // URIClientRequestID in a request ID used by URIClient + // URIClientRequestID in a request ID used by URIClient. URIClientRequestID = types.JSONRPCIntID(-1) ) @@ -52,11 +51,11 @@ func NewURI(remote string) (*URIClient, error) { // Call issues a POST form HTTP request. func (c *URIClient) Call(ctx context.Context, method string, - params map[string]interface{}, result interface{}) (interface{}, error) { - + params map[string]any, result any, +) (any, error) { values, err := argsToURLValues(params) if err != nil { - return nil, fmt.Errorf("failed to encode params: %w", err) + return nil, ErrEncodingParams{Source: err} } req, err := http.NewRequestWithContext( @@ -66,19 +65,19 @@ func (c *URIClient) Call(ctx context.Context, method string, strings.NewReader(values.Encode()), ) if err != nil { - return nil, fmt.Errorf("new request: %w", err) + return nil, ErrCreateRequest{Source: err} } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") resp, err := c.client.Do(req) if err != nil { - return nil, fmt.Errorf("post: %w", err) + return nil, ErrFailedRequest{Source: err} } defer resp.Body.Close() responseBytes, err := io.ReadAll(resp.Body) if err != nil { - return nil, fmt.Errorf("read response body: %w", err) + return nil, ErrReadResponse{Source: err} } return unmarshalResponseBytes(responseBytes, URIClientRequestID, result) diff --git a/rpc/jsonrpc/client/integration_test.go b/rpc/jsonrpc/client/integration_test.go index 45ce6afd11f..dc063547750 100644 --- a/rpc/jsonrpc/client/integration_test.go +++ b/rpc/jsonrpc/client/integration_test.go @@ -25,13 +25,13 @@ func TestWSClientReconnectWithJitter(t *testing.T) { // Max wait time is ceil(1+0.999) + ceil(2+0.999) + ceil(4+0.999) + ceil(...) = 2 + 3 + 5 = 10s + ... maxSleepTime := time.Second * time.Duration(((1< 1 { + trimmedPath := strings.Trim(r.URL.Path, "/") + if trimmedPath != "" && trimmedPath != "v1" { responses = append( responses, types.RPCInvalidRequestError(request.ID, fmt.Errorf("path %s is invalid", r.URL.Path)), @@ -122,7 +124,7 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc, logger log.Logger) http.Han wErr = WriteRPCResponseHTTP(w, responses...) } if wErr != nil { - logger.Error("failed to write responses", "res", responses, "err", wErr) + logger.Error("failed to write responses", "err", wErr) } } } @@ -130,9 +132,8 @@ func makeJSONRPCHandler(funcMap map[string]*RPCFunc, logger log.Logger) http.Han func handleInvalidJSONRPCPaths(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - // Since the pattern "/" matches all paths not matched by other registered patterns, - // we check whether the path is indeed "/", otherwise return a 404 error - if r.URL.Path != "/" { + trimmedPath := strings.Trim(r.URL.Path, "/") + if trimmedPath != "" && trimmedPath != "v1" { http.NotFound(w, r) return } @@ -217,7 +218,7 @@ func jsonParamsToArgs(rpcFunc *RPCFunc, raw []byte) ([]reflect.Value, error) { return nil, fmt.Errorf("unknown type for JSON params: %v. Expected map or array", err) } -// writes a list of available rpc endpoints as an html page +// writes a list of available rpc endpoints as an html page. func writeListOfEndpoints(w http.ResponseWriter, r *http.Request, funcMap map[string]*RPCFunc) { noArgNames := []string{} argNames := []string{} @@ -235,8 +236,9 @@ func writeListOfEndpoints(w http.ResponseWriter, r *http.Request, funcMap map[st buf.WriteString("
Available endpoints:
") for _, name := range noArgNames { + // FIXME: The link should have the version as well. Where can we get it from the request? link := fmt.Sprintf("//%s/%s", r.Host, name) - buf.WriteString(fmt.Sprintf("%s
", link, link)) + buf.WriteString(fmt.Sprintf("%s
", link, name)) } buf.WriteString("
Endpoints that require arguments:
") @@ -253,6 +255,6 @@ func writeListOfEndpoints(w http.ResponseWriter, r *http.Request, funcMap map[st } buf.WriteString("") w.Header().Set("Content-Type", "text/html") - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) w.Write(buf.Bytes()) //nolint: errcheck } diff --git a/rpc/jsonrpc/server/http_json_handler_test.go b/rpc/jsonrpc/server/http_json_handler_test.go index 2d29cb4bbcc..0609e930629 100644 --- a/rpc/jsonrpc/server/http_json_handler_test.go +++ b/rpc/jsonrpc/server/http_json_handler_test.go @@ -13,13 +13,13 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/libs/log" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) func testMux() *http.ServeMux { funcMap := map[string]*RPCFunc{ - "c": NewRPCFunc(func(ctx *types.Context, s string, i int) (string, error) { return "foo", nil }, "s,i"), - "block": NewRPCFunc(func(ctx *types.Context, h int) (string, error) { return "block", nil }, "height", Cacheable("height")), + "c": NewRPCFunc(func(_ *types.Context, _ string, _ int) (string, error) { return "foo", nil }, "s,i"), + "block": NewRPCFunc(func(_ *types.Context, _ int) (string, error) { return "block", nil }, "height", Cacheable("height")), } mux := http.NewServeMux() buf := new(bytes.Buffer) @@ -39,7 +39,7 @@ func TestRPCParams(t *testing.T) { tests := []struct { payload string wantErr string - expectedID interface{} + expectedID any }{ // bad {`{"jsonrpc": "2.0", "id": "0"}`, "Method not found", types.JSONRPCStringID("0")}, @@ -60,7 +60,7 @@ func TestRPCParams(t *testing.T) { } for i, tt := range tests { - req, _ := http.NewRequest("POST", "http://localhost/", strings.NewReader(tt.payload)) + req, _ := http.NewRequest(http.MethodPost, "http://localhost/", strings.NewReader(tt.payload)) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) res := rec.Result() @@ -74,13 +74,13 @@ func TestRPCParams(t *testing.T) { } recv := new(types.RPCResponse) - assert.Nil(t, json.Unmarshal(blob, recv), "#%d: expecting successful parsing of an RPCResponse:\nblob: %s", i, blob) + require.NoError(t, json.Unmarshal(blob, recv), "#%d: expecting successful parsing of an RPCResponse:\nblob: %s", i, blob) assert.NotEqual(t, recv, new(types.RPCResponse), "#%d: not expecting a blank RPCResponse", i) assert.Equal(t, tt.expectedID, recv.ID, "#%d: expected ID not matched in RPCResponse", i) if tt.wantErr == "" { assert.Nil(t, recv.Error, "#%d: not expecting an error", i) } else { - assert.True(t, recv.Error.Code < 0, "#%d: not expecting a positive JSONRPC code", i) + assert.Less(t, recv.Error.Code, 0, "#%d: not expecting a positive JSONRPC code", i) // The wanted error is either in the message or the data assert.Contains(t, recv.Error.Message+recv.Error.Data, tt.wantErr, "#%d: expected substring", i) } @@ -92,7 +92,7 @@ func TestJSONRPCID(t *testing.T) { tests := []struct { payload string wantErr bool - expectedID interface{} + expectedID any }{ // good id {`{"jsonrpc": "2.0", "method": "c", "id": "0", "params": ["a", "10"]}`, false, types.JSONRPCStringID("0")}, @@ -108,7 +108,7 @@ func TestJSONRPCID(t *testing.T) { } for i, tt := range tests { - req, _ := http.NewRequest("POST", "http://localhost/", strings.NewReader(tt.payload)) + req, _ := http.NewRequest(http.MethodPost, "http://localhost/", strings.NewReader(tt.payload)) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) res := rec.Result() @@ -123,13 +123,13 @@ func TestJSONRPCID(t *testing.T) { recv := new(types.RPCResponse) err = json.Unmarshal(blob, recv) - assert.Nil(t, err, "#%d: expecting successful parsing of an RPCResponse:\nblob: %s", i, blob) + require.NoError(t, err, "#%d: expecting successful parsing of an RPCResponse:\nblob: %s", i, blob) if !tt.wantErr { assert.NotEqual(t, recv, new(types.RPCResponse), "#%d: not expecting a blank RPCResponse", i) assert.Equal(t, tt.expectedID, recv.ID, "#%d: expected ID not matched in RPCResponse", i) assert.Nil(t, recv.Error, "#%d: not expecting an error", i) } else { - assert.True(t, recv.Error.Code < 0, "#%d: not expecting a positive JSONRPC code", i) + assert.Less(t, recv.Error.Code, 0, "#%d: not expecting a positive JSONRPC code", i) } } } @@ -137,7 +137,7 @@ func TestJSONRPCID(t *testing.T) { func TestRPCNotification(t *testing.T) { mux := testMux() body := strings.NewReader(`{"jsonrpc": "2.0"}`) - req, _ := http.NewRequest("POST", "http://localhost/", body) + req, _ := http.NewRequest(http.MethodPost, "http://localhost/", body) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) res := rec.Result() @@ -146,8 +146,8 @@ func TestRPCNotification(t *testing.T) { require.True(t, statusOK(res.StatusCode), "should always return 2XX") blob, err := io.ReadAll(res.Body) res.Body.Close() - require.Nil(t, err, "reading from the body should not give back an error") - require.Equal(t, len(blob), 0, "a notification SHOULD NOT be responded to by the server") + require.NoError(t, err, "reading from the body should not give back an error") + require.Empty(t, blob, "a notification SHOULD NOT be responded to by the server") } func TestRPCNotificationInBatch(t *testing.T) { @@ -174,7 +174,7 @@ func TestRPCNotificationInBatch(t *testing.T) { }, } for i, tt := range tests { - req, _ := http.NewRequest("POST", "http://localhost/", strings.NewReader(tt.payload)) + req, _ := http.NewRequest(http.MethodPost, "http://localhost/", strings.NewReader(tt.payload)) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) res := rec.Result() @@ -195,17 +195,16 @@ func TestRPCNotificationInBatch(t *testing.T) { if tt.expectCount > 1 { t.Errorf("#%d: expected an array, couldn't unmarshal it\nblob: %s", i, blob) continue - } else { - // we were expecting an error here, so let's unmarshal a single response - var response types.RPCResponse - err = json.Unmarshal(blob, &response) - if err != nil { - t.Errorf("#%d: expected successful parsing of an RPCResponse\nblob: %s", i, blob) - continue - } - // have a single-element result - responses = []types.RPCResponse{response} } + // we were expecting an error here, so let's unmarshal a single response + var response types.RPCResponse + err = json.Unmarshal(blob, &response) + if err != nil { + t.Errorf("#%d: expected successful parsing of an RPCResponse\nblob: %s", i, blob) + continue + } + // have a single-element result + responses = []types.RPCResponse{response} } if tt.expectCount != len(responses) { t.Errorf("#%d: expected %d response(s), but got %d\nblob: %s", i, tt.expectCount, len(responses), blob) @@ -219,7 +218,7 @@ func TestRPCNotificationInBatch(t *testing.T) { func TestUnknownRPCPath(t *testing.T) { mux := testMux() - req, _ := http.NewRequest("GET", "http://localhost/unknownrpcpath", nil) + req, _ := http.NewRequest(http.MethodGet, "http://localhost/unknownrpcpath", nil) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) res := rec.Result() @@ -232,7 +231,7 @@ func TestUnknownRPCPath(t *testing.T) { func TestRPCResponseCache(t *testing.T) { mux := testMux() body := strings.NewReader(`{"jsonrpc": "2.0","method":"block","id": 0, "params": ["1"]}`) - req, _ := http.NewRequest("Get", "http://localhost/", body) + req, _ := http.NewRequest(http.MethodGet, "http://localhost/", body) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) res := rec.Result() @@ -243,11 +242,11 @@ func TestRPCResponseCache(t *testing.T) { _, err := io.ReadAll(res.Body) res.Body.Close() - require.Nil(t, err, "reading from the body should not give back an error") + require.NoError(t, err, "reading from the body should not give back an error") // send a request with default height. body = strings.NewReader(`{"jsonrpc": "2.0","method":"block","id": 0, "params": ["0"]}`) - req, _ = http.NewRequest("Get", "http://localhost/", body) + req, _ = http.NewRequest(http.MethodGet, "http://localhost/", body) rec = httptest.NewRecorder() mux.ServeHTTP(rec, req) res = rec.Result() @@ -259,11 +258,11 @@ func TestRPCResponseCache(t *testing.T) { _, err = io.ReadAll(res.Body) res.Body.Close() - require.Nil(t, err, "reading from the body should not give back an error") + require.NoError(t, err, "reading from the body should not give back an error") // send a request with default height, but as empty set of parameters. body = strings.NewReader(`{"jsonrpc": "2.0","method":"block","id": 0, "params": []}`) - req, _ = http.NewRequest("Get", "http://localhost/", body) + req, _ = http.NewRequest(http.MethodGet, "http://localhost/", body) rec = httptest.NewRecorder() mux.ServeHTTP(rec, req) res = rec.Result() @@ -275,5 +274,5 @@ func TestRPCResponseCache(t *testing.T) { _, err = io.ReadAll(res.Body) res.Body.Close() - require.Nil(t, err, "reading from the body should not give back an error") + require.NoError(t, err, "reading from the body should not give back an error") } diff --git a/rpc/jsonrpc/server/http_server.go b/rpc/jsonrpc/server/http_server.go index 3b7cbfec87c..e5f651799b7 100644 --- a/rpc/jsonrpc/server/http_server.go +++ b/rpc/jsonrpc/server/http_server.go @@ -10,13 +10,16 @@ import ( "net/http" "os" "runtime/debug" + "strconv" "strings" "time" "golang.org/x/net/netutil" "github.com/cometbft/cometbft/libs/log" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + grpcerr "github.com/cometbft/cometbft/rpc/grpc/errors" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" + cmttime "github.com/cometbft/cometbft/types/time" ) // Config is a RPC server configuration. @@ -106,7 +109,7 @@ func WriteRPCResponseHTTPError( jsonBytes, err := json.Marshal(res) if err != nil { - return fmt.Errorf("json marshal: %w", err) + return ErrMarshalResponse{Source: err} } w.Header().Set("Content-Type", "application/json") @@ -133,7 +136,7 @@ type httpHeader struct { } func writeRPCResponseHTTP(w http.ResponseWriter, headers []httpHeader, res ...types.RPCResponse) error { - var v interface{} + var v any if len(res) == 1 { v = res[0] } else { @@ -142,18 +145,18 @@ func writeRPCResponseHTTP(w http.ResponseWriter, headers []httpHeader, res ...ty jsonBytes, err := json.Marshal(v) if err != nil { - return fmt.Errorf("json marshal: %w", err) + return ErrMarshalResponse{Source: err} } w.Header().Set("Content-Type", "application/json") for _, header := range headers { w.Header().Set(header.name, header.value) } - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) _, err = w.Write(jsonBytes) return err } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // RecoverAndLogHandler wraps an HTTP handler, adding error logging. // If the inner function panics, the outer function recovers, logs, sends an @@ -162,21 +165,21 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Wrap the ResponseWriter to remember the status rww := &responseWriterWrapper{-1, w} - begin := time.Now() + begin := cmttime.Now() - rww.Header().Set("X-Server-Time", fmt.Sprintf("%v", begin.Unix())) + rww.Header().Set("X-Server-Time", strconv.FormatInt(begin.Unix(), 10)) defer func() { // Handle any panics in the panic handler below. Does not use the logger, since we want // to avoid any further panics. However, we try to return a 500, since it otherwise // defaults to 200 and there is no other way to terminate the connection. If that // should panic for whatever reason then the Go HTTP server will handle it and - // terminate the connection - panicing is the de-facto and only way to get the Go HTTP + // terminate the connection - panicking is the de-facto and only way to get the Go HTTP // server to terminate the request and close the connection/stream: // https://github.com/golang/go/issues/17790#issuecomment-258481416 if e := recover(); e != nil { fmt.Fprintf(os.Stderr, "Panic during RPC panic recovery: %v\n%v\n", e, string(debug.Stack())) - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) } }() @@ -188,7 +191,7 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler // If RPCResponse if res, ok := e.(types.RPCResponse); ok { if wErr := WriteRPCResponseHTTP(rww, res); wErr != nil { - logger.Error("failed to write response", "res", res, "err", wErr) + logger.Error("failed to write response", "err", wErr) } } else { // Panics can contain anything, attempt to normalize it as an error. @@ -207,13 +210,13 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler res := types.RPCInternalError(types.JSONRPCIntID(-1), err) if wErr := WriteRPCResponseHTTPError(rww, http.StatusInternalServerError, res); wErr != nil { - logger.Error("failed to write response", "res", res, "err", wErr) + logger.Error("failed to write response", "err", wErr) } } } // Finally, log. - durationMS := time.Since(begin).Nanoseconds() / 1000000 + durationMS := cmttime.Since(begin).Nanoseconds() / 1000000 if rww.Status == -1 { rww.Status = 200 } @@ -230,7 +233,7 @@ func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler }) } -// Remember the status for logging +// Remember the status for logging. type responseWriterWrapper struct { Status int http.ResponseWriter @@ -241,7 +244,7 @@ func (w *responseWriterWrapper) WriteHeader(status int) { w.ResponseWriter.WriteHeader(status) } -// implements http.Hijacker +// implements http.Hijacker. func (w *responseWriterWrapper) Hijack() (net.Conn, *bufio.ReadWriter, error) { return w.ResponseWriter.(http.Hijacker).Hijack() } @@ -261,15 +264,12 @@ func (h maxBytesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func Listen(addr string, maxOpenConnections int) (listener net.Listener, err error) { parts := strings.SplitN(addr, "://", 2) if len(parts) != 2 { - return nil, fmt.Errorf( - "invalid listening address %s (use fully formed addresses, including the tcp:// or unix:// prefix)", - addr, - ) + return nil, grpcerr.ErrInvalidRemoteAddress{Addr: addr} } proto, addr := parts[0], parts[1] listener, err = net.Listen(proto, addr) if err != nil { - return nil, fmt.Errorf("failed to listen on %v: %v", addr, err) + return nil, ErrListening{Addr: addr, Source: err} } if maxOpenConnections > 0 { listener = netutil.LimitListener(listener, maxOpenConnections) diff --git a/rpc/jsonrpc/server/http_server_test.go b/rpc/jsonrpc/server/http_server_test.go index 56f6dba2bfe..28cab820354 100644 --- a/rpc/jsonrpc/server/http_server_test.go +++ b/rpc/jsonrpc/server/http_server_test.go @@ -17,7 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/libs/log" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) type sampleResult struct { @@ -30,7 +30,7 @@ func TestMaxOpenConnections(t *testing.T) { // Start the server. var open int32 mux := http.NewServeMux() - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { if n := atomic.AddInt32(&open, 1); n > int32(max) { t.Errorf("%d open connections, want <= %d", n, max) } @@ -76,7 +76,7 @@ func TestServeTLS(t *testing.T) { defer ln.Close() mux := http.NewServeMux() - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "some body") }) @@ -138,6 +138,7 @@ func TestWriteRPCResponseHTTP(t *testing.T) { assert.Equal(t, `[{"jsonrpc":"2.0","id":-1,"result":{"value":"hello"}},{"jsonrpc":"2.0","id":-1,"result":{"value":"world"}}]`, string(body)) } +// TestWriteRPCResponseHTTPError tests WriteRPCResponseHTTPError. func TestWriteRPCResponseHTTPError(t *testing.T) { w := httptest.NewRecorder() err := WriteRPCResponseHTTPError( @@ -145,10 +146,14 @@ func TestWriteRPCResponseHTTPError(t *testing.T) { http.StatusInternalServerError, types.RPCInternalError(types.JSONRPCIntID(-1), errors.New("foo"))) require.NoError(t, err) + resp := w.Result() body, err := io.ReadAll(resp.Body) - _ = resp.Body.Close() require.NoError(t, err) + + err = resp.Body.Close() + require.NoError(t, err) + assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) assert.Equal(t, `{"jsonrpc":"2.0","id":-1,"error":{"code":-32603,"message":"Internal error","data":"foo"}}`, string(body)) diff --git a/rpc/jsonrpc/server/http_uri_handler.go b/rpc/jsonrpc/server/http_uri_handler.go index 134eff20f03..f0d4e1c7786 100644 --- a/rpc/jsonrpc/server/http_uri_handler.go +++ b/rpc/jsonrpc/server/http_uri_handler.go @@ -10,24 +10,24 @@ import ( cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/libs/log" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) // HTTP + URI handler var reInt = regexp.MustCompile(`^-?[0-9]+$`) -// convert from a function name to the http handler +// convert from a function name to the http handler. func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWriter, *http.Request) { // Always return -1 as there's no ID here. dummyID := types.JSONRPCIntID(-1) // URIClientRequestID // Exception for websocket endpoints if rpcFunc.ws { - return func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, _ *http.Request) { res := types.RPCMethodNotFoundError(dummyID) if wErr := WriteRPCResponseHTTPError(w, http.StatusNotFound, res); wErr != nil { - logger.Error("failed to write response", "res", res, "err", wErr) + logger.Error("failed to write response", "err", wErr) } } } @@ -45,7 +45,7 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit fmt.Errorf("error converting http params to arguments: %w", err), ) if wErr := WriteRPCResponseHTTPError(w, http.StatusInternalServerError, res); wErr != nil { - logger.Error("failed to write response", "res", res, "err", wErr) + logger.Error("failed to write response", "err", wErr) } return } @@ -58,7 +58,7 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit if err != nil { if err := WriteRPCResponseHTTPError(w, http.StatusInternalServerError, types.RPCInternalError(dummyID, err)); err != nil { - logger.Error("failed to write response", "res", result, "err", err) + logger.Error("failed to write response", "err", err) return } return @@ -71,13 +71,13 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWrit err = WriteRPCResponseHTTP(w, resp) } if err != nil { - logger.Error("failed to write response", "res", result, "err", err) + logger.Error("failed to write response", "err", err) return } } } -// Covert an http query to a list of properly typed values. +// Convert an http query to a list of properly typed values. // To be properly decoded the arg must be a concrete type from CometBFT (if its an interface). func httpParamsToArgs(rpcFunc *RPCFunc, r *http.Request) ([]reflect.Value, error) { // skip types.Context @@ -128,24 +128,19 @@ func jsonStringToArg(rt reflect.Type, arg string) (reflect.Value, error) { func nonJSONStringToArg(rt reflect.Type, arg string) (reflect.Value, bool, error) { if rt.Kind() == reflect.Ptr { rv1, ok, err := nonJSONStringToArg(rt.Elem(), arg) - switch { - case err != nil: - return reflect.Value{}, false, err - case ok: - rv := reflect.New(rt.Elem()) - rv.Elem().Set(rv1) - return rv, true, nil - default: - return reflect.Value{}, false, nil + if err != nil || !ok { + return reflect.Value{}, ok, err } - } else { - return _nonJSONStringToArg(rt, arg) + rv := reflect.New(rt.Elem()) + rv.Elem().Set(rv1) + return rv, true, nil } + return _nonJSONStringToArg(rt, arg) } // NOTE: rt.Kind() isn't a pointer. func _nonJSONStringToArg(rt reflect.Type, arg string) (reflect.Value, bool, error) { - isIntString := reInt.Match([]byte(arg)) + isIntString := reInt.MatchString(arg) isQuotedString := strings.HasPrefix(arg, `"`) && strings.HasSuffix(arg, `"`) isHexString := strings.HasPrefix(strings.ToLower(arg), "0x") diff --git a/rpc/jsonrpc/server/parse_test.go b/rpc/jsonrpc/server/parse_test.go index c29224ea2e4..de25be18679 100644 --- a/rpc/jsonrpc/server/parse_test.go +++ b/rpc/jsonrpc/server/parse_test.go @@ -8,18 +8,19 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/libs/bytes" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) func TestParseJSONMap(t *testing.T) { input := []byte(`{"value":"1234","height":22}`) // naive is float,string - var p1 map[string]interface{} + var p1 map[string]any err := json.Unmarshal(input, &p1) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here h, ok := p1["height"].(float64) if assert.True(t, ok, "%#v", p1["height"]) { assert.EqualValues(t, 22, h) @@ -32,12 +33,12 @@ func TestParseJSONMap(t *testing.T) { // preloading map with values doesn't help tmp := 0 - p2 := map[string]interface{}{ + p2 := map[string]any{ "value": &bytes.HexBytes{}, "height": &tmp, } err = json.Unmarshal(input, &p2) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here h, ok := p2["height"].(float64) if assert.True(t, ok, "%#v", p2["height"]) { assert.EqualValues(t, 22, h) @@ -52,14 +53,14 @@ func TestParseJSONMap(t *testing.T) { // struct has unknown types, but hard-coded keys tmp = 0 p3 := struct { - Value interface{} `json:"value"` - Height interface{} `json:"height"` + Value any `json:"value"` + Height any `json:"height"` }{ Height: &tmp, Value: &bytes.HexBytes{}, } err = json.Unmarshal(input, &p3) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here h, ok := p3.Height.(*int) if assert.True(t, ok, "%#v", p3.Height) { assert.Equal(t, 22, *h) @@ -76,7 +77,7 @@ func TestParseJSONMap(t *testing.T) { Height int `json:"height"` }{} err = json.Unmarshal(input, &p4) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.EqualValues(t, 22, p4.Height) assert.EqualValues(t, []byte{0x12, 0x34}, p4.Value) } @@ -85,16 +86,16 @@ func TestParseJSONMap(t *testing.T) { // dynamic keys on map, and we can deserialize to the desired types var p5 map[string]*json.RawMessage err = json.Unmarshal(input, &p5) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here var h int err = json.Unmarshal(*p5["height"], &h) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, 22, h) } var v bytes.HexBytes err = json.Unmarshal(*p5["value"], &v) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, bytes.HexBytes{0x12, 0x34}, v) } } @@ -104,9 +105,9 @@ func TestParseJSONArray(t *testing.T) { input := []byte(`["1234",22]`) // naive is float,string - var p1 []interface{} + var p1 []any err := json.Unmarshal(input, &p1) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here v, ok := p1[0].(string) if assert.True(t, ok, "%#v", p1[0]) { assert.EqualValues(t, "1234", v) @@ -119,9 +120,9 @@ func TestParseJSONArray(t *testing.T) { // preloading map with values helps here (unlike map - p2 above) tmp := 0 - p2 := []interface{}{&bytes.HexBytes{}, &tmp} + p2 := []any{&bytes.HexBytes{}, &tmp} err = json.Unmarshal(input, &p2) - if assert.Nil(t, err) { + if assert.NoError(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here v, ok := p2[0].(*bytes.HexBytes) if assert.True(t, ok, "%#v", p2[0]) { assert.EqualValues(t, []byte{0x12, 0x34}, *v) @@ -134,7 +135,7 @@ func TestParseJSONArray(t *testing.T) { } func TestParseJSONRPC(t *testing.T) { - demo := func(ctx *types.Context, height int, name string) {} + demo := func(_ *types.Context, _ int, _ string) {} call := NewRPCFunc(demo, "height,name") cases := []struct { @@ -158,20 +159,19 @@ func TestParseJSONRPC(t *testing.T) { data := []byte(tc.raw) vals, err := jsonParamsToArgs(call, data) if tc.fail { - assert.NotNil(t, err, i) + require.Error(t, err) } else { - assert.Nil(t, err, "%s: %+v", i, err) - if assert.Equal(t, 2, len(vals), i) { + require.NoError(t, err, "%s: %+v", i, err) + if assert.Len(t, vals, 2, i) { assert.Equal(t, tc.height, vals[0].Int(), i) assert.Equal(t, tc.name, vals[1].String(), i) } } - } } func TestParseURI(t *testing.T) { - demo := func(ctx *types.Context, height int, name string) {} + demo := func(_ *types.Context, _ int, _ string) {} call := NewRPCFunc(demo, "height,name") cases := []struct { @@ -187,7 +187,7 @@ func TestParseURI(t *testing.T) { // can parse numbers quoted, too {[]string{`"7"`, `"flew"`}, 7, "flew", false}, {[]string{`"-10"`, `"bob"`}, -10, "bob", false}, - // cant parse strings uquoted + // can't parse strings uquoted {[]string{`"-10"`, `bob`}, -10, "bob", true}, } for idx, tc := range cases { @@ -196,18 +196,17 @@ func TestParseURI(t *testing.T) { url := fmt.Sprintf( "test.com/method?height=%v&name=%v", tc.raw[0], tc.raw[1]) - req, err := http.NewRequest("GET", url, nil) - assert.NoError(t, err) + req, err := http.NewRequest(http.MethodGet, url, nil) + require.NoError(t, err) vals, err := httpParamsToArgs(call, req) if tc.fail { - assert.NotNil(t, err, i) + require.Error(t, err, i) } else { - assert.Nil(t, err, "%s: %+v", i, err) - if assert.Equal(t, 2, len(vals), i) { + require.NoError(t, err, "%s: %+v", i, err) + if assert.Len(t, vals, 2, i) { assert.Equal(t, tc.height, vals[0].Int(), i) assert.Equal(t, tc.name, vals[1].String(), i) } } - } } diff --git a/rpc/jsonrpc/server/rpc_func.go b/rpc/jsonrpc/server/rpc_func.go index c1984e51fa0..678a95e3b16 100644 --- a/rpc/jsonrpc/server/rpc_func.go +++ b/rpc/jsonrpc/server/rpc_func.go @@ -12,15 +12,18 @@ import ( // RegisterRPCFuncs adds a route for each function in the funcMap, as well as // general jsonrpc and websocket handlers for all functions. "result" is the // interface on which the result objects are registered, and is popualted with -// every RPCResponse +// every RPCResponse. func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc, logger log.Logger) { // HTTP endpoints for funcName, rpcFunc := range funcMap { mux.HandleFunc("/"+funcName, makeHTTPHandler(rpcFunc, logger)) + mux.HandleFunc("/v1/"+funcName, makeHTTPHandler(rpcFunc, logger)) } // JSONRPC endpoints mux.HandleFunc("/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, logger))) + mux.HandleFunc("/v1", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, logger))) + mux.HandleFunc("/v1/", handleInvalidJSONRPCPaths(makeJSONRPCHandler(funcMap, logger))) } type Option func(*RPCFunc) @@ -34,7 +37,7 @@ type Option func(*RPCFunc) func Cacheable(noCacheDefArgs ...string) Option { return func(r *RPCFunc) { r.cacheable = true - r.noCacheDefArgs = make(map[string]interface{}) + r.noCacheDefArgs = make(map[string]any) for _, arg := range noCacheDefArgs { r.noCacheDefArgs[arg] = nil } @@ -48,25 +51,25 @@ func Ws() Option { } } -// RPCFunc contains the introspected type information for a function +// RPCFunc contains the introspected type information for a function. type RPCFunc struct { - f reflect.Value // underlying rpc function - args []reflect.Type // type of each function arg - returns []reflect.Type // type of each return arg - argNames []string // name of each argument - cacheable bool // enable cache control - ws bool // enable websocket communication - noCacheDefArgs map[string]interface{} // a lookup table of args that, if not supplied or are set to default values, cause us to not cache + f reflect.Value // underlying rpc function + args []reflect.Type // type of each function arg + returns []reflect.Type // type of each return arg + argNames []string // name of each argument + cacheable bool // enable cache control + ws bool // enable websocket communication + noCacheDefArgs map[string]any // a lookup table of args that, if not supplied or are set to default values, cause us to not cache } // NewRPCFunc wraps a function for introspection. -// f is the function, args are comma separated argument names -func NewRPCFunc(f interface{}, args string, options ...Option) *RPCFunc { +// f is the function, args are comma separated argument names. +func NewRPCFunc(f any, args string, options ...Option) *RPCFunc { return newRPCFunc(f, args, options...) } // NewWSRPCFunc wraps a function for introspection and use in the websockets. -func NewWSRPCFunc(f interface{}, args string, options ...Option) *RPCFunc { +func NewWSRPCFunc(f any, args string, options ...Option) *RPCFunc { options = append(options, Ws()) return newRPCFunc(f, args, options...) } @@ -95,7 +98,7 @@ func (f *RPCFunc) cacheableWithArgs(args []reflect.Value) bool { return true } -func newRPCFunc(f interface{}, args string, options ...Option) *RPCFunc { +func newRPCFunc(f any, args string, options ...Option) *RPCFunc { var argNames []string if args != "" { argNames = strings.Split(args, ",") @@ -115,8 +118,8 @@ func newRPCFunc(f interface{}, args string, options ...Option) *RPCFunc { return r } -// return a function's argument types -func funcArgTypes(f interface{}) []reflect.Type { +// return a function's argument types. +func funcArgTypes(f any) []reflect.Type { t := reflect.TypeOf(f) n := t.NumIn() typez := make([]reflect.Type, n) @@ -126,8 +129,8 @@ func funcArgTypes(f interface{}) []reflect.Type { return typez } -// return a function's return types -func funcReturnTypes(f interface{}) []reflect.Type { +// return a function's return types. +func funcReturnTypes(f any) []reflect.Type { t := reflect.TypeOf(f) n := t.NumOut() typez := make([]reflect.Type, n) @@ -137,10 +140,10 @@ func funcReturnTypes(f interface{}) []reflect.Type { return typez } -//------------------------------------------------------------- +// ------------------------------------------------------------- -// NOTE: assume returns is result struct and error. If error is not nil, return it -func unreflectResult(returns []reflect.Value) (interface{}, error) { +// NOTE: assume returns is result struct and error. If error is not nil, return it. +func unreflectResult(returns []reflect.Value) (any, error) { errV := returns[1] if errV.Interface() != nil { return nil, fmt.Errorf("%v", errV.Interface()) diff --git a/rpc/jsonrpc/server/ws_handler.go b/rpc/jsonrpc/server/ws_handler.go index 8e07d68dd7a..640d9d59213 100644 --- a/rpc/jsonrpc/server/ws_handler.go +++ b/rpc/jsonrpc/server/ws_handler.go @@ -3,7 +3,6 @@ package server import ( "context" "encoding/json" - "errors" "fmt" "net/http" "reflect" @@ -12,9 +11,9 @@ import ( "github.com/gorilla/websocket" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/service" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) // WebSocket handler @@ -28,7 +27,7 @@ const ( // WebsocketManager provides a WS handler for incoming connections and passes a // map of functions along with any additional params to new connections. -// NOTE: The websocket path is defined externally, e.g. in node/node.go +// NOTE: The websocket path is defined externally, e.g. in node/node.go. type WebsocketManager struct { websocket.Upgrader @@ -46,7 +45,7 @@ func NewWebsocketManager( return &WebsocketManager{ funcMap: funcMap, Upgrader: websocket.Upgrader{ - CheckOrigin: func(r *http.Request) bool { + CheckOrigin: func(_ *http.Request) bool { // TODO ??? // // The default behavior would be relevant to browser-based clients, @@ -243,7 +242,7 @@ func (wsc *wsConnection) OnStop() { } // GetRemoteAddr returns the remote address of the underlying connection. -// It implements WSRPCConnection +// It implements WSRPCConnection. func (wsc *wsConnection) GetRemoteAddr() string { return wsc.remoteAddr } @@ -254,7 +253,7 @@ func (wsc *wsConnection) GetRemoteAddr() string { func (wsc *wsConnection) WriteRPCResponse(ctx context.Context, resp types.RPCResponse) error { select { case <-wsc.Quit(): - return errors.New("connection was stopped") + return ErrConnectionStopped case <-ctx.Done(): return ctx.Err() case wsc.writeChan <- resp: @@ -264,7 +263,7 @@ func (wsc *wsConnection) WriteRPCResponse(ctx context.Context, resp types.RPCRes // TryWriteRPCResponse attempts to push a response to the writeChan, but does // not block. -// It implements WSRPCConnection. It is Goroutine-safe +// It implements WSRPCConnection. It is Goroutine-safe. func (wsc *wsConnection) TryWriteRPCResponse(resp types.RPCResponse) bool { select { case <-wsc.Quit(): @@ -286,7 +285,7 @@ func (wsc *wsConnection) Context() context.Context { return wsc.ctx } -// Read from the socket and subscribe to or unsubscribe from events +// Read from the socket and subscribe to or unsubscribe from events. func (wsc *wsConnection) readRoutine() { // readRoutine will block until response is written or WS connection is closed writeCtx := context.Background() @@ -305,7 +304,7 @@ func (wsc *wsConnection) readRoutine() { } }() - wsc.baseConn.SetPongHandler(func(m string) error { + wsc.baseConn.SetPongHandler(func(_ string) error { return wsc.baseConn.SetReadDeadline(time.Now().Add(wsc.readWait)) }) @@ -381,7 +380,7 @@ func (wsc *wsConnection) readRoutine() { returns := rpcFunc.f.Call(args) // TODO: Need to encode args/returns to string if we want to log them - wsc.Logger.Info("WSJSONRPC", "method", request.Method) + wsc.Logger.Debug("WSJSONRPC", "method", request.Method) result, err := unreflectResult(returns) if err != nil { @@ -398,7 +397,7 @@ func (wsc *wsConnection) readRoutine() { } } -// receives on a write channel and writes out on the socket +// receives on a write channel and writes out on the socket. func (wsc *wsConnection) writeRoutine() { pingTicker := time.NewTicker(wsc.pingPeriod) defer pingTicker.Stop() diff --git a/rpc/jsonrpc/server/ws_handler_test.go b/rpc/jsonrpc/server/ws_handler_test.go index da370088ca6..5f4ccb5cef9 100644 --- a/rpc/jsonrpc/server/ws_handler_test.go +++ b/rpc/jsonrpc/server/ws_handler_test.go @@ -9,48 +9,51 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/libs/log" - types "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) func TestWebsocketManagerHandler(t *testing.T) { s := newWSServer() defer s.Close() - // check upgrader works - d := websocket.Dialer{} - c, dialResp, err := d.Dial("ws://"+s.Listener.Addr().String()+"/websocket", nil) - require.NoError(t, err) - - if got, want := dialResp.StatusCode, http.StatusSwitchingProtocols; got != want { - t.Errorf("dialResp.StatusCode = %q, want %q", got, want) + for _, ep := range []string{"/websocket", "/v1/websocket"} { + // check upgrader works + d := websocket.Dialer{} + c, dialResp, err := d.Dial("ws://"+s.Listener.Addr().String()+ep, nil) + require.NoError(t, err) + + if got, want := dialResp.StatusCode, http.StatusSwitchingProtocols; got != want { + t.Errorf("dialResp.StatusCode = %q, want %q", got, want) + } + + // check basic functionality works + req, err := types.MapToRequest( + types.JSONRPCStringID("TestWebsocketManager"), + "c", + map[string]any{"s": "a", "i": 10}, + ) + require.NoError(t, err) + err = c.WriteJSON(req) + require.NoError(t, err) + + var resp types.RPCResponse + err = c.ReadJSON(&resp) + require.NoError(t, err) + require.Nil(t, resp.Error) + dialResp.Body.Close() } - - // check basic functionality works - req, err := types.MapToRequest( - types.JSONRPCStringID("TestWebsocketManager"), - "c", - map[string]interface{}{"s": "a", "i": 10}, - ) - require.NoError(t, err) - err = c.WriteJSON(req) - require.NoError(t, err) - - var resp types.RPCResponse - err = c.ReadJSON(&resp) - require.NoError(t, err) - require.Nil(t, resp.Error) - dialResp.Body.Close() } func newWSServer() *httptest.Server { funcMap := map[string]*RPCFunc{ - "c": NewWSRPCFunc(func(ctx *types.Context, s string, i int) (string, error) { return "foo", nil }, "s,i"), + "c": NewWSRPCFunc(func(_ *types.Context, _ string, _ int) (string, error) { return "foo", nil }, "s,i"), } wm := NewWebsocketManager(funcMap) wm.SetLogger(log.TestingLogger()) mux := http.NewServeMux() mux.HandleFunc("/websocket", wm.WebsocketHandler) + mux.HandleFunc("/v1/websocket", wm.WebsocketHandler) return httptest.NewServer(mux) } diff --git a/rpc/jsonrpc/test/main.go b/rpc/jsonrpc/test/main.go index b3cb9cf03c5..c3c7a5bf35a 100644 --- a/rpc/jsonrpc/test/main.go +++ b/rpc/jsonrpc/test/main.go @@ -5,8 +5,8 @@ import ( "net/http" "os" + cmtos "github.com/cometbft/cometbft/internal/os" "github.com/cometbft/cometbft/libs/log" - cmtos "github.com/cometbft/cometbft/libs/os" rpcserver "github.com/cometbft/cometbft/rpc/jsonrpc/server" rpctypes "github.com/cometbft/cometbft/rpc/jsonrpc/types" ) @@ -15,7 +15,7 @@ var routes = map[string]*rpcserver.RPCFunc{ "hello_world": rpcserver.NewRPCFunc(HelloWorld, "name,num"), } -func HelloWorld(ctx *rpctypes.Context, name string, num int) (Result, error) { +func HelloWorld(_ *rpctypes.Context, name string, num int) (Result, error) { return Result{fmt.Sprintf("hi %s %d", name, num)}, nil } diff --git a/rpc/jsonrpc/types/types.go b/rpc/jsonrpc/types/types.go index 08ee2f2bbd5..1cf1cfee429 100644 --- a/rpc/jsonrpc/types/types.go +++ b/rpc/jsonrpc/types/types.go @@ -17,19 +17,19 @@ type jsonrpcid interface { isJSONRPCID() } -// JSONRPCStringID a wrapper for JSON-RPC string IDs +// JSONRPCStringID a wrapper for JSON-RPC string IDs. type JSONRPCStringID string func (JSONRPCStringID) isJSONRPCID() {} func (id JSONRPCStringID) String() string { return string(id) } -// JSONRPCIntID a wrapper for JSON-RPC integer IDs +// JSONRPCIntID a wrapper for JSON-RPC integer IDs. type JSONRPCIntID int func (JSONRPCIntID) isJSONRPCID() {} func (id JSONRPCIntID) String() string { return fmt.Sprintf("%d", id) } -func idFromInterface(idInterface interface{}) (jsonrpcid, error) { +func idFromInterface(idInterface any) (jsonrpcid, error) { switch id := idInterface.(type) { case string: return JSONRPCStringID(id), nil @@ -45,23 +45,23 @@ func idFromInterface(idInterface interface{}) (jsonrpcid, error) { } } -//---------------------------------------- +// ---------------------------------------- // REQUEST type RPCRequest struct { JSONRPC string `json:"jsonrpc"` ID jsonrpcid `json:"id,omitempty"` Method string `json:"method"` - Params json.RawMessage `json:"params"` // must be map[string]interface{} or []interface{} + Params json.RawMessage `json:"params"` // must be map[string]any or []any } -// UnmarshalJSON custom JSON unmarshalling due to jsonrpcid being string or int +// UnmarshalJSON custom JSON unmarshalling due to jsonrpcid being string or int. func (req *RPCRequest) UnmarshalJSON(data []byte) error { unsafeReq := struct { JSONRPC string `json:"jsonrpc"` - ID interface{} `json:"id,omitempty"` + ID any `json:"id,omitempty"` Method string `json:"method"` - Params json.RawMessage `json:"params"` // must be map[string]interface{} or []interface{} + Params json.RawMessage `json:"params"` // must be map[string]any or []any }{} err := json.Unmarshal(data, &unsafeReq) @@ -98,8 +98,8 @@ func (req RPCRequest) String() string { return fmt.Sprintf("RPCRequest{%s %s/%X}", req.ID, req.Method, req.Params) } -func MapToRequest(id jsonrpcid, method string, params map[string]interface{}) (RPCRequest, error) { - var paramsMap = make(map[string]json.RawMessage, len(params)) +func MapToRequest(id jsonrpcid, method string, params map[string]any) (RPCRequest, error) { + paramsMap := make(map[string]json.RawMessage, len(params)) for name, value := range params { valueJSON, err := cmtjson.Marshal(value) if err != nil { @@ -116,8 +116,8 @@ func MapToRequest(id jsonrpcid, method string, params map[string]interface{}) (R return NewRPCRequest(id, method, payload), nil } -func ArrayToRequest(id jsonrpcid, method string, params []interface{}) (RPCRequest, error) { - var paramsMap = make([]json.RawMessage, len(params)) +func ArrayToRequest(id jsonrpcid, method string, params []any) (RPCRequest, error) { + paramsMap := make([]json.RawMessage, len(params)) for i, value := range params { valueJSON, err := cmtjson.Marshal(value) if err != nil { @@ -134,7 +134,7 @@ func ArrayToRequest(id jsonrpcid, method string, params []interface{}) (RPCReque return NewRPCRequest(id, method, payload), nil } -//---------------------------------------- +// ---------------------------------------- // RESPONSE type RPCError struct { @@ -158,11 +158,11 @@ type RPCResponse struct { Error *RPCError `json:"error,omitempty"` } -// UnmarshalJSON custom JSON unmarshalling due to jsonrpcid being string or int +// UnmarshalJSON custom JSON unmarshalling due to jsonrpcid being string or int. func (resp *RPCResponse) UnmarshalJSON(data []byte) error { unsafeResp := &struct { JSONRPC string `json:"jsonrpc"` - ID interface{} `json:"id,omitempty"` + ID any `json:"id,omitempty"` Result json.RawMessage `json:"result,omitempty"` Error *RPCError `json:"error,omitempty"` }{} @@ -184,7 +184,7 @@ func (resp *RPCResponse) UnmarshalJSON(data []byte) error { return nil } -func NewRPCSuccessResponse(id jsonrpcid, res interface{}) RPCResponse { +func NewRPCSuccessResponse(id jsonrpcid, res any) RPCResponse { var rawMsg json.RawMessage if res != nil { @@ -246,16 +246,16 @@ func RPCServerError(id jsonrpcid, err error) RPCResponse { return NewRPCErrorResponse(id, -32000, "Server error", err.Error()) } -//---------------------------------------- +// ---------------------------------------- // WSRPCConnection represents a websocket connection. type WSRPCConnection interface { // GetRemoteAddr returns a remote address of the connection. GetRemoteAddr() string // WriteRPCResponse writes the response onto connection (BLOCKING). - WriteRPCResponse(context.Context, RPCResponse) error + WriteRPCResponse(ctx context.Context, res RPCResponse) error // TryWriteRPCResponse tries to write the response onto connection (NON-BLOCKING). - TryWriteRPCResponse(RPCResponse) bool + TryWriteRPCResponse(res RPCResponse) bool // Context returns the connection's context. Context() context.Context } @@ -312,12 +312,12 @@ func (ctx *Context) Context() context.Context { return context.Background() } -//---------------------------------------- +// ---------------------------------------- // SOCKETS // Determine if its a unix or tcp socket. // If tcp, must specify the port; `0.0.0.0` will return incorrectly as "unix" since there's no port -// TODO: deprecate +// TODO: deprecate. func SocketType(listenAddr string) string { socketType := "unix" if len(strings.Split(listenAddr, ":")) >= 2 { diff --git a/rpc/jsonrpc/types/types_test.go b/rpc/jsonrpc/types/types_test.go index 8434f208b8a..8f39d139ea0 100644 --- a/rpc/jsonrpc/types/types_test.go +++ b/rpc/jsonrpc/types/types_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type SampleResult struct { @@ -34,17 +35,20 @@ func TestResponses(t *testing.T) { for _, tt := range responseTests { jsonid := tt.id a := NewRPCSuccessResponse(jsonid, &SampleResult{"hello"}) - b, _ := json.Marshal(a) + b, err := json.Marshal(a) + require.NoError(t, err) s := fmt.Sprintf(`{"jsonrpc":"2.0","id":%v,"result":{"Value":"hello"}}`, tt.expected) assert.Equal(s, string(b)) d := RPCParseError(errors.New("hello world")) - e, _ := json.Marshal(d) + e, err := json.Marshal(d) + require.NoError(t, err) f := `{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error. Invalid JSON","data":"hello world"}}` assert.Equal(f, string(e)) g := RPCMethodNotFoundError(jsonid) - h, _ := json.Marshal(g) + h, err := json.Marshal(g) + require.NoError(t, err) i := fmt.Sprintf(`{"jsonrpc":"2.0","id":%v,"error":{"code":-32601,"message":"Method not found"}}`, tt.expected) assert.Equal(string(h), i) } @@ -58,26 +62,43 @@ func TestUnmarshallResponses(t *testing.T) { []byte(fmt.Sprintf(`{"jsonrpc":"2.0","id":%v,"result":{"Value":"hello"}}`, tt.expected)), response, ) - assert.Nil(err) + require.NoError(t, err) a := NewRPCSuccessResponse(tt.id, &SampleResult{"hello"}) assert.Equal(*response, a) } response := &RPCResponse{} err := json.Unmarshal([]byte(`{"jsonrpc":"2.0","id":true,"result":{"Value":"hello"}}`), response) - assert.NotNil(err) + require.Error(t, err) } func TestRPCError(t *testing.T) { - assert.Equal(t, "RPC error 12 - Badness: One worse than a code 11", - fmt.Sprintf("%v", &RPCError{ - Code: 12, - Message: "Badness", - Data: "One worse than a code 11", - })) + testCases := []struct { + name string + err *RPCError + expected string + }{ + { + name: "With data", + err: &RPCError{ + Code: 12, + Message: "Badness", + Data: "One worse than a code 11", + }, + expected: "RPC error 12 - Badness: One worse than a code 11", + }, + { + name: "Without data", + err: &RPCError{ + Code: 12, + Message: "Badness", + }, + expected: "RPC error 12 - Badness", + }, + } - assert.Equal(t, "RPC error 12 - Badness", - fmt.Sprintf("%v", &RPCError{ - Code: 12, - Message: "Badness", - })) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expected, tc.err.Error()) + }) + } } diff --git a/rpc/openapi/openapi.yaml b/rpc/openapi/openapi.yaml index b0705576857..c285b16f894 100644 --- a/rpc/openapi/openapi.yaml +++ b/rpc/openapi/openapi.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.0 +openapi: 3.0.3 info: title: CometBFT RPC contact: @@ -9,7 +9,7 @@ info: * URI over HTTP * JSONRPC over HTTP - * JSONRPC over websockets + * JSONRPC over WebSockets ## Configuration @@ -27,7 +27,7 @@ info: 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"]` + `cors_allowed_origins = ["http://localhost:26657"]` or if testing from the official documentation site: @@ -38,17 +38,33 @@ info: Arguments which expect strings or byte arrays may be passed as quoted strings, like `"abc"` or as `0x`-prefixed strings, like `0x616263`. + ## Versions + + Up to CometBFT v0.38.x the RPC API version followed CometBFT's version, even if there was + no actual change in the API. + In CometBFT v0.39.0, the RPC API version has changed to v1 and from then on its version + will be independent CometBFT's. + + Also, from CometBFT v0.39.0, the URL used will be suffixed with the RPC version. + For example, to invoke the `block` method, one should use `localhost:26657/v1/block` + as endpoint. + + For backwards compatibility, CometBFT v0.39.x will also supports invoking the methods + without the `v1` suffix, for example, `localhost:26657/block`, returning the exact same response. + However, the support for unsuffixed methods will be dropped in future releases and all users are + encouraged to migrate as soon as possible. + ## URI/HTTP A REST like interface. - curl localhost:26657/block?height=5 + curl localhost:26657/v1/block?height=5 ## JSONRPC/HTTP JSONRPC requests can be POST'd to the root RPC endpoint via HTTP. - curl --header "Content-Type: application/json" --request POST --data '{"method": "block", "params": ["5"], "id": 1}' localhost:26657 + curl --header "Content-Type: application/json" --request POST --data '{"method": "block", "params": ["5"], "id": 1}' localhost:26657/v1 ## JSONRPC/websockets @@ -60,20 +76,20 @@ info: 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 + echo '{ "jsonrpc": "2.0","method": "subscribe","id": 0,"params": {"query": "tm.event='"'NewBlock'"'"} }' | websocat -n -t ws://127.0.0.1:26657/v1/websocket - version: "main" + version: "v1" license: name: Apache 2.0 url: https://github.com/cometbft/cometbft/blob/main/LICENSE servers: - url: https://rpc.cosmos.directory/cosmoshub - description: Interact with the CometBFT RPC from a public node in the Cosmos registry + description: CometBFT running on a public node in the Cosmos registry - url: http://localhost:26657 - description: Interact with CometBFT RPC node running locally + description: CometBFT running locally (`cors_allowed_origins` must be set; see above) tags: - name: Info - description: Informations about the node APIs + description: Information about the node APIs - name: Tx description: Transactions broadcast APIs - name: ABCI @@ -83,13 +99,15 @@ tags: - name: Unsafe description: Unsafe APIs paths: - /broadcast_tx_sync: + /v1/broadcast_tx_sync: get: - summary: Returns with the response from CheckTx. Does not wait for DeliverTx result. + summary: Submits a transaction to the blockchain and returns with the response from CheckTx. tags: - Tx operationId: broadcast_tx_sync description: | + Submits a transaction to be included in the blockchain and returns the response from CheckTx. + Does not wait for DeliverTx result. If you want to be sure that the transaction is included in a block, you can subscribe for the result using JSONRPC via a websocket. See https://docs.cometbft.com/main/core/subscription.html @@ -112,8 +130,8 @@ paths: required: true schema: type: string - example: "456" - description: The transaction + example: '"456"' + description: The transaction hash responses: "200": description: Empty @@ -127,13 +145,15 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /broadcast_tx_async: + /v1/broadcast_tx_async: get: - summary: Returns right away, with no response. Does not wait for CheckTx nor DeliverTx results. + summary: Submits a transaction to the blockchain and returns right away, with no response. tags: - Tx operationId: broadcast_tx_async description: | + Submits a transaction to be included in the blockchain and returns immediately. + Does not wait for CheckTx or DeliverTx results. If you want to be sure that the transaction is included in a block, you can subscribe for the result using JSONRPC via a websocket. See https://docs.cometbft.com/main/core/subscription.html @@ -156,7 +176,7 @@ paths: required: true schema: type: string - example: "123" + example: '"123"' description: The transaction responses: "200": @@ -171,9 +191,9 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /broadcast_tx_commit: + /v1/broadcast_tx_commit: get: - summary: Returns with the responses from CheckTx and DeliverTx. + summary: Submits a transaction to be included in the blockchain and returns CheckTx and DeliverTx results. tags: - Tx operationId: broadcast_tx_commit @@ -198,7 +218,7 @@ paths: required: true schema: type: string - example: "785" + example: "0x1234" description: The transaction responses: "200": @@ -213,7 +233,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /check_tx: + /v1/check_tx: get: summary: Checks the transaction without executing it. tags: @@ -248,14 +268,15 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /health: + /v1/health: get: - summary: Node heartbeat + summary: Gets the node's health status information. tags: - Info operationId: health description: | - Get node health. Returns empty result (200 OK) on success, no response - in case of an error. + Get node health status. + Returns empty result (200 OK) on success, no response - in case of an error. responses: "200": description: Gets Node Health @@ -269,7 +290,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /status: + /v1/status: get: summary: Node Status operationId: status @@ -290,7 +311,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /net_info: + /v1/net_info: get: summary: Network information operationId: net_info @@ -311,14 +332,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /dial_seeds: + /v1/dial_seeds: get: summary: Dial Seeds (Unsafe) operationId: dial_seeds tags: - Unsafe description: | - Dial a peer, this route in under unsafe, and has to manually enabled to use + Dial a peer, this route in under unsafe, and has to be manually enabled to use **Example:** curl 'localhost:26657/dial_seeds?seeds=\["f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:26656","0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:26656"\]' parameters: @@ -343,7 +364,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /dial_peers: + /v1/dial_peers: get: summary: Add Peers/Persistent Peers (unsafe) operationId: dial_peers @@ -393,7 +414,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /blockchain: + /v1/blockchain: get: summary: "Get block headers (max: 20) for minHeight <= height <= maxHeight." operationId: blockchain @@ -432,7 +453,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /header: + /v1/header: get: summary: Get header at a specified height operationId: header @@ -453,7 +474,7 @@ paths: `Cache-Control` header will be set with the default maximum age. responses: "200": - description: Header informations. + description: Header information. content: application/json: schema: @@ -464,7 +485,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /header_by_hash: + /v1/header_by_hash: get: summary: Get header by hash operationId: header_by_hash @@ -485,7 +506,7 @@ paths: maximum age. responses: "200": - description: Header informations. + description: Header information. content: application/json: schema: @@ -496,7 +517,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /block: + /v1/block: get: summary: Get block at a specified height operationId: block @@ -517,7 +538,7 @@ paths: `Cache-Control` header will be set with the default maximum age. responses: "200": - description: Block informations. + description: Block information. content: application/json: schema: @@ -528,7 +549,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /block_by_hash: + /v1/block_by_hash: get: summary: Get block by hash operationId: block_by_hash @@ -549,7 +570,7 @@ paths: maximum age. responses: "200": - description: Block informations. + description: Block information. content: application/json: schema: @@ -560,7 +581,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /block_results: + /v1/block_results: get: summary: Get block results at a specified height operationId: block_results @@ -592,14 +613,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /commit: + /v1/commit: get: summary: Get commit results at a specified height operationId: commit parameters: - in: query name: height - description: height to return. If no height is provided, it will fetch commit informations regarding the latest block. + description: height to return. If no height is provided, it will fetch commit information regarding the latest block. schema: type: integer default: 0 @@ -627,7 +648,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /validators: + /v1/validators: get: summary: Get validator set at a specified height operationId: validators @@ -676,7 +697,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /genesis: + /v1/genesis: get: summary: Get Genesis operationId: genesis @@ -700,7 +721,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /genesis_chunked: + /v1/genesis_chunked: get: summary: Get Genesis in multiple chunks operationId: genesis_chunked @@ -735,7 +756,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /dump_consensus_state: + /v1/dump_consensus_state: get: summary: Get consensus state operationId: dump_consensus_state @@ -761,7 +782,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /consensus_state: + /v1/consensus_state: get: summary: Get consensus state operationId: consensus_state @@ -784,14 +805,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /consensus_params: + /v1/consensus_params: get: summary: Get consensus parameters operationId: consensus_params parameters: - in: query name: height - description: height to return. If no height is provided, it will fetch commit informations regarding the latest block. + description: height to return. If no height is provided, it will fetch commit information regarding the latest block. schema: type: integer default: 0 @@ -816,7 +837,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /unconfirmed_txs: + /v1/unconfirmed_txs: get: summary: Get the list of unconfirmed transactions operationId: unconfirmed_txs @@ -846,7 +867,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /num_unconfirmed_txs: + /v1/num_unconfirmed_txs: get: summary: Get data about unconfirmed transactions operationId: num_unconfirmed_txs @@ -867,7 +888,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /tx_search: + /v1/tx_search: get: summary: Search for transactions description: | @@ -882,7 +903,7 @@ paths: required: true schema: type: string - example: "tx.height=1000" + example: '"tx.height=1000"' - in: query name: prove description: Include proofs of the transactions inclusion in the block @@ -913,8 +934,8 @@ paths: required: false schema: type: string - default: "asc" - example: "asc" + default: '"asc"' + example: '"asc"' tags: - Info responses: @@ -930,11 +951,11 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /block_search: + /v1/block_search: get: - summary: Search for blocks by BeginBlock and EndBlock events + summary: Search for blocks by FinalizeBlock events description: | - Search for blocks by BeginBlock and EndBlock events. + Search for blocks by FinalizeBlock events. See /subscribe for the query syntax. operationId: block_search @@ -945,7 +966,7 @@ paths: required: true schema: type: string - example: "block.height > 1000 AND valset.changed > 0" + example: '"block.height > 1000 AND valset.changed > 0"' - in: query name: page description: "Page number (1-based)" @@ -968,8 +989,8 @@ paths: required: false schema: type: string - default: "desc" - example: "asc" + default: '"desc"' + example: '"asc"' tags: - Info responses: @@ -985,8 +1006,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - - /tx: + /v1/tx: get: summary: Get transactions by hash operationId: tx @@ -1026,7 +1046,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /abci_info: + /v1/abci_info: get: summary: Get info about the application. operationId: abci_info @@ -1050,28 +1070,38 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /abci_query: + /v1/abci_query: get: summary: Query the application for some information. operationId: abci_query parameters: - in: query name: path - description: Path to the data ("/a/b/c") - required: true + description: | + A request path for the application to interpret analogously to a + [URI path component](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) + in e.g. routing. + + Applications MUST interpret "/store" or any path starting with + "/store/" as a query by key on the underlying store, in which case + a key SHOULD be specified in `data`. + required: false schema: type: string - example: "/a/b/c" + example: '"/store/foo"' - in: query name: data - description: Data - required: true + description: | + Request parameters for the application to interpret analogously to a + [URI query component](https://www.rfc-editor.org/rfc/rfc3986#section-3.4), + expressed as hexadecimal-serialized bytes. + required: false schema: type: string - example: "IHAVENOIDEA" + example: "0x636f6d6574626674" - in: query name: height - description: Height (0 means latest) + description: The block height against which to query (0 means latest) required: false schema: type: integer @@ -1079,7 +1109,7 @@ paths: default: 0 - in: query name: prove - description: Include proofs of the transactions inclusion in the block + description: Return Merkle proof with response if possible required: false schema: type: boolean @@ -1102,7 +1132,7 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /broadcast_evidence: + /v1/broadcast_evidence: get: summary: Broadcast evidence of the misbehavior. operationId: broadcast_evidence @@ -1198,7 +1228,7 @@ components: example: "cosmoshub-2" version: type: string - example: "0.32.1" + example: "0.34.27" channels: type: string example: "4020212223303800" @@ -1210,7 +1240,7 @@ components: properties: tx_index: type: string - example: "on" + example: '"on"' rpc_address: type: string example: "tcp:0.0.0.0:26657" @@ -1509,7 +1539,7 @@ components: block: $ref: "#/components/schemas/Block" BlockResponse: - description: Blockc info + description: Block info allOf: - $ref: "#/components/schemas/JSONRPC" - type: object @@ -1580,21 +1610,7 @@ components: codespace: type: string example: "ibc" - begin_block_events: - type: array - nullable: true - items: - type: object - properties: - type: - type: string - example: "app" - attributes: - type: array - nullable: false - items: - $ref: "#/components/schemas/Event" - end_block_events: + finalize_block_events: type: array nullable: true items: @@ -2718,9 +2734,9 @@ components: example: 2 type: object - ###### Reuseable types ###### + ###### Reusable types ###### - # Validator type with proposer prioirty + # Validator type with proposer priority ValidatorPriority: type: object properties: @@ -2808,10 +2824,10 @@ components: properties: key: type: string - example: "YWN0aW9u" + example: "action" value: type: string - example: "c2VuZA==" + example: "send" index: type: boolean example: false diff --git a/rpc/test/helpers.go b/rpc/test/helpers.go index 1103edffac7..0c01a2f3d70 100644 --- a/rpc/test/helpers.go +++ b/rpc/test/helpers.go @@ -9,17 +9,15 @@ import ( "time" abci "github.com/cometbft/cometbft/abci/types" + cfg "github.com/cometbft/cometbft/config" + cmtnet "github.com/cometbft/cometbft/internal/net" "github.com/cometbft/cometbft/internal/test" "github.com/cometbft/cometbft/libs/log" - - cfg "github.com/cometbft/cometbft/config" - cmtnet "github.com/cometbft/cometbft/libs/net" nm "github.com/cometbft/cometbft/node" "github.com/cometbft/cometbft/p2p" "github.com/cometbft/cometbft/privval" "github.com/cometbft/cometbft/proxy" ctypes "github.com/cometbft/cometbft/rpc/core/types" - core_grpc "github.com/cometbft/cometbft/rpc/grpc" rpcclient "github.com/cometbft/cometbft/rpc/jsonrpc/client" ) @@ -30,11 +28,13 @@ type Options struct { recreateConfig bool } -var globalConfig *cfg.Config -var defaultOptions = Options{ - suppressStdout: false, - recreateConfig: false, -} +var ( + globalConfig *cfg.Config + defaultOptions = Options{ + suppressStdout: false, + recreateConfig: false, + } +) func waitForRPC() { laddr := GetConfig().RPC.ListenAddress @@ -44,7 +44,7 @@ func waitForRPC() { } result := new(ctypes.ResultStatus) for { - _, err := client.Call(context.Background(), "status", map[string]interface{}{}, result) + _, err := client.Call(context.Background(), "status", map[string]any{}, result) if err == nil { return } @@ -54,17 +54,7 @@ func waitForRPC() { } } -func waitForGRPC() { - client := GetGRPCClient() - for { - _, err := client.Ping(context.Background(), &core_grpc.RequestPing{}) - if err == nil { - return - } - } -} - -// f**ing long, but unique for each test +// f**ing long, but unique for each test. func makePathname() string { // get path p, err := os.Getwd() @@ -84,10 +74,8 @@ func randPort() int { return port } -func makeAddrs() (string, string, string) { - return fmt.Sprintf("tcp://127.0.0.1:%d", randPort()), - fmt.Sprintf("tcp://127.0.0.1:%d", randPort()), - fmt.Sprintf("tcp://127.0.0.1:%d", randPort()) +func makeAddr() string { + return fmt.Sprintf("tcp://127.0.0.1:%d", randPort()) } func createConfig() *cfg.Config { @@ -95,15 +83,20 @@ func createConfig() *cfg.Config { c := test.ResetTestRoot(pathname) // and we use random ports to run in parallel - tm, rpc, grpc := makeAddrs() - c.P2P.ListenAddress = tm - c.RPC.ListenAddress = rpc + c.P2P.ListenAddress = makeAddr() + c.RPC.ListenAddress = makeAddr() c.RPC.CORSAllowedOrigins = []string{"https://cometbft.com/"} - c.RPC.GRPCListenAddress = grpc + c.GRPC.ListenAddress = makeAddr() + c.GRPC.VersionService.Enabled = true + c.GRPC.Privileged.ListenAddress = makeAddr() + c.GRPC.Privileged.PruningService.Enabled = true + // Set pruning interval to a value lower than the default for some of the + // tests that rely on pruning to occur quickly + c.Storage.Pruning.Interval = 100 * time.Millisecond return c } -// GetConfig returns a config for the test cases as a singleton +// GetConfig returns a config for the test cases as a singleton. func GetConfig(forceCreate ...bool) *cfg.Config { if globalConfig == nil || (len(forceCreate) > 0 && forceCreate[0]) { globalConfig = createConfig() @@ -111,18 +104,13 @@ func GetConfig(forceCreate ...bool) *cfg.Config { return globalConfig } -func GetGRPCClient() core_grpc.BroadcastAPIClient { - grpcAddr := globalConfig.RPC.GRPCListenAddress - return core_grpc.StartGRPCClient(grpcAddr) -} - -// StartTendermint starts a test CometBFT server in a go routine and returns when it is initialized -func StartTendermint(app abci.Application, opts ...func(*Options)) *nm.Node { +// StartCometBFT starts a test CometBFT server in a go routine and returns when it is initialized. +func StartCometBFT(app abci.Application, opts ...func(*Options)) *nm.Node { nodeOpts := defaultOptions for _, opt := range opts { opt(&nodeOpts) } - node := NewTendermint(app, &nodeOpts) + node := NewCometBFT(app, &nodeOpts) err := node.Start() if err != nil { panic(err) @@ -130,7 +118,6 @@ func StartTendermint(app abci.Application, opts ...func(*Options)) *nm.Node { // wait for rpc waitForRPC() - waitForGRPC() if !nodeOpts.suppressStdout { fmt.Println("CometBFT running!") @@ -139,9 +126,9 @@ func StartTendermint(app abci.Application, opts ...func(*Options)) *nm.Node { return node } -// StopTendermint stops a test CometBFT server, waits until it's stopped and +// StopCometBFT stops a test CometBFT server, waits until it's stopped and // cleans up test/config files. -func StopTendermint(node *nm.Node) { +func StopCometBFT(node *nm.Node) { if err := node.Stop(); err != nil { node.Logger.Error("Error when trying to stop node", "err", err) } @@ -149,8 +136,8 @@ func StopTendermint(node *nm.Node) { os.RemoveAll(node.Config().RootDir) } -// NewTendermint creates a new CometBFT server and sleeps forever -func NewTendermint(app abci.Application, opts *Options) *nm.Node { +// NewCometBFT creates a new CometBFT server and sleeps forever. +func NewCometBFT(app abci.Application, opts *Options) *nm.Node { // Create & start node config := GetConfig(opts.recreateConfig) var logger log.Logger @@ -168,7 +155,7 @@ func NewTendermint(app abci.Application, opts *Options) *nm.Node { if err != nil { panic(err) } - node, err := nm.NewNode(config, pv, nodeKey, papp, + node, err := nm.NewNode(context.Background(), config, pv, nodeKey, papp, nm.DefaultGenesisDocProviderFunc(config), cfg.DefaultDBProvider, nm.DefaultMetricsProvider(config.Instrumentation), diff --git a/scripts/db_measurements/measure_db.py b/scripts/db_measurements/measure_db.py new file mode 100755 index 00000000000..6048337bb02 --- /dev/null +++ b/scripts/db_measurements/measure_db.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +import subprocess +import asyncio +import os +import signal + + +LOCAL_NET_LOG = os.path.join("scripts", "db_measurements", "local_net.log") +PAYLOAD_LOG = os.path.join("scripts", "db_measurements", "payload.log") + + +def set_project_root(): + current_file_path = os.path.abspath(__file__) + candidate = os.path.dirname(os.path.dirname(os.path.dirname(current_file_path))) + if os.path.basename(candidate) == "cometbft": + os.chdir(candidate) + return + raise FileNotFoundError("Can't locate project root") + + +async def read_and_handle_process_output(process, handle, *handle_args): + while True: + line = await process.stdout.readline() + if not line: + break + ln = line.decode().strip() + handle(ln, *handle_args) + + + +async def clear_n_launch_localnet(node_started_event): + clear_command = ["sudo", "rm", "-rf", "build/"] + build_command = ["sudo", "make", "build-linux"] + launch_command = ["sudo", "make", "localnet-start"] + subprocess.run(clear_command, capture_output=True, text=True, check=True) + subprocess.run(build_command, capture_output=True, text=True, check=True) + process = await asyncio.create_subprocess_exec(*launch_command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + + def handle(line, event): + if "Started node" in line: + event.set() + with open(LOCAL_NET_LOG, 'a') as f: + f.write(line + "\n") + + asyncio.create_task(read_and_handle_process_output(process, handle, node_started_event)) + + +def prettify_du(s): + return '; '.join([f"{os.path.basename(l.split(' ')[1])}: {l.split(' ')[0]}" for l in filter(len, s.split('\n'))]) + + +async def measure_du(rate, tx_size): + data_path = os.path.join("build", "node0", "data") + measure_command = ["sudo", "du", "-h", data_path] + T = 0 + period = 20 + try: + while True: + try: + result = subprocess.run(measure_command, capture_output=True, text=True, check=True, timeout=10) + pretty_result = prettify_du(result.stdout) + print(f"r {rate}; s {tx_size}; T {T}; storage size: {pretty_result}") + except: + pass + await asyncio.sleep(period) + T += period + except asyncio.CancelledError: + print() + + +async def launch_payload(r, s, T): + payload_script_path = os.path.join("test", "loadtime", "build", "load") + payload_command = [payload_script_path, "-T", str(T), "-r", str(r), "-s", str(s), "--endpoints", "ws://localhost:26657/websocket"] + process = await asyncio.create_subprocess_exec(*payload_command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) + + def handle(line, *args): + print("Payloading") + with open(PAYLOAD_LOG, 'a') as f: + f.write(line + "\n") + + asyncio.create_task(read_and_handle_process_output(process, handle)) + await process.wait() + + +def stop_localnet(): + stop_command = ["sudo", "make", "build", "localnet-stop"] + subprocess.run(stop_command, capture_output=True, text=True, check=True) + + +async def run(): + tx_sizes = [4096] + rates = [1500] + T = 3600 + for tx_size in tx_sizes: + for rate in rates: + node_started_event = asyncio.Event() + localnet_process = asyncio.create_task(clear_n_launch_localnet(node_started_event)) + await node_started_event.wait() + payload_task = asyncio.create_task(launch_payload(rate, tx_size, T)) + measure_task = asyncio.create_task(measure_du(rate, tx_size)) + await payload_task + measure_task.cancel() + stop_localnet() + + +def main(): + set_project_root() + with open(LOCAL_NET_LOG, 'w'): + pass + with open(PAYLOAD_LOG, 'w'): + pass + asyncio.run(run()) + + +main() \ No newline at end of file diff --git a/scripts/dist.sh b/scripts/dist.sh index c615dc6dbf6..c0d2ccadf84 100755 --- a/scripts/dist.sh +++ b/scripts/dist.sh @@ -6,7 +6,7 @@ set -e # Get the version from the environment, or try to figure it out. if [ -z $VERSION ]; then - VERSION=$(awk -F\" 'TMCoreSemVer =/ { print $2; exit }' < version/version.go) + VERSION=$(awk -F\" 'CMTSemVer =/ { print $2; exit }' < version/version.go) fi if [ -z "$VERSION" ]; then echo "Please specify a version." @@ -41,7 +41,7 @@ for arch in "${arch_list[@]}"; do for os in "${os_list[@]}"; do if [[ "$XC_EXCLUDE" != *" $os/$arch "* ]]; then echo "--> $os/$arch" - GOOS=${os} GOARCH=${arch} go build -ldflags "-s -w -X ${GIT_IMPORT}.TMCoreSemVer=${VERSION}" -tags="${BUILD_TAGS}" -o "build/pkg/${os}_${arch}/cometbft" ./cmd/cometbft + GOOS=${os} GOARCH=${arch} go build -ldflags "-s -w -X ${GIT_IMPORT}.CMTSemVer=${VERSION}" -tags="${BUILD_TAGS}" -o "build/pkg/${os}_${arch}/cometbft" ./cmd/cometbft fi done done diff --git a/scripts/json2wal/main.go b/scripts/json2wal/main.go index 48470858708..052380a2576 100644 --- a/scripts/json2wal/main.go +++ b/scripts/json2wal/main.go @@ -14,7 +14,7 @@ import ( "os" "strings" - cs "github.com/cometbft/cometbft/consensus" + cs "github.com/cometbft/cometbft/internal/consensus" cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/types" ) @@ -31,7 +31,7 @@ func main() { } defer f.Close() - walFile, err := os.OpenFile(os.Args[2], os.O_EXCL|os.O_WRONLY|os.O_CREATE, 0666) + walFile, err := os.OpenFile(os.Args[2], os.O_EXCL|os.O_WRONLY|os.O_CREATE, 0o666) if err != nil { panic(fmt.Errorf("failed to open WAL file: %v", err)) } diff --git a/scripts/metricsgen/metricsdiff/metricsdiff.go b/scripts/metricsgen/metricsdiff/metricsdiff.go index 5ed72ff97cc..2070b175cba 100644 --- a/scripts/metricsgen/metricsdiff/metricsdiff.go +++ b/scripts/metricsgen/metricsdiff/metricsdiff.go @@ -64,16 +64,16 @@ func main() { if err != nil { log.Fatalf("Open: %v", err) } - defer fa.Close() fb, err := os.Open(flag.Arg(1)) if err != nil { log.Fatalf("Open: %v", err) } - defer fb.Close() md, err := DiffFromReaders(fa, fb) if err != nil { log.Fatalf("Generating diff: %v", err) } + fa.Close() + fb.Close() fmt.Print(md) } @@ -126,7 +126,7 @@ func toList(l map[string]*dto.MetricFamily) metricsList { for name, family := range l { r[idx] = parsedMetric{ name: name, - labels: labelsToStringList(family.Metric[0].Label), + labels: labelsToStringList(family.GetMetric()[0].GetLabel()), } idx++ } diff --git a/scripts/metricsgen/metricsdiff/metricsdiff_test.go b/scripts/metricsgen/metricsdiff/metricsdiff_test.go index 122eaf67393..c72d2d4c501 100644 --- a/scripts/metricsgen/metricsdiff/metricsdiff_test.go +++ b/scripts/metricsgen/metricsdiff/metricsdiff_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - metricsdiff "github.com/cometbft/cometbft/scripts/metricsgen/metricsdiff" + metricsdiff "github.com/cometbft/cometbft/scripts/metricsgen/metricsdiff" //nolint:revive // this only works with metricsdiff in front ) func TestDiff(t *testing.T) { diff --git a/scripts/metricsgen/metricsgen.go b/scripts/metricsgen/metricsgen.go index 1da45cb83f7..159cf733b26 100644 --- a/scripts/metricsgen/metricsgen.go +++ b/scripts/metricsgen/metricsgen.go @@ -145,6 +145,7 @@ func main() { log.Fatalf("Generating code: %v", err) } } + func ignoreTestFiles(f fs.FileInfo) bool { return !strings.Contains(f.Name(), "_test.go") } @@ -162,13 +163,15 @@ func ParseMetricsDir(dir string, structName string) (TemplateData, error) { return TemplateData{}, fmt.Errorf("multiple packages found in %s", dir) } if len(d) == 0 { - return TemplateData{}, fmt.Errorf("no go pacakges found in %s", dir) + return TemplateData{}, fmt.Errorf("no go packages found in %s", dir) } // Grab the package name. var pkgName string var pkg *ast.Package - for pkgName, pkg = range d { + // TODO(thane): Figure out a more readable way of implementing this. + + for pkgName, pkg = range d { //nolint:revive } td := TemplateData{ Package: pkgName, @@ -210,9 +213,7 @@ func GenerateMetricsFile(w io.Writer, td TemplateData) error { } func findMetricsStruct(files map[string]*ast.File, structName string) (*ast.StructType, string, error) { - var ( - st *ast.StructType - ) + var st *ast.StructType for _, file := range files { mPkgName, err := extractMetricsPackageName(file.Imports) if err != nil { @@ -272,7 +273,7 @@ func extractHelpMessage(cg *ast.CommentGroup) string { } var help []string //nolint: prealloc for _, c := range cg.List { - mt := strings.TrimPrefix(c.Text, "//metrics:") + mt := strings.TrimPrefix(c.Text, "// metrics:") if mt != c.Text { return strings.TrimSpace(mt) } @@ -282,7 +283,7 @@ func extractHelpMessage(cg *ast.CommentGroup) string { } func isMetric(e ast.Expr, mPkgName string) bool { - return strings.Contains(types.ExprString(e), fmt.Sprintf("%s.", mPkgName)) + return strings.Contains(types.ExprString(e), mPkgName+".") } func extractLabels(bl *ast.BasicLit) string { diff --git a/scripts/metricsgen/metricsgen_test.go b/scripts/metricsgen/metricsgen_test.go index 8a797dca4e8..88c697e24b7 100644 --- a/scripts/metricsgen/metricsgen_test.go +++ b/scripts/metricsgen/metricsgen_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" - metricsgen "github.com/cometbft/cometbft/scripts/metricsgen" + metricsgen "github.com/cometbft/cometbft/scripts/metricsgen" //nolint:revive // this only works with metricsgen in front ) const testDataDir = "./testdata" @@ -37,6 +37,7 @@ func TestSimpleTemplate(t *testing.T) { } } +// TestFromData tests that the metricsgen tool can parse a directory of metrics and generate a file. func TestFromData(t *testing.T) { infos, err := os.ReadDir(testDataDir) if err != nil { @@ -180,6 +181,49 @@ func TestParseMetricsStruct(t *testing.T) { }, }, }, + { + name: "parse description from comments", + metricsStruct: `type Metrics struct { + // myCounter is a counter. + // It does count. + myCounter metrics.Counter + nonMetric string + }`, + expected: metricsgen.TemplateData{ + Package: pkgName, + ParsedMetrics: []metricsgen.ParsedMetricField{ + { + Description: "myCounter is a counter. It does count.", + TypeName: "Counter", + FieldName: "myCounter", + MetricName: "my_counter", + }, + }, + }, + }, + { + name: "parse short description from comments", + metricsStruct: `type Metrics struct { + // myCounter is a counter. + // + // myCounter needs a super long description, + // we don't want it on the description. + // metrics:It does count. + myCounter metrics.Counter + nonMetric string + }`, + expected: metricsgen.TemplateData{ + Package: pkgName, + ParsedMetrics: []metricsgen.ParsedMetricField{ + { + Description: "It does count.", + TypeName: "Counter", + FieldName: "myCounter", + MetricName: "my_counter", + }, + }, + }, + }, } for _, testCase := range metricsTests { t.Run(testCase.name, func(t *testing.T) { @@ -244,16 +288,15 @@ func TestParseAliasedMetric(t *testing.T) { td, err := metricsgen.ParseMetricsDir(dir, "Metrics") require.NoError(t, err) - expected := - metricsgen.TemplateData{ - Package: "mypkg", - ParsedMetrics: []metricsgen.ParsedMetricField{ - { - TypeName: "Gauge", - FieldName: "m", - MetricName: "m", - }, + expected := metricsgen.TemplateData{ + Package: "mypkg", + ParsedMetrics: []metricsgen.ParsedMetricField{ + { + TypeName: "Gauge", + FieldName: "m", + MetricName: "m", }, - } + }, + } require.Equal(t, expected, td) } diff --git a/scripts/mockery_generate.sh b/scripts/mockery_generate.sh index 2509e0cdbeb..16e205311f9 100755 --- a/scripts/mockery_generate.sh +++ b/scripts/mockery_generate.sh @@ -2,5 +2,5 @@ # # Invoke Mockery v2 to update generated mocks for the given type. -go run github.com/vektra/mockery/v2 --disable-version-string --case underscore --name "$*" +go run github.com/vektra/mockery/v2@latest --disable-version-string --case underscore --name "$*" diff --git a/scripts/proto-gen.sh b/scripts/proto-gen.sh index 981cec74027..436b49b25c9 100755 --- a/scripts/proto-gen.sh +++ b/scripts/proto-gen.sh @@ -14,6 +14,6 @@ docker run --rm -i -v "$PWD":/w --workdir=/w golang:1.20-alpine sh <<"EOF" apk add git make go install github.com/bufbuild/buf/cmd/buf -go install github.com/cosmos/gogoproto/protoc-gen-gogofaster@latest +go install github.com/cosmos/gogoproto/protoc-gen-gocosmos@latest make proto-gen EOF diff --git a/scripts/qa/reporting/README.md b/scripts/qa/reporting/README.md index 2ae33380cbc..a285d8c2f0f 100644 --- a/scripts/qa/reporting/README.md +++ b/scripts/qa/reporting/README.md @@ -1,6 +1,6 @@ # Reporting Scripts -This directory contains some utility scripts used in the reporting/QA. +This directory contains some utility scripts used for generating reports of QA processes. * [`latency_throughput.py`](./latency_throughput.py) is a Python script that uses [matplotlib] to plot a graph of transaction latency vs throughput rate based on @@ -17,8 +17,8 @@ This directory contains some utility scripts used in the reporting/QA. ## Setup -Execute the following within this directory (the same directory as the -`latency_throughput.py` file). +Before running the Python scripts, execute the following within this directory (the same directory +as the `latency_throughput.py` file). ```bash # Create a virtual environment into which to install your dependencies @@ -32,65 +32,48 @@ pip install -r requirements.txt ``` ## Latency vs Throughput Plotting -To show the instructions and parameter options, execute +To show the instructions and parameter options, execute ```bash ./latency_throughput.py --help ``` +Be sure that the virtual environment is enabled before running the script. -Example: - +For example, the following command will generate a PNG file called `cmt_v1.png` in the current +directory based on the `raw.csv` file generated by the reporting tool. The `-t` flag overrides the +default title at the top of the plot. ```bash -# Do the following while ensuring that the virtual environment is activated (see -# the Setup steps). -# -# This will generate a plot in a PNG file called 'tm034.png' in the current -# directory based on the reporting tool CSV output in the "raw.csv" file. The -# '-t' flag overrides the default title at the top of the plot. - -./latency_throughput.py \ - -t 'CometBFT v0.34.x Latency vs Throughput' \ - ./tm034.png \ - /path/to/csv/files/raw.csv +./latency_throughput.py -t 'CometBFT v1.x Latency vs Throughput' ./cmt_v1.png /path/to/results/raw.csv ``` ## Latency vs Throughput Plotting (version 2) -Example: +The `latency_plotter.py` script generates a series of plots in the `imgs` folder. +Plots include combined experiment plots and experiments as subplots. +- `all_experiments`: plots of all experiments as individual subplots. +- `all_configs`: plots of all experiments, grouped by configuration (r,c). +- `cXrY.png`: Independent plot of experiments of configuration (c=X,r=Y) as different curves. +- `cXrY_merged.png`: Independent plot of experiments of configuration (c=X,r=Y) combined as single curve. +- `e_ID.png`: independent plot with just experiment with id ID as a single curve. + +Example: ```bash -# Do the following while ensuring that the virtual environment is activated (see -# the Setup steps). -# -# This will generate a series of plots in the `imgs` folder. -# Plots include combined experiment plots and experiments as subplots. -# - all_experiments - plots of all experiments as individual subplots. -# - all_configs - plots of all experiments, grouped by configuration (r,c). -# cXrY.png - Independent plot of experiments of configuration (c=X,r=Y) as different curves. -# cXrY_merged.png - Independent plot of experiments of configuration (c=X,r=Y) combined as single curve. -# e_ID.png - independent plot with just experiment with id ID as a single curve. - - -python3 latency_plotter.py /path/to/csv/files/raw.csv +./latency_plotter.py v1.0.0-alpha.2 /path/to/results/raw.csv ``` +Be sure that the virtual environment is enabled before running the script. ## Prometheus metrics -1. Ensure that Prometheus is running locally and listening on port 9090. -2. Tweak the script to your needs - 1. Adjust the time window - 2. Select the right fork - 3. Tweak/add/remove metrics -3. Run the script as follows - ```bash - # Do the following while ensuring that the virtual environment is activated (see - # the Setup steps). - # - # This will generate a series of plots in the folder `imgs` of the current folder. - - mkdir imgs - python3 prometheus_plotter.py - ``` -4. Plots are saved in the `imgs` folder. +The `prometheus_plotter.py` script generates a series of plots in the folder `imgs` of the current folder. + +Before running the script, check that a Prometheus server in `localhost:9090`. This is the default URL hardcoded in the script. + +Run the script from the virtual environment as follows: +```bash +./prometheus_plotter.py +``` + +For details and examples of how to run the script, just run `python3 prometheus_plotter.py` [matplotlib]: https://matplotlib.org/ [pandas]: https://pandas.pydata.org diff --git a/scripts/qa/reporting/latency_plotter.py b/scripts/qa/reporting/latency_plotter.py old mode 100644 new mode 100755 index 7d62287ef14..64e022d07bb --- a/scripts/qa/reporting/latency_plotter.py +++ b/scripts/qa/reporting/latency_plotter.py @@ -1,144 +1,171 @@ +#!/usr/bin/env python3 + import sys import os -from datetime import datetime import pytz +from datetime import datetime import matplotlib as mpl import matplotlib.pyplot as plt - import numpy as np import pandas as pd -release = 'abci++vef_Smoke' +IMAGES_DIR = 'imgs' +#fig_title = 'Vote Extensions Testnet' +fig_title = 'Rotating Nodes Test' + +def usage(): + print(f"Usage: {sys.argv[0]} release_name raw_csv_path") + exit(1) + #FIXME: figure out in which timezone prometheus was running to adjust to UTC. -tz = pytz.timezone('America/Sao_Paulo') - -if len(sys.argv) != 2: - print('Pls provide the raw.csv file') - exit() -else: - csvpath = sys.argv[1] - if not os.path.exists(csvpath): - print('Pls provide a valid the raw.csv file') - exit() +tz = pytz.timezone('UTC') + + +def plot_all_experiments(release, csv): + # Group by experiment + groups = csv.groupby(['experiment_id']) + + # number of rows and columns in the graph + ncols = 2 if groups.ngroups > 1 else 1 + nrows = int( np.ceil(groups.ngroups / ncols)) if groups.ngroups > 1 else 1 + fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(6*ncols, 4*nrows), sharey=False) + fig.tight_layout(pad=5.0) + + # Plot experiments as subplots + for (key,ax) in zip(groups.groups.keys(), [axes] if ncols == 1 else axes.flatten()): + group = groups.get_group(key) + ax.set_ylabel('latency (s)') + ax.set_xlabel('experiment time (s)') + ax.set_title(key) + ax.grid(True) + + # Group by connection number and transaction rate + paramGroups = group.groupby(['connections','rate']) + for (subKey) in paramGroups.groups.keys(): + subGroup = paramGroups.get_group(subKey) + startTime = subGroup.block_time.min() + endTime = subGroup.block_time.max() + subGroup.block_time = subGroup.block_time.apply(lambda x: x - startTime ) + mean = subGroup.duration_ns.mean() + localStartTime = tz.localize(datetime.fromtimestamp(startTime)).astimezone(pytz.utc) + localEndTime = tz.localize(datetime.fromtimestamp(endTime)).astimezone(pytz.utc) + print('experiment', key ,'start', localStartTime.strftime("%Y-%m-%dT%H:%M:%SZ"), 'end', localEndTime.strftime("%Y-%m-%dT%H:%M:%SZ"), 'duration', endTime - startTime, "mean", mean) + + (con,rate) = subKey + label = 'c='+str(con) + ' r='+ str(rate) + ax.axhline(y = mean, color = 'r', linestyle = '-', label="mean") + ax.scatter(subGroup.block_time, subGroup.duration_ns, label=label) + ax.legend() + + # Save individual axes + extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) + img_path = os.path.join(IMAGES_DIR, f'e_{key}.png') + fig.savefig(img_path, bbox_inches=extent.expanded(1.4, 1.5)) + + fig.suptitle(fig_title + ' - ' + release) + + # Save the figure with subplots + fig.savefig(os.path.join(IMAGES_DIR, 'all_experiments.png')) + + +def plot_all_configs(release, csv): + # Group by configuration + groups = csv.groupby(['connections','rate']) + + # number of rows and columns in the graph + ncols = 2 if groups.ngroups > 1 else 1 + nrows = int( np.ceil(groups.ngroups / ncols)) if groups.ngroups > 1 else 1 + fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(6*ncols, 4*nrows), sharey=True) + fig.tight_layout(pad=5.0) + + # Plot configurations as subplots + for (key,ax) in zip(groups.groups.keys(), [axes] if ncols == 1 else axes.flatten()): + group = groups.get_group(key) + ax.set_ylabel('latency (s)') + ax.set_xlabel('experiment time (s)') + ax.grid(True) + (con,rate) = key + label = 'c='+str(con) + ' r='+ str(rate) + ax.set_title(label) + + # Group by experiment + paramGroups = group.groupby(['experiment_id']) + for (subKey) in paramGroups.groups.keys(): + subGroup = paramGroups.get_group((subKey,)) + startTime = subGroup.block_time.min() + subGroupMod = subGroup.block_time.apply(lambda x: x - startTime) + ax.scatter(subGroupMod, subGroup.duration_ns, label=label) + #ax.legend() - print(csvpath) -path = os.path.join('imgs') + #Save individual axes + extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) + img_path = os.path.join(IMAGES_DIR, f'c{con}r{rate}.png') + fig.savefig(img_path, bbox_inches=extent.expanded(1.4, 1.5)) -#Load the CSV -csv = pd.read_csv(csvpath) + fig.suptitle(fig_title + ' - ' + release) -#Transform ns to s in the latency/duration -csv['duration_ns'] = csv['duration_ns'].apply(lambda x: x/10**9) -csv['block_time'] = csv['block_time'].apply(lambda x: x/10**9) + # Save the figure with subplots + fig.savefig(os.path.join(IMAGES_DIR, 'all_configs.png')) -#Group by experiment -groups = csv.groupby(['experiment_id']) -#number of rows and columns in the graph -ncols = 2 if groups.ngroups > 1 else 1 -nrows = int( np.ceil(groups.ngroups / ncols)) if groups.ngroups > 1 else 1 -fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(6*ncols, 4*nrows), sharey=False) -fig.tight_layout(pad=5.0) +def plot_merged(release, csv): + # Group by configuration + groups = csv.groupby(['connections','rate']) + # number of rows and columns in the graph + ncols = 2 if groups.ngroups > 1 else 1 + nrows = int( np.ceil(groups.ngroups / ncols)) if groups.ngroups > 1 else 1 + fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(6*ncols, 4*nrows), sharey=True) + fig.tight_layout(pad=5.0) -#Plot experiments as subplots -for (key,ax) in zip(groups.groups.keys(), [axes] if ncols == 1 else axes.flatten()): - group = groups.get_group(key) - ax.set_ylabel('latency (s)') - ax.set_xlabel('experiment time (s)') - ax.set_title(key) - ax.grid(True) + # Plot configurations as subplots + for (key,ax) in zip(groups.groups.keys(), [axes] if ncols == 1 else axes.flatten()): + group = groups.get_group(key) + ax.set_ylabel('latency (s)') + ax.set_xlabel('experiment time (s)') + ax.grid(True) + (con,rate) = key + label = 'c='+str(con) + ' r='+ str(rate) + ax.set_title(label) + + # Group by experiment, but merge them as a single experiment + paramGroups = group.groupby(['experiment_id']) + for (subKey) in paramGroups.groups.keys(): + subGroup = paramGroups.get_group((subKey,)) + startTime = subGroup.block_time.min() + subGroupMod = subGroup.block_time.apply(lambda x: x - startTime) + ax.scatter(subGroupMod, subGroup.duration_ns, marker='o',c='#1f77b4') + + # Save individual axes + extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) + (con, rate) = key + img_path = os.path.join(IMAGES_DIR, f'c{con}r{rate}_merged.png') + fig.savefig(img_path, bbox_inches=extent) - #Group by connection number and transaction rate - paramGroups = group.groupby(['connections','rate']) - for (subKey) in paramGroups.groups.keys(): - subGroup = paramGroups.get_group(subKey) - startTime = subGroup['block_time'].min() - dt = tz.localize(datetime.fromtimestamp(startTime)).astimezone(pytz.utc) - print('exp ' + key + ' starts at ' + dt.strftime("%Y-%m-%dT%H:%M:%SZ")) - subGroupMod = subGroup['block_time'].apply(lambda x: x - startTime) + plt.show() - (con,rate) = subKey - label = 'c='+str(con) + ' r='+ str(rate) - ax.scatter(subGroupMod, subGroup.duration_ns, label=label) - ax.legend() - - #Save individual axes - extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) - fig.savefig(os.path.join(path,'e_'+key + '.png'), bbox_inches=extent.expanded(1.2, 1.2)) - -fig.suptitle('200-node testnet experiments - ' + release) - -# Save the figure with subplots -fig.savefig(os.path.join(path,'all_experiments.png')) - - - -#Group by configuration -groups = csv.groupby(['connections','rate']) - -#number of rows and columns in the graph -ncols = 2 if groups.ngroups > 1 else 1 -nrows = int( np.ceil(groups.ngroups / ncols)) if groups.ngroups > 1 else 1 -fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(6*ncols, 4*nrows), sharey=True) -fig.tight_layout(pad=5.0) - -#Plot configurations as subplots -for (key,ax) in zip(groups.groups.keys(), [axes] if ncols == 1 else axes.flatten()): - group = groups.get_group(key) - ax.set_ylabel('latency (s)') - ax.set_xlabel('experiment time (s)') - ax.grid(True) - (con,rate) = key - label = 'c='+str(con) + ' r='+ str(rate) - ax.set_title(label) - - #Group by experiment - paramGroups = group.groupby(['experiment_id']) - for (subKey) in paramGroups.groups.keys(): - subGroup = paramGroups.get_group(subKey) - startTime = subGroup['block_time'].min() - subGroupMod = subGroup['block_time'].apply(lambda x: x - startTime) - ax.scatter(subGroupMod, subGroup.duration_ns, label=label) - #ax.legend() - - #Save individual axes - extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) - fig.savefig(os.path.join(path,'c'+str(con) + 'r'+ str(rate) + '.png'), bbox_inches=extent.expanded(1.2, 1.2)) - -fig.suptitle('200-node testnet configurations - ' + release) - -# Save the figure with subplots -fig.savefig(os.path.join(path,'all_configs.png')) - - -fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(6*ncols, 4*nrows), sharey=True) -fig.tight_layout(pad=5.0) - -#Plot configurations as subplots -for (key,ax) in zip(groups.groups.keys(), [axes] if ncols == 1 else axes.flatten()): - group = groups.get_group(key) - ax.set_ylabel('latency (s)') - ax.set_xlabel('experiment time (s)') - ax.grid(True) - (con,rate) = key - label = 'c='+str(con) + ' r='+ str(rate) - ax.set_title(label) - - #Group by experiment, but merge them as a single experiment - paramGroups = group.groupby(['experiment_id']) - for (subKey) in paramGroups.groups.keys(): - subGroup = paramGroups.get_group(subKey) - startTime = subGroup['block_time'].min() - subGroupMod = subGroup['block_time'].apply(lambda x: x - startTime) - ax.scatter(subGroupMod, subGroup.duration_ns, marker='o',c='#1f77b4') - - #Save individual axes - extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted()) - (con,rate) = key - fig.savefig(os.path.join(path,'c'+str(con) + 'r'+ str(rate) + '_merged.png'), bbox_inches=extent) - -plt.show() + +if __name__ == "__main__": + if len(sys.argv) < 2 or not (sys.argv[1] and sys.argv[2]): + usage() + release = sys.argv[1] + csv_path = sys.argv[2] + + if not os.path.exists(csv_path): + print('Please provide a valid raw.csv file') + exit() + csv = pd.read_csv(csv_path) + + # Transform ns to s in the latency/duration + csv['duration_ns'] = csv['duration_ns'].apply(lambda x: x/10**9) + csv['block_time'] = csv['block_time'].apply(lambda x: x/10**9) + + if not os.path.exists(IMAGES_DIR): + os.makedirs(IMAGES_DIR) + + plot_all_experiments(release, csv) + plot_all_configs(release, csv) + plot_merged(release, csv) diff --git a/scripts/qa/reporting/latency_throughput.py b/scripts/qa/reporting/latency_throughput.py index adaa4b76ca2..c048068171c 100755 --- a/scripts/qa/reporting/latency_throughput.py +++ b/scripts/qa/reporting/latency_throughput.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + """ A simple script to parse the CSV output from the loadtime reporting tool (see https://github.com/cometbft/cometbft/tree/main/test/loadtime/cmd/report). @@ -15,33 +16,8 @@ import matplotlib.pyplot as plt import numpy as np -DEFAULT_TITLE = "CometBFT latency vs throughput" - - -def main(): - parser = argparse.ArgumentParser( - description="Renders a latency vs throughput diagram " - "for a set of transactions provided by the loadtime reporting tool", - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument('-t', - '--title', - default=DEFAULT_TITLE, - help='Plot title') - parser.add_argument('output_image', - help='Output image file (in PNG format)') - parser.add_argument( - 'input_csv_file', - nargs='+', - help="CSV input file from which to read transaction data " - "- must have been generated by the loadtime reporting tool") - args = parser.parse_args() - logging.basicConfig(format='%(levelname)s\t%(message)s', - stream=sys.stdout, - level=logging.INFO) - plot_latency_vs_throughput(args.input_csv_file, - args.output_image, - title=args.title) +DEFAULT_TITLE = "CometBFT latency vs throughput" def plot_latency_vs_throughput(input_files, output_image, title=DEFAULT_TITLE): @@ -167,4 +143,25 @@ def compute_experiments_stats(experiments): if __name__ == "__main__": - main() + parser = argparse.ArgumentParser( + description="Renders a latency vs throughput diagram " + "for a set of transactions provided by the loadtime reporting tool", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-t', + '--title', + default=DEFAULT_TITLE, + help='Plot title') + parser.add_argument('output_image', + help='Output image file (in PNG format)') + parser.add_argument( + 'input_csv_file', + nargs='+', + help="CSV input file from which to read transaction data " + "- must have been generated by the loadtime reporting tool") + args = parser.parse_args() + + logging.basicConfig(format='%(levelname)s\t%(message)s', + stream=sys.stdout, + level=logging.INFO) + + plot_latency_vs_throughput(args.input_csv_file, args.output_image, title=args.title) diff --git a/scripts/qa/reporting/prometheus_plotter.py b/scripts/qa/reporting/prometheus_plotter.py old mode 100644 new mode 100755 index e504441bf69..a83fd9211de --- a/scripts/qa/reporting/prometheus_plotter.py +++ b/scripts/qa/reporting/prometheus_plotter.py @@ -1,92 +1,153 @@ -# pip install numpy pandas matplotlib requests +#!/usr/bin/env python3 -import sys +# Requirements: +# pip install requests matplotlib pandas prometheus-pandas import os +import requests +import sys -import matplotlib as mpl import matplotlib.pyplot as plt - +import matplotlib.dates as md import numpy as np import pandas as pd -import requests from urllib.parse import urljoin - -from prometheus_pandas import query - -release = 'v0.37.x-alpha3' -path = os.path.join('imgs') -prometheus = query.Prometheus('http://localhost:9090') - -# Time window -#window_size = dict(seconds=150) #CMT 0.37.x-alpha3 -window_size = dict(seconds=126) #TM v0.37 (200 nodes) baseline -#window_size = dict(seconds=130) #homogeneous -#window_size = dict(seconds=127) #baseline -ext_window_size = dict(seconds=180) - -# Use the time provided by latency_plotter for the selected experiment. -#left_end = '2023-02-08T13:12:20Z' #cmt2 tm1 -#left_end = '2023-02-08T10:31:50Z' #cmt1 tm2 -#left_end = '2023-02-14T15:18:00Z' #cmt1 tm1 -#left_end = '2023-02-07T18:07:00Z' #homogeneous -#left_end = '2022-10-13T19:41:23Z' #baseline -#left_end = '2023-02-22T18:56:29Z' #CMT 0.37.x-alpha3 -#left_end = '2022-10-13T15:57:50Z' #TM v0.37 (200 nodes) baseline -left_end = '2023-03-20T19:45:35Z' #feature/abci++vef merged with main (7d8c9d426) - -right_end = pd.to_datetime(left_end) + pd.Timedelta(**window_size) -time_window = (left_end, right_end.strftime('%Y-%m-%dT%H:%M:%SZ')) - -ext_right_end = pd.to_datetime(left_end) + pd.Timedelta(**ext_window_size) -ext_time_window = (left_end, ext_right_end.strftime('%Y-%m-%dT%H:%M:%SZ')) - - - -fork='cometbft' -#fork='tendermint' - -# Do prometheus queries -queries = [ - (( fork + '_mempool_size', time_window[0], time_window[1], '1s'), 'mempool_size', dict(ylabel='TXs', xlabel='time (s)', title='Mempool Size', legend=False, figsize=(10,6), grid=True, kind='area',stacked=True), False), - (( fork + '_p2p_peers', time_window[0], time_window[1], '1s'), 'peers', dict(ylabel='# Peers', xlabel='time (s)', title='Peers', legend=False, figsize=(10,6), grid=True), True), - (( 'avg(' + fork + '_mempool_size)', time_window[0], time_window[1], '1s'), 'avg_mempool_size', dict(ylabel='TXs', xlabel='time (s)', title='Average Mempool Size', legend=False, figsize=(10,6), grid=True), False), - #(( 'cometbft_consensus_height', time_window[0], time_window[1], '1s'), 'blocks_regular', dict(ylabel='# Blocks', xlabel='time (s)', title='Blocks in time', legend=False, figsize=(10,6), grid=True), False), - (( fork + '_consensus_rounds', time_window[0], time_window[1], '1s'), 'rounds', dict(ylabel='# Rounds', xlabel='time (s)', title='Rounds per block', legend=False, figsize=(10,6), grid=True), False), - (( 'rate(' + fork + '_consensus_height[20s])*60', time_window[0], time_window[1], '1s'), 'block_rate_regular', dict(ylabel='Blocks/min', xlabel='time (s)', title='Rate of block creation', legend=False, figsize=(10,6), grid=True), True), - #(( 'avg(rate(cometbft_consensus_height[20s])*60)', time_window[0], time_window[1], '1s'), 'block_rate_avg_reg', dict(ylabel='Blocks/min', xlabel='time (s)', title='Rate of block creation', legend=False, figsize=(10,6), grid=True), False), - #(( 'cometbft_consensus_total_txs', time_window[0], time_window[1], '1s'), 'total_txs_regular', dict(ylabel='# TXs', xlabel='time (s)', title='Transactions in time', legend=False, figsize=(10,6), grid=True), False), - (( 'rate(' + fork + '_consensus_total_txs[20s])*60', time_window[0], time_window[1], '1s'), 'total_txs_rate_regular', dict(ylabel='TXs/min', xlabel='time (s)', title='Rate of transaction processing', legend=False, figsize=(10,6), grid=True), True), - #(( 'avg(rate(cometbft_consensus_total_txs[20s])*60)', time_window[0], time_window[1], '1s'), 'total_txs_rate_avg_reg', dict(ylabel='TXs/min', xlabel='time (s)', title='Rate of transaction processing', legend=False, figsize=(10,6), grid=True), False), - (( 'process_resident_memory_bytes', time_window[0], time_window[1], '1s'), 'memory', dict(ylabel='Memory (bytes)', xlabel='time (s)', title='Memory usage', legend=False, figsize=(10,6), grid=True), False), - (( 'avg(process_resident_memory_bytes)', time_window[0], time_window[1], '1s'), 'avg_memory', dict(ylabel='Memory (bytes)', xlabel='time (s)', title='Average Memory usage', legend=False, figsize=(10,6), grid=True), False), - (( 'node_load1', time_window[0], time_window[1], '1s'), 'cpu', dict(ylabel='Load', xlabel='time (s)', title='Node load', legend=False, figsize=(10,6), grid=True), False), - (( 'avg(node_load1)', time_window[0], time_window[1], '1s'), 'avg_cpu', dict(ylabel='Load', xlabel='time (s)', title='Average Node load', legend=False, figsize=(10,6), grid=True), False), - #extended window metrics - (( fork + '_consensus_height', ext_time_window[0], ext_time_window[1], '1s'), 'blocks', dict(ylabel='# Blocks', xlabel='time (s)', title='Blocks in time', legend=False, figsize=(10,6), grid=True), False), - (( 'rate(' + fork + '_consensus_height[20s])*60', ext_time_window[0], ext_time_window[1], '1s'), 'block_rate', dict(ylabel='Blocks/min', xlabel='time (s)', title='Rate of block creation', legend=False, figsize=(10,6), grid=True), True), - (( fork + '_consensus_total_txs', ext_time_window[0], ext_time_window[1], '1s'), 'total_txs', dict(ylabel='# TXs', xlabel='time (s)', title='Transactions in time', legend=False, figsize=(10,6), grid=True), False), - (( 'rate(' + fork + '_consensus_total_txs[20s])*60', ext_time_window[0], ext_time_window[1], '1s'), 'total_txs_rate', dict(ylabel='TXs/min', xlabel='time (s)', title='Rate of transaction processing', legend=False, figsize=(10,6), grid=True), True), -] - -for (query, file_name, pandas_params, plot_average) in queries: - print(query) - - data_frame = prometheus.query_range(*query) - #Tweak the x ticks - delta_index = pd.to_timedelta(data_frame.index.strftime('%H:%M:%S')) - data_frame = data_frame.set_index(delta_index) - - data_frame.plot(**pandas_params) - if plot_average: - average = data_frame.mean(axis=1) - data_frame['__average__'] = average - pandas_params['lw'] = 8 - pandas_params['style'] = ['--'] - pandas_params['color'] = ['red'] - data_frame['__average__'].plot(**pandas_params) - - plt.savefig(os.path.join(path, file_name + '.png')) - plt.plot() - -plt.show() +from prometheus_pandas import query as prometheus_query + + +PROMETHEUS_URL = 'http://localhost:9090' +IMAGES_DIR = 'imgs' +TEST_CASES = ['200_nodes', 'rotating', 'vote_extensions'] + + +def usage(): + print("Usage:") + print(f"\t{sys.argv[0]} release_name start_time window_size test_case") + print("where:") + print(f"- start_time is a UTF time in '%Y-%m-%dT%H:%M:%SZ' format") + print(f"- window size is in seconds") + print(f"- test_case is one of {TEST_CASES}") + print(f"Example: \t{sys.argv[0]} v1.0.0-alpha.2 2024-03-21T08:45:23Z 180 200_nodes") + exit(1) + + +def queries_200_nodes(time_window, ext_time_window): + return [ + (( 'cometbft_mempool_size', time_window[0], time_window[1], '1s'), 'mempool_size', dict(ylabel='TXs', xlabel='time (s)', title='Mempool Size', legend=False, figsize=(10,6), grid=True, ylim=(0, 5100), kind='area',stacked=True), False), + (( 'avg(cometbft_mempool_size)', time_window[0], time_window[1], '1s'), 'avg_mempool_size', dict(ylabel='TXs', xlabel='time (s)', title='Average Mempool Size', legend=False, figsize=(10,6), grid=True, ylim=(0, 5100)), False), + (( 'max(cometbft_mempool_size)', time_window[0], time_window[1], '1s'), 'mempool_size_max', dict(ylabel='TXs', xlabel='time (s)', title='Maximum Mempool Size', legend=False, figsize=(10,6), grid=True, ylim=(0, 5100)), False), + (( 'cometbft_p2p_peers', time_window[0], time_window[1], '1s'), 'peers', dict(ylabel='# Peers', xlabel='time (s)', title='Peers', legend=False, figsize=(10,6), grid=True, ylim=(0, 150)), True), + #(( 'cometbft_consensus_height', time_window[0], time_window[1], '1s'), 'blocks_regular', dict(ylabel='# Blocks', xlabel='time (s)', title='Blocks in time', legend=False, figsize=(10,6), grid=True), False), + (( 'cometbft_consensus_rounds', time_window[0], time_window[1], '1s'), 'rounds', dict(ylabel='# Rounds', xlabel='time (s)', title='Rounds per block', legend=False, figsize=(10,6), grid=True, ylim=(0, 4)), False), + (( 'rate(cometbft_consensus_height[20s])*60', time_window[0], time_window[1], '1s'), 'block_rate_regular', dict(ylabel='Blocks/min', xlabel='time (s)', title='Rate of block creation', legend=False, figsize=(10,6), grid=True, ylim=(0, 120)), True), + #(( 'avg(rate(cometbft_consensus_height[20s])*60)', time_window[0], time_window[1], '1s'), 'block_rate_avg_reg', dict(ylabel='Blocks/min', xlabel='time (s)', title='Rate of block creation', legend=False, figsize=(10,6), grid=True), False), + #(( 'cometbft_consensus_total_txs', time_window[0], time_window[1], '1s'), 'total_txs_regular', dict(ylabel='# TXs', xlabel='time (s)', title='Transactions in time', legend=False, figsize=(10,6), grid=True), False), + (( 'rate(cometbft_consensus_total_txs[20s])*60', time_window[0], time_window[1], '1s'), 'total_txs_rate_regular', dict(ylabel='TXs/min', xlabel='time (s)', title='Rate of transaction processing', legend=False, figsize=(10,6), grid=True, ylim=(0, 50000)), True), + #(( 'avg(rate(cometbft_consensus_total_txs[20s])*60)', time_window[0], time_window[1], '1s'), 'total_txs_rate_avg_reg', dict(ylabel='TXs/min', xlabel='time (s)', title='Rate of transaction processing', legend=False, figsize=(10,6), grid=True), False), + (( 'process_resident_memory_bytes', time_window[0], time_window[1], '1s'), 'memory', dict(ylabel='Memory (bytes)', xlabel='time (s)', title='Memory usage', legend=False, figsize=(10,6), grid=True, ylim=(0, 2e9)), False), + (( 'avg(process_resident_memory_bytes)', time_window[0], time_window[1], '1s'), 'avg_memory', dict(ylabel='Memory (bytes)', xlabel='time (s)', title='Average Memory usage', legend=False, figsize=(10,6), grid=True, ylim=(0, 2e9)), False), + (( 'node_load1', time_window[0], time_window[1], '1s'), 'cpu', dict(ylabel='Load', xlabel='time (s)', title='Node load', legend=False, figsize=(10,6), grid=True, ylim=(0, 6)), False), + (( 'avg(node_load1)', time_window[0], time_window[1], '1s'), 'avg_cpu', dict(ylabel='Load', xlabel='time (s)', title='Average Node load', legend=False, figsize=(10,6), grid=True, ylim=(0, 6)), False), + (( 'cometbft_consensus_block_size_bytes/1024/1024', time_window[0], time_window[1], '1s'), 'block_size_bytes', dict(ylabel='Mb', xlabel='time (s)', title='Block size (Mb)', legend=False, figsize=(10,6), grid=True, ylim=(0, 4.1)), False), + + # Extended window metrics + (( 'cometbft_consensus_height', ext_time_window[0], ext_time_window[1], '1s'), 'blocks', dict(ylabel='# Blocks', xlabel='time (s)', title='Blocks in time', legend=False, figsize=(10,6), grid=True), False), + (( 'rate(cometbft_consensus_height[20s])*60', ext_time_window[0], ext_time_window[1], '1s'), 'block_rate', dict(ylabel='Blocks/min', xlabel='time (s)', title='Rate of block creation', legend=False, figsize=(10,6), grid=True), True), + (( 'cometbft_consensus_total_txs', ext_time_window[0], ext_time_window[1], '1s'), 'total_txs', dict(ylabel='# TXs', xlabel='time (s)', title='Transactions in time', legend=False, figsize=(10,6), grid=True), False), + (( 'rate(cometbft_consensus_total_txs[20s])*60', ext_time_window[0], ext_time_window[1], '1s'), 'total_txs_rate', dict(ylabel='TXs/min', xlabel='time (s)', title='Rate of transaction processing', legend=False, figsize=(10,6), grid=True, ylim=(0, 50000)), True), + ] + + +def queries_rotating(time_window): + return [ + (( 'rate(cometbft_consensus_height[20s])*60<1000>0', time_window[0], time_window[1], '1s'), 'rotating_block_rate', dict(ylabel='blocks/min', xlabel='time', title='Rate of Block Creation', legend=False, figsize=(10,6), grid=True), False), + (( 'rate(cometbft_consensus_total_txs[20s])*60', time_window[0], time_window[1], '1s'), 'rotating_txs_rate', dict(ylabel='TXs/min', xlabel='time', title='Rate of Transaction processing', legend=False, figsize=(10,6), grid=True), False), + (( 'cometbft_consensus_height{job=~"ephemeral.*"}>cometbft_blocksync_latest_block_height{job=~"ephemeral.*"} or cometbft_blocksync_latest_block_height{job=~"ephemeral.*"}', + time_window[0], time_window[1], '1s'), 'rotating_eph_heights', dict(ylabel='height', xlabel='time', title='Heights of Ephemeral Nodes', legend=False, figsize=(10,6), grid=True), False), + (( 'cometbft_p2p_peers', time_window[0], time_window[1], '1s'), 'rotating_peers', dict(ylabel='# peers', xlabel='time', title='Peers', legend=False, figsize=(10,6), grid=True), False), + (( 'avg(process_resident_memory_bytes)', time_window[0], time_window[1], '1s'), 'rotating_avg_memory', dict(ylabel='memory (bytes)', xlabel='time', title='Average Memory Usage', legend=False, figsize=(10,6), grid=True), False), + (( 'node_load1', time_window[0], time_window[1], '1s'), 'rotating_cpu', dict(ylabel='load', xlabel='time', title='Node Load', legend=False, figsize=(10,6), grid=True), False), + ] + + +def queries_vote_extensions(time_window): + return [ + (( 'cometbft_mempool_size', time_window[0], time_window[1], '1s'), 'mempool_size', dict(ylabel='TXs', xlabel='time (s)', title='Mempool Size', legend=False, figsize=(10,6), grid=True, kind='area',stacked=True), False), + (( 'cometbft_mempool_size', time_window[0], time_window[1], '1s'), 'mempool_size_not_stacked', dict(ylabel='TXs', xlabel='time (s)', title='Mempool Size', legend=False, figsize=(10,6), grid=True, stacked=False), False), + (( 'cometbft_p2p_peers', time_window[0], time_window[1], '1s'), 'peers', dict(ylabel='# Peers', xlabel='time (s)', title='Peers', legend=False, figsize=(10,6), grid=True), True), + (( 'avg(cometbft_mempool_size)', time_window[0], time_window[1], '1s'), 'avg_mempool_size', dict(ylabel='TXs', xlabel='time (s)', title='Average Mempool Size', legend=False, figsize=(10,6), grid=True), False), + (( 'cometbft_consensus_rounds', time_window[0], time_window[1], '1s'), 'rounds', dict(ylabel='# Rounds', xlabel='time (s)', title='Rounds per block', legend=False, figsize=(10,6), grid=True), False), + (( 'process_resident_memory_bytes', time_window[0], time_window[1], '1s'), 'memory', dict(ylabel='Memory (bytes)', xlabel='time (s)', title='Memory usage', legend=False, figsize=(10,6), grid=True), False), + (( 'avg(process_resident_memory_bytes)', time_window[0], time_window[1], '1s'), 'avg_memory', dict(ylabel='Memory (bytes)', xlabel='time (s)', title='Average Memory usage', legend=False, figsize=(10,6), grid=True), False), + (( 'node_load1', time_window[0], time_window[1], '1s'), 'cpu', dict(ylabel='Load', xlabel='time (s)', title='Node load', legend=False, figsize=(10,6), grid=True), False), + (( 'avg(node_load1)', time_window[0], time_window[1], '1s'), 'avg_cpu', dict(ylabel='Load', xlabel='time (s)', title='Average Node load', legend=False, figsize=(10,6), grid=True), False), + (( 'cometbft_consensus_height', time_window[0], time_window[1], '1s'), 'blocks', dict(ylabel='# Blocks', xlabel='time (s)', title='Blocks in time', legend=False, figsize=(10,6), grid=True), False), + (( 'rate(cometbft_consensus_height[20s])*60', time_window[0], time_window[1], '1s'), 'block_rate', dict(ylabel='Blocks/min', xlabel='time (s)', title='Rate of block creation', legend=False, figsize=(10,6), grid=True), True), + (( 'cometbft_consensus_total_txs', time_window[0], time_window[1], '1s'), 'total_txs', dict(ylabel='# TXs', xlabel='time (s)', title='Transactions in time', legend=False, figsize=(10,6), grid=True), False), + (( 'rate(cometbft_consensus_total_txs[20s])*60', time_window[0], time_window[1], '1s'), 'total_txs_rate', dict(ylabel='TXs/min', xlabel='time (s)', title='Rate of transaction processing', legend=False, figsize=(10,6), grid=True), True), + ] + + +def main(release, start_time, window_size, test_case): + prometheus = prometheus_query.Prometheus(PROMETHEUS_URL) + + end_time = pd.to_datetime(start_time) + pd.Timedelta(**dict(seconds=window_size)) + time_window = (start_time, end_time.strftime('%Y-%m-%dT%H:%M:%SZ')) + + ext_end_time = pd.to_datetime(start_time) + pd.Timedelta(**dict(seconds=window_size+50)) + ext_time_window = (start_time, ext_end_time.strftime('%Y-%m-%dT%H:%M:%SZ')) + + # Select queries depending on the test case. + match test_case: + case "200_nodes": + queries = queries_200_nodes(time_window, ext_time_window) + case "rotating": + queries = queries_rotating(time_window) + case "vote_extensions": + queries = queries_vote_extensions(time_window) + case _: + print(f"Error: Unknown test case {test_case}") + return + + imgs_dir = os.path.join(IMAGES_DIR, test_case) + if not os.path.exists(imgs_dir): + os.makedirs(imgs_dir) + + # Query Prometheus and plot images. + for (query, file_name, pandas_params, plot_average) in queries: + print(f"query: {query}") + + df = prometheus.query_range(*query) + #Tweak the x ticks + df = df.set_index(md.date2num(df.index)) + + if df.empty: + print('No data found! Check the timestamps or the query.') + continue + + pandas_params["title"] += " - " + release + ax = df.plot(**pandas_params) + if plot_average: + average = df.mean(axis=1) + df['__average__'] = average + pandas_params['lw'] = 8 + pandas_params['style'] = ['--'] + pandas_params['color'] = ['red'] + ax = df['__average__'].plot(**pandas_params) + + ax.xaxis.set_major_formatter(md.DateFormatter('%H:%M:%S')) + plt.savefig(os.path.join(imgs_dir, file_name + '.png')) + plt.plot() + + plt.show() + + +if __name__ == "__main__": + if len(sys.argv) < 5 or not (sys.argv[1] and sys.argv[2] and sys.argv[3] and sys.argv[4]): + usage() + + release = sys.argv[1] + start_time = sys.argv[2] + window_size = sys.argv[3] + test_case = sys.argv[4] + main(release, start_time, int(window_size), test_case) diff --git a/scripts/qa/reporting/requirements.txt b/scripts/qa/reporting/requirements.txt index f499ed1d36d..ebd949edd31 100644 --- a/scripts/qa/reporting/requirements.txt +++ b/scripts/qa/reporting/requirements.txt @@ -1,14 +1,14 @@ contourpy==1.0.5 cycler==0.11.0 -fonttools==4.37.4 +fonttools==4.43.0 kiwisolver==1.4.4 matplotlib==3.6.3 -numpy==1.24.2 +numpy==1.26.4 packaging==21.3 -Pillow==9.3.0 +Pillow==10.2.0 pyparsing==3.0.9 python-dateutil==2.8.2 six==1.16.0 pandas==1.5.3 prometheus-pandas==0.3.2 -requests==2.28.2 +requests==2.31.0 diff --git a/scripts/wal2json/main.go b/scripts/wal2json/main.go index 7c2c3c87c7e..3926143b396 100644 --- a/scripts/wal2json/main.go +++ b/scripts/wal2json/main.go @@ -12,7 +12,7 @@ import ( "io" "os" - cs "github.com/cometbft/cometbft/consensus" + cs "github.com/cometbft/cometbft/internal/consensus" cmtjson "github.com/cometbft/cometbft/libs/json" ) @@ -57,6 +57,5 @@ func main() { fmt.Println("Failed to write message", err) os.Exit(1) //nolint:gocritic } - } } diff --git a/spec/README.md b/spec/README.md index 921c68b7cb0..7504faa49d4 100644 --- a/spec/README.md +++ b/spec/README.md @@ -30,17 +30,17 @@ please submit them to our [bug bounty](https://cometbft.com/security)! - [Consensus Algorithm](./consensus/consensus.md) - [Creating a proposal](./consensus/creating-proposal.md) -- [Time](./consensus/bft-time.md) +- [Time](./consensus/time.md) - [Light-Client](./consensus/light-client/README.md) ### P2P and Network Protocols -- [The Base P2P Layer](./p2p/node.md): multiplex the protocols ("reactors") on authenticated and encrypted TCP connections -- [Peer Exchange (PEX)](./p2p/messages/pex.md): gossip known peer addresses so peers can find each other -- [Block Sync](./p2p/messages/block-sync.md): gossip blocks so peers can catch up quickly -- [Consensus](./p2p/messages/consensus.md): gossip votes and block parts so new blocks can be committed -- [Mempool](./p2p/messages/mempool.md): gossip transactions so they get included in blocks -- [Evidence](./p2p/messages/evidence.md): sending invalid evidence will stop the peer +- [The Base P2P Layer](./p2p/legacy-docs/node.md): multiplex the protocols ("reactors") on authenticated and encrypted TCP connections +- [Peer Exchange (PEX)](./p2p/legacy-docs/messages/pex.md): gossip known peer addresses so peers can find each other +- [Block Sync](./p2p/legacy-docs/messages/block-sync.md): gossip blocks so peers can catch up quickly +- [Consensus](./p2p/legacy-docs/messages/consensus.md): gossip votes and block parts so new blocks can be committed +- [Mempool](./p2p/legacy-docs/messages/mempool.md): gossip transactions so they get included in blocks +- [Evidence](./p2p/legacy-docs/messages/evidence.md): sending invalid evidence will stop the peer ### RPC diff --git a/spec/abci/README.md b/spec/abci/README.md index 4c29cc547f8..5842047a971 100644 --- a/spec/abci/README.md +++ b/spec/abci/README.md @@ -1,39 +1,41 @@ --- order: 1 parent: - title: ABCI++ + title: ABCI 2.0 order: 3 --- -# ABCI++ +# ABCI 2.0 ## Introduction -ABCI++ is a major evolution of ABCI (**A**pplication **B**lock**c**hain **I**nterface). -Like its predecessor, ABCI++ is the interface between CometBFT (a state-machine +ABCI 2.0 is a major evolution of ABCI (**A**pplication **B**lock**c**hain **I**nterface). +ABCI is the interface between CometBFT (a state-machine replication engine) and the actual state machine being replicated (i.e., the Application). The API consists of a set of _methods_, each with a corresponding `Request` and `Response` message type. +> Note: ABCI 2.0 is colloquially called ABCI++. To be precise in these documents, we will refer to the exact version of ABCI under discussion, currently 2.0. + The methods are always initiated by CometBFT. The Application implements its logic -for handling all ABCI++ methods. -Thus, CometBFT always sends the `Request*` messages and receives the `Response*` messages +for handling all ABCI methods. +Thus, CometBFT always sends the `*Request` messages and receives the `*Response` messages in return. -All ABCI++ messages and methods are defined in [protocol buffers](https://github.com/cometbft/cometbft/blob/main/proto/tendermint/abci/types.proto). +All ABCI messages and methods are defined in [protocol buffers](https://github.com/cometbft/cometbft/blob/main/proto/cometbft/abci/v1/types.proto). This allows CometBFT to run with applications written in many programming languages. This specification is split as follows: - [Overview and basic concepts](./abci++_basic_concepts.md) - interface's overview and concepts needed to understand other parts of this specification. -- [Methods](./abci++_methods.md) - complete details on all ABCI++ methods +- [Methods](./abci++_methods.md) - complete details on all ABCI methods and message types. - [Requirements for the Application](./abci++_app_requirements.md) - formal requirements on the Application's logic to ensure CometBFT properties such as liveness. These requirements define what CometBFT expects from the Application; second part on managing ABCI application state and related topics. - [CometBFT's expected behavior](./abci++_comet_expected_behavior.md) - specification of - how the different ABCI++ methods may be called by CometBFT. This explains what the Application + how the different ABCI methods may be called by CometBFT. This explains what the Application is to expect from CometBFT. - [Example scenarios](./abci++_example_scenarios.md) - specific scenarios showing why the Application needs to account for any CometBFT's behaviour prescribed by the specification. diff --git a/spec/abci/abci++_app_requirements.md b/spec/abci/abci++_app_requirements.md index 7ed84e83378..f9743b21cf5 100644 --- a/spec/abci/abci++_app_requirements.md +++ b/spec/abci/abci++_app_requirements.md @@ -5,34 +5,58 @@ title: Requirements for the Application # Requirements for the Application -- [Formal Requirements](#formal-requirements) -- [Managing the Application state and related topics](#managing-the-application-state-and-related-topics) - - [Connection State](#connection-state) - - [Concurrency](#concurrency) - - [Finalize Block](#finalizeblock) - - [Commit](#commit) - - [Candidate States](#candidate-states) - - [States and ABCI++ Connections](#states-and-abci%2B%2B-connections) - - [Consensus Connection](#consensus-connection) - - [Mempool Connection](#mempool-connection) - - [Info/Query Connection](#infoquery-connection) - - [Snapshot Connection](#snapshot-connection) - - [Transaction Results](#transaction-results) - - [Updating the Validator Set](#updating-the-validator-set) - - [Consensus Parameters](#consensus-parameters) - - [List of Parameters](#list-of-parameters) - - [Updating Consensus Parameters](#updating-consensus-parameters) - - [Query](#query) - - [Query Proofs](#query-proofs) - - [Peer Filtering](#peer-filtering) - - [Paths](#paths) - - [Crash Recovery](#crash-recovery) - - [State Sync](#state-sync) -- [Application configuration required to switch to ABCI2.0](#application-configuration-required-to-switch-to-abci-20) - +- [Requirements for the Application](#requirements-for-the-application) + - [Formal Requirements](#formal-requirements) + - [Consensus Connection Requirements](#consensus-connection-requirements) + - [Mempool Connection Requirements](#mempool-connection-requirements) + - [Managing the Application state and related topics](#managing-the-application-state-and-related-topics) + - [Connection State](#connection-state) + - [Concurrency](#concurrency) + - [FinalizeBlock](#finalizeblock) + - [Commit](#commit) + - [Candidate States](#candidate-states) + - [States and ABCI Connections](#states-and-abci-connections) + - [Consensus Connection](#consensus-connection) + - [Mempool Connection](#mempool-connection) + - [Replay Protection](#replay-protection) + - [Info/Query Connection](#infoquery-connection) + - [Snapshot Connection](#snapshot-connection) + - [Transaction Results](#transaction-results) + - [Gas](#gas) + - [Specifics of `CheckTxResponse`](#specifics-of-checktxresponse) + - [Specifics of `ExecTxResult`](#specifics-of-exectxresult) + - [Updating the Validator Set](#updating-the-validator-set) + - [Consensus Parameters](#consensus-parameters) + - [List of Parameters](#list-of-parameters) + - [BlockParams.MaxBytes](#blockparamsmaxbytes) + - [BlockParams.MaxGas](#blockparamsmaxgas) + - [EvidenceParams.MaxAgeDuration](#evidenceparamsmaxageduration) + - [EvidenceParams.MaxAgeNumBlocks](#evidenceparamsmaxagenumblocks) + - [EvidenceParams.MaxBytes](#evidenceparamsmaxbytes) + - [ValidatorParams.PubKeyTypes](#validatorparamspubkeytypes) + - [VersionParams.App](#versionparamsapp) + - [ABCIParams.VoteExtensionsEnableHeight](#abciparamsvoteextensionsenableheight) + - [Updating Consensus Parameters](#updating-consensus-parameters) + - [`InitChain`](#initchain) + - [`FinalizeBlock`, `PrepareProposal`/`ProcessProposal`](#finalizeblock-prepareproposalprocessproposal) + - [`Query`](#query) + - [Query Proofs](#query-proofs) + - [Peer Filtering](#peer-filtering) + - [Paths](#paths) + - [Crash Recovery](#crash-recovery) + - [State Sync](#state-sync) + - [Taking Snapshots](#taking-snapshots) + - [Bootstrapping a Node](#bootstrapping-a-node) + - [Snapshot Discovery](#snapshot-discovery) + - [Snapshot Restoration](#snapshot-restoration) + - [Snapshot Verification](#snapshot-verification) + - [Transition to Consensus](#transition-to-consensus) + - [Application configuration required to switch to ABCI 2.0](#application-configuration-required-to-switch-to-abci-20) ## Formal Requirements +### Consensus Connection Requirements + This section specifies what CometBFT expects from the Application. It is structured as a set of formal requirements that can be used for testing and verification of the Application's logic. @@ -42,14 +66,14 @@ proposer. Let *sp,h-1* be *p*'s Application's state committed for height *h-1*. Let *vp* (resp. *vq*) be the block that *p*'s (resp. *q*'s) CometBFT passes on to the Application -via `RequestPrepareProposal` as proposer of round *rp* (resp *rq*), height *h*, +via `PrepareProposalRequest` as proposer of round *rp* (resp *rq*), height *h*, also known as the raw proposal. Let *up* (resp. *uq*) the possibly modified block *p*'s (resp. *q*'s) Application -returns via `ResponsePrepareProposal` to CometBFT, also known as the prepared proposal. +returns via `PrepareProposalResponse` to CometBFT, also known as the prepared proposal. Process *p*'s prepared proposal can differ in two different rounds where *p* is the proposer. -* Requirement 1 [`PrepareProposal`, timeliness]: If *p*'s Application fully executes prepared blocks in +- Requirement 1 [`PrepareProposal`, timeliness]: If *p*'s Application fully executes prepared blocks in `PrepareProposal` and the network is in a synchronous period while processes *p* and *q* are in *rp*, then the value of *TimeoutPropose* at *q* must be such that *q*'s propose timer does not time out (which would result in *q* prevoting `nil` in *rp*). @@ -57,25 +81,26 @@ Process *p*'s prepared proposal can differ in two different rounds where *p* is Full execution of blocks at `PrepareProposal` time stands on CometBFT's critical path. Thus, Requirement 1 ensures the Application or operator will set a value for `TimeoutPropose` such that the time it takes to fully execute blocks in `PrepareProposal` does not interfere with CometBFT's propose timer. -Note that the violation of Requirement 1 may lead to further rounds, but will not +Note that the violation of Requirement 1 may lead to further rounds, but will not compromise liveness because even though `TimeoutPropose` is used as the initial value for proposal timeouts, CometBFT will be dynamically adjust these timeouts such that they will eventually be enough for completing `PrepareProposal`. -* Requirement 2 [`PrepareProposal`, tx-size]: When *p*'s Application calls `ResponsePrepareProposal`, the - total size in bytes of the transactions returned does not exceed `RequestPrepareProposal.max_tx_bytes`. +- Requirement 2 [`PrepareProposal`, tx-size]: When *p*'s Application calls `PrepareProposal`, the + total size in bytes of the transactions returned does not exceed `PrepareProposalRequest.max_tx_bytes`. -Busy blockchains might seek to maximize the amount of transactions included in each block. Under those conditions, -CometBFT might choose to increase the transactions passed to the Application via `RequestPrepareProposal.txs` -beyond the `RequestPrepareProposal.max_tx_bytes` limit. The idea is that, if the Application drops some of -those transactions, it can still return a transaction list whose byte size is as close to -`RequestPrepareProposal.max_tx_bytes` as possible. Thus, Requirement 2 ensures that the size in bytes of the -transaction list returned by the application will never cause the resulting block to go beyond its byte size -limit. +Busy blockchains might seek to gain full visibility into transactions in CometBFT's mempool, +rather than having visibility only on *a* subset of those transactions that fit in a block. +The application can do so by setting `ConsensusParams.Block.MaxBytes` to -1. +This instructs CometBFT (a) to enforce the maximum possible value for `MaxBytes` (100 MB) at CometBFT level, +and (b) to provide *all* transactions in the mempool when calling `PrepareProposal`. +Under these settings, the aggregated size of all transactions may exceed `PrepareProposalRequest.max_tx_bytes`. +Hence, Requirement 2 ensures that the size in bytes of the transaction list returned by the application will never +cause the resulting block to go beyond its byte size limit. -* Requirement 3 [`PrepareProposal`, `ProcessProposal`, coherence]: For any two correct processes *p* and *q*, - if *q*'s CometBFT calls `RequestProcessProposal` on *up*, - *q*'s Application returns Accept in `ResponseProcessProposal`. +- Requirement 3 [`PrepareProposal`, `ProcessProposal`, coherence]: For any two correct processes *p* and *q*, + if *q*'s CometBFT calls `ProcessProposal` on *up*, + *q*'s Application returns Accept in `ProcessProposalResponse`. Requirement 3 makes sure that blocks proposed by correct processes *always* pass the correct receiving process's `ProcessProposal` check. @@ -86,14 +111,14 @@ likely hit the bug at the same time. This would result in most (or all) processe serious consequences on CometBFT's liveness that this entails. Due to its criticality, Requirement 3 is a target for extensive testing and automated verification. -* Requirement 4 [`ProcessProposal`, determinism-1]: `ProcessProposal` is a (deterministic) function of the current +- Requirement 4 [`ProcessProposal`, determinism-1]: `ProcessProposal` is a (deterministic) function of the current state and the block that is about to be applied. In other words, for any correct process *p*, and any arbitrary block *u*, - if *p*'s CometBFT calls `RequestProcessProposal` on *u* at height *h*, + if *p*'s CometBFT calls `ProcessProposal` on *u* at height *h*, then *p*'s Application's acceptance or rejection **exclusively** depends on *u* and *sp,h-1*. -* Requirement 5 [`ProcessProposal`, determinism-2]: For any two correct processes *p* and *q*, and any arbitrary +- Requirement 5 [`ProcessProposal`, determinism-2]: For any two correct processes *p* and *q*, and any arbitrary block *u*, - if *p*'s (resp. *q*'s) CometBFT calls `RequestProcessProposal` on *u* at height *h*, + if *p*'s (resp. *q*'s) CometBFT calls `ProcessProposal` on *u* at height *h*, then *p*'s Application accepts *u* if and only if *q*'s Application accepts *u*. Note that this requirement follows from Requirement 4 and the Agreement property of consensus. @@ -104,24 +129,24 @@ the bug from fulfilling Requirements 4 or 5 (effectively making those processes In such a scenario, CometBFT's liveness cannot be guaranteed. Again, this is a problem in practice if most validators are running the same software, as they are likely to hit the bug at the same point. There is currently no clear solution to help with this situation, so -the Application designers/implementors must proceed very carefully with the logic/implementation +the Application designers/implementers must proceed very carefully with the logic/implementation of `ProcessProposal`. As a general rule `ProcessProposal` SHOULD always accept the block. According to the Tendermint consensus algorithm, currently adopted in CometBFT, a correct process can broadcast at most one precommit message in round *r*, height *h*. -Since, as stated in the [Methods](./abci++_methods.md#extendvote) section, `ResponseExtendVote` +Since, as stated in the [Methods](./abci++_methods.md#extendvote) section, `ExtendVote` is only called when the consensus algorithm is about to broadcast a non-`nil` precommit message, a correct process can only produce one vote extension in round *r*, height *h*. Let *erp* be the vote extension that the Application of a correct process *p* returns via -`ResponseExtendVote` in round *r*, height *h*. -Let *wrp* be the proposed block that *p*'s CometBFT passes to the Application via `RequestExtendVote` +`ExtendVoteResponse` in round *r*, height *h*. +Let *wrp* be the proposed block that *p*'s CometBFT passes to the Application via `ExtendVoteRequest` in round *r*, height *h*. -* Requirement 6 [`ExtendVote`, `VerifyVoteExtension`, coherence]: For any two different correct +- Requirement 6 [`ExtendVote`, `VerifyVoteExtension`, coherence]: For any two different correct processes *p* and *q*, if *q* receives *erp* from *p* in height *h*, *q*'s - Application returns Accept in `ResponseVerifyVoteExtension`. + Application returns Accept in `VerifyVoteExtensionResponse`. Requirement 6 constrains the creation and handling of vote extensions in a similar way as Requirement 3 constrains the creation and handling of proposed blocks. @@ -131,15 +156,15 @@ However, if there is a (deterministic) bug in `ExtendVote` or `VerifyVoteExtensi we will face the same liveness issues as described for Requirement 5, as Precommit messages with invalid vote extensions will be discarded. -* Requirement 7 [`VerifyVoteExtension`, determinism-1]: `VerifyVoteExtension` is a (deterministic) function of +- Requirement 7 [`VerifyVoteExtension`, determinism-1]: `VerifyVoteExtension` is a (deterministic) function of the current state, the vote extension received, and the prepared proposal that the extension refers to. In other words, for any correct process *p*, and any arbitrary vote extension *e*, and any arbitrary - block *w*, if *p*'s (resp. *q*'s) CometBFT calls `RequestVerifyVoteExtension` on *e* and *w* at height *h*, + block *w*, if *p*'s (resp. *q*'s) CometBFT calls `VerifyVoteExtension` on *e* and *w* at height *h*, then *p*'s Application's acceptance or rejection **exclusively** depends on *e*, *w* and *sp,h-1*. -* Requirement 8 [`VerifyVoteExtension`, determinism-2]: For any two correct processes *p* and *q*, +- Requirement 8 [`VerifyVoteExtension`, determinism-2]: For any two correct processes *p* and *q*, and any arbitrary vote extension *e*, and any arbitrary block *w*, - if *p*'s (resp. *q*'s) CometBFT calls `RequestVerifyVoteExtension` on *e* and *w* at height *h*, + if *p*'s (resp. *q*'s) CometBFT calls `VerifyVoteExtension` on *e* and *w* at height *h*, then *p*'s Application accepts *e* if and only if *q*'s Application accepts *e*. Note that this requirement follows from Requirement 7 and the Agreement property of consensus. @@ -152,47 +177,80 @@ Requirements 7 and 8 can be violated by a bug inducing non-determinism in Extra care should be put in the implementation of `ExtendVote` and `VerifyVoteExtension`. As a general rule, `VerifyVoteExtension` SHOULD always accept the vote extension. -* Requirement 9 [*all*, no-side-effects]: *p*'s calls to `RequestPrepareProposal`, - `RequestProcessProposal`, `RequestExtendVote`, and `RequestVerifyVoteExtension` at height *h* do +- Requirement 9 [*all*, no-side-effects]: *p*'s calls to `PrepareProposal`, + `ProcessProposal`, `ExtendVote`, and `VerifyVoteExtension` at height *h* do not modify *sp,h-1*. - -* Requirement 10 [`ExtendVote`, `FinalizeBlock`, non-dependency]: for any correct process *p*, +- Requirement 10 [`ExtendVote`, `FinalizeBlock`, non-dependency]: for any correct process *p*, and any vote extension *e* that *p* received at height *h*, the computation of *sp,h* does not depend on *e*. -The call to correct process *p*'s `RequestFinalizeBlock` at height *h*, with block *vp,h* +The call to correct process *p*'s `FinalizeBlock` at height *h*, with block *vp,h* passed as parameter, creates state *sp,h*. Additionally, *p*'s `FinalizeBlock` creates a set of transaction results *Tp,h*. -* Requirement 11 [`FinalizeBlock`, determinism-1]: For any correct process *p*, +- Requirement 11 [`FinalizeBlock`, determinism-1]: For any correct process *p*, *sp,h* exclusively depends on *sp,h-1* and *vp,h*. -* Requirement 12 [`FinalizeBlock`, determinism-2]: For any correct process *p*, +- Requirement 12 [`FinalizeBlock`, determinism-2]: For any correct process *p*, the contents of *Tp,h* exclusively depend on *sp,h-1* and *vp,h*. Note that Requirements 11 and 12, combined with the Agreement property of consensus ensure state machine replication, i.e., the Application state evolves consistently at all correct processes. -Finally, notice that neither `PrepareProposal` nor `ExtendVote` have determinism-related +Also, notice that neither `PrepareProposal` nor `ExtendVote` have determinism-related requirements associated. Indeed, `PrepareProposal` is not required to be deterministic: -* *up* may depend on *vp* and *sp,h-1*, but may also depend on other values or operations. -* *vp = vq ⇏ up = uq*. +- *up* may depend on *vp* and *sp,h-1*, but may also depend on other values or operations. +- *vp = vq ⇏ up = uq*. Likewise, `ExtendVote` can also be non-deterministic: -* *erp* may depend on *wrp* and *sp,h-1*, +- *erp* may depend on *wrp* and *sp,h-1*, but may also depend on other values or operations. -* *wrp = wrq ⇏ +- *wrp = wrq ⇏ erp = erq* +### Mempool Connection Requirements + +Let *CheckTxCodestx,p,h* denote the set of result codes returned by *p*'s Application, +via `CheckTxResponse`, +to successive calls to `CheckTx` occurring while the Application is at height *h* +and having transaction *tx* as parameter. +*CheckTxCodestx,p,h* is a set since *p*'s Application may +return different result codes during height *h*. +If *CheckTxCodestx,p,h* is a singleton set, i.e. the Application always returned +the same result code in `CheckTxResponse` while at height *h*, +we define *CheckTxCodetx,p,h* as the singleton value of *CheckTxCodestx,p,h*. +If *CheckTxCodestx,p,h* is not a singleton set, *CheckTxCodetx,p,h* is undefined. +Let predicate *OK(CheckTxCodetx,p,h)* denote whether *CheckTxCodetx,p,h* is `SUCCESS`. + +- Requirement 13 [`CheckTx`, eventual non-oscillation]: For any transaction *tx*, + there exists a boolean value *b*, + and a height *hstable* such that, + for any correct process *p*, + *CheckTxCodetx,p,h* is defined, and + *OK(CheckTxCodetx,p,h) = b* + for any height *h ≥ hstable*. + +Requirement 13 ensures that +a transaction will eventually stop oscillating between `CheckTx` success and failure +if it stays in *p's* mempool for long enough. +This condition on the Application's behavior allows the mempool to ensure that +a transaction will leave the mempool of all full nodes, +either because it is expunged everywhere due to failing `CheckTx` calls, +or because it stays valid long enough to be gossipped, proposed and decided. +Although Requirement 13 defines a global *hstable*, application developers +can consider such stabilization height as local to process *p* (*hp,stable*), +without loss for generality. +In contrast, the value of *b* MUST be the same across all processes. + ## Managing the Application state and related topics ### Connection State -CometBFT maintains four concurrent ABCI++ connections, namely +CometBFT maintains four concurrent ABCI connections, namely [Consensus Connection](#consensus-connection), [Mempool Connection](#mempool-connection), [Info/Query Connection](#infoquery-connection), and @@ -202,7 +260,7 @@ the state for each connection, which are synchronized upon `Commit` calls. #### Concurrency -In principle, each of the four ABCI++ connections operates concurrently with one +In principle, each of the four ABCI connections operates concurrently with one another. This means applications need to ensure access to state is thread safe. Both the [default in-process ABCI client](https://github.com/cometbft/cometbft/blob/main/abci/client/local_client.go#L13) @@ -216,20 +274,6 @@ time. The existence of this global mutex means Go application developers can get thread safety for application state by routing all reads and writes through the ABCI system. Thus it may be unsafe to expose application state directly to an RPC interface, and unless explicit measures are taken, all queries should be routed through the ABCI Query method. - - - - - #### FinalizeBlock When the consensus algorithm decides on a block, CometBFT uses `FinalizeBlock` to send the @@ -267,22 +311,22 @@ Likewise, CometBFT calls `ProcessProposal` upon reception of a proposed block fr network. The proposed block's data that is disclosed to the Application by these two methods is the following: -* the transaction list -* the `LastCommit` referring to the previous block -* the block header's hash (except in `PrepareProposal`, where it is not known yet) -* list of validators that misbehaved -* the block's timestamp -* `NextValidatorsHash` -* Proposer address +- the transaction list +- the `LastCommit` referring to the previous block +- the block header's hash (except in `PrepareProposal`, where it is not known yet) +- list of validators that misbehaved +- the block's timestamp +- `NextValidatorsHash` +- Proposer address The Application may decide to *immediately* execute the given block (i.e., upon `PrepareProposal` or `ProcessProposal`). There are two main reasons why the Application may want to do this: -* *Avoiding invalid transactions in blocks*. +- *Avoiding invalid transactions in blocks*. In order to be sure that the block does not contain *any* invalid transaction, there may be no way other than fully executing the transactions in the block as though it was the *decided* block. -* *Quick `FinalizeBlock` execution*. +- *Quick `FinalizeBlock` execution*. Upon reception of the decided block via `FinalizeBlock`, if that same block was executed upon `PrepareProposal` or `ProcessProposal` and the resulting state was kept in memory, the Application can simply apply that state (faster) to the main state, rather than reexecuting @@ -305,7 +349,7 @@ to bound memory usage. As a general rule, the Application should be ready to dis before `FinalizeBlock`, even if one of them might end up corresponding to the decided block and thus have to be reexecuted upon `FinalizeBlock`. -### States and ABCI++ Connections +### States and ABCI Connections #### Consensus Connection @@ -333,9 +377,9 @@ responded to and no new ones can begin. After the `Commit` call returns, while still holding the mempool lock, `CheckTx` is run again on all transactions that remain in the node's local mempool after filtering those included in the block. -Parameter `Type` in `RequestCheckTx` -indicates whether an incoming transaction is new (`CheckTxType_New`), or a -recheck (`CheckTxType_Recheck`). +Parameter `Type` in `CheckTxRequest` +indicates whether an incoming transaction is new (`CHECK_TX_TYPE_NEW`), or a +recheck (`CHECK_TX_TYPE_RECHECK`). Finally, after re-checking transactions in the mempool, CometBFT will unlock the mempool connection. New transactions are once again able to be processed through `CheckTx`. @@ -346,7 +390,7 @@ Since the transaction cannot be guaranteed to be checked against the exact same will be executed as part of a (potential) decided block, `CheckTx` shouldn't check *everything* that affects the transaction's validity, in particular those checks whose validity may depend on transaction ordering. `CheckTx` is weak because a Byzantine node need not care about `CheckTx`; -it can propose a block full of invalid transactions if it wants. The mechanism ABCI++ has +it can propose a block full of invalid transactions if it wants. The mechanism ABCI, from version 1.0, has in place for dealing with such behavior is `ProcessProposal`. ##### Replay Protection @@ -385,11 +429,11 @@ For more information, see Section [State Sync](#state-sync). The Application is expected to return a list of [`ExecTxResult`](./abci%2B%2B_methods.md#exectxresult) in -[`ResponseFinalizeBlock`](./abci%2B%2B_methods.md#finalizeblock). The list of transaction +[`FinalizeBlockResponse`](./abci%2B%2B_methods.md#finalizeblock). The list of transaction results MUST respect the same order as the list of transactions delivered via -[`RequestFinalizeBlock`](./abci%2B%2B_methods.md#finalizeblock). +[`FinalizeBlockRequest`](./abci%2B%2B_methods.md#finalizeblock). This section discusses the fields inside this structure, along with the fields in -[`ResponseCheckTx`](./abci%2B%2B_methods.md#checktx), +[`CheckTxResponse`](./abci%2B%2B_methods.md#checktx), whose semantics are similar. The `Info` and `Log` fields are @@ -421,8 +465,8 @@ or validation should fail before it can use more resources than it requested. When `MaxGas > -1`, CometBFT enforces the following rules: -* `GasWanted <= MaxGas` for every transaction in the mempool -* `(sum of GasWanted in a block) <= MaxGas` when proposing a block +- `GasWanted <= MaxGas` for every transaction in the mempool +- `(sum of GasWanted in a block) <= MaxGas` when proposing a block If `MaxGas == -1`, no rules about gas are enforced. @@ -440,11 +484,11 @@ it can use `PrepareProposal` and `ProcessProposal` to enforce that `(sum of GasW in all proposed or prevoted blocks, we have: -* `(sum of GasUsed in a block) <= MaxGas` for every block +- `(sum of GasUsed in a block) <= MaxGas` for every block The `GasUsed` field is ignored by CometBFT. -#### Specifics of `ResponseCheckTx` +#### Specifics of `CheckTxResponse` If `Code != 0`, it will be rejected from the mempool and hence not broadcasted to other peers and not included in a proposal block. @@ -453,9 +497,9 @@ not broadcasted to other peers and not included in a proposal block. deterministic since, given a transaction, nodes' Applications might have a different *CheckTxState* values when they receive it and check their validity via `CheckTx`. -CometBFT ignores this value in `ResponseCheckTx`. +CometBFT ignores this value in `CheckTxResponse`. -From v0.34.x on, there is a `Priority` field in `ResponseCheckTx` that can be +From v0.34.x on, there is a `Priority` field in `CheckTxResponse` that can be used to explicitly prioritize transactions in the mempool for inclusion in a block proposal. @@ -501,21 +545,21 @@ duplicates, the block execution will fail irrecoverably. Structure `ValidatorUpdate` contains a public key, which is used to identify the validator: The public key currently supports three types: -* `ed25519` -* `secp256k1` -* `sr25519` +- `ed25519` +- `secp256k1` +- `sr25519` Structure `ValidatorUpdate` also contains an `ìnt64` field denoting the validator's new power. Applications must ensure that `ValidatorUpdate` structures abide by the following rules: -* power must be non-negative -* if power is set to 0, the validator must be in the validator set; it will be removed from the set -* if power is greater than 0: - * if the validator is not in the validator set, it will be added to the +- power must be non-negative +- if power is set to 0, the validator must be in the validator set; it will be removed from the set +- if power is greater than 0: + - if the validator is not in the validator set, it will be added to the set with the given power - * if the validator is in the validator set, its power will be adjusted to the given power -* the total power of the new validator set must not exceed `MaxTotalVotingPower`, where + - if the validator is in the validator set, its power will be adjusted to the given power +- the total power of the new validator set must not exceed `MaxTotalVotingPower`, where `MaxTotalVotingPower = MaxInt64 / 8` Note the updates returned after processing the block at height `H` will only take effect @@ -534,25 +578,19 @@ all full nodes have the same value at a given height. #### List of Parameters -These are the current consensus parameters (as of v0.37.x): - -1. [BlockParams.MaxBytes](#blockparamsmaxbytes) -2. [BlockParams.MaxGas](#blockparamsmaxgas) -3. [EvidenceParams.MaxAgeDuration](#evidenceparamsmaxageduration) -4. [EvidenceParams.MaxAgeNumBlocks](#evidenceparamsmaxagenumblocks) -5. [EvidenceParams.MaxBytes](#evidenceparamsmaxbytes) -6. [ValidatorParams.PubKeyTypes](#validatorparamspubkeytypes) -7. [VersionParams.App](#versionparamsapp) - +These are the current consensus parameters (as of v1.0.x): + +1. [BlockParams.MaxBytes](#blockparamsmaxbytes) +2. [BlockParams.MaxGas](#blockparamsmaxgas) +3. [EvidenceParams.MaxAgeDuration](#evidenceparamsmaxageduration) +4. [EvidenceParams.MaxAgeNumBlocks](#evidenceparamsmaxagenumblocks) +5. [EvidenceParams.MaxBytes](#evidenceparamsmaxbytes) +6. [FeatureParams.PbtsEnableHeight](#featureparamspbtsenableheight) +7. [FeatureParams.VoteExtensionsEnableHeight](#featureparamsvoteextensionsenableheight) +8. [ValidatorParams.PubKeyTypes](#validatorparamspubkeytypes) +9. [VersionParams.App](#versionparamsapp) +10. [SynchronyParams.Precision](#synchronyparamsprecision) +11. [SynchronyParams.MessageDelay](#synchronyparamsmessagedelay) ##### BlockParams.MaxBytes @@ -562,7 +600,33 @@ This is enforced by the consensus algorithm. This implies a maximum transaction size that is this `MaxBytes`, less the expected size of the header, the validator set, and any included evidence in the block. -Must have `0 < MaxBytes < 100 MB`. +The Application should be aware that honest validators *may* produce and +broadcast blocks with up to the configured `MaxBytes` size. +As a result, the consensus +[timeout parameters](../../docs/explanation/core/configuration.md#consensus-timeouts-explained) +adopted by nodes should be configured so as to account for the worst-case +latency for the delivery of a full block with `MaxBytes` size to all validators. + +If the Application wants full control over the size of blocks, +it can do so by enforcing a byte limit set up at the Application level. +This Application-internal limit is used by `PrepareProposal` to bound the total size +of transactions it returns, and by `ProcessProposal` to reject any received block +whose total transaction size is bigger than the enforced limit. +In such case, the Application MAY set `MaxBytes` to -1. + +If the Application sets value -1, consensus will: + +- consider that the actual value to enforce is 100 MB +- will provide *all* transactions in the mempool in calls to `PrepareProposal` + +Must have `MaxBytes == -1` OR `0 < MaxBytes <= 100 MB`. + +> Bear in mind that the default value for the `BlockParams.MaxBytes` consensus +> parameter accepts as valid blocks with size up to 21 MB. +> If the Application's use case does not need blocks of that size, +> or if the impact (specially on bandwidth consumption and block latency) +> of propagating blocks of that size was not evaluated, +> it is strongly recommended to wind down this default value. ##### BlockParams.MaxGas @@ -607,110 +671,65 @@ a block minus its overhead ( ~ `BlockParams.MaxBytes`). Must have `MaxBytes > 0`. -##### ValidatorParams.PubKeyTypes - -The parameter restricts the type of keys validators can use. The parameter uses ABCI pubkey naming, not Amino names. - -##### VersionParams.App - -This is the version of the ABCI application. - - -##### ABCIParams.VoteExtensionsEnableHeight -This parameter is either 0 or a positive height at which vote extensions -become mandatory. If the value is zero (which is the default), vote -extensions are not required. Otherwise, at all heights greater than the -configured height `H` vote extensions must be present (even if empty). -When the configured height `H` is reached, `PrepareProposal` will not -include vote extensions yet, but `ExtendVote` and `VerifyVoteExtension` will -be called. Then, when reaching height `H+1`, `PrepareProposal` will -include the vote extensions from height `H`. For all heights after `H` +##### SynchronyParams.MessageDelay -* vote extensions cannot be disabled, -* they are mandatory: all precommit messages sent MUST have an extension - attached. Nevertheless, the application MAY provide 0-length - extensions. +This sets a bound on how long a proposal message may take to reach all +validators on a network and still be considered valid. -Must always be set to a future height. Once set to a value different from -0, its value must not be changed. +This parameter is used by the +[Proposer-Based Timestamps (PBTS)](../consensus/proposer-based-timestamp/README.md) +algorithm. #### Updating Consensus Parameters @@ -726,7 +745,7 @@ value to be updated to the default. ##### `InitChain` -`ResponseInitChain` includes a `ConsensusParams` parameter. +`InitChainResponse` includes a `ConsensusParams` parameter. If `ConsensusParams` is `nil`, CometBFT will use the params loaded in the genesis file. If `ConsensusParams` is not `nil`, CometBFT will use it. This way the application can determine the initial consensus parameters for the @@ -734,7 +753,7 @@ blockchain. ##### `FinalizeBlock`, `PrepareProposal`/`ProcessProposal` -`ResponseFinalizeBlock` accepts a `ConsensusParams` parameter. +`FinalizeBlockResponse` accepts a `ConsensusParams` parameter. If `ConsensusParams` is `nil`, CometBFT will do nothing. If `ConsensusParams` is not `nil`, CometBFT will use it. This way the application can update the consensus parameters over time. @@ -777,9 +796,9 @@ For such applications, the `AppHash` provides a much more efficient way to verif ABCI applications can take advantage of more efficient light-client proofs for their state as follows: -* return the Merkle root of the deterministic application state in - `ResponseFinalizeBlock.Data`. This Merkle root will be included as the `AppHash` in the next block. -* return efficient Merkle proofs about that application state in `ResponseQuery.Proof` +- return the Merkle root of the deterministic application state in + `FinalizeBlockResponse.Data`. This Merkle root will be included as the `AppHash` in the next block. +- return efficient Merkle proofs about that application state in `QueryResponse.Proof` that can be verified using the `AppHash` of the corresponding block. For instance, this allows an application's light-client to verify proofs of @@ -787,7 +806,7 @@ absence in the application state, something which is much less efficient to do u Some applications (eg. Ethereum, Cosmos-SDK) have multiple "levels" of Merkle trees, where the leaves of one tree are the root hashes of others. To support this, and -the general variability in Merkle proofs, the `ResponseQuery.Proof` has some minimal structure: +the general variability in Merkle proofs, the `QueryResponse.Proof` has some minimal structure: ```protobuf message ProofOps { @@ -814,9 +833,9 @@ the list should match the `AppHash` being verified against. When CometBFT connects to a peer, it sends two queries to the ABCI application using the following paths, with no additional data: -* `/p2p/filter/addr/`, where `` denote the IP address and +- `/p2p/filter/addr/`, where `` denote the IP address and the port of the connection -* `p2p/filter/id/`, where `` is the peer node ID (ie. the +- `p2p/filter/id/`, where `` is the peer node ID (ie. the pubkey.Address() for the peer's PubKey) If either of these queries return a non-zero ABCI code, CometBFT will refuse @@ -834,33 +853,34 @@ implementation of ### Crash Recovery -CometBFT and the application are expected to crash together and there should not +CometBFT and the application are expected to crash together and there should not exist a scenario where the application has persisted state of a height greater than the latest height persisted by CometBFT. -In practice, persisting the state of a height consists of three steps, the last of which +In practice, persisting the state of a height consists of three steps, the last of which is the call to the application's `Commit` method, the only place where the application is expected to persist/commit its state. On startup (upon recovery), CometBFT calls the `Info` method on the Info Connection to get the latest committed state of the app. The app MUST return information consistent with the -last block for which it successfully completed `Commit`. +last block for which it successfully completed `Commit`. + +The three steps performed before the state of a height is considered persisted are: -The three steps performed before the state of a height is considered persisted are: - The block is stored by CometBFT in the blockstore - CometBFT has stored the state returned by the application through `FinalizeBlockResponse` -- The application has committed its state within `Commit`. - +- The application has committed its state within `Commit`. + The following diagram depicts the order in which these events happen, and the corresponding ABCI functions that are called and executed by CometBFT and the application: -``` +``` APP: Execute block Persist application state / return ResultFinalizeBlock / - / / + / / Event: ------------- block_stored ------------ / ------------ state_stored --------------- / ----- app_persisted_state | / | / | -CometBFT: Decide --- Persist block -- Call FinalizeBlock - Persist results ---------- Call Commit -- +CometBFT: Decide --- Persist block -- Call FinalizeBlock - Persist results ---------- Call Commit -- on in the (txResults, validator Block block store updates...) @@ -868,26 +888,27 @@ CometBFT: Decide --- Persist block -- Call FinalizeBlock - Persist results ----- As these three steps are not atomic, we observe different cases based on which steps have been executed before the crash occurred -(we assume that at least `block_stored` has been executed, otherwise, there is no state persisted, +(we assume that at least `block_stored` has been executed, otherwise, there is no state persisted, and the operations for this height are repeated entirely): - `block_stored`: we replay `FinalizeBlock` and the steps afterwards. - `block_stored` and `state_stored`: As the app did not persist its state within `Commit`, we need to re-execute - `FinalizeBlock` to retrieve the results and compare them to the state stored by CometBFT within `state_stored`. + `FinalizeBlock` to retrieve the results and compare them to the state stored by CometBFT within `state_stored`. The expected case is that the states will match, otherwise CometBFT panics. -- `block_stored`, `state_stored`, `app_persisted_state`: we move on to the next height. +- `block_stored`, `state_stored`, `app_persisted_state`: we move on to the next height. Based on the sequence of these events, CometBFT will panic if any of the steps in the sequence happen out of order, -that is if: +that is if: + - The application has persisted a block at a height higher than the blocked saved during `state_stored`. - The `block_stored` step persisted a block at a height smaller than the `state_stored` -- And the difference between the heights of the blocks persisted by `state_stored` and `block_stored` is more +- And the difference between the heights of the blocks persisted by `state_stored` and `block_stored` is more than 1 (this corresponds to a scenario where we stored two blocks in the block store but never persisted the state of the first block, which should never happen). -A special case is when a crash happens before the first block is committed - that is, after calling +A special case is when a crash happens before the first block is committed - that is, after calling `InitChain`. In that case, the application's state should still be at height 0 and thus `InitChain` -will be called again. +will be called again. ### State Sync @@ -913,20 +934,20 @@ Applications that want to support state syncing must take state snapshots at reg this is accomplished is entirely up to the application. A snapshot consists of some metadata and a set of binary chunks in an arbitrary format: -* `Height (uint64)`: The height at which the snapshot is taken. It must be taken after the given +- `Height (uint64)`: The height at which the snapshot is taken. It must be taken after the given height has been committed, and must not contain data from any later heights. -* `Format (uint32)`: An arbitrary snapshot format identifier. This can be used to version snapshot +- `Format (uint32)`: An arbitrary snapshot format identifier. This can be used to version snapshot formats, e.g. to switch from Protobuf to MessagePack for serialization. The application can use this when restoring to choose whether to accept or reject a snapshot. -* `Chunks (uint32)`: The number of chunks in the snapshot. Each chunk contains arbitrary binary +- `Chunks (uint32)`: The number of chunks in the snapshot. Each chunk contains arbitrary binary data, and should be less than 16 MB; 10 MB is a good starting point. -* `Hash ([]byte)`: An arbitrary hash of the snapshot. This is used to check whether a snapshot is +- `Hash ([]byte)`: An arbitrary hash of the snapshot. This is used to check whether a snapshot is the same across nodes when downloading chunks. -* `Metadata ([]byte)`: Arbitrary snapshot metadata, e.g. chunk hashes for verification or any other +- `Metadata ([]byte)`: Arbitrary snapshot metadata, e.g. chunk hashes for verification or any other necessary info. For a snapshot to be considered the same across nodes, all of these fields must be identical. When @@ -937,14 +958,14 @@ application via the ABCI `ListSnapshots` method to discover available snapshots, snapshot chunks via `LoadSnapshotChunk`. The application is free to choose how to implement this and which formats to use, but must provide the following guarantees: -* **Consistent:** A snapshot must be taken at a single isolated height, unaffected by +- **Consistent:** A snapshot must be taken at a single isolated height, unaffected by concurrent writes. This can be accomplished by using a data store that supports ACID transactions with snapshot isolation. -* **Asynchronous:** Taking a snapshot can be time-consuming, so it must not halt chain progress, +- **Asynchronous:** Taking a snapshot can be time-consuming, so it must not halt chain progress, for example by running in a separate thread. -* **Deterministic:** A snapshot taken at the same height in the same format must be identical +- **Deterministic:** A snapshot taken at the same height in the same format must be identical (at the byte level) across nodes, including all metadata. This ensures good availability of chunks, and that they fit together across nodes. @@ -1029,17 +1050,17 @@ Once the snapshots have all been restored, CometBFT gathers additional informati bootstrapping the node (e.g. chain ID, consensus parameters, validator sets, and block headers) from the genesis file and light client RPC servers. It also calls `Info` to verify the following: -* that the app hash from the snapshot it has delivered to the Application matches the apphash +- that the app hash from the snapshot it has delivered to the Application matches the apphash stored in the next height's block -* that the version that the Application returns in `ResponseInfo` matches the version in the +- that the version that the Application returns in `InfoResponse` matches the version in the current height's block header Once the state machine has been restored and CometBFT has gathered this additional -information, it transitions to consensus. As of ABCI 2.0, CometBFT ensures the neccessary conditions -to switch are met [RFC-100](./../../docs/rfc/rfc-100-abci-vote-extension-propag.md#base-implementation-persist-and-propagate-extended-commit-history). -From the application's point of view, these operations are transparent, unless the application has just upgraded to ABCI 2.0. +information, it transitions to consensus. As of ABCI 2.0, CometBFT ensures the necessary conditions +to switch are met [RFC-100](../../docs/references/rfc/rfc-100-abci-vote-extension-propag.md#base-implementation-persist-and-propagate-extended-commit-history). +From the application's point of view, these operations are transparent, unless the application has just upgraded to ABCI 2.0. In that case, the application needs to be properly configured and aware of certain constraints in terms of when -to provide vote extensions. More details can be found in the section below. +to provide vote extensions. More details can be found in the section below. Once a node switches to consensus, it operates like any other node, apart from having a truncated block history at the height of the restored snapshot. @@ -1047,21 +1068,21 @@ Once a node switches to consensus, it operates like any other node, apart from h Introducing vote extensions requires changes to the configuration of the application. -First of all, switching to a version of CometBFT with vote extensions, requires a coordinated upgrade. -For a detailed description on the upgrade path, please refer to the corresponding -[section](./../../docs/rfc/rfc-100-abci-vote-extension-propag.md#upgrade-path) in RFC-100. +First of all, switching to a version of CometBFT with vote extensions, requires a coordinated upgrade. +For a detailed description on the upgrade path, please refer to the corresponding +[section](../../docs/references/rfc/rfc-100-abci-vote-extension-propag.md#upgrade-path) in RFC-100. -There is a newly introduced [**consensus parameter**](./abci%2B%2B_app_requirements.md#abciparamsvoteextensionsenableheight): `VoteExtensionsEnableHeight`. -This parameter represents the height at which vote extensions are +There is a newly introduced [**consensus parameter**](./abci%2B%2B_app_requirements.md#abciparamsvoteextensionsenableheight): `VoteExtensionsEnableHeight`. +This parameter represents the height at which vote extensions are required for consensus to proceed, with 0 being the default value (no vote extensions). A chain can enable vote extensions either: -* at genesis by setting `VoteExtensionsEnableHeight` to be equal, e.g., to the `InitialHeight` -* or via the application logic by changing the `ConsensusParam` to configure the +- at genesis by setting `VoteExtensionsEnableHeight` to be equal, e.g., to the `InitialHeight` +- or via the application logic by changing the `ConsensusParam` to configure the `VoteExtensionsEnableHeight`. Once the (coordinated) upgrade to ABCI 2.0 has taken place, at height *hu*, the value of `VoteExtensionsEnableHeight` MAY be set to some height, *he*, -which MUST be higher than the current height of the chain. Thus the earliest value for +which MUST be higher than the current height of the chain. Thus the earliest value for *he* is *hu* + 1. Once a node reaches the configured height, @@ -1073,7 +1094,7 @@ Likewise, for all heights *h < he*, any precommit messages that *do* will also be rejected as malformed. Height *he* is somewhat special, as calls to `PrepareProposal` MUST NOT have vote extension data, but all precommit votes in that height MUST carry a vote extension, -even if the extension is `nil`. +even if the extension is `nil`. Height *he + 1* is the first height for which `PrepareProposal` MUST have vote extension data and all precommit votes in that height MUST have a vote extension. diff --git a/spec/abci/abci++_basic_concepts.md b/spec/abci/abci++_basic_concepts.md index 08675aeffa0..f4a806cdd85 100644 --- a/spec/abci/abci++_basic_concepts.md +++ b/spec/abci/abci++_basic_concepts.md @@ -6,7 +6,7 @@ title: Overview and basic concepts ## Outline - [Overview and basic concepts](#overview-and-basic-concepts) - - [ABCI++ vs. ABCI](#abci-vs-abci) + - [ABCI 2.0 vs. legacy ABCI](#abci-20-vs-legacy-abci) - [Method overview](#method-overview) - [Consensus/block execution methods](#consensusblock-execution-methods) - [Mempool methods](#mempool-methods) @@ -24,7 +24,7 @@ title: Overview and basic concepts # Overview and basic concepts -## ABCI++ vs. ABCI +## ABCI 2.0 vs. legacy ABCI [↑ Back to Outline](#outline) @@ -40,13 +40,13 @@ as the Application cannot require validators to do more than executing the trans finalized blocks. This includes features such as threshold cryptography, and guaranteed IBC connection attempts. -ABCI++ addresses these limitations by allowing the application to intervene at three key places of +ABCI 2.0 addresses these limitations by allowing the application to intervene at three key places of consensus execution: (a) at the moment a new proposal is to be created, (b) at the moment a -proposal is to be validated, and (c) at the moment a (precommit) vote is sent/received. +proposal is to be validated, and (c) at the moment a (precommit) vote is sent/received. The new interface allows block proposers to perform application-dependent work in a block through the `PrepareProposal` method (a); and validators to perform application-dependent work -and checks in a proposed block through the `ProcessProposal` method (b); and applications to require their validators -to do more than just validate blocks through the `ExtendVote` and `VerifyVoteExtensions` methods (c). +and checks in a proposed block through the `ProcessProposal` method (b); and applications to require their validators +to do more than just validate blocks through the `ExtendVote` and `VerifyVoteExtension` methods (c). Furthermore, ABCI 2.0 coalesces {`BeginBlock`, [`DeliverTx`], `EndBlock`} into `FinalizeBlock`, as a simplified, efficient way to deliver a decided block to the Application. @@ -60,7 +60,7 @@ Methods can be classified into four categories: *consensus*, *mempool*, *info*, ### Consensus/block execution methods -The first time a new blockchain is started, CometBFT calls `InitChain`. From then on, method +The first time a new blockchain is started, CometBFT calls `InitChain`. From then on, method `FinalizeBlock` is executed upon the decision of each block, resulting in an updated Application state. During the execution of an instance of consensus, which decides the block for a given height, and before method `FinalizeBlock` is called, methods `PrepareProposal`, `ProcessProposal`, @@ -75,29 +75,29 @@ call sequences of these methods. proposer to perform application-dependent work in a block before proposing it. This enables, for instance, batch optimizations to a block, which has been empirically demonstrated to be a key component for improved performance. Method `PrepareProposal` is called - every time CometBFT is about to broadcast a Proposal message and _validValue_ is `nil`. + every time CometBFT is about to broadcast a Proposal message and *validValue* is `nil`. CometBFT gathers outstanding transactions from the mempool, generates a block header, and uses them to create a block to propose. Then, it calls - `RequestPrepareProposal` with the newly created proposal, called *raw proposal*. The Application - can make changes to the raw proposal, such as modifying the set of transactions or the order - in which they appear, and returns the - (potentially) modified proposal, called *prepared proposal* in the `ResponsePrepareProposal` - call. The logic modifying the raw proposal can be non-deterministic. + `PrepareProposal` with the newly created proposal, called *raw proposal*. The Application + can make changes to the raw proposal, such as reordering, adding and removing transactions, before returning the + (potentially) modified proposal, called *prepared proposal* in the `PrepareProposalResponse`. + The logic modifying the raw proposal MAY be non-deterministic. - [**ProcessProposal:**](./abci++_methods.md#processproposal) It allows a validator to perform application-dependent work in a proposed block. This enables features such as immediate block execution, and allows the Application to reject invalid blocks. - CometBFT calls it when it receives a proposal and _validValue_ is `nil`. - The Application cannot modify the proposal at this point but can reject it if it is + CometBFT calls it when it receives a proposal and *validValue* is `nil`. + The Application cannot modify the proposal at this point but can reject it if invalid. If that is the case, the consensus algorithm will prevote `nil` on the proposal, which has strong liveness implications for CometBFT. As a general rule, the Application SHOULD accept a prepared proposal passed via `ProcessProposal`, even if a part of the proposal is invalid (e.g., an invalid transaction); the Application can ignore the invalid part of the prepared proposal at block execution time. + The logic in `ProcessProposal` MUST be deterministic. -- [**ExtendVote:**](./abci++_methods.md#extendvote) It allows applications to force their - validators to do more than just validate within consensus. `ExtendVote` allows applications to +- [**ExtendVote:**](./abci++_methods.md#extendvote) It allows applications to let their + validators do more than just validate within consensus. `ExtendVote` allows applications to include non-deterministic data, opaque to the consensus algorithm, to precommit messages (the final round of voting). The data, called *vote extension*, will be broadcast and received together with the vote it is extending, and will be made available to the Application in the next height, @@ -105,6 +105,7 @@ call sequences of these methods. CometBFT calls `ExtendVote` when the consensus algorithm is about to send a non-`nil` precommit message. If the Application does not have vote extension information to provide at that time, it returns a 0-length byte array as its vote extension. + The logic in `ExtendVote` MAY be non-deterministic. - [**VerifyVoteExtension:**](./abci++_methods.md#verifyvoteextension) It allows validators to validate the vote extension data attached to a precommit message. If the validation @@ -112,21 +113,22 @@ call sequences of these methods. This has a negative impact on liveness, i.e., if vote extensions repeatedly cannot be verified by correct validators, the consensus algorithm may not be able to finalize a block even if sufficiently many (+2/3) validators send precommit votes for that block. Thus, `VerifyVoteExtension` - should be used with special care. + should be implemented with special care. As a general rule, an Application that detects an invalid vote extension SHOULD - accept it in `ResponseVerifyVoteExtension` and ignore it in its own logic. CometBFT calls it when - a process receives a precommit message with a (possibly empty) vote extension. + accept it in `VerifyVoteExtensionResponse` and ignore it in its own logic. CometBFT calls it when + a process receives a precommit message with a (possibly empty) vote extension, for the current height. It is not called for precommit votes received after the height is concluded but while waiting to accumulate more precommit votes. + The logic in `VerifyVoteExtension` MUST be deterministic. - [**FinalizeBlock:**](./abci++_methods.md#finalizeblock) It delivers a decided block to the Application. The Application must execute the transactions in the block deterministically and update its state accordingly. Cryptographic commitments to the block and transaction results, - returned via the corresponding parameters in `ResponseFinalizeBlock`, are included in the header + returned via the corresponding parameters in `FinalizeBlockResponse`, are included in the header of the next block. CometBFT calls it when a new block is decided. - [**Commit:**](./abci++_methods.md#commit) Instructs the Application to persist its state. It is a fundamental part of CometBFT's crash-recovery mechanism that ensures the synchronization between CometBFT and the Application upon recovery. CometBFT calls it just after - having persisted the data returned by calls to `ResponseFinalizeBlock`. The Application can now discard + having persisted the data returned by calls to `FinalizeBlockResponse`. The Application can now discard any state or data except the one resulting from executing the transactions in the decided block. ### Mempool methods @@ -152,7 +154,7 @@ call sequences of these methods. State sync allows new nodes to rapidly bootstrap by discovering, fetching, and applying state machine (application) snapshots instead of replaying historical blocks. For more details, see the -[state sync documentation](../p2p/messages/state-sync.md). +[state sync documentation](../p2p/legacy-docs/messages/state-sync.md). New nodes discover and request snapshots from other nodes in the P2P network. A CometBFT node that receives a request for snapshots from a peer will call @@ -202,23 +204,26 @@ More details on managing state across connections can be found in the section on ## Proposal timeout -Immediate execution requires the Application to fully execute the prepared block -before returning from `PrepareProposal`, this means that CometBFT cannot make progress -during the block execution. -This stands on the consensus algorithm critical path: if the Application takes a long time -executing the block, the default value of *TimeoutPropose* might not be sufficient -to accommodate the long block execution time and non-proposer nodes might time -out and prevote `nil`. The proposal, in this case, will probably be rejected and a new round will be necessary. +`PrepareProposal` stands on the consensus algorithm critical path, +i.e., CometBFT cannot make progress while this method is being executed. +Hence, if the Application takes a long time preparing a proposal, +the default value of *TimeoutPropose* might not be sufficient +to accommodate the method's execution and validator nodes might time out and prevote `nil`. +The proposal, in this case, will probably be rejected and a new round will be necessary. - -Operators will need to adjust the default value of *TimeoutPropose* in CometBFT's configuration file, +Timeouts are automatically increased for each new round of a height and, if the execution of `PrepareProposal` is bound, eventually *TimeoutPropose* will be long enough to accommodate the execution of `PrepareProposal`. +However, relying on this self adaptation could lead to performance degradation and, therefore, +operators are suggested to adjust the initial value of *TimeoutPropose* in CometBFT's configuration file, in order to suit the needs of the particular application being deployed. +This is particularly important if applications implement *immediate execution*. +To implement this technique, proposers need to execute the block being proposed within `PrepareProposal`, which could take longer than *TimeoutPropose*. + ## Deterministic State-Machine Replication [↑ Back to Outline](#outline) -ABCI++ applications must implement deterministic finite-state machines to be +ABCI applications must implement deterministic finite-state machines to be securely replicated by the CometBFT consensus engine. This means block execution must be strictly deterministic: given the same ordered set of transactions, all nodes will compute identical responses, for all @@ -233,15 +238,20 @@ from block execution (`FinalizeBlock` calls), and not through any other kind of request. This is the only way to ensure all nodes see the same transactions and compute the same results. -Some Applications may choose to implement immediate execution, which entails executing the blocks -that are about to be proposed (via `PrepareProposal`), and those that the Application is asked to -validate (via `ProcessProposal`). However, the state changes caused by processing those +Applications that implement immediate execution (execute the blocks +that are about to be proposed, in `PrepareProposal`, or that require validation, in `ProcessProposal`) produce a new candidate state before a block is decided. +The state changes caused by processing those proposed blocks must never replace the previous state until `FinalizeBlock` confirms -the block decided. +that the proposed block was decided and `Commit` is invoked for it. + +The same is true to Applications that quickly accept blocks and execute the +blocks optimistically in parallel with the remaining consensus steps to save +time during `FinalizeBlock`; they must only apply state changes in `Commit`. Additionally, vote extensions or the validation thereof (via `ExtendVote` or `VerifyVoteExtension`) must *never* have side effects on the current state. -They can only be used when their data is provided in a `RequestPrepareProposal` call. +Their data can only be used when provided in a `PrepareProposal` call but, again, +without side effects to the app state. If there is some non-determinism in the state machine, consensus will eventually fail as nodes disagree over the correct values for the block header. The @@ -266,19 +276,20 @@ Sources of non-determinism in applications may include: See [#56](https://github.com/tendermint/abci/issues/56) for the original discussion. -Note that some methods (`Query`, `FinalizeBlock`) return non-deterministic data in the form -of `Info` and `Log` fields. The `Log` is intended for the literal output from the Application's -logger, while the `Info` is any additional info that should be returned. These are the only fields -that are not included in block header computations, so we don't need agreement -on them. All other fields in the `Response*` must be strictly deterministic. +Note that some methods (e.g., `Query` and `FinalizeBlock`) may return +non-deterministic data in the form of `Info`, `Log` and/or `Events` fields. The +`Log` is intended for the literal output from the Application's logger, while +the `Info` is any additional info that should be returned. These fields are not +included in block header computations, so we don't need agreement on them. See +each field's description on whether it must be deterministic or not. ## Events [↑ Back to Outline](#outline) Method `FinalizeBlock` includes an `events` field at the top level in its -`Response*`, and one `events` field per transaction included in the block. -Applications may respond to this ABCI++ method with an event list for each executed +`FinalizeBlockResponse`, and one `events` field per transaction included in the block. +Applications may respond to this ABCI 2.0 method with an event list for each executed transaction, and a general event list for the block itself. Events allow applications to associate metadata with transactions and blocks. Events returned via `FinalizeBlock` do not impact the consensus algorithm in any way @@ -290,7 +301,8 @@ execution. `Event` values can be used to index transactions and blocks according happened during their execution. Each event has a `type` which is meant to categorize the event for a particular -`Response*` or `Tx`. A `Response*` or `Tx` may contain multiple events with duplicate +`FinalizeBlockResponse` or `Tx`. A `FinalizeBlockResponse` or `Tx` may contain +multiple events with duplicate `type` values, where each distinct entry is meant to categorize attributes for a particular event. Every key and value in an event's attributes must be UTF-8 encoded strings along with the event type itself. @@ -302,9 +314,11 @@ message Event { } ``` -The attributes of an `Event` consist of a `key`, a `value`, and an `index` flag. The -index flag notifies the CometBFT indexer to index the attribute. The value of -the `index` flag is non-deterministic and may vary across different nodes in the network. +The attributes of an `Event` consist of a `key`, a `value`, and an `index` +flag. The index flag notifies the CometBFT indexer to index the attribute. + +The `type` and `attributes` fields are non-deterministic and may vary across +different nodes in the network. ```protobuf message EventAttribute { @@ -317,7 +331,7 @@ message EventAttribute { Example: ```go - abci.ResponseFinalizeBlock{ + abci.FinalizeBlockResponse{ // ... Events: []abci.Event{ { @@ -358,7 +372,7 @@ irrefutable proof of malicious behavior by a network participant. It is the resp CometBFT to detect such malicious behavior. When malicious behavior is detected, CometBFT will gossip evidences of misbehavior to other nodes and commit the evidences to the chain once they are verified by a subset of validators. These evidences will then be -passed on to the Application through ABCI++. It is the responsibility of the +passed on to the Application through ABCI. It is the responsibility of the Application to handle evidence of misbehavior and exercise punishment. There are two forms of evidence: Duplicate Vote and Light Client Attack. More @@ -379,7 +393,7 @@ enum EvidenceType { [↑ Back to Outline](#outline) -The `Query` and `CheckTx` methods include a `Code` field in their `Response*`. +The `Query` and `CheckTx` methods include a `Code` field in their `*Response`. Field `Code` is meant to contain an application-specific response code. A response code of `0` indicates no error. Any other response code indicates to CometBFT that an error occurred. @@ -405,18 +419,18 @@ The handling of non-zero response codes by CometBFT is described below. ### `CheckTx` -When CometBFT receives a `ResponseCheckTx` with a non-zero `Code`, the associated +When CometBFT receives a `CheckTxResponse` with a non-zero `Code`, the associated transaction will not be added to CometBFT's mempool or it will be removed if it is already included. ### `ExecTxResult` (as part of `FinalizeBlock`) The `ExecTxResult` type delivers transaction results from the Application to CometBFT. When -CometBFT receives a `ResponseFinalizeBlock` containing an `ExecTxResult` with a non-zero `Code`, +CometBFT receives a `FinalizeBlockResponse` containing an `ExecTxResult` with a non-zero `Code`, the response code is logged. Past `Code` values can be queried by clients. As the transaction was part of a decided block, the `Code` does not influence consensus. ### `Query` -When CometBFT receives a `ResponseQuery` with a non-zero `Code`, this code is +When CometBFT receives a `QueryResponse` with a non-zero `Code`, this code is returned directly to the client that initiated the query. diff --git a/spec/abci/abci++_client_server.md b/spec/abci/abci++_client_server.md index b6b11a18bb9..202ab863c3f 100644 --- a/spec/abci/abci++_client_server.md +++ b/spec/abci/abci++_client_server.md @@ -8,7 +8,7 @@ title: Client and Server This section is for those looking to implement their own ABCI Server, perhaps in a new programming language. -You are expected to have read all previous sections of ABCI++ specification, namely +You are expected to have read all previous sections of ABCI specification, namely [Basic Concepts](./abci%2B%2B_basic_concepts.md), [Methods](./abci%2B%2B_methods.md), [Application Requirements](./abci%2B%2B_app_requirements.md), and @@ -17,19 +17,13 @@ You are expected to have read all previous sections of ABCI++ specification, nam ## Message Protocol and Synchrony The message protocol consists of pairs of requests and responses defined in the -[protobuf file](https://github.com/cometbft/cometbft/blob/main/proto/tendermint/abci/types.proto). +[protobuf file](https://github.com/cometbft/cometbft/blob/main/proto/cometbft/abci/v1/types.proto). Some messages have no fields, while others may include byte-arrays, strings, integers, or custom protobuf types. For more details on protobuf, see the [documentation](https://developers.google.com/protocol-buffers/docs/overview). - ## Server Implementations To use ABCI in your programming language of choice, there must be an ABCI diff --git a/spec/abci/abci++_comet_expected_behavior.md b/spec/abci/abci++_comet_expected_behavior.md index b330588aa41..ded2110e990 100644 --- a/spec/abci/abci++_comet_expected_behavior.md +++ b/spec/abci/abci++_comet_expected_behavior.md @@ -17,10 +17,10 @@ what will happen during a block height _h_ in these frequent, benign conditions: * Consensus will decide in round 0, for height _h_; * `PrepareProposal` will be called exactly once at the proposer process of round 0, height _h_; * `ProcessProposal` will be called exactly once at all processes, and - will return _accept_ in its `Response*`; + will return _accept_ in its `ProcessProposalResponse`; * `ExtendVote` will be called exactly once at all processes; * `VerifyVoteExtension` will be called exactly _n-1_ times at each validator process, where _n_ is - the number of validators, and will always return _accept_ in its `Response*`; + the number of validators, and will always return _accept_ in its `VerifyVoteExtensionResponse`; * `FinalizeBlock` will be called exactly once at all processes, conveying the same prepared block that all calls to `PrepareProposal` and `ProcessProposal` had previously reported for height _h_; and @@ -28,35 +28,36 @@ what will happen during a block height _h_ in these frequent, benign conditions: However, the Application logic must be ready to cope with any possible run of the consensus algorithm for a given height, including bad periods (byzantine proposers, network being asynchronous). -In these cases, the sequence of calls to ABCI++ methods may not be so straightforward, but +In these cases, the sequence of calls to ABCI methods may not be so straightforward, but the Application should still be able to handle them, e.g., without crashing. The purpose of this section is to define what these sequences look like in a precise way. As mentioned in the [Basic Concepts](./abci%2B%2B_basic_concepts.md) section, CometBFT -acts as a client of ABCI++ and the Application acts as a server. Thus, it is up to CometBFT to -determine when and in which order the different ABCI++ methods will be called. A well-written +acts as a client of ABCI and the Application acts as a server. Thus, it is up to CometBFT to +determine when and in which order the different ABCI methods will be called. A well-written Application design should consider _any_ of these possible sequences. The following grammar, written in case-sensitive Augmented Backus–Naur form (ABNF, specified in [IETF rfc7405](https://datatracker.ietf.org/doc/html/rfc7405)), specifies all possible -sequences of calls to ABCI++, taken by a correct process, across all heights from the genesis block, +sequences of calls to ABCI, taken by a **correct process**, across all heights from the genesis block, including recovery runs, from the point of view of the Application. ```abnf start = clean-start / recovery -clean-start = init-chain [state-sync] consensus-exec +clean-start = ( app-handshake / state-sync ) consensus-exec +app-handshake = info init-chain state-sync = *state-sync-attempt success-sync info state-sync-attempt = offer-snapshot *apply-chunk success-sync = offer-snapshot 1*apply-chunk -recovery = info consensus-exec +recovery = info [init-chain] consensus-exec consensus-exec = (inf)consensus-height -consensus-height = *consensus-round decide commit +consensus-height = *consensus-round finalize-block commit consensus-round = proposer / non-proposer -proposer = *got-vote [prepare-proposal process-proposal] [extend] +proposer = *got-vote [prepare-proposal [process-proposal]] [extend] extend = *got-vote extend-vote *got-vote non-proposer = *got-vote [process-proposal] [extend] @@ -68,7 +69,7 @@ prepare-proposal = %s"" process-proposal = %s"" extend-vote = %s"" got-vote = %s"" -decide = %s"" +finalize-block = %s"" commit = %s"" ``` @@ -88,7 +89,7 @@ by the grammar above. Other reasons depend on the method in question: Finally, method `Info` is a special case. The method's purpose is three-fold, it can be used 1. as part of handling an RPC call from an external client, -2. as a handshake between CometBFT and the Application upon recovery to check whether any blocks need +2. as a handshake between CometBFT and the Application to check whether any blocks need to be replayed, and 3. at the end of _state-sync_ to verify that the correct state has been reached. @@ -104,12 +105,19 @@ Let us now examine the grammar line by line, providing further details. >start = clean-start / recovery >``` -* If the process is starting from scratch, CometBFT first calls `InitChain`, then it may optionally - start a _state-sync_ mechanism to catch up with other processes. Finally, it enters normal - consensus execution. +* If the process is starting from scratch, depending on whether the _state-sync_ is enabled, it engages in the handshake +with the Application, or it starts the _state-sync_ mechanism to catch up with other processes. Finally, it enters +normal consensus execution. >```abnf ->clean-start = init-chain [state-sync] consensus-exec +>clean-start = ( app-handshake / state-sync ) consensus-exec +>``` + +* If _state-sync_ is disabled, CometBFT calls `Info` method and then +since the process is starting from scratch and the Application has no state CometBFT calls `InitChain`. + +>```abnf +>app-handshake = info init_chain >``` * In _state-sync_ mode, CometBFT makes one or more attempts at synchronizing the Application's state. @@ -118,10 +126,10 @@ Let us now examine the grammar line by line, providing further details. to provide the Application with all the snapshots needed, in order to reconstruct the state locally. A successful attempt must provide at least one chunk via `ApplySnapshotChunk`. At the end of a successful attempt, CometBFT calls `Info` to make sure the reconstructed state's - _AppHash_ matches the one in the block header at the corresponding height. Note that the state - of the application does not contain vote extensions itself. The application can rely on - [CometBFT to ensure](./../../docs/rfc/rfc-100-abci-vote-extension-propag.md#base-implementation-persist-and-propagate-extended-commit-history) - the node has all the relevant data to proceed with the execution beyond this point. + _AppHash_ matches the one in the block header at the corresponding height. Note that the state + of the application does not contain vote extensions itself. The application can rely on + [CometBFT to ensure](../../docs/references/rfc/rfc-100-abci-vote-extension-propag.md#base-implementation-persist-and-propagate-extended-commit-history) + the node has all the relevant data to proceed with the execution beyond this point. >```abnf >state-sync = *state-sync-attempt success-sync info @@ -129,11 +137,11 @@ Let us now examine the grammar line by line, providing further details. >success-sync = offer-snapshot 1*apply-chunk >``` -* In recovery mode, CometBFT first calls `Info` to know from which height it needs to replay decisions - to the Application. After this, CometBFT enters normal consensus execution. +* In recovery mode, CometBFT first calls `Info` to know from which height it needs to replay decisions to the Application. If the Application +did not store any state CometBFT calls `InitChain`. After this, CometBFT enters consensus execution, first in replay mode, if there are blocks to replay, and then in normal mode. >```abnf ->recovery = info consensus-exec +>recovery = info [init-chain] consensus-exec >``` * The non-terminal `consensus-exec` is a key point in this grammar. It is an infinite sequence of @@ -151,13 +159,22 @@ Let us now examine the grammar line by line, providing further details. rounds, this means the process is replaying an already decided value (catch-up mode). >```abnf ->consensus-height = *consensus-round decide commit +>consensus-height = *consensus-round finalize-block commit >consensus-round = proposer / non-proposer >``` -* For every round, if the local process is the proposer of the current round, CometBFT calls `PrepareProposal`, followed by `ProcessProposal`. -These two always come together because they reflect the same proposal that the process -also delivers to itself. +* For every round, if the local process is the proposer of the current round, CometBFT calls `PrepareProposal`. + A successful execution of `PrepareProposal` implies in a proposal block being (i)signed and (ii)stored + (e.g., in stable storage). + + A crash during this step will direct how the node proceeds the next time it is executed, for the same round, after restarted. + If it crashed before (i), then, during the recovery, `PrepareProposal` will execute as if for the first time. + Following a crash between (i) and (ii) and in (the likely) case `PrepareProposal` produces a different block, + the signing of this block will fail, which means that the new block will not be stored or broadcast. + If the crash happened after (ii), then signing fails but nothing happens to the stored block. + + If a block was stored, it is sent to all validators, including the proposer. + Receiving a proposal block triggers `ProcessProposal` with such a block. Then, optionally, the Application is asked to extend its vote for that round. Calls to `VerifyVoteExtension` can come at any time: the @@ -165,7 +182,7 @@ also delivers to itself. of this height. >```abnf ->proposer = *got-vote [prepare-proposal process-proposal] [extend] +>proposer = *got-vote [prepare-proposal [process-proposal]] [extend] >extend = *got-vote extend-vote *got-vote >``` @@ -180,7 +197,7 @@ also delivers to itself. >non-proposer = *got-vote [process-proposal] [extend] >``` -* Finally, the grammar describes all its terminal symbols, which denote the different ABCI++ method calls that +* Finally, the grammar describes all its terminal symbols, which denote the different ABCI method calls that may appear in a sequence. >```abnf @@ -192,16 +209,16 @@ also delivers to itself. >process-proposal = %s"" >extend-vote = %s"" >got-vote = %s"" ->decide = %s"" +>finalize-block = %s"" >commit = %s"" >``` -## Adapting existing Applications that use ABCI +## Adapting existing Applications that use legacy ABCI -In some cases, an existing Application using the legacy ABCI may need to be adapted to work with ABCI++ -with as minimal changes as possible. In this case, of course, ABCI++ will not provide any advantage with respect -to the existing implementation, but will keep the same guarantees already provided by ABCI. -Here is how ABCI++ methods should be implemented. +In some cases, an existing Application using the legacy ABCI may need to be adapted to work with new version of ABCI +with as minimal changes as possible. In this case, of course, new ABCI versions will not provide any advantage with respect +to the legacy ABCI implementation, but will keep the same guarantees. +Here is how ABCI methods should be implemented. First of all, all the methods that did not change from ABCI 0.17.0 to ABCI 2.0, namely `Echo`, `Flush`, `Info`, `InitChain`, `Query`, `CheckTx`, `ListSnapshots`, `LoadSnapshotChunk`, `OfferSnapshot`, and `ApplySnapshotChunk`, do not need @@ -209,60 +226,62 @@ to undergo any changes in their implementation. As for the new methods: +Introduced in ABCI 1.0: + * `PrepareProposal` must create a list of [transactions](./abci++_methods.md#prepareproposal) - by copying over the transaction list passed in `RequestPrepareProposal.txs`, in the same order. - + by copying over the transaction list passed in `PrepareProposalRequest.txs`, in the same order. The Application must check whether the size of all transactions exceeds the byte limit - (`RequestPrepareProposal.max_tx_bytes`). If so, the Application must remove transactions at the + (`PrepareProposalRequest.max_tx_bytes`). If so, the Application must remove transactions at the end of the list until the total byte size is at or below the limit. -* `ProcessProposal` must set `ResponseProcessProposal.status` to _accept_ and return. -* `ExtendVote` is to set `ResponseExtendVote.extension` to an empty byte array and return. -* `VerifyVoteExtension` must set `ResponseVerifyVoteExtension.accept` to _true_ if the extension is +* `ProcessProposal` must set `ProcessProposalResponse.status` to _accept_ and return. + +Introduced in ABCI 2.0: + +* `ExtendVote` is to set `ExtendVoteResponse.extension` to an empty byte array and return. +* `VerifyVoteExtension` must set `VerifyVoteExtensionResponse.accept` to _true_ if the extension is an empty byte array and _false_ otherwise, then return. * `FinalizeBlock` is to coalesce the implementation of methods `BeginBlock`, `DeliverTx`, and `EndBlock`. Legacy applications looking to reuse old code that implemented `DeliverTx` should wrap the legacy `DeliverTx` logic in a loop that executes one transaction iteration per - transaction in `RequestFinalizeBlock.tx`. + transaction in `FinalizeBlockRequest.tx`. -Finally, `Commit`, which is kept in ABCI++, no longer returns the `AppHash`. It is now up to +Finally, `Commit`, which is kept in ABCI 2.0, no longer returns the `AppHash`. It is now up to `FinalizeBlock` to do so. Thus, a slight refactoring of the old `Commit` implementation will be needed to move the return of `AppHash` to `FinalizeBlock`. -## Accomodating for vote extensions +## Accommodating for vote extensions In a manner transparent to the application, CometBFT ensures the node is provided with all -the data it needs to participate in consensus. +the data it needs to participate in consensus. In the case of recovering from a crash, or joining the network via state sync, CometBFT will make -sure the node acquires the necessary vote extensions before switching to consensus. +sure the node acquires the necessary vote extensions before switching to consensus. -If a node is already in consensus but falls behind, during catch-up, CometBFT will provide the node with +If a node is already in consensus but falls behind, during catch-up, CometBFT will provide the node with vote extensions from past heights by retrieving the extensions within `ExtendedCommit` for old heights that it had previously stored. -We realize this is sub-optimal due to the increase in storage needed to store the extensions, we are +We realize this is sub-optimal due to the increase in storage needed to store the extensions, we are working on an optimization of this implementation which should alleviate this concern. However, the application can use the existing `retain_height` parameter to decide how much history it wants to keep, just as is done with the block history. The network-wide implications of the usage of `retain_height` stay the same. -The decision to store -historical commits and potential optimizations, are discussed in detail in [RFC-100](./../../docs/rfc/rfc-100-abci-vote-extension-propag.md#current-limitations-and-possible-implementations) +The decision to store +historical commits and potential optimizations, are discussed in detail in [RFC-100](../../docs/references/rfc/rfc-100-abci-vote-extension-propag.md#current-limitations-and-possible-implementations) -## Handling upgrades to ABCI 2.0 +## Handling upgrades to ABCI 2.0 -If applications upgrade to ABCI 2.0, CometBFT internally ensures that the [application setup](./abci%2B%2B_app_requirements.md#application-configuration-required-to-switch-to-abci-20) is reflected in its operation. -CometBFT retrieves from the application configuration the value of `VoteExtensionsEnableHeight`( *he*,), -the height at which vote extensions are required for consensus to proceed, and uses it to determine the data it stores and data it sends to a peer -that is catching up. +If applications upgrade to ABCI 2.0, CometBFT internally ensures that the [application setup](./abci%2B%2B_app_requirements.md#application-configuration-required-to-switch-to-abci-20) is reflected in its operation. +CometBFT retrieves from the application configuration the value of `VoteExtensionsEnableHeight`( _he_,), +the height at which vote extensions are required for consensus to proceed, and uses it to determine the data it stores and data it sends to a peer that is catching up. -Namely, upon saving the block for a given height *h* in the block store at decision time -- if *h ≥ he*, the corresponding extended commit that was used to decide locally is saved as well -- if *h < he*, there are no changes to the data saved +Namely, upon saving the block for a given height _h_ in the block store at decision time -In the catch-up mechanism, when a node *f* realizes that another peer is at height *hp*, which is more than 2 heights behind, -- if *hp ≥ he*, *f* uses the extended commit to - reconstruct the precommit votes with their corresponding extensions -- if *hp < he*, *f* uses the canonical commit to reconstruct the precommit votes, - as done for ABCI 1.0 and earlier. - +* if _h ≥ he_, the corresponding extended commit that was used to decide locally is saved as well +* if _h < he_, there are no changes to the data saved +In the catch-up mechanism, when a node _f_ realizes that another peer is at height _hp_, which is more than 2 heights behind height _hf_, +* if _hp ≥ he_, _f_ uses the extended commit to + reconstruct the precommit votes with their corresponding extensions +* if _hp < he_, _f_ uses the canonical commit to reconstruct the precommit votes, + as done for ABCI 1.0 and earlier. diff --git a/spec/abci/abci++_example_scenarios.md b/spec/abci/abci++_example_scenarios.md index 93fb6a7a6f7..c92431cc20a 100644 --- a/spec/abci/abci++_example_scenarios.md +++ b/spec/abci/abci++_example_scenarios.md @@ -1,52 +1,55 @@ --- order: 6 -title: ABCI++ extra +title: ABCI extra --- # Introduction -In the section [CometBFT's expected behaviour](./abci++_comet_expected_behavior.md#valid-method-call-sequences), -we presented the most common behaviour, usually referred to as the good case. -However, the grammar specified in the same section is more general and covers more scenarios -that an Application designer needs to account for. +In the section [CometBFT's expected behaviour](./abci++_comet_expected_behavior.md#valid-method-call-sequences), +we presented the most common behaviour, usually referred to as the good case. +However, the grammar specified in the same section is more general and covers more scenarios +that an Application designer needs to account for. -In this section, we give more information about these possible scenarios. We focus on methods -introduced by ABCI++: `PrepareProposal` and `ProcessProposal`. Specifically, we concentrate -on the part of the grammar presented below. +In this section, we give more information about these possible scenarios. We focus on methods +introduced by ABCI 1.0: `PrepareProposal` and `ProcessProposal`. Specifically, we concentrate +on the part of the grammar presented below. ```abnf -consensus-height = *consensus-round decide commit +consensus-height = *consensus-round finalize-block commit consensus-round = proposer / non-proposer proposer = [prepare-proposal process-proposal] non-proposer = [process-proposal] ``` -We can see from the grammar that we can have several rounds before deciding a block. The reasons +We can see from the grammar that we can have several rounds before deciding a block. The reasons why one round may not be enough are: + * network asynchrony, and -* a Byzantine process being the proposer. +* a Byzantine process being the proposer. -If we assume that the consensus algorithm decides on block $X$ in round $r$, in the rounds +If we assume that the consensus algorithm decides on block $X$ in round $r$, in the rounds $r' <= r$, CometBFT can exhibit any of the following behaviours: -1. Call `PrepareProposal` and/or `ProcessProposal` for block $X$. +1. Call `PrepareProposal` and/or `ProcessProposal` for block $X$. 1. Call `PrepareProposal` and/or `ProcessProposal` for block $Y \neq X$. 1. Does not call `PrepareProposal` and/or `ProcessProposal`. -In the rounds when it is the proposer, CometBFT's `PrepareProposal` call is always followed by the -`ProcessProposal` call. The reason is that the process always delivers the proposal to itself, which -triggers the `ProcessProposal` call. +In the rounds in which the process is the proposer, CometBFT's `PrepareProposal` call is always followed by the +`ProcessProposal` call. The reason is that the process also broadcasts the proposal to itself, which is locally delivered and triggers the `ProcessProposal` call. +The proposal processed by `ProcessProposal` is the same as what was returned by any of the preceding `PrepareProposal` invoked for the same height and round. +While in the absence of restarts there is only one such preceding invocations, if the proposer restarts there could have been one extra invocation to `PrepareProposal` for each restart. -As the number of rounds the consensus algorithm needs to decide in a given run is a priori unknown, the -application needs to account for any number of rounds, where each round can exhibit any of these three -behaviours. Recall that the application is unaware of the internals of consensus and thus of the rounds. +As the number of rounds the consensus algorithm needs to decide in a given run is a priori unknown, the +application needs to account for any number of rounds, where each round can exhibit any of these three +behaviours. Recall that the application is unaware of the internals of consensus and thus of the rounds. # Possible scenarios -The unknown number of rounds we can have when following the consensus algorithm yields a vast number of -scenarios we can expect. Listing them all is unfeasible. However, here we give several of them and draw the + +The unknown number of rounds we can have when following the consensus algorithm yields a vast number of +scenarios we can expect. Listing them all is unfeasible. However, here we give several of them and draw the main conclusions. Specifically, we will show that before block $X$ is decided: - -1. On a correct node, `PrepareProposal` may be called multiple times and for different blocks ([**Scenario 1**](#scenario-1)). + +1. On a correct node, `PrepareProposal` may be called multiple times and for different blocks ([**Scenario 1**](#scenario-1)). 1. On a correct node, `ProcessProposal` may be called multiple times and for different blocks ([**Scenario 2**](#scenario-2)). 1. On a correct node, `PrepareProposal` and `ProcessProposal` for block $X$ may not be called ([**Scenario 3**](#scenario-3)). 1. On a correct node, `PrepareProposal` and `ProcessProposal` may not be called at all ([**Scenario 4**](#scenario-4)). @@ -54,12 +57,12 @@ main conclusions. Specifically, we will show that before block $X$ is decided: ## Basic information -Each scenario is presented from the perspective of a process $p$. More precisely, we show what happens in -each round's $step$ of the [Tendermint consensus algorithm](https://arxiv.org/pdf/1807.04938.pdf). While in -practice the consensus algorithm works with respect to voting power of the validators, in this document -we refer to number of processes (e.g., $n$, $f+1$, $2f+1$) for simplicity. The legend is below: +Each scenario is presented from the perspective of a process $p$. More precisely, we show what happens in +each round's $step$ of the [Tendermint consensus algorithm](https://arxiv.org/pdf/1807.04938.pdf). While in +practice the consensus algorithm works with respect to voting power of the validators, in this document +we refer to number of processes (e.g., $n$, $f+1$, $2f+1$) for simplicity. The legend is below: -### Round X: +### Round X 1. **Propose:** Describes what happens while $step_p = propose$. 1. **Prevote:** Describes what happens while $step_p = prevote$. @@ -69,93 +72,93 @@ we refer to number of processes (e.g., $n$, $f+1$, $2f+1$) for simplicity. The l $p$ calls `ProcessProposal` many times with different values. -### Round 0: - -1. **Propose:** The proposer of this round is a Byzantine process, and it chooses not to send the proposal -message. Therefore, $p$'s $timeoutPropose$ expires, it sends $Prevote$ for $nil$, and it does not call -`ProcessProposal`. All correct processes do the same. -1. **Prevote:** $p$ eventually receives $2f+1$ $Prevote$ messages for $nil$ and starts $timeoutPrevote$. -When $timeoutPrevote$ expires it sends $Precommit$ for $nil$. -1. **Precommit:** $p$ eventually receives $2f+1$ $Precommit$ messages for $nil$ and starts $timeoutPrecommit$. -When it expires, it moves to the next round. - -### Round 1: - -1. **Propose:** A correct process is the proposer in this round. Its $validValue$ is $nil$, and it is free -to generate and propose a new block $Y$. Process $p$ receives this proposal in time, calls `ProcessProposal` -for block $Y$, and broadcasts a $Prevote$ message for it. -1. **Prevote:** Due to network asynchrony less than $2f+1$ processes send $Prevote$ for this block. -Therefore, $p$ does not update $validValue$ in this round. -1. **Precommit:** Since less than $2f+1$ processes send $Prevote$, no correct process will lock on this -block and send $Precommit$ message. As a consequence, $p$ does not decide on $Y$. - -### Round 2: - -1. **Propose:** Same as in [**Round 1**](#round-1), just another correct process is the proposer, and it -proposes another value $Z$. Process $p$ receives the proposal on time, calls `ProcessProposal` for new block -$Z$, and broadcasts a $Prevote$ message for it. +### Round 0 + +1. **Propose:** The proposer of this round is a Byzantine process, and it chooses not to send the proposal +message. Therefore, $p$'s $timeoutPropose$ expires, it sends $Prevote$ for $nil$, and it does not call +`ProcessProposal`. All correct processes do the same. +1. **Prevote:** $p$ eventually receives $2f+1$ $Prevote$ messages for $nil$ and starts $timeoutPrevote$. +When $timeoutPrevote$ expires it sends $Precommit$ for $nil$. +1. **Precommit:** $p$ eventually receives $2f+1$ $Precommit$ messages for $nil$ and starts $timeoutPrecommit$. +When it expires, it moves to the next round. + +### Round 1 + +1. **Propose:** A correct process is the proposer in this round. Its $validValue$ is $nil$, and it is free +to generate and propose a new block $Y$. Process $p$ receives this proposal in time, calls `ProcessProposal` +for block $Y$, and broadcasts a $Prevote$ message for it. +1. **Prevote:** Due to network asynchrony less than $2f+1$ processes send $Prevote$ for this block. +Therefore, $p$ does not update $validValue$ in this round. +1. **Precommit:** Since less than $2f+1$ processes send $Prevote$, no correct process will lock on this +block and send $Precommit$ message. As a consequence, $p$ does not decide on $Y$. + +### Round 2 + +1. **Propose:** Same as in [**Round 1**](#round-1), just another correct process is the proposer, and it +proposes another value $Z$. Process $p$ receives the proposal on time, calls `ProcessProposal` for new block +$Z$, and broadcasts a $Prevote$ message for it. 1. **Prevote:** Same as in [**Round 1**](#round-1). 1. **Precommit:** Same as in [**Round 1**](#round-1). -Rounds like these can continue until we have a round in which process $p$ updates its $validValue$ or until -we reach round $r$ where process $p$ decides on a block. After that, it will not call `ProcessProposal` -anymore for this height. +Rounds like these can continue until we have a round in which process $p$ updates its $validValue$ or until +we reach round $r$ where process $p$ decides on a block. After that, it will not call `ProcessProposal` +anymore for this height. -## Scenario 2 +## Scenario 2 $p$ calls `PrepareProposal` many times with different values. -### Round 0: +### Round 0 -1. **Propose:** Process $p$ is the proposer in this round. Its $validValue$ is $nil$, and it is free to -generate and propose new block $Y$. Before proposing, it calls `PrepareProposal` for $Y$. After that, it -broadcasts the proposal, delivers it to itself, calls `ProcessProposal` and broadcasts $Prevote$ for it. -1. **Prevote:** Due to network asynchrony less than $2f+1$ processes receive the proposal on time and send -$Prevote$ for it. Therefore, $p$ does not update $validValue$ in this round. -1. **Precommit:** Since less than $2f+1$ processes send $Prevote$, no correct process will lock on this -block and send non-$nil$ $Precommit$ message. As a consequence, $p$ does not decide on $Y$. +1. **Propose:** Process $p$ is the proposer in this round. Its $validValue$ is $nil$, and it is free to +generate and propose new block $Y$. Before proposing, it calls `PrepareProposal` for $Y$. After that, it +broadcasts the proposal, delivers it to itself, calls `ProcessProposal` and broadcasts $Prevote$ for it. +1. **Prevote:** Due to network asynchrony less than $2f+1$ processes receive the proposal on time and send +$Prevote$ for it. Therefore, $p$ does not update $validValue$ in this round. +1. **Precommit:** Since less than $2f+1$ processes send $Prevote$, no correct process will lock on this +block and send non-$nil$ $Precommit$ message. As a consequence, $p$ does not decide on $Y$. -After this round, we can have multiple rounds like those in [Scenario 1](#scenario-1). The important thing -is that process $p$ should not update its $validValue$. Consequently, when process $p$ reaches the round -when it is again the proposer, it will ask the mempool for the new block again, and the mempool may return a -different block $Z$, and we can have the same round as [Round 0](#round-0-1) just for a different block. As -a result, process $p$ calls `PrepareProposal` again but for a different value. When it reaches round $r$ -some process will propose block $X$ and if $p$ receives $2f+1$ $Precommit$ messages, it will decide on this -value. +After this round, we can have multiple rounds like those in [Scenario 1](#scenario-1). The important thing +is that process $p$ should not update its $validValue$. Consequently, when process $p$ reaches the round +when it is again the proposer, it will ask the mempool for the new block again, and the mempool may return a +different block $Z$, and we can have the same round as [Round 0](#round-0-1) just for a different block. As +a result, process $p$ calls `PrepareProposal` again but for a different value. When it reaches round $r$ +some process will propose block $X$ and if $p$ receives $2f+1$ $Precommit$ messages, it will decide on this +value. -## Scenario 3 +## Scenario 3 -$p$ calls `PrepareProposal` and `ProcessProposal` for many values, but decides on a value for which it did +$p$ calls `PrepareProposal` and `ProcessProposal` for many values, but decides on a value for which it did not call `PrepareProposal` or `ProcessProposal`. -In this scenario, in all rounds before $r$ we can have any round presented in [Scenario 1](#scenario-1) or +In this scenario, in all rounds before $r$ we can have any round presented in [Scenario 1](#scenario-1) or [Scenario 2](#scenario-2). What is important is that: -- no proposer proposed block $X$ or if it did, process $p$, due to asynchrony, did not receive it in time, + +* no proposer proposed block $X$ or if it did, process $p$, due to asynchrony, did not receive it in time, so it did not call `ProcessProposal`, and -- if $p$ was the proposer it proposed some other value $\neq X$. +* if $p$ was the proposer it proposed some other value $\neq X$. -### Round $r$: +### Round $r$ -1. **Propose:** A correct process is the proposer in this round, and it proposes block $X$. +1. **Propose:** A correct process is the proposer in this round, and it proposes block $X$. Due to asynchrony, the proposal message arrives to process $p$ after its $timeoutPropose$ expires and it sends $Prevote$ for $nil$. Consequently, process $p$ does not call `ProcessProposal` for block $X$. However, the same proposal arrives at other processes before their $timeoutPropose$ expires, and they send $Prevote$ for this proposal. -1. **Prevote:** Process $p$ receives $2f+1$ $Prevote$ messages for proposal $X$, updates correspondingly its -$validValue$ and $lockedValue$ and sends $Precommit$ message. All correct processes do the same. -1. **Precommit:** Finally, process $p$ receives $2f+1$ $Precommit$ messages, and decides on block $X$. +1. **Prevote:** Process $p$ receives $2f+1$ $Prevote$ messages for proposal $X$, updates correspondingly its +$validValue$ and $lockedValue$ and sends $Precommit$ message. All correct processes do the same. +1. **Precommit:** Finally, process $p$ receives $2f+1$ $Precommit$ messages, and decides on block $X$. ## Scenario 4 -[Scenario 3](#scenario-3) can be translated into a scenario where $p$ does not call `PrepareProposal` and -`ProcessProposal` at all. For this, it is necessary that process $p$ is not the proposer in any of the -rounds $0 <= r' <= r$ and that due to network asynchrony or Byzantine proposer, it does not receive the -proposal before $timeoutPropose$ expires. As a result, it will enter round $r$ without calling -`PrepareProposal` and `ProcessProposal` before it, and as shown in Round $r$ of [Scenario 3](#scenario-3) it -will decide in this round. Again without calling any of these two calls. - +[Scenario 3](#scenario-3) can be translated into a scenario where $p$ does not call `PrepareProposal` and +`ProcessProposal` at all. For this, it is necessary that process $p$ is not the proposer in any of the +rounds $0 <= r' <= r$ and that due to network asynchrony or Byzantine proposer, it does not receive the +proposal before $timeoutPropose$ expires. As a result, it will enter round $r$ without calling +`PrepareProposal` and `ProcessProposal` before it, and as shown in Round $r$ of [Scenario 3](#scenario-3) it +will decide in this round. Again without calling any of these two calls. diff --git a/spec/abci/abci++_methods.md b/spec/abci/abci++_methods.md index a50f04653c0..297e4d0db69 100644 --- a/spec/abci/abci++_methods.md +++ b/spec/abci/abci++_methods.md @@ -14,7 +14,7 @@ title: Methods * **Response**: * `Message (string)`: The input string * **Usage**: - * Echo a string to test an abci client/server implementation + * Echo a string to test an ABCI client/server implementation ### Flush @@ -29,8 +29,8 @@ title: Methods * **Request**: - | Name | Type | Description | Field Number | - |---------------|--------|------------------------------------------|--------------| + | Name | Type | Description | Field Number | + |---------------|--------|----------------------------------------|--------------| | version | string | The CometBFT software semantic version | 1 | | block_version | uint64 | The CometBFT Block Protocol version | 2 | | p2p_version | uint64 | The CometBFT P2P Protocol version | 3 | @@ -38,13 +38,13 @@ title: Methods * **Response**: - | Name | Type | Description | Field Number | - |---------------------|--------|-----------------------------------------------------|--------------| - | data | string | Some arbitrary information | 1 | - | version | string | The application software semantic version | 2 | - | app_version | uint64 | The application protocol version | 3 | - | last_block_height | int64 | Latest height for which the app persisted its state | 4 | - | last_block_app_hash | bytes | Latest AppHash returned by `Commit` | 5 | + | Name | Type | Description | Field Number | Deterministic | + |---------------------|--------|-----------------------------------------------------|--------------|---------------| + | data | string | Some arbitrary information | 1 | N/A | + | version | string | The application software semantic version | 2 | N/A | + | app_version | uint64 | The application protocol version | 3 | N/A | + | last_block_height | int64 | Latest height for which the app persisted its state | 4 | N/A | + | last_block_app_hash | bytes | Latest AppHash returned by `FinalizeBlock` | 5 | N/A | * **Usage**: * Return information about the application state. @@ -71,48 +71,48 @@ title: Methods * **Response**: - | Name | Type | Description | Field Number | - |------------------|----------------------------------------------|--------------------------------------------------|--------------| - | consensus_params | [ConsensusParams](#consensusparams) | Initial consensus-critical parameters (optional) | 1 | - | validators | repeated [ValidatorUpdate](#validatorupdate) | Initial validator set (optional). | 2 | - | app_hash | bytes | Initial application hash. | 3 | + | Name | Type | Description | Field Number | Deterministic | + |------------------|----------------------------------------------|--------------------------------------------------|--------------|---------------| + | consensus_params | [ConsensusParams](#consensusparams) | Initial consensus-critical parameters (optional) | 1 | Yes | + | validators | repeated [ValidatorUpdate](#validatorupdate) | Initial validator set (optional). | 2 | Yes | + | app_hash | bytes | Initial application hash. | 3 | Yes | * **Usage**: * Called once upon genesis. - * If `ResponseInitChain.Validators` is empty, the initial validator set will be the `RequestInitChain.Validators` - * If `ResponseInitChain.Validators` is not empty, it will be the initial - validator set (regardless of what is in `RequestInitChain.Validators`). + * If `InitChainResponse.Validators` is empty, the initial validator set will be the `InitChainRequest.Validators` + * If `InitChainResponse.Validators` is not empty, it will be the initial + validator set (regardless of what is in `InitChainRequest.Validators`). * This allows the app to decide if it wants to accept the initial validator set proposed by CometBFT (ie. in the genesis file), or if it wants to use a different one (perhaps computed based on some application specific information in the genesis file). - * Both `RequestInitChain.Validators` and `ResponseInitChain.Validators` are [ValidatorUpdate](#validatorupdate) structs. + * Both `InitChainRequest.Validators` and `InitChainResponse.Validators` are [ValidatorUpdate](#validatorupdate) structs. So, technically, they both are _updating_ the set of validators from the empty set. ### Query * **Request**: - | Name | Type | Description | Field Number | - |--------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| - | data | bytes | Raw query bytes. Can be used with or in lieu of Path. | 1 | - | path | string | Path field of the request URI. Can be used with or in lieu of `data`. Apps MUST interpret `/store` as a query by key on the underlying store. The key SHOULD be specified in the `data` field. Apps SHOULD allow queries over specific types like `/accounts/...` or `/votes/...` | 2 | - | height | int64 | The block height for which you want the query (default=0 returns data for the latest committed block). Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 | 3 | - | prove | bool | Return Merkle proof with response if possible | 4 | + | Name | Type | Description | Field Number | + |--------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| + | data | bytes | Request parameters for the application to interpret analogously to a [URI query component](https://www.rfc-editor.org/rfc/rfc3986#section-3.4). Can be used with or in lieu of `path`. | 1 | + | path | string | A request path for the application to interpret analogously to a [URI path component](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) in e.g. routing. Can be used with or in lieu of `data`. Applications MUST interpret "/store" or any path starting with "/store/" as a query by key on the underlying store, in which case a key SHOULD be specified in `data`. Applications SHOULD allow queries over specific types like `/accounts/...` or `/votes/...`. | 2 | + | height | int64 | The block height against which to query (default=0 returns data for the latest committed block). Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1. | 3 | + | prove | bool | Return Merkle proof with response if possible. | 4 | * **Response**: - | Name | Type | Description | Field Number | - |-----------|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| - | code | uint32 | Response code. | 1 | - | log | string | The output of the application's logger. **May be non-deterministic.** | 3 | - | info | string | Additional information. **May be non-deterministic.** | 4 | - | index | int64 | The index of the key in the tree. | 5 | - | key | bytes | The key of the matching data. | 6 | - | value | bytes | The value of the matching data. | 7 | - | proof_ops | [ProofOps](#proofops) | Serialized proof for the value data, if requested, to be verified against the `app_hash` for the given Height. | 8 | - | height | int64 | The block height from which data was derived. Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 | 9 | - | codespace | string | Namespace for the `code`. | 10 | + | Name | Type | Description | Field Number | Deterministic | + |-----------|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|---------------| + | code | uint32 | Response code. | 1 | N/A | + | log | string | The output of the application's logger. | 3 | N/A | + | info | string | Additional information. | 4 | N/A | + | index | int64 | The index of the key in the tree. | 5 | N/A | + | key | bytes | The key of the matching data. | 6 | N/A | + | value | bytes | The value of the matching data. | 7 | N/A | + | proof_ops | [ProofOps](#proofops) | Serialized proof for the value data, if requested, to be verified against the `app_hash` for the given Height. | 8 | N/A | + | height | int64 | The block height from which data was derived. Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 | 9 | N/A | + | codespace | string | Namespace for the `code`. | 10 | N/A | * **Usage**: * Query for data from the application at current or past height. @@ -124,21 +124,23 @@ title: Methods * **Request**: - | Name | Type | Description | Field Number | - |------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| - | tx | bytes | The request transaction bytes | 1 | - | type | CheckTxType | One of `CheckTx_New` or `CheckTx_Recheck`. `CheckTx_New` is the default and means that a full check of the tranasaction is required. `CheckTx_Recheck` types are used when the mempool is initiating a normal recheck of a transaction. | 2 | + | Name | Type | Description | Field Number | + |------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| + | tx | bytes | The request transaction bytes | 1 | + | type | CheckTxType | One of `CheckTx_New` or `CheckTx_Recheck`. `CheckTx_New` is the default and means that a full check of the tranasaction is required. `CheckTx_Recheck` types are used when the mempool is initiating a normal recheck of a transaction. | 2 | * **Response**: - | Name | Type | Description | Field Number | - |------------|-------------------------------------------------------------|-----------------------------------------------------------------------|--------------| - | code | uint32 | Response code. | 1 | - | data | bytes | Result bytes, if any. | 2 | - | gas_wanted | int64 | Amount of gas requested for transaction. | 5 | - | codespace | string | Namespace for the `code`. | 8 | - | sender | string | The transaction's sender (e.g. the signer) | 9 | - | priority | int64 | The transaction's priority (for mempool ordering) | 10 | + | Name | Type | Description | Field Number | Deterministic | + |------------|---------------------------------------------------|----------------------------------------------------------------------|--------------|---------------| + | code | uint32 | Response code. | 1 | N/A | + | data | bytes | Result bytes, if any. | 2 | N/A | + | log | string | The output of the application's logger. | 3 | N/A | + | info | string | Additional information. | 4 | N/A | + | gas_wanted | int64 | Amount of gas requested for transaction. | 5 | N/A | + | gas_used | int64 | Amount of gas consumed by transaction. | 6 | N/A | + | events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing transactions (e.g. by account). | 7 | N/A | + | codespace | string | Namespace for the `code`. | 8 | N/A | * **Usage**: @@ -149,7 +151,7 @@ title: Methods * `CheckTx` validates the transaction against the current state of the application, for example, checking signatures and account balances, but does not apply any of the state changes described in the transaction. - * Transactions where `ResponseCheckTx.Code != 0` will be rejected - they will not be broadcast + * Transactions where `CheckTxResponse.Code != 0` will be rejected - they will not be broadcast to other nodes or included in a proposal block. CometBFT attributes no other value to the response code. @@ -159,22 +161,19 @@ title: Methods * **Request**: - | Name | Type | Description | Field Number | - |--------|-------|------------------------------------|--------------| - Commit signals the application to persist application state. It takes no parameters. * **Response**: - | Name | Type | Description | Field Number | - |---------------|-------|------------------------------------------------------------------------|--------------| - | retain_height | int64 | Blocks below this height may be removed. Defaults to `0` (retain all). | 3 | + | Name | Type | Description | Field Number | Deterministic | + |---------------|-------|------------------------------------------------------------------------|--------------|---------------| + | retain_height | int64 | Blocks below this height may be removed. Defaults to `0` (retain all). | 3 | No | * **Usage**: * Signal the Application to persist the application state. - Application is expected to persist its state at the end of this call, before calling `ResponseCommit`. - * Use `ResponseCommit.retain_height` with caution! If all nodes in the network remove historical + Application is expected to persist its state at the end of this call, before calling `Commit`. + * Use `CommitResponse.retain_height` with caution! If all nodes in the network remove historical blocks then this data is permanently lost, and no new nodes will be able to join the network and bootstrap, unless state sync is enabled on the chain. Historical blocks may also be required for other purposes, e.g. auditing, replay of non-persisted heights, light client verification, and so on. @@ -183,16 +182,13 @@ title: Methods * **Request**: - | Name | Type | Description | Field Number | - |--------|-------|------------------------------------|--------------| - Empty request asking the application for a list of snapshots. * **Response**: - | Name | Type | Description | Field Number | - |-----------|--------------------------------|--------------------------------|--------------| - | snapshots | repeated [Snapshot](#snapshot) | List of local state snapshots. | 1 | + | Name | Type | Description | Field Number | Deterministic | + |-----------|--------------------------------|--------------------------------|--------------|---------------| + | snapshots | repeated [Snapshot](#snapshot) | List of local state snapshots. | 1 | N/A | * **Usage**: * Used during state sync to discover available snapshots on peers. @@ -210,9 +206,9 @@ title: Methods * **Response**: - | Name | Type | Description | Field Number | - |-------|-------|--------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| - | chunk | bytes | The binary chunk contents, in an arbitrary format. Chunk messages cannot be larger than 16 MB _including metadata_, so 10 MB is a good starting point. | 1 | + | Name | Type | Description | Field Number | Deterministic | + |-------|-------|--------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|---------------| + | chunk | bytes | The binary chunk contents, in an arbitrary format. Chunk messages cannot be larger than 16 MB _including metadata_, so 10 MB is a good starting point. | 1 | N/A | * **Usage**: * Used during state sync to retrieve snapshot chunks from peers. @@ -228,9 +224,9 @@ title: Methods * **Response**: - | Name | Type | Description | Field Number | - |--------|-------------------|-----------------------------------|--------------| - | result | [Result](#result) | The result of the snapshot offer. | 1 | + | Name | Type | Description | Field Number | Deterministic | + |--------|-------------------|-----------------------------------|--------------|---------------| + | result | [Result](#result) | The result of the snapshot offer. | 1 | N/A | #### Result @@ -255,25 +251,25 @@ title: Methods can be spoofed by adversaries, so applications should employ additional verification schemes to avoid denial-of-service attacks. The verified `AppHash` is automatically checked against the restored application at the end of snapshot restoration. - * For more information, see the `Snapshot` data type or the [state sync section](../p2p/messages/state-sync.md). + * For more information, see the `Snapshot` data type or the [state sync section](../p2p/legacy-docs/messages/state-sync.md). ### ApplySnapshotChunk * **Request**: - | Name | Type | Description | Field Number | - |--------|--------|-----------------------------------------------------------------------------|--------------| + | Name | Type | Description | Field Number | + |--------|--------|---------------------------------------------------------------------------|--------------| | index | uint32 | The chunk index, starting from `0`. CometBFT applies chunks sequentially. | 1 | - | chunk | bytes | The binary chunk contents, as returned by `LoadSnapshotChunk`. | 2 | - | sender | string | The P2P ID of the node who sent this chunk. | 3 | + | chunk | bytes | The binary chunk contents, as returned by `LoadSnapshotChunk`. | 2 | + | sender | string | The P2P ID of the node who sent this chunk. | 3 | * **Response**: - | Name | Type | Description | Field Number | - |----------------|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| - | result | Result (see below) | The result of applying this chunk. | 1 | - | refetch_chunks | repeated uint32 | Refetch and reapply the given chunks, regardless of `result`. Only the listed chunks will be refetched, and reapplied in sequential order. | 2 | - | reject_senders | repeated string | Reject the given P2P senders, regardless of `Result`. Any chunks already applied will not be refetched unless explicitly requested, but queued chunks from these senders will be discarded, and new chunks or other snapshots rejected. | 3 | + | Name | Type | Description | Field Number | Deterministic | + |----------------|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|---------------| + | result | Result (see below) | The result of applying this chunk. | 1 | N/A | + | refetch_chunks | repeated uint32 | Refetch and reapply the given chunks, regardless of `result`. Only the listed chunks will be refetched, and reapplied in sequential order. | 2 | N/A | + | reject_senders | repeated string | Reject the given P2P senders, regardless of `Result`. Any chunks already applied will not be refetched unless explicitly requested, but queued chunks from these senders will be discarded, and new chunks or other snapshots rejected. | 3 | N/A | ```proto enum Result { @@ -299,7 +295,7 @@ title: Methods peers are available), it will reject the snapshot and try a different one via `OfferSnapshot`. The application should be prepared to reset and accept it or abort as appropriate. -## New methods introduced in ABCI++ +## New methods introduced in ABCI 2.0 ### PrepareProposal @@ -311,7 +307,7 @@ title: Methods |----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------|--------------| | max_tx_bytes | int64 | Currently configured maximum size in bytes taken by the modified transactions. | 1 | | txs | repeated bytes | Preliminary list of transactions that have been picked as part of the block to propose. | 2 | - | local_last_commit | [ExtendedCommitInfo](#extendedcommitinfo) | Info about the last commit, obtained locally from CometBFT's data structures. | 3 | + | local_last_commit | [ExtendedCommitInfo](#extendedcommitinfo) | Info about the last commit, obtained locally from CometBFT's data structures. | 3 | | misbehavior | repeated [Misbehavior](#misbehavior) | List of information about validators that misbehaved. | 4 | | height | int64 | The height of the block that will be proposed. | 5 | | time | [google.protobuf.Timestamp][protobuf-timestamp] | Timestamp of the block that that will be proposed. | 6 | @@ -320,28 +316,29 @@ title: Methods * **Response**: - | Name | Type | Description | Field Number | - |-------------------------|--------------------------------------------------|---------------------------------------------------------------------------------------------|--------------| - | txs | repeated bytes | Possibly modified list of transactions that have been picked as part of the proposed block. | 2 | + | Name | Type | Description | Field Number | Deterministic | + |------|----------------|---------------------------------------------------------------------------------------------|--------------|---------------| + | txs | repeated bytes | Possibly modified list of transactions that have been picked as part of the proposed block. | 2 | No | * **Usage**: - * `RequestPrepareProposal`'s parameters `txs`, `misbehavior`, `height`, `time`, - `next_validators_hash`, and `proposer_address` are the same as in `RequestProcessProposal` - and `RequestFinalizeBlock`. - * `RequestPrepareProposal.local_last_commit` is a set of the precommit votes that allowed the - decision of the previous block, together with their corresponding vote extensions. + * `PrepareProposalRequest`'s fields `txs`, `misbehavior`, `height`, `time`, + `next_validators_hash`, and `proposer_address` are the same as in `ProcessProposalRequest` + and `FinalizeBlockRequest`. + * `PrepareProposalRequest.local_last_commit` is a set of the precommit votes for the previous + height, including the ones that led to the decision of the previous block, + together with their corresponding vote extensions. * The `height`, `time`, and `proposer_address` values match the values from the header of the proposed block. - * `RequestPrepareProposal` contains a preliminary set of transactions `txs` that CometBFT + * `PrepareProposalRequest` contains a preliminary set of transactions `txs` that CometBFT retrieved from the mempool, called _raw proposal_. The Application can modify this - set and return a modified set of transactions via `ResponsePrepareProposal.txs` . + set and return a modified set of transactions via `PrepareProposalResponse.txs` . * The Application _can_ modify the raw proposal: it can reorder, remove or add transactions. - Let `tx` be a transaction in `txs` (set of transactions within `RequestPrepareProposal`): + Let `tx` be a transaction in `txs` (set of transactions within `PrepareProposalRequest`): * If the Application considers that `tx` should not be proposed in this block, e.g., there are other transactions with higher priority, then it should not include it in - `ResponsePrepareProposal.txs`. However, this will not remove `tx` from the mempool. + `PrepareProposalResponse.txs`. However, this will not remove `tx` from the mempool. * If the Application wants to add a new transaction to the proposed block, then the - Application includes it in `ResponsePrepareProposal.txs`. CometBFT will not add + Application includes it in `PrepareProposalResponse.txs`. CometBFT will not add the transaction to the mempool. * The Application should be aware that removing and adding transactions may compromise _traceability_. @@ -355,57 +352,58 @@ title: Methods traceability, it is its responsibility's to support it. For instance, the Application could attach to a transformed transaction a list with the hashes of the transactions it derives from. - * CometBFT MAY include a list of transactions in `RequestPrepareProposal.txs` whose total - size in bytes exceeds `RequestPrepareProposal.max_tx_bytes`. - Therefore, if the size of `RequestPrepareProposal.txs` is greater than - `RequestPrepareProposal.max_tx_bytes`, the Application MUST remove transactions to ensure - that the `RequestPrepareProposal.max_tx_bytes` limit is respected by those transactions - returned in `ResponsePrepareProposal.txs` . + * The Application MAY configure CometBFT to include a list of transactions in `PrepareProposalRequest.txs` + whose total size in bytes exceeds `PrepareProposalRequest.max_tx_bytes`. + If the Application sets `ConsensusParams.Block.MaxBytes` to -1, CometBFT + will include _all_ transactions currently in the mempool in `PrepareProposalRequest.txs`, + which may not fit in `PrepareProposalRequest.max_tx_bytes`. + Therefore, if the size of `PrepareProposalRequest.txs` is greater than + `PrepareProposalRequest.max_tx_bytes`, the Application MUST remove transactions to ensure + that the `PrepareProposalRequest.max_tx_bytes` limit is respected by those transactions + returned in `PrepareProposalResponse.txs`. + This is specified in [Requirement 2](./abci%2B%2B_app_requirements.md). * As a result of executing the prepared proposal, the Application may produce block events or transaction events. The Application must keep those events until a block is decided and then pass them on to CometBFT via - `ResponseFinalizeBlock`. + `FinalizeBlockResponse`. * CometBFT does NOT provide any additional validity checks (such as checking for duplicate transactions). - - * If CometBFT fails to validate the `ResponsePrepareProposal`, CometBFT will assume the + * If CometBFT fails to validate the `PrepareProposalResponse`, CometBFT will assume the Application is faulty and crash. - * The implementation of `PrepareProposal` can be non-deterministic. + * The implementation of `PrepareProposal` MAY be non-deterministic. #### When does CometBFT call "PrepareProposal" ? - When a validator _p_ enters consensus round _r_, height _h_, in which _p_ is the proposer, and _p_'s _validValue_ is `nil`: 1. CometBFT collects outstanding transactions from _p_'s mempool * the transactions will be collected in order of priority * _p_'s CometBFT creates a block header. -2. _p_'s CometBFT calls `RequestPrepareProposal` with the newly generated block, the local +2. _p_'s CometBFT calls `PrepareProposal` with the newly generated block, the local commit of the previous height (with vote extensions), and any outstanding evidence of misbehavior. The call is synchronous: CometBFT's execution will block until the Application returns from the call. 3. The Application uses the information received (transactions, commit info, misbehavior, time) to (potentially) modify the proposal. - * the Application MAY fully execute the block and produce a candidate state — immediate - execution + * the Application MAY fully execute the block and produce a candidate state (immediate execution) * the Application can manipulate transactions: * leave transactions untouched * add new transactions (not present initially) to the proposal * remove transactions from the proposal (but not from the mempool thus effectively _delaying_ them) - the - Application does not include the transaction in `ResponsePrepareProposal.txs`. + Application does not include the transaction in `PrepareProposalResponse.txs`. * modify transactions (e.g. aggregate them). As explained above, this compromises client traceability, unless it is implemented at the Application level. * reorder transactions - the Application reorders transactions in the list + * the Application MAY use the vote extensions in the commit info to modify the proposal, in which case it is suggested + that extensions be validated in the same maner as done in `VerifyVoteExtension`, since extensions of votes included + in the commit info after the minimum of +2/3 had been reached are not verified. 4. The Application includes the transaction list (whether modified or not) in the return parameters (see the rules in section _Usage_), and returns from the call. 5. _p_ uses the (possibly) modified block as _p_'s proposal in round _r_, height _h_. Note that, if _p_ has a non-`nil` _validValue_ in round _r_, height _h_, -the consensus algorithm will use it as proposal and will not call `RequestPrepareProposal`. +the consensus algorithm will use it as proposal and will not call `PrepareProposal`. ### ProcessProposal @@ -426,29 +424,31 @@ the consensus algorithm will use it as proposal and will not call `RequestPrepar * **Response**: - | Name | Type | Description | Field Number | - |-------------------------|--------------------------------------------------|-----------------------------------------------------------------------------------|--------------| - | status | [ProposalStatus](#proposalstatus) | `enum` that signals if the application finds the proposal valid. | 1 | + | Name | Type | Description | Field Number | Deterministic | + |--------|-----------------------------------|------------------------------------------------------------------|--------------|---------------| + | status | [ProposalStatus](#proposalstatus) | `enum` that signals if the application finds the proposal valid. | 1 | Yes | * **Usage**: * Contains all information on the proposed block needed to fully execute it. * The Application may fully execute the block as though it was handling - `RequestFinalizeBlock`. + `FinalizeBlock`. * However, any resulting state changes must be kept as _candidate state_, and the Application should be ready to discard it in case another block is decided. - * `RequestProcessProposal` is also called at the proposer of a round. The reason for this is to - inform the Application of the block header's hash, which cannot be done at `PrepareProposal` - time. In this case, the call to `RequestProcessProposal` occurs right after the call to - `RequestPrepareProposal`. + * `ProcessProposal` is also called at the proposer of a round. + Normally the call to `ProcessProposal` occurs right after the call to `PrepareProposal` and + `ProcessProposalRequest` matches the block produced based on `PrepareProposalResponse` (i.e., + `PrepareProposalRequest.txs` equals `ProcessProposalRequest.txs`). + However, no such guarantee is made since, in the presence of failures, `ProcessProposalRequest` may match + `PrepareProposalResponse` from an earlier invocation or `ProcessProposal` may not be invoked at all. * The height and time values match the values from the header of the proposed block. - * If `ResponseProcessProposal.status` is `REJECT`, consensus assumes the proposal received + * If `ProcessProposalResponse.status` is `REJECT`, consensus assumes the proposal received is not valid. - * The Application MAY fully execute the block — immediate execution + * The Application MAY fully execute the block (immediate execution) * The implementation of `ProcessProposal` MUST be deterministic. Moreover, the value of - `ResponseProcessProposal.status` MUST **exclusively** depend on the parameters passed in - the call to `RequestProcessProposal`, and the last committed Application state + `ProcessProposalResponse.status` MUST **exclusively** depend on the parameters passed in + the `ProcessProposalRequest`, and the last committed Application state (see [Requirements](./abci++_app_requirements.md) section). - * Moreover, application implementors SHOULD always set `ResponseProcessProposal.status` to `ACCEPT`, + * Moreover, application implementers SHOULD always set `ProcessProposalResponse.status` to `ACCEPT`, unless they _really_ know what the potential liveness implications of returning `REJECT` are. #### When does CometBFT call "ProcessProposal" ? @@ -456,17 +456,17 @@ the consensus algorithm will use it as proposal and will not call `RequestPrepar When a node _p_ enters consensus round _r_, height _h_, in which _q_ is the proposer (possibly _p_ = _q_): 1. _p_ sets up timer `ProposeTimeout`. -2. If _p_ is the proposer, _p_ executes steps 1-6 in [PrepareProposal](#prepareproposal). +2. If _p_ is the proposer, _p_ executes steps 1-5 in [PrepareProposal](#prepareproposal). 3. Upon reception of Proposal message (which contains the header) for round _r_, height _h_ from _q_, _p_ verifies the block header. 4. Upon reception of Proposal message, along with all the block parts, for round _r_, height _h_ from _q_, _p_ follows the validators' algorithm to check whether it should prevote for the proposed block, or `nil`. 5. If the validators' consensus algorithm indicates _p_ should prevote non-nil: - 1. CometBFT calls `RequestProcessProposal` with the block. The call is synchronous. + 1. CometBFT calls `ProcessProposal` with the block. The call is synchronous. 2. The Application checks/processes the proposed block, which is read-only, and returns - `ACCEPT` or `REJECT` in the `ResponseProcessProposal.status` field. - * The Application, depending on its needs, may call `ResponseProcessProposal` + `ACCEPT` or `REJECT` in the `ProcessProposalResponse.status` field. + * The Application, depending on its needs, may call `ProcessProposal` * either after it has completely processed the block (immediate execution), * or after doing some basic checks, and process the block asynchronously. In this case the Application will not be able to reject the block, or force prevote/precommit `nil` @@ -476,7 +476,6 @@ When a node _p_ enters consensus round _r_, height _h_, in which _q_ is the prop 3. If _p_ is a validator and the returned value is * `ACCEPT`: _p_ prevotes on this proposal for round _r_, height _h_. * `REJECT`: _p_ prevotes `nil`. - * ### ExtendVote @@ -484,25 +483,31 @@ When a node _p_ enters consensus round _r_, height _h_, in which _q_ is the prop * **Request**: - | Name | Type | Description | Field Number | - |--------|-------|-------------------------------------------------------------------------------|--------------| - | hash | bytes | The header hash of the proposed block that the vote extension is to refer to. | 1 | - | height | int64 | Height of the proposed block (for sanity check). | 2 | + | Name | Type | Description | Field Number | + |----------------------|-------------------------------------------------|-------------------------------------------------------------------------------------------|--------------| + | hash | bytes | The header hash of the proposed block that the vote extension is to refer to. | 1 | + | height | int64 | Height of the proposed block (for sanity check). | 2 | + | time | [google.protobuf.Timestamp][protobuf-timestamp] | Timestamp of the proposed block (that the extension is to refer to). | 3 | + | txs | repeated bytes | List of transactions of the block that the extension is to refer to. | 4 | + | proposed_last_commit | [CommitInfo](#commitinfo) | Info about the last proposed block's last commit. | 5 | + | misbehavior | repeated [Misbehavior](#misbehavior) | List of information about validators that misbehaved contained in the proposed block. | 6 | + | next_validators_hash | bytes | Merkle root of the next validator set contained in the proposed block. | 7 | + | proposer_address | bytes | [Address](../core/data_structures.md#address) of the validator that created the proposal. | 8 | * **Response**: - | Name | Type | Description | Field Number | - |-------------------|-------|---------------------------------------------------------|--------------| - | vote_extension | bytes | Information signed by by CometBFT. Can have 0 length. | 1 | + | Name | Type | Description | Field Number | Deterministic | + |----------------|-------|-------------------------------------------------------|--------------|---------------| + | vote_extension | bytes | Information signed by by CometBFT. Can have 0 length. | 1 | No | * **Usage**: - * `ResponseExtendVote.vote_extension` is application-generated information that will be signed + * `ExtendVoteResponse.vote_extension` is application-generated information that will be signed by CometBFT and attached to the Precommit message. * The Application may choose to use an empty vote extension (0 length). - * `RequestExtendVote.hash` corresponds to the hash of a proposed block that was made available - to the Application in a previous call to `ProcessProposal` for the current height. - * `ResponseExtendVote.vote_extension` will only be attached to a non-`nil` Precommit message. If the consensus algorithm is to - precommit `nil`, it will not call `RequestExtendVote`. + * The contents of `ExtendVoteRequest` correspond to the proposed block on which the consensus algorithm + will send the Precommit message. + * `ExtendVoteResponse.vote_extension` will only be attached to a non-`nil` Precommit message. If the consensus algorithm is to + precommit `nil`, it will not call `ExtendVote`. * The Application logic that creates the extension can be non-deterministic. #### When does CometBFT call `ExtendVote`? @@ -515,9 +520,9 @@ When a validator _p_ is in consensus state _prevote_ of round _r_, height _h_, i then _p_ locks _v_ and sends a Precommit message in the following way 1. _p_ sets _lockedValue_ and _validValue_ to _v_, and sets _lockedRound_ and _validRound_ to _r_ -2. _p_'s CometBFT calls `RequestExtendVote` with _id(v)_ (`RequestExtendVote.hash`). The call is synchronous. -3. The Application returns an array of bytes, `ResponseExtendVote.extension`, which is not interpreted by the consensus algorithm. -4. _p_ sets `ResponseExtendVote.extension` as the value of the `extension` field of type +2. _p_'s CometBFT calls `ExtendVote` with _v_ (in `ExtendVoteRequest`). The call is synchronous. +3. The Application returns an array of bytes, `ExtendVoteResponse.extension`, which is not interpreted by the consensus algorithm. +4. _p_ sets `ExtendVoteResponse.extension` as the value of the `extension` field of type [CanonicalVoteExtension](../core/data_structures.md#canonicalvoteextension), populates the other fields in [CanonicalVoteExtension](../core/data_structures.md#canonicalvoteextension), and signs the populated data structure. @@ -528,7 +533,7 @@ then _p_ locks _v_ and sends a Precommit message in the following way 7. _p_ broadcasts the Precommit message. In the cases when _p_ is to broadcast `precommit nil` messages (either _2f+1_ `prevote nil` messages received, -or _timeoutPrevote_ triggered), _p_'s CometBFT does **not** call `RequestExtendVote` and will not include +or _timeoutPrevote_ triggered), _p_'s CometBFT does **not** call `ExtendVote` and will not include a [CanonicalVoteExtension](../core/data_structures.md#canonicalvoteextension) field in the `precommit nil` message. ### VerifyVoteExtension @@ -542,30 +547,30 @@ a [CanonicalVoteExtension](../core/data_structures.md#canonicalvoteextension) fi | hash | bytes | The hash of the proposed block that the vote extension refers to. | 1 | | validator_address | bytes | [Address](../core/data_structures.md#address) of the validator that signed the extension. | 2 | | height | int64 | Height of the block (for sanity check). | 3 | - | vote_extension | bytes | Application-specific information signed by CometBFT. Can have 0 length. | 4 | + | vote_extension | bytes | Application-specific information signed by CometBFT. Can have 0 length. | 4 | * **Response**: - | Name | Type | Description | Field Number | - |--------|-------------------------------|----------------------------------------------------------------|--------------| - | status | [VerifyStatus](#verifystatus) | `enum` signaling if the application accepts the vote extension | 1 | + | Name | Type | Description | Field Number | Deterministic | + |--------|-------------------------------|----------------------------------------------------------------|--------------|---------------| + | status | [VerifyStatus](#verifystatus) | `enum` signaling if the application accepts the vote extension | 1 | Yes | * **Usage**: - * `RequestVerifyVoteExtension.vote_extension` can be an empty byte array. The Application's + * `VerifyVoteExtensionRequest.vote_extension` can be an empty byte array. The Application's interpretation of it should be that the Application running at the process that sent the vote chose not to extend it. - CometBFT will always call `RequestVerifyVoteExtension`, even for 0 length vote extensions. - * `RequestVerifyVoteExtension` is not called for precommit votes sent by the local process. - * `RequestVerifyVoteExtension.hash` refers to a proposed block. There is not guarantee that + CometBFT will always call `VerifyVoteExtension`, even for 0 length vote extensions. + * `VerifyVoteExtension` is not called for precommit votes sent by the local process. + * `VerifyVoteExtensionRequest.hash` refers to a proposed block. There is no guarantee that this proposed block has previously been exposed to the Application via `ProcessProposal`. - * If `ResponseVerifyVoteExtension.status` is `REJECT`, the consensus algorithm will reject the whole received vote. + * If `VerifyVoteExtensionResponse.status` is `REJECT`, the consensus algorithm will reject the whole received vote. See the [Requirements](./abci++_app_requirements.md) section to understand the potential liveness implications of this. * The implementation of `VerifyVoteExtension` MUST be deterministic. Moreover, the value of - `ResponseVerifyVoteExtension.status` MUST **exclusively** depend on the parameters passed in - the call to `RequestVerifyVoteExtension`, and the last committed Application state + `VerifyVoteExtensionResponse.status` MUST **exclusively** depend on the parameters passed in + the `VerifyVoteExtensionRequest`, and the last committed Application state (see [Requirements](./abci++_app_requirements.md) section). - * Moreover, application implementers SHOULD always set `ResponseVerifyVoteExtension.status` to `ACCEPT`, + * Moreover, application implementers SHOULD always set `VerifyVoteExtensionResponse.status` to `ACCEPT`, unless they _really_ know what the potential liveness implications of returning `REJECT` are. #### When does CometBFT call `VerifyVoteExtension`? @@ -576,14 +581,20 @@ message for round _r_, height _h_ from validator _q_ (_q_ ≠ _p_): 1. If the Precommit message does not contain a vote extension with a valid signature, _p_ discards the Precommit message as invalid. * a 0-length vote extension is valid as long as its accompanying signature is also valid. -2. Else, _p_'s CometBFT calls `RequestVerifyVoteExtension`. -3. The Application returns `ACCEPT` or `REJECT` via `ResponseVerifyVoteExtension.status`. +2. Else, _p_'s CometBFT calls `VerifyVoteExtension`. +3. The Application returns `ACCEPT` or `REJECT` via `VerifyVoteExtensionResponse.status`. 4. If the Application returns * `ACCEPT`, _p_ will keep the received vote, together with its corresponding vote extension in its internal data structures. It will be used to populate the [ExtendedCommitInfo](#extendedcommitinfo) - structure in calls to `RequestPrepareProposal`, in rounds of height _h + 1_ where _p_ is the proposer. + structure in calls to `PrepareProposal`, in rounds of height _h + 1_ where _p_ is the proposer. * `REJECT`, _p_ will deem the Precommit message invalid and discard it. +When a node _p_ is in consensus round _0_, height _h_, and _p_ receives a Precommit +message for CommitRound _r_, height _h-1_ from validator _q_ (_q_ ≠ _p_), _p_ +MAY add the Precommit message and associated extension to [ExtendedCommitInfo](#extendedcommitinfo) +without calling `VerifyVoteExtension` to verify it. + + ### FinalizeBlock #### Parameters and Types @@ -603,53 +614,53 @@ message for round _r_, height _h_ from validator _q_ (_q_ ≠ _p_): * **Response**: - | Name | Type | Description | Field Number | - |-------------------------|-------------------------------------------------------------|----------------------------------------------------------------------------------|--------------| - | events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing | 1 | - | tx_results | repeated [ExecTxResult](#exectxresult) | List of structures containing the data resulting from executing the transactions | 2 | - | validator_updates | repeated [ValidatorUpdate](#validatorupdate) | Changes to validator set (set voting power to 0 to remove). | 3 | - | consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to gas, size, and other consensus-related parameters. | 4 | - | app_hash | bytes | The Merkle root hash of the application state. | 5 | + | Name | Type | Description | Field Number | Deterministic | + |-------------------------|---------------------------------------------------|----------------------------------------------------------------------------------|--------------|---------------| + | events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing | 1 | No | + | tx_results | repeated [ExecTxResult](#exectxresult) | List of structures containing the data resulting from executing the transactions | 2 | Yes | + | validator_updates | repeated [ValidatorUpdate](#validatorupdate) | Changes to validator set (set voting power to 0 to remove). | 3 | Yes | + | consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to gas, size, and other consensus-related parameters. | 4 | Yes | + | app_hash | bytes | The Merkle root hash of the application state. | 5 | Yes | * **Usage**: * Contains the fields of the newly decided block. * This method is equivalent to the call sequence `BeginBlock`, [`DeliverTx`], and `EndBlock` in the previous version of ABCI. * The height and time values match the values from the header of the proposed block. - * The Application can use `RequestFinalizeBlock.decided_last_commit` and `RequestFinalizeBlock.misbehavior` + * The Application can use `FinalizeBlockRequest.decided_last_commit` and `FinalizeBlockRequest.misbehavior` to determine rewards and punishments for the validators. - * The Application executes the transactions in `RequestFinalizeBlock.txs` deterministically, + * The Application executes the transactions in `FinalizeBlockRequest.txs` deterministically, according to the rules set up by the Application, before returning control to CometBFT. Alternatively, it can apply the candidate state corresponding to the same block previously executed via `PrepareProposal` or `ProcessProposal`. - * `ResponseFinalizeBlock.tx_results[i].Code == 0` only if the _i_-th transaction is fully valid. - * The Application must provide values for `ResponseFinalizeBlock.app_hash`, - `ResponseFinalizeBlock.tx_results`, `ResponseFinalizeBlock.validator_updates`, and - `ResponseFinalizeBlock.consensus_param_updates` as a result of executing the block. - * The values for `ResponseFinalizeBlock.validator_updates`, or - `ResponseFinalizeBlock.consensus_param_updates` may be empty. In this case, CometBFT will keep + * `FinalizeBlockResponse.tx_results[i].Code == 0` only if the _i_-th transaction is fully valid. + * The Application must provide values for `FinalizeBlockResponse.app_hash`, + `FinalizeBlockResponse.tx_results`, `FinalizeBlockResponse.validator_updates`, and + `FinalizeBlockResponse.consensus_param_updates` as a result of executing the block. + * The values for `FinalizeBlockResponse.validator_updates`, or + `FinalizeBlockResponse.consensus_param_updates` may be empty. In this case, CometBFT will keep the current values. - * `ResponseFinalizeBlock.validator_updates`, triggered by block `H`, affect validation + * `FinalizeBlockResponse.validator_updates`, triggered by block `H`, affect validation for blocks `H+1`, `H+2`, and `H+3`. Heights following a validator update are affected in the following way: * Height `H+1`: `NextValidatorsHash` includes the new `validator_updates` value. * Height `H+2`: The validator set change takes effect and `ValidatorsHash` is updated. * Height `H+3`: `*_last_commit` fields in `PrepareProposal`, `ProcessProposal`, and `FinalizeBlock` now include the altered validator set. - * `ResponseFinalizeBlock.consensus_param_updates` returned for block `H` apply to the consensus + * `FinalizeBlockResponse.consensus_param_updates` returned for block `H` apply to the consensus params for block `H+1`. For more information on the consensus parameters, see the [consensus parameters](./abci%2B%2B_app_requirements.md#consensus-parameters) section. - * `ResponseFinalizeBlock.app_hash` contains an (optional) Merkle root hash of the application state. - * `ResponseFinalizeBlock.app_hash` is included as the `Header.AppHash` in the next block. - * `ResponseFinalizeBlock.app_hash` may also be empty or hard-coded, but MUST be + * `FinalizeBlockResponse.app_hash` contains an (optional) Merkle root hash of the application state. + * `FinalizeBlockResponse.app_hash` is included as the `Header.AppHash` in the next block. + * `FinalizeBlockResponse.app_hash` may also be empty or hard-coded, but MUST be **deterministic** - it must not be a function of anything that did not come from the parameters - of `RequestFinalizeBlock` and the previous committed state. + of `FinalizeBlockRequest` and the previous committed state. * Later calls to `Query` can return proofs about the application state anchored in this Merkle root hash. * The implementation of `FinalizeBlock` MUST be deterministic, since it is making the Application's state evolve in the context of state machine replication. - * Currently, CometBFT will fill up all fields in `RequestFinalizeBlock`, even if they were - already passed on to the Application via `RequestPrepareProposal` or `RequestProcessProposal`. + * Currently, CometBFT will fill up all fields in `FinalizeBlockRequest`, even if they were + already passed on to the Application via `PrepareProposalRequest` or `ProcessProposalRequest`. #### When does CometBFT call `FinalizeBlock`? @@ -663,20 +674,20 @@ When a node _p_ is in consensus height _h_, and _p_ receives then _p_ decides block _v_ and finalizes consensus for height _h_ in the following way 1. _p_ persists _v_ as the decision for height _h_. -2. _p_'s CometBFT calls `RequestFinalizeBlock` with _v_'s data. The call is synchronous. +2. _p_'s CometBFT calls `FinalizeBlock` with _v_'s data. The call is synchronous. 3. _p_'s Application executes block _v_. 4. _p_'s Application calculates and returns the _AppHash_, along with a list containing the outputs of each of the transactions executed. 5. _p_'s CometBFT hashes all the transaction outputs and stores it in _ResultHash_. 6. _p_'s CometBFT persists the transaction outputs, _AppHash_, and _ResultsHash_. 7. _p_'s CometBFT locks the mempool — no calls to `CheckTx` on new transactions. -8. _p_'s CometBFT calls `RequestCommit` to instruct the Application to persist its state. +8. _p_'s CometBFT calls `Commit` to instruct the Application to persist its state. 9. _p_'s CometBFT, optionally, re-checks all outstanding transactions in the mempool against the newly persisted Application state. 10. _p_'s CometBFT unlocks the mempool — newly received transactions can now be checked. 11. _p_ starts consensus for height _h+1_, round 0 -## Data Types existing in ABCI +## Data Types (exist before ABCI 2.0) Most of the data structures used in ABCI are shared [common data structures](../core/data_structures.md). In certain cases, ABCI uses different data structures which are documented here: @@ -684,14 +695,14 @@ Most of the data structures used in ABCI are shared [common data structures](../ * **Fields**: - | Name | Type | Description | Field Number | - |---------|-------|---------------------------------------------------------------------|--------------| - | address | bytes | [Address](../core/data_structures.md#address) of validator | 1 | - | power | int64 | Voting power of the validator | 3 | + | Name | Type | Description | Field Number | + |---------|-------|------------------------------------------------------------|--------------| + | address | bytes | [Address](../core/data_structures.md#address) of validator | 1 | + | power | int64 | Voting power of the validator | 3 | * **Usage**: * Validator identified by address - * Used as part of VoteInfo within `CommitInfo` (used in `ProcessProposal` and `FinalizeBlock`), + * Used as part of VoteInfo within `CommitInfo` (used in `ProcessProposal` and `FinalizeBlock`), and `ExtendedCommitInfo` (used in `PrepareProposal`). * Does not include PubKey to avoid sending potentially large quantum pubkeys over the ABCI @@ -700,10 +711,10 @@ Most of the data structures used in ABCI are shared [common data structures](../ * **Fields**: - | Name | Type | Description | Field Number | - |---------|--------------------------------------------------|-------------------------------|--------------| - | pub_key | [Public Key](../core/data_structures.md#pub_key) | Public key of the validator | 1 | - | power | int64 | Voting power of the validator | 2 | + | Name | Type | Description | Field Number | Deterministic | + |---------|--------------------------------------------------|-------------------------------|--------------|---------------| + | pub_key | [Public Key](../core/data_structures.md#pub_key) | Public key of the validator | 1 | Yes | + | power | int64 | Voting power of the validator | 2 | Yes | * **Usage**: * Validator identified by PubKey @@ -713,13 +724,13 @@ Most of the data structures used in ABCI are shared [common data structures](../ * **Fields**: - | Name | Type | Description | Field Number | - |--------------------|-------------------------------------------------|------------------------------------------------------------------------------|--------------| - | type | [MisbehaviorType](#misbehaviortype) | Type of the misbehavior. An enum of possible misbehaviors. | 1 | - | validator | [Validator](#validator) | The offending validator | 2 | - | height | int64 | Height when the offense occurred | 3 | - | time | [google.protobuf.Timestamp][protobuf-timestamp] | Timestamp of the block that was committed at height `height` | 4 | - | total_voting_power | int64 | Total voting power of the validator set at height `height` | 5 | + | Name | Type | Description | Field Number | + |--------------------|-------------------------------------------------|--------------------------------------------------------------|--------------| + | type | [MisbehaviorType](#misbehaviortype) | Type of the misbehavior. An enum of possible misbehaviors. | 1 | + | validator | [Validator](#validator) | The offending validator | 2 | + | height | int64 | Height when the offense occurred | 3 | + | time | [google.protobuf.Timestamp][protobuf-timestamp] | Timestamp of the block that was committed at height `height` | 4 | + | total_voting_power | int64 | Total voting power of the validator set at height `height` | 5 | #### MisbehaviorType @@ -737,59 +748,61 @@ Most of the data structures used in ABCI are shared [common data structures](../ * **Fields**: - | Name | Type | Description | Field Number | - |-----------|---------------------------------------------------------------|------------------------------------------------------------------------------|--------------| - | block | [BlockParams](../core/data_structures.md#blockparams) | Parameters limiting the size of a block and time between consecutive blocks. | 1 | - | evidence | [EvidenceParams](../core/data_structures.md#evidenceparams) | Parameters limiting the validity of evidence of byzantine behaviour. | 2 | - | validator | [ValidatorParams](../core/data_structures.md#validatorparams) | Parameters limiting the types of public keys validators can use. | 3 | - | version | [VersionsParams](../core/data_structures.md#versionparams) | The ABCI application version. | 4 | + | Name | Type | Description | Field Number | Deterministic | + | --------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------ | ------------- | + | block | [BlockParams](../core/data_structures.md#blockparams) | Parameters limiting the size of a block and time between consecutive blocks. | 1 | Yes | + | evidence | [EvidenceParams](../core/data_structures.md#evidenceparams) | Parameters limiting the validity of evidence of byzantine behaviour. | 2 | Yes | + | validator | [ValidatorParams](../core/data_structures.md#validatorparams) | Parameters limiting the types of public keys validators can use. | 3 | Yes | + | version | [VersionsParams](../core/data_structures.md#versionparams) | The ABCI application version. | 4 | Yes | + | abci | [ABCIParams](../core/data_structures.md#abciparams) | ABCI-related parameters. | 5 | Yes | + | synchrony | [SynchronyParams](../core/data_structures.md#synchronyparams) | Parameters determining the validity bounds of a proposal timestamp. | 6 | Yes | ### ProofOps * **Fields**: - | Name | Type | Description | Field Number | - |------|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| - | ops | repeated [ProofOp](#proofop) | List of chained Merkle proofs, of possibly different types. The Merkle root of one op is the value being proven in the next op. The Merkle root of the final op should equal the ultimate root hash being verified against.. | 1 | + | Name | Type | Description | Field Number | Deterministic | + |------|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|---------------| + | ops | repeated [ProofOp](#proofop) | List of chained Merkle proofs, of possibly different types. The Merkle root of one op is the value being proven in the next op. The Merkle root of the final op should equal the ultimate root hash being verified against.. | 1 | N/A | ### ProofOp * **Fields**: - | Name | Type | Description | Field Number | - |------|--------|------------------------------------------------|--------------| - | type | string | Type of Merkle proof and how it's encoded. | 1 | - | key | bytes | Key in the Merkle tree that this proof is for. | 2 | - | data | bytes | Encoded Merkle proof for the key. | 3 | + | Name | Type | Description | Field Number | Deterministic | + |------|--------|------------------------------------------------|--------------|---------------| + | type | string | Type of Merkle proof and how it's encoded. | 1 | N/A | + | key | bytes | Key in the Merkle tree that this proof is for. | 2 | N/A | + | data | bytes | Encoded Merkle proof for the key. | 3 | N/A | ### Snapshot * **Fields**: - | Name | Type | Description | Field Number | - |----------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| - | height | uint64 | The height at which the snapshot was taken (after commit). | 1 | - | format | uint32 | An application-specific snapshot format, allowing applications to version their snapshot data format and make backwards-incompatible changes. CometBFT does not interpret this. | 2 | - | chunks | uint32 | The number of chunks in the snapshot. Must be at least 1 (even if empty). | 3 | - | hash | bytes | An arbitrary snapshot hash. Must be equal only for identical snapshots across nodes. CometBFT does not interpret the hash, it only compares them. | 4 | - | metadata | bytes | Arbitrary application metadata, for example chunk hashes or other verification data. | 5 | + | Name | Type | Description | Field Number | Deterministic | + |----------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|---------------| + | height | uint64 | The height at which the snapshot was taken (after commit). | 1 | N/A | + | format | uint32 | An application-specific snapshot format, allowing applications to version their snapshot data format and make backwards-incompatible changes. CometBFT does not interpret this. | 2 | N/A | + | chunks | uint32 | The number of chunks in the snapshot. Must be at least 1 (even if empty). | 3 | N/A | + | hash | bytes | An arbitrary snapshot hash. Must be equal only for identical snapshots across nodes. CometBFT does not interpret the hash, it only compares them. | 4 | N/A | + | metadata | bytes | Arbitrary application metadata, for example chunk hashes or other verification data. | 5 | N/A | * **Usage**: - * Used for state sync snapshots, see the [state sync section](../p2p/messages/state-sync.md) for details. + * Used for state sync snapshots, see the [state sync section](../p2p/legacy-docs/messages/state-sync.md) for details. * A snapshot is considered identical across nodes only if _all_ fields are equal (including `Metadata`). Chunks may be retrieved from all nodes that have the same snapshot. * When sent across the network, a snapshot message can be at most 4 MB. -## Data types introduced or modified in ABCI++ +## Data types introduced or modified in ABCI 2.0 ### VoteInfo * **Fields**: - | Name | Type | Description | Field Number | - |-----------------------------|-------------------------|----------------------------------------------------------------|--------------| - | validator | [Validator](#validator) | The validator that sent the vote. | 1 | - | signed_last_block | bool | Indicates whether or not the validator signed the last block. | 2 | + | Name | Type | Description | Field Number | + |-------------------|-------------------------|---------------------------------------------------------------|--------------| + | validator | [Validator](#validator) | The validator that sent the vote. | 1 | + | signed_last_block | bool | Indicates whether or not the validator signed the last block. | 2 | * **Usage**: * Indicates whether a validator signed the last block, allowing for rewards based on validator availability. @@ -819,6 +832,12 @@ Most of the data structures used in ABCI are shared [common data structures](../ | round | int32 | Commit round. Reflects the round at which the block proposer decided in the previous height. | 1 | | votes | repeated [VoteInfo](#voteinfo) | List of validators' addresses in the last validator set with their voting information. | 2 | +* **Notes** + * The `VoteInfo` in `votes` are ordered by the voting power of the validators (descending order, highest to lowest voting power). + * CometBFT guarantees the `votes` ordering through its logic to update the validator set in which, in the end, the validators are sorted (descending) by their voting power. + * The ordering is also persisted when a validator set is saved in the store. + * The validator set is loaded from the store when building the `CommitInfo`, ensuring order is maintained from the persisted validator set. + ### ExtendedCommitInfo * **Fields**: @@ -828,20 +847,26 @@ Most of the data structures used in ABCI are shared [common data structures](../ | round | int32 | Commit round. Reflects the round at which the block proposer decided in the previous height. | 1 | | votes | repeated [ExtendedVoteInfo](#extendedvoteinfo) | List of validators' addresses in the last validator set with their voting information, including vote extensions. | 2 | +* **Notes** + * The `ExtendedVoteInfo` in `votes` are ordered by the voting power of the validators (descending order, highest to lowest voting power). + * CometBFT guarantees the `votes` ordering through its logic to update the validator set in which, in the end, the validators are sorted (descending) by their voting power. + * The ordering is also persisted when a validator set is saved in the store. + * The validator set is loaded from the store when building the `ExtendedCommitInfo`, ensuring order is maintained from the persisted validator set. + ### ExecTxResult * **Fields**: - | Name | Type | Description | Field Number | - |------------|-------------------------------------------------------------|-----------------------------------------------------------------------|--------------| - | code | uint32 | Response code. | 1 | - | data | bytes | Result bytes, if any. | 2 | - | log | string | The output of the application's logger. **May be non-deterministic.** | 3 | - | info | string | Additional information. **May be non-deterministic.** | 4 | - | gas_wanted | int64 | Amount of gas requested for transaction. | 5 | - | gas_used | int64 | Amount of gas consumed by transaction. | 6 | - | events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing transactions (e.g. by account). | 7 | - | codespace | string | Namespace for the `code`. | 8 | + | Name | Type | Description | Field Number | Deterministic | + |------------|---------------------------------------------------|----------------------------------------------------------------------|--------------|---------------| + | code | uint32 | Response code. | 1 | Yes | + | data | bytes | Result bytes, if any. | 2 | Yes | + | log | string | The output of the application's logger. | 3 | No | + | info | string | Additional information. | 4 | No | + | gas_wanted | int64 | Amount of gas requested for transaction. | 5 | Yes | + | gas_used | int64 | Amount of gas consumed by transaction. | 6 | Yes | + | events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing transactions (e.g. by account). | 7 | No | + | codespace | string | Namespace for the `code`. | 8 | Yes | ### ProposalStatus diff --git a/spec/consensus/bft-time.md b/spec/consensus/bft-time.md index 9312d9b390f..8b6bf1ef792 100644 --- a/spec/consensus/bft-time.md +++ b/spec/consensus/bft-time.md @@ -3,54 +3,124 @@ order: 2 --- # BFT Time -CometBFT provides a deterministic, Byzantine fault-tolerant, source of time. -Time in CometBFT is defined with the Time field of the block header. - -It satisfies the following properties: - -- Time Monotonicity: Time is monotonically increasing, i.e., given -a header H1 for height h1 and a header H2 for height `h2 = h1 + 1`, `H1.Time < H2.Time`. -- Time Validity: Given a set of Commit votes that forms the `block.LastCommit` field, a range of -valid values for the Time field of the block header is defined only by -Precommit messages (from the LastCommit field) sent by correct processes, i.e., -a faulty process cannot arbitrarily increase the Time value. - -In the context of CometBFT, time is of type int64 and denotes UNIX time in milliseconds, i.e., -corresponds to the number of milliseconds since January 1, 1970. -Before defining rules that need to be enforced by Tendermint, the consensus algorithm adopted in CometBFT, -so the properties above holds, we introduce the following definition: - -- median of a Commit is equal to the median of `Vote.Time` fields of the `Vote` messages, -where the value of `Vote.Time` is counted number of times proportional to the process voting power. As -the voting power is not uniform (one process one vote), a vote message is actually an aggregator of the same votes whose -number is equal to the voting power of the process that has casted the corresponding votes message. - -Let's consider the following example: - -- we have four processes p1, p2, p3 and p4, with the following voting power distribution (p1, 23), (p2, 27), (p3, 10) -and (p4, 10). The total voting power is 70 (`N = 3f+1`, where `N` is the total voting power, and `f` is the maximum voting -power of the faulty processes), so we assume that the faulty processes have at most 23 of voting power. -Furthermore, we have the following vote messages in some LastCommit field (we ignore all fields except Time field): - - (p1, 100), (p2, 98), (p3, 1000), (p4, 500). We assume that p3 and p4 are faulty processes. Let's assume that the - `block.LastCommit` message contains votes of processes p2, p3 and p4. Median is then chosen the following way: - the value 98 is counted 27 times, the value 1000 is counted 10 times and the value 500 is counted also 10 times. - So the median value will be the value 98. No matter what set of messages with at least `2f+1` voting power we - choose, the median value will always be between the values sent by correct processes. - -We ensure Time Monotonicity and Time Validity properties by the following rules: - -- let rs denotes `RoundState` (consensus internal state) of some process. Then -`rs.ProposalBlock.Header.Time == median(rs.LastCommit) && -rs.Proposal.Timestamp == rs.ProposalBlock.Header.Time`. - -- Furthermore, when creating the `vote` message, the following rules for determining `vote.Time` field should hold: - - - if `rs.LockedBlock` is defined then - `vote.Time = max(rs.LockedBlock.Timestamp + time.Millisecond, time.Now())`, where `time.Now()` - denotes local Unix time in milliseconds - - - else if `rs.Proposal` is defined then - `vote.Time = max(rs.Proposal.Timestamp + time.Millisecond,, time.Now())`, - - - otherwise, `vote.Time = time.Now())`. In this case vote is for `nil` so it is not taken into account for - the timestamp of the next block. +BFT Time is a Byzantine fault-tolerant algorithm for computing [block times](./time.md). + +> :warning: +> CometBFT `v1.x` introduced [Proposer-Based Timestamps (PBTS)][pbts-spec], +> intended to be a replacement for BFT Time. +> Users are strongly encouraged to adopt the PBTS algorithm in new chains, or +> when upgrading existing chains, as the BFT Time algorithm MAY be deprecated +> in a future version of CometBFT. + +## Overview + +BFT Time computes the `Time` of a block proposed in height `H` of consensus +from the `Timestamp` field of the `Precommit` messages broadcast by +validators in the commit `Round` of the previous height `H-1`. + +In order to commit a block, a node needs to receive `Precommit` messages for +the corresponding `BlockID` from validators whose cumulative voting power is +more than `2/3` of the total voting power. +The received `Precommit` messages should refer to the same round, the commit `Round`. +A set of `Precommit` messages with the properties above mentioned is a `Commit`. +A `Commit` set of height `H` is included in blocks proposed in height `H+1`. + +BFT Time computes the `Time` field of a block proposed in height `H` deterministically +from the `LastCommit` field of the block, which is a `Commit` set from +height `H-1`, using the `MedianTime` method defined as follows: + +- `MedianTime`: the weighted median of `Timestamp` fields of `Precommit` + messages forming a `Commit` set, with weights defined by the validators' voting powers. + The weighted median is produced by considering the value of each `Timestamp` + value a number of times proportional to the voting power of the corresponding validator. + +The median of a set of values is one of the values of the set, so the +`Time` of a proposed block is one of the `Timestamp` fields of the `Precommit` +messages included in the `LastCommit` set of that block. + +### Example + +Consider the following example: + +- We have four validators p1, p2, p3 and p4, with voting power + distribution: (p1, 23), (p2, 27), (p3, 10), (p4, 10). + The total voting power is 70, so we assume that the faulty validators have at + most 23 of voting power (since `N < 3F`, where `N` is the total voting + power and `F` is the maximum voting power of faulty validators). +- We have the following `Precommit` messages in some `Commit` field (notice that we + ignore all fields except the validator name and the `Timestamp` field): (p1, 100), (p2, 98), (p3, 1000), (p4, 500). + We assume that p3 and p4 are faulty validators, as they propose block times + far much higher (far in the future) than p1 and p2. +- Let's assume that the `block.LastCommit` field contains `Precommit`s of + validators p2, p3 and p4. +- The `MedianTime` is then chosen the following way: the value 98 (p2) is + counted 27 times, the value 1000 (p3) is counted 10 times and the value 500 +(p4) is counted also 10 times. The median value will be `98`. + +Notice that, no matter what set of `Precommit` messages with at least `2/3` of +the total voting power we choose, the `MedianTime` value will always be a +value among the `Timestamp` values produced by correct validators. +By correct here we assume non-malicious validators whose clocks are reasonably +accurated with to time. + +## Operation + +In order to implement BFT Time, validators need to set the `Timestamp` field of +`Precommit` messages they sign and broadcast, and block proposers need to +compute the block `Time` from the `LastCommit` set. + +### Vote Time + +When producing a `Precommit` message, a validator should set the `Timestamp` field as follows: + +1. Let `now` be the clock time of the validator. +2. If `LockedBlock` is defined, set `Timestamp = max(now, LockedBlock.Time + 1ms)`. +3. Else if `ProposalBlock` is defined, set `Timestamp = max(now, ProposalBlock.Time + 1ms)`. +4. Otherwise, set `Timestamp = now`. + +The `LockedBlock`, if set, is the block for which the validator is issuing a `Precommit`. +The `ProposalBlock` is the block proposed in that round; in favorable runs, it +matches the `LockedBlock`. + + +The validator in practice _proposes_ the `Time` for the next block when setting +the `Timestamp` of its `Precommit`. +The proposed `Time` is, by default, the validator's current clock time. +To ensure [Time Monotonicity](./time.md#properties), the `Time` of the next block should be +higher than the `Time` of the block to be committed in the current height. +So if `now` is smaller than `Time`, the validator proposes the `Time` of the block to be committed +plus a small delta, set to `1ms`. + +### Proposed Time + +The proposer of a round of consensus produces a block to be proposed. +The proposed block must include a `Commit` set from the commit round of the +previous height, as the block's `LastCommit` field. + +The `Time` for the proposed block is then set as `Block.Time = MedianTime(block.LastCommit)`. + +Since the block `Time` is produced in a deterministic way, every node that +receives the proposed block, can validate `Block.Time` using the same +procedure. Blocks with wrongly computed block times are rejected. + +## Properties + +BFT Time guarantees the two main [properties](./time.md#properties) for block times: + +- **Time Monotonicity**: the [production](#vote-time) of `Timestamp` fields for + `Precommit` messages at correct validators ensures that the `Time` proposed + for the next block is higher than the `Time` of the current block. + Since the `Time` of a block is retrieved from a `Precommit` + produced by a correct validator, monotonicity is guaranteed. + +- **Byzantine Fault Tolerance**: given a `Commit` set that forms the + `LastCommit` field, a range of [valid values](#proposed-time) for the `Time` field of the + block is defined only by `Precommit` messages produced by correct validators, + i.e., faulty validators cannot arbitrarily influence (increase or decrease) the + `Time` value. + +Notice that the guarantees rely on the fact that the voting power owned by +Byzantine validators is limited, more specifically, is less than 1/3 of the +total voting power, which is also a requirement for the consensus algorithm. + +[pbts-spec]: ./proposer-based-timestamp/README.md diff --git a/spec/consensus/consensus-paper/IEEEtran.bst b/spec/consensus/consensus-paper/IEEEtran.bst index 53fbc030aae..f4bd88dead1 100644 --- a/spec/consensus/consensus-paper/IEEEtran.bst +++ b/spec/consensus/consensus-paper/IEEEtran.bst @@ -635,7 +635,7 @@ numnames % item. % % "output" does check for the presence of a previous empty item and will -% remove an empty item rather than outputing it. +% remove an empty item rather than outputting it. % % "output.warn" is like "output", but will issue a warning if it detects % an empty item. diff --git a/spec/consensus/consensus-paper/IEEEtran.cls b/spec/consensus/consensus-paper/IEEEtran.cls index 9c967d555f0..56cb47f1a4e 100644 --- a/spec/consensus/consensus-paper/IEEEtran.cls +++ b/spec/consensus/consensus-paper/IEEEtran.cls @@ -125,7 +125,7 @@ % margins will be the same and the text will be horizontally centered. % For final submission to IEEE, authors should use US letter (8.5 X 11in) % paper. Note that authors should ensure that all post-processing -% (ps, pdf, etc.) uses the same paper specificiation as the .tex document. +% (ps, pdf, etc.) uses the same paper specification as the .tex document. % Problems here are by far the number one reason for incorrect margins. % IEEEtran will automatically set the default paper size under pdflatex % (without requiring a change to pdftex.cfg), so this issue is more @@ -268,7 +268,7 @@ \newtoks\@IEEEtrantmptoksA % we use \CLASSOPTIONpt so that we can ID the point size (even for 9pt docs) -% as well as LaTeX's \@ptsize to retain some compatability with some +% as well as LaTeX's \@ptsize to retain some compatibility with some % external packages \def\@ptsize{0} % LaTeX does not support 9pt, so we set \@ptsize to 0 - same as that of 10pt @@ -342,7 +342,7 @@ % default to US letter paper, 10pt, twocolumn, one sided, final, journal \ExecuteOptions{letterpaper,10pt,twocolumn,oneside,final,journal} -% overrride these defaults per user requests +% override these defaults per user requests \ProcessOptions @@ -2016,7 +2016,7 @@ Using a default centering column instead}% -% creates a vertical rule that extends from the bottom to the top a a cell +% creates a vertical rule that extends from the bottom to the top a cell % Provided in case other packages redefine \vline some other way. % usage: \IEEEeqnarrayvrule[rule thickness] % If no argument is provided, \arrayrulewidth will be used for the rule thickness. @@ -2359,7 +2359,7 @@ Using a default centering column instead}% \vrule width0pt height\dimen0 depth\dimen2\relax\fi} -% creates an invisible strut, useable even outside \IEEEeqnarray +% creates an invisible strut, usable even outside \IEEEeqnarray % if \IEEEvisiblestrutstrue, the strut will be visible and 0.2pt wide. % usage: \IEEEstrut[height][depth][font size commands] % default is \IEEEstrut[0.7\normalbaselineskip][0.3\normalbaselineskip][\relax] @@ -2469,7 +2469,7 @@ $$\@ignoretrue} \newif\if@IEEElastlinewassubequation% \@IEEElastlinewassubequationfalse -% IEEEeqnarray uses a modifed \\ instead of the plain \cr to +% IEEEeqnarray uses a modified \\ instead of the plain \cr to % end rows. This allows for things like \\*[vskip amount] % This "cr" macros are modified versions those for LaTeX2e's eqnarray % the {\ifnum0=`} braces must be kept away from the last column to avoid @@ -2504,7 +2504,7 @@ $$\@ignoretrue} \@IEEEappendtoksA{&}% \advance\@IEEEeqncolcnt by 1\relax% update the col count \repeat - % this number of &'s will take us the the isolation column + % this number of &'s will take us the isolation column \fi % execute the &'s \the\@IEEEtrantmptoksA% @@ -2639,7 +2639,7 @@ $$\@ignoretrue} -% IEEEeqnarraybox uses a modifed \\ instead of the plain \cr to +% IEEEeqnarraybox uses a modified \\ instead of the plain \cr to % end rows. This allows for things like \\[vskip amount] % This "cr" macros are modified versions those for LaTeX2e's eqnarray % For IEEEeqnarraybox, \\* is the same as \\ @@ -2728,7 +2728,7 @@ $$\@ignoretrue} \@IEEEgrabfirstoken#1\relax\relax\noindent % \@IEEEgrabfirstoken has the first token, the rest are discarded % n = number -% g = glue (any other char in catagory 12) +% g = glue (any other char in category 12) % c = letter % e = \end % u = undefined @@ -2878,7 +2878,7 @@ in the IEEEeqnarray column specifications.}% \toks0={##}% % make preamble advance col counter if this environment needs this \if@advanceIEEEeqncolcnt\@IEEEappendtoksA{\global\advance\@IEEEeqncolcnt by 1\relax}\fi -% insert the column defintion into the preamble, being careful not to expand +% insert the column definition into the preamble, being careful not to expand % the column definition \@IEEEappendtoksA{\tabskip=\@IEEEBPcurglue}% \@IEEEappendNOEXPANDtoksA{\begingroup\csname @IEEEeqnarraycolPRE}% @@ -3305,7 +3305,7 @@ between column types.}% \rule[-0.3\@IEEEtrantmpdimenA]{0pt}{\@IEEEtrantmpdimenA}} -% blocks to hold the authors' names and affilations. +% blocks to hold the authors' names and affiliations. % Makes formatting easy for conferences % % use real definitions in conference mode @@ -4289,8 +4289,8 @@ between column types.}% % floating point values \@IEEEtrantmpdimenB=0.005\@IEEEtrantmpdimenA% \multiply\@IEEEtrantmpdimenB by \@IEEEtrantmpcountA% -% \@IEEEPARstartfont is globaly set to the calculated font of the big letter -% We need to carry this out of the local calculation area to to create the +% \@IEEEPARstartfont is globally set to the calculated font of the big letter +% We need to carry this out of the local calculation area to create the % big letter. \global\font\@IEEEPARstartfont\@IEEEPARstartFONTNAME\space at \@IEEEtrantmpdimenB% % Now set \@IEEEtrantmpdimenA to the width of the big letter @@ -4381,7 +4381,7 @@ between column types.}% % if this page does not have enough space, break it and lets start % with a new one \@IEEEtranneedspace{\@IEEEtrantmpdimenA}{\relax}% -% nominal spacer can strech, not shrink use 1fil so user can out stretch with \vfill +% nominal spacer can stretch, not shrink use 1fil so user can out stretch with \vfill \vskip \@IEEEBIOskipN plus 1fil minus 0\baselineskip% % the default box for where the photo goes \def\@IEEEtempbiographybox{{\setlength{\fboxsep}{0pt}\framebox{% diff --git a/spec/consensus/consensus-paper/lit.bib b/spec/consensus/consensus-paper/lit.bib index 4abc83e70cb..9b9d52d59ba 100644 --- a/spec/consensus/consensus-paper/lit.bib +++ b/spec/consensus/consensus-paper/lit.bib @@ -345,7 +345,7 @@ @InProceedings{BCBT96:wdag month = {Oct}, volume = {1151}, ISBN = {3-540-61769-8}, - pubisher = {Springer}, + publisher = {Springer}, series = {Lecture Notes in Computer Science}, } diff --git a/spec/consensus/creating-proposal.md b/spec/consensus/creating-proposal.md index cb43c8ebb41..3280093a91b 100644 --- a/spec/consensus/creating-proposal.md +++ b/spec/consensus/creating-proposal.md @@ -4,40 +4,58 @@ order: 2 # Creating a proposal A block consists of a header, transactions, votes (the commit), -and a list of evidence of malfeasance (ie. signing conflicting votes). +and a list of evidence of malfeasance (eg. signing conflicting votes). -We include no more than 1/10th of the maximum block size -(`ConsensusParams.Block.MaxBytes`) of evidence with each block. +Outstanding evidence items get priority over outstanding transactions in the mempool. +All in all, the block MUST NOT exceed `ConsensusParams.Block.MaxBytes`, +or 100MB if `ConsensusParams.Block.MaxBytes == -1`. ## Reaping transactions from the mempool When we reap transactions from the mempool, we calculate maximum data size by subtracting maximum header size (`MaxHeaderBytes`), the maximum -amino overhead for a block (`MaxAminoOverheadForBlock`), the size of +protobuf overhead for a block (`MaxOverheadForBlock`), the size of the last commit (if present) and evidence (if present). While reaping -we account for amino overhead for each transaction. +we account for protobuf overhead for each transaction. ```go -func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 { - return maxBytes - +func MaxDataBytes(maxBytes, evidenceBytes int64, valsCount int) int64 { + return maxBytes - MaxOverheadForBlock - MaxHeaderBytes - - int64(valsCount)*MaxVoteBytes - - int64(evidenceCount)*MaxEvidenceBytes + MaxCommitBytes(valsCount) - + evidenceBytes } ``` +If `ConsensusParams.Block.MaxBytes == -1`, we reap *all* outstanding transactions from the mempool + +## Preparing the proposal + +Once the transactions have been reaped from the mempool according to the rules described above, +CometBFT calls `PrepareProposal` to the application with the transaction list that has just been reaped. +As part of this call the application can remove, add, or reorder transactions in the transaction list. + +The `PrepareProposalRequest` contains two important fields: + +* `MaxTxBytes`, which contains the value returned by `MaxDataBytes` described above. + The application MUST NOT return a list of transactions whose size exceeds this number. +* `Txs`, which contains the list of reaped transactions. + +For more details on `PrepareProposal`, please see the +[relevant part of the spec](../abci/abci%2B%2B_methods.md#prepareproposal) + ## Validating transactions in the mempool -Before we accept a transaction in the mempool, we check if it's size is no more +Before we accept a transaction in the mempool, we check if its size is no more than {MaxDataSize}. {MaxDataSize} is calculated using the same formula as -above, except we subtract the max number of evidence, {MaxNum} by the maximum size of evidence +above, except we assume there is no evidence. ```go -func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 { - return maxBytes - - MaxOverheadForBlock - - MaxHeaderBytes - - (maxNumEvidence * MaxEvidenceBytes) +func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 { + return maxBytes - + MaxOverheadForBlock - + MaxHeaderBytes - + MaxCommitBytes(valsCount) } ``` diff --git a/spec/consensus/evidence.md b/spec/consensus/evidence.md index b3f3de5c6a3..9dac695995a 100644 --- a/spec/consensus/evidence.md +++ b/spec/consensus/evidence.md @@ -4,7 +4,7 @@ # Evidence Evidence is an important component of CometBFT's security model. Whilst the core -consensus protocol provides correctness gaurantees for state machine replication +consensus protocol provides correctness guarantees for state machine replication that can tolerate less than 1/3 failures, the evidence system looks to detect and gossip byzantine faults whose combined power is greater than or equal to 1/3. It is worth noting that the evidence system is designed purely to detect possible attacks, gossip them, @@ -77,7 +77,7 @@ should be committed within a certain period from the point that it occurred (timely). Timelines is defined by the `EvidenceParams`: `MaxAgeNumBlocks` and `MaxAgeDuration`. In Proof of Stake chains where validators are bonded, evidence age should be less than the unbonding period so validators still can be -punished. Given these two propoerties the following initial checks are made. +punished. Given these two properties the following initial checks are made. 1. Has the evidence expired? This is done by taking the height of the `Vote` within `DuplicateVoteEvidence` or `CommonHeight` within @@ -126,11 +126,11 @@ Valid Light Client Attack Evidence must adhere to the following rules: ## Gossiping -If a node verifies evidence it then broadcasts it to all peers, continously sending +If a node verifies evidence it then broadcasts it to all peers, continuously sending the same evidence once every 10 seconds until the evidence is seen on chain or expires. -## Commiting on Chain +## Committing on Chain Evidence takes strict priority over regular transactions, thus a block is filled with evidence first and transactions take up the remainder of the space. To diff --git a/spec/consensus/proposer-based-timestamp/README.md b/spec/consensus/proposer-based-timestamp/README.md index 2972d8765b9..2af05c43aae 100644 --- a/spec/consensus/proposer-based-timestamp/README.md +++ b/spec/consensus/proposer-based-timestamp/README.md @@ -1,20 +1,132 @@ -# Proposer-Based Timestamps +# Proposer-Based Timestamps (PBTS) -This section describes a version of the Tendermint consensus algorithm, adopted in CometBFT, -which uses proposer-based timestamps. +This document describes a version of the Tendermint consensus algorithm +that uses proposer-based timestamps. -## Contents +PBTS is a Byzantine fault-tolerant algorithm used by CometBFT for computing [block times](../time.md). -- [Proposer-Based Time][main] (entry point) -- [Part I - System Model and Properties][sysmodel] -- [Part II - Protocol Specification][algorithm] +## Overview + +With PBTS, the timestamp of a block is assigned by its +proposer, according with its local clock. +In other words, the proposer of a block also *proposes* a timestamp for the block. +Validators can accept or reject a proposed block. +A block is only accepted if its timestamp is acceptable. +A proposed timestamp is acceptable if it is *received* within a certain time window, +determined by synchronous parameters. + +The motivation for introducing this new method for assigning timestamps is +summarized in the [first draft proposal][main_v1]. + +### Synchronous Parameters + +For validating timestamps, PBTS augments the system model considered by the +consensus algorithm with *synchronous assumptions*: + +- **Synchronized clocks**: simultaneous clock reads at any two correct validators +differ by at most `PRECISION`; + +- **Bounded message delays**: the end-to-end delay for delivering a `Proposal` + message, broadcast by a correct proposer, to all correct validators is + bounded by `MSGDELAY`. + +`PRECISION` and `MSGDELAY` are consensus parameters, shared by all validators, +that define whether the timestamp of a block is acceptable, +according with the introduced `timely` predicate. + +#### Note on Liveness + +Setting too small values for synchronous parameters can compromise, +possibly in an irreversible way, liveness of consensus. +This is particularly relevant for the `MSGDELAY` parameter. +When the `Proposal` end-to-end delay is underestimated or unrealistic, proposed block +times can be rejected by all correct nodes. + +In order to prevent networks with bad parameters from not making progress (that is, +remaining at the consensus instance for same height forever), the `MSGDELAY` +parameter has become adaptive in the implementation. +This means that the `MSGDELAY` parameter should be interpreted in the form `MSGDELAY(r)`, where `r` is the +consensus round, with `MSGDELAY(r+1) > MSGDELAY(r)`. +The original `MSGDELAY` is therefore in practice `MSGDELAY(0)`. + +More details and discussion on [issue 2184][issue2184]. + +### Timestamp Validation + +The `timely` predicate is defined as follows. +Let `proposalReceiveTime` be the time, read from its local clock, at +which a validator receives a `Proposal` message for a `block` with timestamp `ts = block.time`. +The proposed timestamp `ts` can be accepted if both: + + - `ts <= proposalReceiveTime + PRECISION` + - `ts >= proposalReceiveTime - MSGDELAY - PRECISION` + +The following diagram graphically represents the conditions for accepting a proposed timestamp: + +![diagram](./diagram.png) + +A more detailed and formalized description of the `timely` predicate is available in the +[System Model and Properties][sysmodel] document. + +## Implementation + +The implementation of PBTS requires some changes in Tendermint consensus algorithm, +summarized below: + +- A proposer timestamps a block with the current time, read from its local clock. +The block's timestamp represents the time at which it was assembled +(after the `getValue()` call in line 18 of the [arXiv][arXiv] algorithm): + + - Block timestamps are definitive, meaning that the original timestamp + is retained when a block is re-proposed (line 16); + + - To preserve monotonicity, a proposer might need to wait until its clock + reads a time greater than the timestamp of the previous block; + +- A validator only prevotes for a block if its timestamp is considered `timely` +(compared to the original algorithm, a check is added to line 23). +Otherwise, the validator prevotes `nil` (line 26): + + - Validators register the time at which they received `Proposal` messages, + in order to evaluate the `timely` predicate; + + - Blocks that are re-proposed because they received `2f+1 Prevotes` + in a previous round (line 28) are not subject to the `timely` predicate, + as their timestamps have already been evaluated at a previous round. + +The full solution is detailed and formalized in the [Algorithm Specification][algorithm] document. + +## Further details + +- [System Model and Properties][sysmodel] +- [Algorithm Specification][algorithm] - [TLA+ Specification][proposertla] +### Issues + +- [cometbft#2184: PBTS: should synchrony parameters be adaptive?][issue2184] +- [tendermint/spec#355: PBTS: evidence][issue355]: can we punish Byzantine proposers? +- [tendermint/spec#377: PBTS: margins for proposal times assigned by Byzantine proposers][issue377] + + +[main_v1]: ./v1/pbts_001_draft.md + +[algorithm]: ./pbts-algorithm.md +[algorithm_v1]: ./v1/pbts-algorithm_001_draft.md -[algorithm]: ./pbts-algorithm_001_draft.md +[sysmodel]: ./pbts-sysmodel.md +[sysmodel_v1]: ./v1/pbts-sysmodel_001_draft.md +[timely-predicate]: ./pbts-sysmodel.md#timely-predicate -[sysmodel]: ./pbts-sysmodel_001_draft.md +[proposertla]: ./tla/README.md -[main]: ./pbts_001_draft.md +[bfttime]: ../bft-time.md +[arXiv]: https://arxiv.org/pdf/1807.04938.pdf -[proposertla]: ./tla/TendermintPBT_001_draft.tla +[issue353]: https://github.com/tendermint/spec/issues/353 +[issue355]: https://github.com/tendermint/spec/issues/355 +[issue370]: https://github.com/tendermint/spec/issues/370 +[issue371]: https://github.com/tendermint/spec/issues/371 +[issue372]: https://github.com/tendermint/spec/issues/372 +[issue377]: https://github.com/tendermint/spec/issues/377 +[issue2184]: https://github.com/cometbft/cometbft/issues/2184 diff --git a/spec/consensus/proposer-based-timestamp/diagram.png b/spec/consensus/proposer-based-timestamp/diagram.png new file mode 100644 index 00000000000..bf8df8cb770 Binary files /dev/null and b/spec/consensus/proposer-based-timestamp/diagram.png differ diff --git a/spec/consensus/proposer-based-timestamp/pbts-algorithm.md b/spec/consensus/proposer-based-timestamp/pbts-algorithm.md new file mode 100644 index 00000000000..9197ee646f3 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/pbts-algorithm.md @@ -0,0 +1,170 @@ +# PBTS: Algorithm Specification + +## Proposal Time + +PBTS computes, for a proposed value `v`, the proposal time `v.time` with bounded difference to the actual real-time the proposed value was generated. +The proposal time is read from the clock of the process that proposes a value for the first time, which is its original proposer. + +With PBTS, therefore, we assume that processes have access to **synchronized clocks**. +The proper definition of what it means can be found in the [system model][sysmodel], +but essentially we assume that two correct processes do not simultaneously read from their clocks +time values that differ by more than `PRECISION`, which is a system parameter. + +### Proposal times are definitive + +When a value `v` is produced by a process, it also assigns the associated proposal time `v.time`. +If the same value `v` is then re-proposed in a subsequent round of consensus, +it retains its original time, assigned by its original proposer. + +A value `v` should re-proposed when it becomes locked by the network, i.e., when it receives `2f + 1 PREVOTES` in a round `r` of consensus. +This means that processes with `2f + 1`-equivalent voting power accepted both `v` and its associated time `v.time` in round `r`. +Since the originally proposed value and its associated time were considered valid, there is no reason for reassigning `v.time`. + +> In the [first version][algorithm_v1] of this specification, proposals were defined as pairs `(v, time)`. +> In addition, the same value `v` could be proposed, in different rounds, but would be associated with distinct times each time it was re-proposed. +> Since this possibility does not exist in this second specification, the proposal time became part of the proposed value. +> With this simplification, several small changes to the [arXiv][arXiv] algorithm are no longer required. + +## Time Monotonicity + +Values decided in successive heights of consensus must have increasing times, so: + +- Monotonicity: for any process `p` and any two decided heights `h` and `h'`, if `h > h'` then `decision_p[h].time > decision_p[h'].time`. + +To ensure time monotonicity, it is enough to ensure that a value `v` proposed by process `p` at height `h_p` has `v.time > decision_p[h_p-1].time`. +So, if process `p` is the proposer of a round of height `h_p` and reads from its clock a time `now_p <= decision_p[h_p-1]`, +it should postpone the generation of its proposal until `now_p > decision_p[h_p-1]`. + +> Although it should be considered, this scenario is unlikely during regular operation, +as from `decision_p[h_p-1].time` and the start of height `h_p`, a complete consensus instance need to be concluded. + +Notice that monotonicity is not introduced by this proposal, as it is already ensured by [`BFT Time`][bfttime]. +In `BFT Time`, the `Timestamp` field of every `Precommit` message of height `h_p` sent by a correct process is required to be larger than `decision_p[h_p-1].time`. +As one of such `Timestamp` fields becomes the time assigned to a value proposed at height `h_p`, time monotonicity is observed. + +The time monotonicity of values proposed in heights of consensus is verified by the `valid()` predicate, to which every proposed value is submitted. +A value rejected by `valid()` is not accepted by any correct process. + +## Timely Predicate + +PBTS introduces a new requirement for a process to accept a proposal: the proposal time must be `timely`. +It is a temporal requirement, associated with the following +[synchrony assumptions][sysmodel] regarding the behavior of processes and the network: + +- Synchronized clocks: the values simultaneously read from clocks of any two correct processes differ by at most `PRECISION`; +- Bounded transmission delays: the real time interval between the sending of a proposal at a correct process and the reception of the proposal at any correct process is upper bounded by `MSGDELAY`. + - With the introduction of [adaptive message delays](./pbts-sysmodel.md#pbts-msg-delay-adaptive0), + the `MSGDELAY` parameter should be interpreted as `MSGDELAY(r)`, where `r` is the current round, + where it is expected `MSGDELAY(r+1) > MSGDELAY(r)`. + +#### **[PBTS-RECEPTION-STEP.1]** + +Let `now_p` be the time, read from the clock of process `p`, at which `p` receives the proposed value `v` of round `r`. +The proposal time is considered `timely` by `p` when: + +1. `now_p >= v.time - PRECISION` +1. `now_p <= v.time + MSGDELAY + PRECISION` + +The first condition derives from the fact that the generation and sending of `v` precedes its reception. +The minimum receiving time `now_p` for `v.time` be considered `timely` by `p` is derived from the extreme scenario when +the clock of `p` is `PRECISION` *behind* of the clock of the proposer of `v`, and the proposal's transmission delay is `0` (minimum). + +The second condition derives from the assumption of an upper bound for the transmission delay of a proposal. +The maximum receiving time `now_p` for `v.time` be considered `timely` by `p` is derived from the extreme scenario when +the clock of `p` is `PRECISION` *ahead* of the clock of the proposer of `v`, and the proposal's transmission delay is `MSGDELAY` (maximum). + +## Updated Consensus Algorithm + +The following changes are proposed for the algorithm in the [arXiv paper][arXiv]. + +### Updated `StartRound` function + +There are two additions to operation of the **proposer** of a round: + +1. To ensure time monotonicity, the proposer does not propose a value until its +current local time, represented by `now_p` in the algorithm, +becomes greater than the previously decided value's time +2. When the proposer produce a new proposal it sets the proposal's time to its current local time + - No changes are made to the logic when a proposer has a non-nil `validValue_p`, which retains its original proposal time. + +#### **[PBTS-ALG-STARTROUND.1]** + +```go +function StartRound(round) { + round_p ← round + step_p ← propose + if proposer(h_p, round_p) = p { + if validValue_p != nil { + proposal ← validValue_p // proposal.time unchanged + } else { + wait until now_p > decision_p[h_p-1].time // time monotonicity + proposal ← getValue() + proposal.time ← now_p // proposal time set to current local time + } + broadcast ⟨PROPOSAL, h_p, round_p, proposal, validRound_p⟩ + } else { + schedule OnTimeoutPropose(h_p,round_p) to be executed after timeoutPropose(round_p) + } +} +``` + +### Updated upon clause of line 22 + +The rule on line 22 applies to values `v` proposed for the first time, i.e., +for proposals not backed by `2f + 1 PREVOTE`s for `v` in a previous round. +The `PROPOSAL` message, in this case, has a valid round `vr = -1`. + +The new rule for issuing a `PREVOTE` for a proposed value `v` +requires the proposal time to be `timely`: + +#### **[PBTS-ALG-UPON-PROP.1]** + +```go +upon ⟨PROPOSAL, h_p, round_p, v, −1⟩ from proposer(h_p, round_p) while step_p = propose do { + if timely(v.time) ∧ valid(v) ∧ (lockedRound_p = −1 ∨ lockedValue_p = v) { + broadcast ⟨PREVOTE, h_p, round_p, id(v)⟩ + } + else { + broadcast ⟨PREVOTE, h_p, round_p, nil⟩ + } + step_p ← prevote +} +``` + +The `timely` predicate considers the time at which the `PROPOSAL` message is received. +Although not represented above, for the sake of simplicity, it is assumed that the +`PROPOSAL` receive time is registered and provided to the `timely` predicate. + +### Unchanged upon clause of line 28 + +The rule on line 28 applies to values `v` re-proposed in the current round +because its proposer received `2f + 1 PREVOTE`s for `v` in a previous round +`vr`, therefore updating its `validValue_p` to `v` and `validRound_p` to `vr`. + +This means that there was a round `r <= vr` in which `2f + 1` processes +accepted a `PROPOSAL` for `v`, proposed at round `r` for the first time, with +`vr = -1`. +These processes executed the line 22 of the algorithm and broadcast a +`PREVOTE` for `v`, indicating in particular, that they have judged `v.time` +as `timely` in round `r`. + +Since `v.time` was considered `timely` by `2f + 1` processes in a previous +round, and provided that `v.time` cannot be updated when `v` is re-proposed, +the evaluation of `timely` predicate is not necessary in this case. + +For a more formal explanation and a proof of this assertion, refer to the +[properties][sysmodel-pol] section. + +**All other rules remain unchanged.** + +Back to [main document][main]. + +[main]: ./README.md + +[algorithm_v1]: ./v1/pbts-algorithm_001_draft.md + +[sysmodel]: ./pbts-sysmodel.md +[sysmodel-pol]: ./pbts-sysmodel.md#derived-proof-of-locks + +[bfttime]: ../bft-time.md +[arXiv]: https://arxiv.org/pdf/1807.04938.pdf diff --git a/spec/consensus/proposer-based-timestamp/pbts-sysmodel.md b/spec/consensus/proposer-based-timestamp/pbts-sysmodel.md new file mode 100644 index 00000000000..52bcbc1ce99 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/pbts-sysmodel.md @@ -0,0 +1,357 @@ +# PBTS: System Model and Properties + +## Outline + + - [System model](#system-model) + - [Synchronized clocks](#synchronized-clocks) + - [Message delays](#message-delays) + - [Problem Statement](#problem-statement) + - [Timely Predicate](#timely-predicate) + - [Timely Proof-of-Locks](#timely-proof-of-locks) + - [Derived Proof-of-Locks](#derived-proof-of-locks) + - [Temporal Analysis](#temporal-analysis) + - [Safety](#safety) + - [Liveness](#liveness) + +## System Model + +#### **[PBTS-CLOCK-NEWTON.0]** + +There is a reference Newtonian real-time `t`. + +No process has direct access to this reference time, used only for specification purposes. +The reference real-time is assumed to be aligned with the Coordinated Universal Time (UTC). + +### Synchronized clocks + +Processes are assumed to be equipped with synchronized clocks, +aligned with the Coordinated Universal Time (UTC). + +This requires processes to periodically synchronize their local clocks with an +external and trusted source of the time (e.g. NTP servers). +Each synchronization cycle aligns the process local clock with the external +source of time, making it a *fairly accurate* source of real time. +The periodic (re)synchronization aims to correct the *drift* of local clocks, +which tend to pace slightly faster or slower than the real time. + +To avoid an excessive level detail in the parameters and guarantees of +synchronized clocks, we adopt a single system parameter `PRECISION` to +encapsulate the potential inaccuracy of the synchronization mechanisms, +and drifts of local clocks from real time. + +#### **[PBTS-CLOCK-PRECISION.0]** + +There exists a system parameter `PRECISION`, such that +for any two processes `p` and `q`, with local clocks `C_p` and `C_q`: + +- If `p` and `q` are equipped with synchronized clocks, + then for any real-time `t` we have `|C_p(t) - C_q(t)| <= PRECISION`. + +`PRECISION` thus bounds the difference on the times simultaneously read by processes +from their local clocks, so that their clocks can be considered synchronized. + +### Message Delays + +To properly evaluate whether the time assigned to a proposal is consistent with the real time, +we need some information regarding the time it takes for a message carrying a proposal +to reach all its (correct) destinations. +More precisely, the *maximum delay* for delivering a proposal to its destinations allows +defining a lower bound, a *minimum time* that a correct process assigns to proposal. + +#### **[PBTS-MSG-DELAY.0]** + +There exists a system parameter `MSGDELAY` for end-to-end delays of proposal messages, +such for any two correct processes `p` and `q`: + +- If `p` sends a proposal message `m` at real time `t` and `q` receives `m` at + real time `t'`, then `t <= t' <= t + MSGDELAY`. + +Notice that, as a system parameter, `MSGDELAY` should be observed for any +proposal message broadcast by correct processes: it is a *worst-case* parameter. +As message delays depends on the message size, the above requirement implicitly +indicates that the size of proposal messages is either fixed or upper bounded. + +#### **[PBTS-MSG-DELAY-ADAPTIVE.0]** + +This specification is written assuming that there exists an end-to-end maximum +delay `maxMsgDelay` observed in the network, possibly unknown, and +that the chosen value for `MSGDELAY` is such that `MSGDELAY >= maxMsgDelay`. +Under this assumption, all properties described in this specification are satisfied. + +However, it is possible that in some networks the `MSGDELAY` parameters +selected by operators is too small, i.e., `MSGDELAY < maxMsgDelay`. +In order to tolerate this possibility, we propose the adoption of adaptive +end-to-end delays, namely a relaxation of [PBTS-MSG-DELAY.0] where the +`MSGDELAY` value increases each time consensus requires a new round. +In this way, after a number of rounds, the adopted `MSGDELAY` should match the +actual, but possibly unknown, end-to-end `maxMsgDelay`. +This is a typical approach in partial synchronous models. + +The adaptive system parameter `MSGDELAY(r)` is defined as follows. +Lets `p` and `q` be any correct processes: + +- If `p` sends a proposal message `m` from round `r` at real time `t` and `q` receives `m` at + real time `t'`, then `t < t' <= t + MSGDELAY(r)`. + +The adaptiveness is represented by the assumption that the value of the +parameter increases over rounds, i.e., `MSGDELAY(r+1) > MSGDELAY(r)`. +The initial value `MSGDELAY(0)` is equal to `MSGDELAY` as in [PBTS-MSG-DELAY.0]. + +For the sake of correctness and formal verification, if `MSGDELAY` is +chosen sufficiently large, then the fact that it increments in later rounds +(i) in practice will never be experienced, +and (ii) also has no theoretical implications. +The adaptation (increment) of `MSGDELAY` is only introduced here to handle +potential misconfiguration. + +## Problem Statement + +This section defines the properties of Tendermint consensus algorithm +(cf. the [arXiv paper][arXiv]) in this system model. + +#### **[PBTS-PROPOSE.0]** + +A proposer proposes a consensus value `v` that includes a proposal time +`v.time`. + +#### **[PBTS-INV-AGREEMENT.0]** + +- [Agreement] No two correct processes decide different values. + +This implies that no two correct processes decide, in particular, different +proposal times. + +#### **[PBTS-INV-VALID.0]** + +- [Validity] If a correct process decides on value `v`, then `v` satisfies a + predefined `valid` predicate. + +With respect to PBTS, the `valid` predicate requires proposal times to be +[monotonic][time-monotonicity] over heights of +consensus. + +#### **[PBTS-INV-MONOTONICITY.0]** + +- If a correct process decides on value `v` at the height `h` of consensus, + thus setting `decision[h] = v`, then `v.time > decision[h'].time` for all + previous heights `h' < h`. + +The monotonicity of proposal times +implicitly assumes that heights of consensus are executed in order. + +#### **[PBTS-INV-TIMELY.0]** + +- [Time-Validity] If a correct process decides on value `v`, then the proposal + time `v.time` was considered `timely` by at least one correct process. + +The following section defines the `timely` predicate +that restricts the allowed decisions based +on the proposal time `v.time` associated with a proposed value `v`. + +## Timely Predicate + +For PBTS, a `proposal` is a tuple `(v, v.time, v.round)`, where: + +- `v` is the proposed value; +- `v.time` is the associated proposal time; +- `v.round` is the round at which `v` was first proposed. + +We include the proposal round `v.round` in the proposal definition because a +value `v` can be proposed in multiple rounds of consensus, +but the evaluation of the `timely` predicate is only relevant at round `v.round`. + +> Considering the algorithm in the [arXiv paper][arXiv], a new proposal is +> produced by the `getValue()` method (line 18), invoked by the proposer `p` of round +> `round_p` when starting the round with `validValue_p = nil`. +> In this case, the proposed value is broadcast in a `PROPOSAL` message with +> `vr = validRound_p = -1`. + +#### **[PBTS-PROPOSAL-RECEPTION.0]** + +The `timely` predicate is evaluated when a process receives a proposal. +More precisely, let `p` be a correct process: + +- `proposalReceptionTime(p,r)` is the time `p` reads from its local clock when + it receives the proposal of round `r`. + +#### **[PBTS-TIMELY.0]** + +Lets `(v, v.time, v.round)` be a proposal, then `v.time` is considered `timely` by a correct process +`p` if: + +1. `proposalReceptionTime(p,v.round)` is set, and +1. `proposalReceptionTime(p,v.round) >= v.time - PRECISION`, and +1. `proposalReceptionTime(p,v.round) <= v.time + MSGDELAY(v.round) + PRECISION`. + +A correct process only sends a `PREVOTE` for `v` at round `v.round` if the +associated proposal time `v.time` is considered `timely`. + +> Considering the algorithm in the [arXiv paper][arXiv], the `timely` predicate +> is evaluated by a process `p` when it receives a valid `PROPOSAL` message +> from the proposer of the current round `round_p` with `vr = -1` (line 22). + +### Timely Proof-of-Locks + +A *Proof-of-Lock* is a set of `PREVOTE` messages of round of consensus for the +same value from processes whose cumulative voting power is at least `2f + 1`. +We denote as `POL(v,r)` a proof-of-lock of value `v` at round `r`. + +For PBTS, we are particularly interested in the `POL(v,v.round)` produced in +the round `v.round` at which a value `v` was first proposed. +We call it a *timely* proof-of-lock for `v` because it can only be observed +if at least one correct process considered it `timely`: + +#### **[PBTS-TIMELY-POL.0]** + +If + +- there is a valid `POL(v,r)` with `r = v.round`, and +- `POL(v,v.round)` contains a `PREVOTE` message from at least one correct process, + +Then, let `p` is a such correct process: + +- `p` received a `PROPOSAL` message of round `v.round`, and +- the `PROPOSAL` message contained a proposal `(v, v.time, v.round)`, and +- `p` was in round `v.round` and evaluated the proposal time `v.time` as `timely`. + +The existence of a such correct process `p` is guaranteed provided that the +voting power of Byzantine processes is bounded by `2f`. + +### Derived Proof-of-Locks + +The existence of `POL(v,r)` is a requirement for the decision of `v` at round +`r` of consensus. + +At the same time, the Time-Validity property establishes that if `v` is decided +then a timely proof-of-lock `POL(v,v.round)` must have been produced. + +So, we need to demonstrate here that any valid `POL(v,r)` is either a timely +proof-of-lock or it is derived from a timely proof-of-lock: + +#### **[PBTS-DERIVED-POL.0]** + +If + +- there is a valid `POL(v,r)`, and +- `POL(v,r)` contains a `PREVOTE` message from at least one correct process, + +Then + +- there is a valid `POL(v,v.round)` with `v.round <= r` which is a timely proof-of-lock. + +The above relation is trivially observed when `r = v.round`, as `POL(v,r)` must +be a timely proof-of-lock. +Notice that we cannot have `r < v.round`, as `v.round` is defined as the first +round at which `v` was proposed. + +For `r > v.round` we need to demonstrate that if there is a valid `POL(v,r)`, +then a timely `POL(v,v.round)` was previously obtained. +We observe that a condition for observing a `POL(v,r)` is that the proposer of +round `r` has broadcast a `PROPOSAL` message for `v`. +As `r > v.round`, we can affirm that `v` was not produced in round `r`. +Instead, by the protocol operation, `v` was a *valid value* for the proposer of +round `r`, which means that if the proposer has observed a `POL(v,vr)` with `vr +< r`. +The above operation considers a *correct* proposer, but since a `POL(v,r)` was +produced (by hypothesis) we can affirm that at least one correct process (also) +observed a `POL(v,vr)`. + +> Considering the algorithm in the [arXiv paper][arXiv], `v` was proposed by +> the proposer `p` of round `round_p` because its `validValue_p` variable was +> set to `v`. +> The `PROPOSAL` message broadcast by the proposer, in this case, had `vr = validRound_p > -1`, +> and it could only be accepted by processes that also observed a `POL(v,vr)`. + +Thus, if there is a `POL(v,r)` with `r > v.round`, then there is a valid +`POL(v,vr)` with `v.round <= vr < r`. +If `vr = v.round` then `POL(vr,v)` is a timely proof-of-lock and we are done. +Otherwise, there is another valid `POL(v,vr')` with `v.round <= vr' < vr`, +and the above reasoning can be recursively applied until we get `vr' = v.round` +and observe a timely proof-of-lock. + +## Temporal analysis + +In this section we present invariants that need be observed for ensuring that +PBTS is both safe and live. + +In addition to the variables and system parameters already defined, we use +`beginRound(p,r)` as the value of process `p`'s local clock +when it starts round `r` of consensus. + +### Safety + +The safety of PBTS requires that if a value `v` is decided, then at least one +correct process `p` considered the associated proposal time `v.time` timely. +Following the definition of [timely proposal times](#pbts-timely0) and +proof-of-locks, we require this condition to be asserted at a specific round of +consensus, defined as `v.round`: + +#### **[PBTS-SAFETY.0]** + +If + +- there is a valid commit `C` for a value `v` +- `C` contains a `PRECOMMIT` message from at least one correct process + +then there is a correct process `p` (not necessarily the same above considered) such that: + +- `beginRound(p,v.round) <= proposalReceptionTime(p,v.round) <= beginRound(p,v.round+1)` and +- `v.time <= proposalReceptionTime(p,v.round) + PRECISION` and +- `v.time >= proposalReceptionTime(p,v.round) - MSGDELAY(v.round) - PRECISION` + +That is, a correct process `p` started round `v.round` and, while still at +round `v.round`, received a `PROPOSAL` message from round `v.round` proposing +`v`. +Moreover, the reception time of the original proposal for `v`, according with +`p`'s local clock, enabled `p` to consider the proposal time `v.time` as +`timely`. +This is the requirement established by PBTS for issuing a `PREVOTE` for the +proposal `(v, v.time, v.round)`, so for the eventual decision of `v`. + +### Liveness + +The liveness of PBTS relies on correct processes accepting proposal times +assigned by correct proposers. +We thus present a set of conditions for assigning a proposal time `v.time` so +that every correct process should be able to issue a `PREVOTE` for `v`. + +#### **[PBTS-LIVENESS.0]** + +If + +- the proposer of a round `r` of consensus is correct +- and it proposes a value `v` for the first time, with associated proposal time `v.time` + +then the proposal `(v, v.time, r)` is accepted by every correct process provided that: + +- `min{p is correct : beginRound(p,r)} <= v.time <= max{p is correct : beginRound(p,r)}` and +- `max{p is correct : beginRound(p,r)} <= v.time + MSGDELAY(r) + PRECISION <= min{p is correct : beginRound(p,r+1)}` + +The first condition establishes a range of safe proposal times `v.time` for round `r`. +This condition is trivially observed if a correct proposer `p` sets `v.time` to the time it +reads from its clock when starting round `r` and proposing `v`. +A `PROPOSAL` message sent by `p` at local time `v.time` should not be received +by any correct process before its local clock reads `v.time - PRECISION`, so +that condition 2 of [PBTS-TIMELY.0] is observed. + +The second condition establishes that every correct process should start round +`v.round` at a local time that allows `v.time` to still be considered timely, +according to condition 3. of [PBTS-TIMELY.0]. +In addition, it requires correct processes to stay long enough in round +`v.round` so that they can receive the `PROPOSAL` message of round `v.round`. +It assumed here that the proposer of `v` broadcasts a `PROPOSAL` message at +time `v.time`, according to its local clock, so that every correct process +should receive this message by time `v.time + MSGDELAY(v.round) + PRECISION`, according +to their local clocks. + +Back to [main document][main]. + +[main]: ./README.md + +[algorithm]: ./pbts-algorithm.md +[time-monotonicity]: ./pbts-algorithm.md#time-monotonicity + +[sysmodel]: ./pbts-sysmodel.md +[sysmodel_v1]: ./v1/pbts-sysmodel_001_draft.md + +[arXiv]: https://arxiv.org/pdf/1807.04938.pdf diff --git a/spec/consensus/proposer-based-timestamp/tla/.gitignore b/spec/consensus/proposer-based-timestamp/tla/.gitignore new file mode 100644 index 00000000000..e25bf38d4b6 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/.gitignore @@ -0,0 +1 @@ +intermediate/ diff --git a/spec/consensus/proposer-based-timestamp/tla/Apalache.tla b/spec/consensus/proposer-based-timestamp/tla/Apalache.tla new file mode 100644 index 00000000000..044bff666f7 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/Apalache.tla @@ -0,0 +1,109 @@ +--------------------------- MODULE Apalache ----------------------------------- +(* + * This is a standard module for use with the Apalache model checker. + * The meaning of the operators is explained in the comments. + * Many of the operators serve as additional annotations of their arguments. + * As we like to preserve compatibility with TLC and TLAPS, we define the + * operator bodies by erasure. The actual interpretation of the operators is + * encoded inside Apalache. For the moment, these operators are mirrored in + * the class at.forsyte.apalache.tla.lir.oper.ApalacheOper. + * + * Igor Konnov, Jure Kukovec, Informal Systems 2020-2021 + *) + +(** + * An assignment of an expression e to a state variable x. Typically, one + * uses the non-primed version of x in the initializing predicate Init and + * the primed version of x (that is, x') in the transition predicate Next. + * Although TLA+ does not have a concept of a variable assignment, we find + * this concept extremely useful for symbolic model checking. In pure TLA+, + * one would simply write x = e, or x \in {e}. + * + * Apalache automatically converts some expressions of the form + * x = e or x \in {e} into assignments. However, if you like to annotate + * assignments by hand, you can use this operator. + * + * For a further discussion on that matter, see: + * https://github.com/informalsystems/apalache/blob/ik/idiomatic-tla/docs/idiomatic/assignments.md + *) +x := e == x = e + +(** + * A generator of a data structure. Given a positive integer `bound`, and + * assuming that the type of the operator application is known, we + * recursively generate a TLA+ data structure as a tree, whose width is + * bound by the number `bound`. + * + * The body of this operator is redefined by Apalache. + *) +Gen(size) == {} + +(** + * Convert a set of pairs S to a function F. Note that if S contains at least + * two pairs <> and <> such that x = u and y /= v, + * then F is not uniquely defined. We use CHOOSE to resolve this ambiguity. + * Apalache implements a more efficient encoding of this operator + * than the default one. + * + * @type: Set(<>) => (a -> b); + *) +SetAsFun(S) == + LET Dom == { x: <> \in S } + Rng == { y: <> \in S } + IN + [ x \in Dom |-> CHOOSE y \in Rng: <> \in S ] + +(** + * As TLA+ is untyped, one can use function- and sequence-specific operators + * interchangeably. However, to maintain correctness w.r.t. our type-system, + * an explicit cast is needed when using functions as sequences. + *) +LOCAL INSTANCE Sequences +FunAsSeq(fn, maxSeqLen) == SubSeq(fn, 1, maxSeqLen) + +(** + * Annotating an expression \E x \in S: P as Skolemizable. That is, it can + * be replaced with an expression c \in S /\ P(c) for a fresh constant c. + * Not every exisential can be replaced with a constant, this should be done + * with care. Apalache detects Skolemizable expressions by static analysis. + *) +Skolem(e) == e + +(** + * A hint to the model checker to expand a set S, instead of dealing + * with it symbolically. Apalache finds out which sets have to be expanded + * by static analysis. + *) +Expand(S) == S + +(** + * A hint to the model checker to replace its argument Cardinality(S) >= k + * with a series of existential quantifiers for a constant k. + * Similar to Skolem, this has to be done carefully. Apalache automatically + * places this hint by static analysis. + *) +ConstCardinality(cardExpr) == cardExpr + +(** + * The folding operator, used to implement computation over a set. + * Apalache implements a more efficient encoding than the one below. + * (from the community modules). + *) +RECURSIVE FoldSet(_,_,_) +FoldSet( Op(_,_), v, S ) == IF S = {} + THEN v + ELSE LET w == CHOOSE x \in S: TRUE + IN LET T == S \ {w} + IN FoldSet( Op, Op(v,w), T ) + +(** + * The folding operator, used to implement computation over a sequence. + * Apalache implements a more efficient encoding than the one below. + * (from the community modules). + *) +RECURSIVE FoldSeq(_,_,_) +FoldSeq( Op(_,_), v, seq ) == IF seq = <<>> + THEN v + ELSE FoldSeq( Op, Op(v,Head(seq)), Tail(seq) ) + +=============================================================================== diff --git a/spec/consensus/proposer-based-timestamp/tla/MC_PBT.tla b/spec/consensus/proposer-based-timestamp/tla/MC_PBT.tla new file mode 100644 index 00000000000..53f7336fbf0 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/MC_PBT.tla @@ -0,0 +1,77 @@ +----------------------------- MODULE MC_PBT ------------------------------- +CONSTANT + \* @type: ROUND -> PROCESS; + Proposer + +VARIABLES + \* @type: PROCESS -> ROUND; + round, \* a process round number + \* @type: PROCESS -> STEP; + step, \* a process step + \* @type: PROCESS -> DECISION; + decision, \* process decision + \* @type: PROCESS -> VALUE; + lockedValue, \* a locked value + \* @type: PROCESS -> ROUND; + lockedRound, \* a locked round + \* @type: PROCESS -> PROPOSAL; + validValue, \* a valid value + \* @type: PROCESS -> ROUND; + validRound \* a valid round + +\* time-related variables +VARIABLES + \* @type: PROCESS -> TIME; + localClock, \* a process local clock: Corr -> Ticks + \* @type: TIME; + realTime \* a reference Newtonian real time + +\* book-keeping variables +VARIABLES + \* @type: ROUND -> Set(PROPMESSAGE); + msgsPropose, \* PROPOSE messages broadcast in the system, Rounds -> Messages + \* @type: ROUND -> Set(PREMESSAGE); + msgsPrevote, \* PREVOTE messages broadcast in the system, Rounds -> Messages + \* @type: ROUND -> Set(PREMESSAGE); + msgsPrecommit, \* PRECOMMIT messages broadcast in the system, Rounds -> Messages + \* @type: Set(MESSAGE); + evidence, \* the messages that were used by the correct processes to make transitions + \* @type: ACTION; + action, \* we use this variable to see which action was taken + \* @type: PROCESS -> Set(PROPMESSAGE); + receivedTimelyProposal, \* used to keep track when a process receives a timely VALUE message + \* @type: <> -> TIME; + inspectedProposal \* used to keep track when a process tries to receive a message + +\* Invariant support +VARIABLES + \* @type: ROUND -> TIME; + beginRound, \* the minimum of the local clocks at the time any process entered a new round + \* @type: PROCESS -> TIME; + endConsensus, \* the local time when a decision is made + \* @type: ROUND -> TIME; + lastBeginRound, \* the maximum of the local clocks in each round + \* @type: ROUND -> TIME; + proposalTime, \* the real time when a proposer proposes in a round + \* @type: ROUND -> TIME; + proposalReceivedTime \* the real time when a correct process first receives a proposal message in a round + + +INSTANCE TendermintPBT_002_draft WITH + Corr <- {"c1", "c2"}, + Faulty <- {"f3", "f4"}, + N <- 4, + T <- 1, + ValidValues <- { "v0", "v1" }, + InvalidValues <- {"v2"}, + MaxRound <- 5, + MaxTimestamp <- 10, + MinTimestamp <- 2, + Delay <- 2, + Precision <- 2 + +\* run Apalache with --cinit=CInit +CInit == \* the proposer is arbitrary -- works for safety + Proposer \in [Rounds -> AllProcs] + +============================================================================= diff --git a/spec/consensus/proposer-based-timestamp/tla/MC_PBT_2C_2F.tla b/spec/consensus/proposer-based-timestamp/tla/MC_PBT_2C_2F.tla new file mode 100644 index 00000000000..d7de3df73cd --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/MC_PBT_2C_2F.tla @@ -0,0 +1,68 @@ +----------------------------- MODULE MC_PBT_2C_2F ------------------------------- +CONSTANT + \* @type: ROUND -> PROCESS; + Proposer + +VARIABLES + \* @type: PROCESS -> ROUND; + round, \* a process round number + \* @type: PROCESS -> STEP; + step, \* a process step + \* @type: PROCESS -> DECISION; + decision, \* process decision + \* @type: PROCESS -> VALUE; + lockedValue, \* a locked value + \* @type: PROCESS -> ROUND; + lockedRound, \* a locked round + \* @type: PROCESS -> PROPOSAL; + validValue, \* a valid value + \* @type: PROCESS -> ROUND; + validRound \* a valid round + +\* time-related variables +VARIABLES + \* @type: PROCESS -> TIME; + localClock, \* a process local clock: Corr -> Ticks + \* @type: TIME; + realTime \* a reference Newtonian real time + +\* book-keeping variables +VARIABLES + \* @type: ROUND -> Set(PROPMESSAGE); + msgsPropose, \* PROPOSE messages broadcast in the system, Rounds -> Messages + \* @type: ROUND -> Set(PREMESSAGE); + msgsPrevote, \* PREVOTE messages broadcast in the system, Rounds -> Messages + \* @type: ROUND -> Set(PREMESSAGE); + msgsPrecommit, \* PRECOMMIT messages broadcast in the system, Rounds -> Messages + \* @type: Set(MESSAGE); + evidence, \* the messages that were used by the correct processes to make transitions + \* @type: ACTION; + action, \* we use this variable to see which action was taken + \* @type: <> -> TIME; + proposalReceptionTime \* used to keep track when a process receives a message + +\* Invariant support +VARIABLES + \* @type: <> -> TIME; + beginRound \* the minimum of the local clocks at the time any process entered a new round + +INSTANCE TendermintPBT WITH + Corr <- {"c1", "c2"}, + Faulty <- {"f3", "f4"}, + N <- 4, + T <- 1, + ValidValues <- { "v0", "v1" }, + InvalidValues <- {"v2"}, + MaxRound <- 3, + MaxTimestamp <- 7, + MinTimestamp <- 2, + Delay <- 2, + Precision <- 2, + PreloadAllFaultyMsgs <- TRUE, + N_GEN <- 5 + +\* run Apalache with --cinit=CInit +CInit == \* the proposer is arbitrary -- works for safety + ArbitraryProposer + +============================================================================= diff --git a/spec/consensus/proposer-based-timestamp/tla/MC_PBT_3C_1F.tla b/spec/consensus/proposer-based-timestamp/tla/MC_PBT_3C_1F.tla new file mode 100644 index 00000000000..aec3d17a913 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/MC_PBT_3C_1F.tla @@ -0,0 +1,68 @@ +----------------------------- MODULE MC_PBT_3C_1F ------------------------------- +CONSTANT + \* @type: ROUND -> PROCESS; + Proposer + +VARIABLES + \* @type: PROCESS -> ROUND; + round, \* a process round number + \* @type: PROCESS -> STEP; + step, \* a process step + \* @type: PROCESS -> DECISION; + decision, \* process decision + \* @type: PROCESS -> VALUE; + lockedValue, \* a locked value + \* @type: PROCESS -> ROUND; + lockedRound, \* a locked round + \* @type: PROCESS -> PROPOSAL; + validValue, \* a valid value + \* @type: PROCESS -> ROUND; + validRound \* a valid round + +\* time-related variables +VARIABLES + \* @type: PROCESS -> TIME; + localClock, \* a process local clock: Corr -> Ticks + \* @type: TIME; + realTime \* a reference Newtonian real time + +\* book-keeping variables +VARIABLES + \* @type: ROUND -> Set(PROPMESSAGE); + msgsPropose, \* PROPOSE messages broadcast in the system, Rounds -> Messages + \* @type: ROUND -> Set(PREMESSAGE); + msgsPrevote, \* PREVOTE messages broadcast in the system, Rounds -> Messages + \* @type: ROUND -> Set(PREMESSAGE); + msgsPrecommit, \* PRECOMMIT messages broadcast in the system, Rounds -> Messages + \* @type: Set(MESSAGE); + evidence, \* the messages that were used by the correct processes to make transitions + \* @type: ACTION; + action, \* we use this variable to see which action was taken + \* @type: <> -> TIME; + proposalReceptionTime \* used to keep track when a process receives a message + +\* Invariant support +VARIABLES + \* @type: <> -> TIME; + beginRound \* the minimum of the local clocks at the time any process entered a new round + +INSTANCE TendermintPBT WITH + Corr <- {"c1", "c2", "c3"}, + Faulty <- {"f4"}, + N <- 4, + T <- 1, + ValidValues <- { "v0", "v1" }, + InvalidValues <- {"v2"}, + MaxRound <- 3, + MaxTimestamp <- 7, + MinTimestamp <- 2, + Delay <- 2, + Precision <- 2, + PreloadAllFaultyMsgs <- TRUE, + N_GEN <- 5 + +\* run Apalache with --cinit=CInit +CInit == \* the proposer is arbitrary -- works for safety + ArbitraryProposer + +============================================================================= diff --git a/spec/consensus/proposer-based-timestamp/tla/README.md b/spec/consensus/proposer-based-timestamp/tla/README.md new file mode 100644 index 00000000000..bca0c48d825 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/README.md @@ -0,0 +1,46 @@ +# PBTS: TLA+ modeling and verification tests + +The TLA+ specification [TendermintPBT.tla](./TendermintPBT.tla) models +Tendermint consensus algorithm with added clocks and proposer-based timestamps. + +## How to run tests + +The script `runApalache.sh` runs Apalache against one of the model files in this repository. This document describes how to use it. + +1. Get Apalache, by following [these](https://apalache.informal.systems/docs/apalache/installation/index.html) instructions. Summarized: + + 1. `git clone https://github.com/informalsystems/apalache.git` + 2. `make package` + +2. Define an environment variable `APALACHE_HOME` and set it to the directory where you cloned the repository (resp. unpacked the prebuilt release). `$APALACHE_HOME/bin/apalache-mc` should point to the run script. + +3. Execute `./runApalache.sh CMD N CM DD` where: + + 1. `CMD` is the command. Either "check" or "typecheck". Default: "typecheck" + 2. `N` is the number of steps if `CMD=check`. Ignored if `CMD=typecheck`. Default: 10 + 3. `MC` is a Boolean flag that controls whether the model checked has a 2/3+ majority of correct processes. Default: true + - if `MC` is `true`, the `MC_PBT_3C_1F.tla` is used as input + - if `MC` is `false`, the `MC_PBT_2C_2F.tla` is used as input + 4. `DD` is a Boolean flag that controls Apalache's `--discard-disabled` flag (See [here](https://apalache.informal.systems/docs/apalache/running.html)). Ignored if `CMD=typecheck`. Default: false + +The results will be written to `_apalache-out` (see the [Apalache documentation](https://apalache.informal.systems/docs/adr/009adr-outputs.html)). + +Example: +```sh +./runApalache.sh check 2 +``` +Checks 2 steps of `MC_PBT_3C_1F.tla` and +```sh +./runApalache.sh check 10 false +``` +Checks 10 steps of `MC_PBT_2C_2F.tla` + +## Updating the experiments log + +A summary of experiments performed is kept in [`experiment_log.md`](./experiment_log.md). + +After running a particularly significant test, copy the raw outputs from +`_apalache-out` to `experiment_data` and update `experiment_log.md` accordingly. +See `experiment_data/May2022/` for a suggested directory layout. + +Make sure to copy at least the `detailed.log` and `run.txt` files, as well as any counterexample files, if present. diff --git a/spec/consensus/proposer-based-timestamp/tla/TendermintPBT.tla b/spec/consensus/proposer-based-timestamp/tla/TendermintPBT.tla new file mode 100644 index 00000000000..fe418105fac --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/TendermintPBT.tla @@ -0,0 +1,898 @@ +-------------------- MODULE TendermintPBT --------------------------- +(* + A TLA+ specification of a simplified Tendermint consensus algorithm, with added clocks + and proposer-based timestamps. This TLA+ specification extends and modifies + the Tendermint TLA+ specification for fork accountability: + https://github.com/tendermint/spec/blob/master/spec/light-client/accountability/TendermintAcc_004_draft.tla + + * Version 2. A preliminary specification. + + Zarko Milosevic, Igor Konnov, Informal Systems, 2019-2020. + Ilina Stoilkovska, Josef Widder, Informal Systems, 2021. + Jure Kukovec, Informal Systems, 2022. + *) + +EXTENDS Integers, FiniteSets, Apalache, Sequences, typedefs + +(********************* PROTOCOL PARAMETERS **********************************) +\* General protocol parameters +CONSTANTS + \* @type: Set(PROCESS); + Corr, \* the set of correct processes + \* @type: Set(PROCESS); + Faulty, \* the set of Byzantine processes, may be empty + \* @type: Int; + N, \* the total number of processes: correct, defective, and Byzantine + \* @type: Int; + T, \* an upper bound on the number of Byzantine processes + \* @type: Set(VALUE); + ValidValues, \* the set of valid values, proposed both by correct and faulty + \* @type: Set(VALUE); + InvalidValues, \* the set of invalid values, never proposed by the correct ones + \* @type: ROUND; + MaxRound, \* the maximal round number + \* @type: ROUND -> PROCESS; + Proposer \* the proposer function from Rounds to AllProcs + +\* Time-related parameters +CONSTANTS + \* @type: TIME; + MaxTimestamp, \* the maximal value of the clock tick + \* @type: TIME; + MinTimestamp, \* the minimal value of the clock tick + \* @type: TIME; + Delay, \* message delay + \* @type: TIME; + Precision \* clock precision: the maximal difference between two local clocks + +ASSUME(N = Cardinality(Corr \union Faulty)) + +\* Modeling parameter +CONSTANTS + \* @type: Bool; + PreloadAllFaultyMsgs, + \* @type: Int; + N_GEN + +(*************************** DEFINITIONS ************************************) +\* @type: Set(PROCESS); +AllProcs == Corr \union Faulty \* the set of all processes +\* @type: Set(ROUND); +Rounds == 0..MaxRound \* the set of potential rounds +\* @type: Set(TIME); +Timestamps == 0..MaxTimestamp \* the set of clock ticks +\* @type: ROUND; +NilRound == -1 \* a special value to denote a nil round, outside of Rounds +\* @type: TIME; +NilTimestamp == -1 \* a special value to denote a nil timestamp, outside of Ticks +\* @type: Set(ROUND); +RoundsOrNil == Rounds \union {NilRound} +\* @type: Set(VALUE); +Values == ValidValues \union InvalidValues \* the set of all values +\* @type: VALUE; +NilValue == "None" \* a special value for a nil round, outside of Values +\* @type: Set(PROPOSAL); +Proposals == Values \X Timestamps \X Rounds +\* @type: PROPOSAL; +NilProposal == <> +\* @type: Set(VALUE); +ValuesOrNil == Values \union {NilValue} +\* @type: Set(DECISION); +Decisions == Proposals \X Rounds +\* @type: DECISION; +NilDecision == <> + +ArbitraryProposer == Proposer \in [Rounds -> AllProcs] +CorrectProposer == Proposer \in [Rounds -> Corr] +CyclicalProposer == + LET ProcOrder == + LET App(s,e) == Append(s,e) + IN ApaFoldSet(App, <<>>, AllProcs) + IN Proposer = [ r \in Rounds |-> ProcOrder[1 + (r % N)] ] + +ValidProposals == ValidValues \X (MinTimestamp..MaxTimestamp) \X Rounds +\* a value hash is modeled as identity +\* @type: (t) => t; +Id(v) == v + +\* The validity predicate +\* @type: (PROPOSAL) => Bool; +IsValid(p) == p \in ValidProposals + +\* Time validity check. If we want MaxTimestamp = \infty, set ValidTime(t) == TRUE +ValidTime(t) == t < MaxTimestamp + +\* @type: (PROPMESSAGE) => VALUE; +MessageValue(msg) == msg.proposal[1] +\* @type: (PROPMESSAGE) => TIME; +MessageTime(msg) == msg.proposal[2] +\* @type: (PROPMESSAGE) => ROUND; +MessageRound(msg) == msg.proposal[3] + +\* @type: (TIME, TIME) => Bool; +IsTimely(processTime, messageTime) == + /\ processTime >= messageTime - Precision + /\ processTime <= messageTime + Precision + Delay + +\* the two thresholds that are used in the algorithm +\* @type: Int; +THRESHOLD1 == T + 1 \* at least one process is not faulty +\* @type: Int; +THRESHOLD2 == 2 * T + 1 \* a quorum when having N > 3 * T + +\* @type: (TIME, TIME) => TIME; +Min2(a,b) == IF a <= b THEN a ELSE b +\* @type: (Set(TIME)) => TIME; +Min(S) == ApaFoldSet( Min2, MaxTimestamp, S ) +\* Min(S) == CHOOSE x \in S : \A y \in S : x <= y + +\* @type: (TIME, TIME) => TIME; +Max2(a,b) == IF a >= b THEN a ELSE b +\* @type: (Set(TIME)) => TIME; +Max(S) == ApaFoldSet( Max2, NilTimestamp, S ) +\* Max(S) == CHOOSE x \in S : \A y \in S : y <= x + +\* @type: (Set(MESSAGE)) => Int; +Card(S) == + LET + \* @type: (Int, MESSAGE) => Int; + PlusOne(i, m) == i + 1 + IN ApaFoldSet( PlusOne, 0, S ) + +(********************* PROTOCOL STATE VARIABLES ******************************) +VARIABLES + \* @type: PROCESS -> ROUND; + round, \* a process round number + \* @type: PROCESS -> STEP; + step, \* a process step + \* @type: PROCESS -> DECISION; + decision, \* process decision + \* @type: PROCESS -> VALUE; + lockedValue, \* a locked value + \* @type: PROCESS -> ROUND; + lockedRound, \* a locked round + \* @type: PROCESS -> PROPOSAL; + validValue, \* a valid value + \* @type: PROCESS -> ROUND; + validRound \* a valid round + +coreVars == + <> + +\* time-related variables +VARIABLES + \* @type: PROCESS -> TIME; + localClock, \* a process local clock: Corr -> Ticks + \* @type: TIME; + realTime \* a reference Newtonian real time + +temporalVars == <> + +\* book-keeping variables +VARIABLES + \* @type: ROUND -> Set(PROPMESSAGE); + msgsPropose, \* PROPOSE messages broadcast in the system, Rounds -> Messages + \* @type: ROUND -> Set(PREMESSAGE); + msgsPrevote, \* PREVOTE messages broadcast in the system, Rounds -> Messages + \* @type: ROUND -> Set(PREMESSAGE); + msgsPrecommit, \* PRECOMMIT messages broadcast in the system, Rounds -> Messages + \* @type: Set(MESSAGE); + evidence, \* the messages that were used by the correct processes to make transitions + \* @type: ACTION; + action, \* we use this variable to see which action was taken + \* @type: <> -> TIME; + proposalReceptionTime \* used to keep track when a process receives a message + +\* Action is excluded from the tuple, because it always changes +bookkeepingVars == + <> + +\* Invariant support +VARIABLES + \* @type: <> -> TIME; + beginRound \* the minimum of the local clocks at the time any process entered a new round + +(* to see a type invariant, check TendermintAccInv3 *) + +(********************* PROTOCOL INITIALIZATION ******************************) +\* @type: (ROUND) => Set(PROPMESSAGE); +FaultyProposals(r) == + [ + type : {"PROPOSAL"}, + src : Faulty, + round : {r}, + proposal : Proposals, + validRound: RoundsOrNil + ] + +\* @type: Set(PROPMESSAGE); +AllFaultyProposals == + [ + type : {"PROPOSAL"}, + src : Faulty, + round : Rounds, + proposal : Proposals, + validRound: RoundsOrNil + ] + +\* @type: (ROUND) => Set(PREMESSAGE); +FaultyPrevotes(r) == + [ + type : {"PREVOTE"}, + src : Faulty, + round: {r}, + id : Proposals + ] + +\* @type: Set(PREMESSAGE); +AllFaultyPrevotes == + [ + type : {"PREVOTE"}, + src : Faulty, + round: Rounds, + id : Proposals + ] + +\* @type: (ROUND) => Set(PREMESSAGE); +FaultyPrecommits(r) == + [ + type : {"PRECOMMIT"}, + src : Faulty, + round: {r}, + id : Proposals + ] + +\* @type: Set(PREMESSAGE); +AllFaultyPrecommits == + [ + type : {"PRECOMMIT"}, + src : Faulty, + round: Rounds, + id : Proposals + ] + +\* @type: Set(PROPMESSAGE); +AllProposals == + [ + type : {"PROPOSAL"}, + src : AllProcs, + round : Rounds, + proposal : Proposals, + validRound: RoundsOrNil + ] + +\* @type: (ROUND) => Set(PROPMESSAGE); +RoundProposals(r) == + [ + type : {"PROPOSAL"}, + src : AllProcs, + round : {r}, + proposal : Proposals, + validRound: RoundsOrNil + ] + +\* @type: (ROUND -> Set(MESSAGE)) => Bool; +BenignRoundsInMessages(msgfun) == + \* the message function never contains a message for a wrong round + \A r \in Rounds: + \A m \in msgfun[r]: + r = m.round + +\* @type: (ROUND -> Set(MESSAGE), Set(MESSAGE)) => Bool; +BenignAndSubset(msgfun, set) == + /\ \A r \in Rounds: + \* The generated values belong to SUBSET set + /\ msgfun[r] \subseteq set + \* the message function never contains a message for a wrong round + /\ \A m \in msgfun[r]: r = m.round + +InitGen == + /\ msgsPropose \in [Rounds -> Gen(N_GEN)] + /\ msgsPrevote \in [Rounds -> Gen(N_GEN)] + /\ msgsPrecommit \in [Rounds -> Gen(N_GEN)] + /\ BenignAndSubset(msgsPropose, AllFaultyProposals) + /\ BenignAndSubset(msgsPrevote, AllFaultyPrevotes) + /\ BenignAndSubset(msgsPrecommit, AllFaultyPrecommits) + +InitPreloadAllMsgs == + /\ msgsPropose \in [Rounds -> SUBSET AllFaultyProposals] + /\ msgsPrevote \in [Rounds -> SUBSET AllFaultyPrevotes] + /\ msgsPrecommit \in [Rounds -> SUBSET AllFaultyPrecommits] + /\ BenignRoundsInMessages(msgsPropose) + /\ BenignRoundsInMessages(msgsPrevote) + /\ BenignRoundsInMessages(msgsPrecommit) + +InitMsgs == + \/ /\ PreloadAllFaultyMsgs + \* /\ InitPreloadAllMsgs + /\ InitGen + \/ /\ ~PreloadAllFaultyMsgs + /\ msgsPropose = [r \in Rounds |-> {}] + /\ msgsPrevote = [r \in Rounds |-> {}] + /\ msgsPrecommit = [r \in Rounds |-> {}] + +\* The initial states of the protocol. Some faults can be in the system already. +Init == + /\ round = [p \in Corr |-> 0] + /\ localClock \in [Corr -> MinTimestamp..(MinTimestamp + Precision)] + /\ realTime = 0 + /\ step = [p \in Corr |-> "PROPOSE"] + /\ decision = [p \in Corr |-> NilDecision] + /\ lockedValue = [p \in Corr |-> NilValue] + /\ lockedRound = [p \in Corr |-> NilRound] + /\ validValue = [p \in Corr |-> NilProposal] + /\ validRound = [p \in Corr |-> NilRound] + /\ InitMsgs + /\ proposalReceptionTime = [r \in Rounds, p \in Corr |-> NilTimestamp] + /\ evidence = {} + /\ action = "Init" + /\ beginRound = + [r \in Rounds, c \in Corr |-> + IF r = 0 + THEN localClock[c] + ELSE MaxTimestamp + ] + +lastBeginRound == [ r \in Rounds |-> + Max({beginRound[r,p] : p \in Corr}) +] + +firstBeginRound == [ r \in Rounds |-> + Min({beginRound[r,p] : p \in Corr}) +] + +\* Faulty processes send messages +FaultyBroadcast == + /\ ~PreloadAllFaultyMsgs + /\ action' = "FaultyBroadcast" + /\ \E r \in Rounds: + \/ \E msgs \in SUBSET FaultyProposals(r): + /\ msgsPropose' = [msgsPropose EXCEPT ![r] = @ \union msgs] + /\ UNCHANGED <> + /\ UNCHANGED + <<(*msgsPropose,*) msgsPrevote, msgsPrecommit, + evidence, (*action,*) proposalReceptionTime>> + \/ \E msgs \in SUBSET FaultyPrevotes(r): + /\ msgsPrevote' = [msgsPrevote EXCEPT ![r] = @ \union msgs] + /\ UNCHANGED <> + /\ UNCHANGED + <> + \/ \E msgs \in SUBSET FaultyPrecommits(r): + /\ msgsPrecommit' = [msgsPrecommit EXCEPT ![r] = @ \union msgs] + /\ UNCHANGED <> + /\ UNCHANGED + <> + +(************************ MESSAGE PASSING ********************************) +\* @type: (PROCESS, ROUND, PROPOSAL, ROUND) => Bool; +BroadcastProposal(pSrc, pRound, pProposal, pValidRound) == + LET + \* @type: PROPMESSAGE; + newMsg == + [ + type |-> "PROPOSAL", + src |-> pSrc, + round |-> pRound, + proposal |-> pProposal, + validRound |-> pValidRound + ] + IN + /\ msgsPropose' = [msgsPropose EXCEPT ![pRound] = msgsPropose[pRound] \union {newMsg}] + +\* @type: (PROCESS, ROUND, PROPOSAL) => Bool; +BroadcastPrevote(pSrc, pRound, pId) == + LET + \* @type: PREMESSAGE; + newMsg == + [ + type |-> "PREVOTE", + src |-> pSrc, + round |-> pRound, + id |-> pId + ] + IN + /\ msgsPrevote' = [msgsPrevote EXCEPT ![pRound] = msgsPrevote[pRound] \union {newMsg}] + +\* @type: (PROCESS, ROUND, PROPOSAL) => Bool; +BroadcastPrecommit(pSrc, pRound, pId) == + LET + \* @type: PREMESSAGE; + newMsg == + [ + type |-> "PRECOMMIT", + src |-> pSrc, + round |-> pRound, + id |-> pId + ] + IN + /\ msgsPrecommit' = [msgsPrecommit EXCEPT ![pRound] = msgsPrecommit[pRound] \union {newMsg}] + +(***************************** TIME **************************************) + +\* [PBTS-CLOCK-PRECISION.0] +\* @type: Bool; +SynchronizedLocalClocks == + \A p \in Corr : \A q \in Corr : + p /= q => + \/ /\ localClock[p] >= localClock[q] + /\ localClock[p] - localClock[q] < Precision + \/ /\ localClock[p] < localClock[q] + /\ localClock[q] - localClock[p] < Precision + +\* [PBTS-PROPOSE.0] +\* @type: (VALUE, TIME, ROUND) => PROPOSAL; +Proposal(v, t, r) == + <> + +\* [PBTS-DECISION-ROUND.0] +\* @type: (PROPOSAL, ROUND) => DECISION; +Decision(p, r) == + <> + +(**************** MESSAGE PROCESSING TRANSITIONS *************************) +\* lines 12-13 +\* @type: (PROCESS, ROUND) => Bool; +StartRound(p, r) == + /\ step[p] /= "DECIDED" \* a decided process does not participate in consensus + /\ round' = [round EXCEPT ![p] = r] + /\ step' = [step EXCEPT ![p] = "PROPOSE"] + \* We only need to update (last)beginRound[r] once a process enters round `r` + /\ beginRound' = [beginRound EXCEPT ![r,p] = localClock[p]] + +\* lines 14-19, a proposal may be sent later +\* @type: (PROCESS) => Bool; +InsertProposal(p) == + LET r == round[p] IN + /\ p = Proposer[r] + /\ step[p] = "PROPOSE" + \* if the proposer is sending a proposal, then there are no other proposals + \* by the correct processes for the same round + /\ \A m \in msgsPropose[r]: m.src /= p + /\ \E v \in ValidValues: + LET proposal == + IF validValue[p] /= NilProposal + THEN validValue[p] + ELSE Proposal(v, localClock[p], r) + IN + /\ BroadcastProposal(p, r, proposal, validRound[p]) + /\ UNCHANGED <> + /\ UNCHANGED + <<(*msgsPropose,*) msgsPrevote, msgsPrecommit, + evidence, proposalReceptionTime>> + /\ UNCHANGED beginRound + /\ action' = "InsertProposal" + +\* a new action used to register the proposal and note the reception time. +\* [PBTS-RECEPTION-STEP.0] +\* @type: (PROCESS) => Bool; +ReceiveProposal(p) == + \E v \in Values, t \in Timestamps: + /\ LET r == round[p] IN + LET + \* @type: PROPMESSAGE; + msg == + [ + type |-> "PROPOSAL", + src |-> Proposer[round[p]], + round |-> round[p], + proposal |-> Proposal(v, t, r), + validRound |-> NilRound + ] + IN + /\ msg \in msgsPropose[round[p]] + /\ proposalReceptionTime[r,p] = NilTimestamp + /\ proposalReceptionTime' = [proposalReceptionTime EXCEPT ![r,p] = localClock[p]] + /\ UNCHANGED <> + /\ UNCHANGED + <> + /\ UNCHANGED beginRound + /\ action' = "ReceiveProposal" + +\* lines 22-27 +\* @type: (PROCESS) => Bool; +UponProposalInPropose(p) == + \E v \in Values, t \in Timestamps: + LET + r == round[p] + IN LET + \* @type: PROPOSAL; + prop == Proposal(v,t,r) + IN + /\ step[p] = "PROPOSE" (* line 22 *) + /\ LET + \* @type: PROPMESSAGE; + msg == + [ + type |-> "PROPOSAL", + src |-> Proposer[r], + round |-> r, + proposal |-> prop, + validRound |-> NilRound + ] + IN + /\ evidence' = {msg} \union evidence + /\ LET mid == (* line 23 *) + IF + \* Timeliness is checked against the process time, as was + \* recorded in proposalReceptionTime, not as it is now. + \* In the implementation, if the proposal is not timely, then we prevote + \* nil. In the natural-language specification, nothing happens. + \* This specification maintains consistency with the implementation. + /\ IsTimely( proposalReceptionTime[r, p], t) \* updated line 22 + /\ IsValid(prop) + /\ (lockedRound[p] = NilRound \/ lockedValue[p] = v) + THEN Id(prop) + ELSE NilProposal + IN + BroadcastPrevote(p, r, mid) \* lines 24-26 + /\ step' = [step EXCEPT ![p] = "PREVOTE"] + /\ UNCHANGED <> + /\ UNCHANGED + <> + /\ UNCHANGED + <> + /\ action' = "UponProposalInPropose" + +\* lines 28-33 +\* [PBTS-ALG-OLD-PREVOTE.0] +\* @type: (PROCESS) => Bool; +UponProposalInProposeAndPrevote(p) == + \E v \in Values, t \in Timestamps, vr \in Rounds, pr \in Rounds: + LET + r == round[p] + IN LET + \* @type: PROPOSAL; + prop == Proposal(v,t,pr) + IN + /\ step[p] = "PROPOSE" /\ 0 <= vr /\ vr < r \* line 28, the while part + /\ pr <= vr + /\ LET + \* @type: PROPMESSAGE; + msg == + [ + type |-> "PROPOSAL", + src |-> Proposer[r], + round |-> r, + proposal |-> prop, + validRound |-> vr + ] + IN + \* Changed from 001: no need to re-check timeliness + /\ msg \in msgsPropose[r] \* line 28 + /\ LET PV == { m \in msgsPrevote[vr]: m.id = Id(prop) } IN + /\ Cardinality(PV) >= THRESHOLD2 \* line 28 + /\ evidence' = PV \union {msg} \union evidence + /\ LET mid == (* line 29 *) + IF IsValid(prop) /\ (lockedRound[p] <= vr \/ lockedValue[p] = v) + THEN Id(prop) + ELSE NilProposal + IN + BroadcastPrevote(p, r, mid) \* lines 24-26 + /\ step' = [step EXCEPT ![p] = "PREVOTE"] + /\ UNCHANGED <> + /\ UNCHANGED + <> + /\ UNCHANGED + <> + /\ action' = "UponProposalInProposeAndPrevote" + +\* lines 34-35 + lines 61-64 (onTimeoutPrevote) +\* @type: (PROCESS) => Bool; +UponQuorumOfPrevotesAny(p) == + /\ step[p] = "PREVOTE" \* line 34 and 61 + /\ \E MyEvidence \in SUBSET msgsPrevote[round[p]]: + \* find the unique voters in the evidence + LET Voters == { m.src: m \in MyEvidence } IN + \* compare the number of the unique voters against the threshold + /\ Cardinality(Voters) >= THRESHOLD2 \* line 34 + /\ evidence' = MyEvidence \union evidence + /\ BroadcastPrecommit(p, round[p], NilProposal) + /\ step' = [step EXCEPT ![p] = "PRECOMMIT"] + /\ UNCHANGED <> + /\ UNCHANGED + <> + /\ UNCHANGED + <> + /\ action' = "UponQuorumOfPrevotesAny" + +\* lines 36-46 +\* [PBTS-ALG-NEW-PREVOTE.0] +\* @type: (PROCESS) => Bool; +UponProposalInPrevoteOrCommitAndPrevote(p) == + \E v \in ValidValues, t \in Timestamps, vr \in RoundsOrNil: + LET + r == round[p] + IN LET + \* @type: PROPOSAL; + prop == Proposal(v,t,r) + IN + /\ step[p] \in {"PREVOTE", "PRECOMMIT"} \* line 36 + /\ LET + \* @type: PROPMESSAGE; + msg == + [ + type |-> "PROPOSAL", + src |-> Proposer[r], + round |-> r, + proposal |-> prop, + validRound |-> vr + ] + IN + \* Changed from 001: no need to re-check timeliness + /\ msg \in msgsPropose[r] \* line 36 + /\ LET PV == { m \in msgsPrevote[r]: m.id = Id(prop) } IN + /\ Cardinality(PV) >= THRESHOLD2 \* line 36 + /\ evidence' = PV \union {msg} \union evidence + /\ IF step[p] = "PREVOTE" + THEN \* lines 38-41: + /\ lockedValue' = [lockedValue EXCEPT ![p] = v] + /\ lockedRound' = [lockedRound EXCEPT ![p] = r] + /\ BroadcastPrecommit(p, r, Id(prop)) + /\ step' = [step EXCEPT ![p] = "PRECOMMIT"] + ELSE + UNCHANGED <> + \* lines 42-43 + /\ validValue' = [validValue EXCEPT ![p] = prop] + /\ validRound' = [validRound EXCEPT ![p] = r] + /\ UNCHANGED <> + /\ UNCHANGED + <> + /\ UNCHANGED + <> + /\ action' = "UponProposalInPrevoteOrCommitAndPrevote" + +\* lines 47-48 + 65-67 (onTimeoutPrecommit) +\* @type: (PROCESS) => Bool; +UponQuorumOfPrecommitsAny(p) == + /\ \E MyEvidence \in SUBSET msgsPrecommit[round[p]]: + \* find the unique committers in the evidence + LET Committers == { m.src: m \in MyEvidence } IN + \* compare the number of the unique committers against the threshold + /\ Cardinality(Committers) >= THRESHOLD2 \* line 47 + /\ evidence' = MyEvidence \union evidence + /\ round[p] + 1 \in Rounds + /\ StartRound(p, round[p] + 1) + /\ UNCHANGED temporalVars + /\ UNCHANGED + <<(*round, step,*) decision, lockedValue, + lockedRound, validValue, validRound>> + /\ UNCHANGED + <> + /\ action' = "UponQuorumOfPrecommitsAny" + +\* lines 49-54 +\* [PBTS-ALG-DECIDE.0] +\* @type: (PROCESS) => Bool; +UponProposalInPrecommitNoDecision(p) == + /\ decision[p] = NilDecision \* line 49 + /\ \E v \in ValidValues, t \in Timestamps (* line 50*) , r \in Rounds, pr \in Rounds, vr \in RoundsOrNil: + LET + \* @type: PROPOSAL; + prop == Proposal(v,t,pr) + IN + /\ LET + \* @type: PROPMESSAGE; + msg == + [ + type |-> "PROPOSAL", + src |-> Proposer[r], + round |-> r, + proposal |-> prop, + validRound |-> vr + ] + IN + /\ msg \in msgsPropose[r] \* line 49 + /\ proposalReceptionTime[r,p] /= NilTimestamp \* Keep? + /\ LET PV == { m \in msgsPrecommit[r]: m.id = Id(prop) } IN + /\ Cardinality(PV) >= THRESHOLD2 \* line 49 + /\ evidence' = PV \union {msg} \union evidence + /\ decision' = [decision EXCEPT ![p] = Decision(prop, r)] \* update the decision, line 51 + \* The original algorithm does not have 'DECIDED', but it increments the height. + \* We introduced 'DECIDED' here to prevent the process from changing its decision. + /\ step' = [step EXCEPT ![p] = "DECIDED"] + /\ UNCHANGED temporalVars + /\ UNCHANGED + <> + /\ UNCHANGED + <> + /\ UNCHANGED beginRound + /\ action' = "UponProposalInPrecommitNoDecision" + +\* the actions below are not essential for safety, but added for completeness + +\* lines 20-21 + 57-60 +\* @type: (PROCESS) => Bool; +OnTimeoutPropose(p) == + /\ step[p] = "PROPOSE" + /\ p /= Proposer[round[p]] + /\ BroadcastPrevote(p, round[p], NilProposal) + /\ step' = [step EXCEPT ![p] = "PREVOTE"] + /\ UNCHANGED <> + /\ UNCHANGED + <> + /\ UNCHANGED + <> + /\ action' = "OnTimeoutPropose" + +\* lines 44-46 +\* @type: (PROCESS) => Bool; +OnQuorumOfNilPrevotes(p) == + /\ step[p] = "PREVOTE" + /\ LET PV == { m \in msgsPrevote[round[p]]: m.id = Id(NilProposal) } IN + /\ Cardinality(PV) >= THRESHOLD2 \* line 36 + /\ evidence' = PV \union evidence + /\ BroadcastPrecommit(p, round[p], Id(NilProposal)) + /\ step' = [step EXCEPT ![p] = "PRECOMMIT"] + /\ UNCHANGED <> + /\ UNCHANGED + <> + /\ UNCHANGED + <> + /\ action' = "OnQuorumOfNilPrevotes" + +\* lines 55-56 +\* @type: (PROCESS) => Bool; +OnRoundCatchup(p) == + \E r \in Rounds: + /\ r > round[p] + /\ LET RoundMsgs == msgsPropose[r] \union msgsPrevote[r] \union msgsPrecommit[r] IN + \E MyEvidence \in SUBSET RoundMsgs: + LET Faster == { m.src: m \in MyEvidence } IN + /\ Cardinality(Faster) >= THRESHOLD1 + /\ evidence' = MyEvidence \union evidence + /\ StartRound(p, r) + /\ UNCHANGED temporalVars + /\ UNCHANGED + <<(*round, step,*) decision, lockedValue, + lockedRound, validValue, validRound>> + /\ UNCHANGED + <> + /\ action' = "OnRoundCatchup" + + +(********************* PROTOCOL TRANSITIONS ******************************) +\* advance the global clock +\* @type: Bool; +AdvanceRealTime == + /\ ValidTime(realTime) + /\ \E t \in Timestamps: + /\ t > realTime + /\ realTime' = t + /\ localClock' = [p \in Corr |-> localClock[p] + (t - realTime)] + /\ UNCHANGED <> + /\ action' = "AdvanceRealTime" + +\* process timely messages +\* @type: (PROCESS) => Bool; +MessageProcessing(p) == + \* start round + \/ InsertProposal(p) + \* reception step + \/ ReceiveProposal(p) + \* processing step + \/ UponProposalInPropose(p) + \/ UponProposalInProposeAndPrevote(p) + \/ UponQuorumOfPrevotesAny(p) + \/ UponProposalInPrevoteOrCommitAndPrevote(p) + \/ UponQuorumOfPrecommitsAny(p) + \/ UponProposalInPrecommitNoDecision(p) + \* the actions below are not essential for safety, but added for completeness + \/ OnTimeoutPropose(p) + \/ OnQuorumOfNilPrevotes(p) + \/ OnRoundCatchup(p) + +(* + * A system transition. In this specificatiom, the system may eventually deadlock, + * e.g., when all processes decide. This is expected behavior, as we focus on safety. + *) +Next == + \/ AdvanceRealTime + \/ FaultyBroadcast + \/ /\ SynchronizedLocalClocks + /\ \E p \in Corr: MessageProcessing(p) + +----------------------------------------------------------------------------- + +(*************************** INVARIANTS *************************************) + +\* [PBTS-INV-AGREEMENT.0] +AgreementOnValue == + \A p, q \in Corr: + /\ decision[p] /= NilDecision + /\ decision[q] /= NilDecision + => \E v \in ValidValues, t \in Timestamps, pr \in Rounds, r1 \in Rounds, r2 \in Rounds : + LET prop == Proposal(v,t,pr) + IN + /\ decision[p] = Decision(prop, r1) + /\ decision[q] = Decision(prop, r2) + +DisagreementOnValue == + \E p, q \in Corr: + \E p1 \in ValidProposals, p2 \in ValidProposals, r1 \in Rounds, r2 \in Rounds: + /\ p1 /= p2 + /\ decision[p] = Decision(p1, r1) + /\ decision[q] = Decision(p2, r2) + +\* [PBTS-INV-VALID.0] +ConsensusValidValue == + \A p \in Corr: + \* decision[p] = Decision(Proposal(v,t,pr), r) + LET prop == decision[p][1] IN + prop /= NilProposal => prop[1] \in ValidValues + +\* [PBTS-INV-MONOTONICITY.0] +\* TODO: we would need to compare timestamps of blocks from different height + +\* [PBTS-INV-TIMELY.0] +ConsensusTimeValid == + \A p \in Corr: + \* if a process decides on v and t + \E v \in ValidValues, t \in Timestamps, pr \in Rounds, dr \in Rounds : + \* FIXME: do we need to enforce pr <= dr? + decision[p] = Decision(Proposal(v,t,pr), dr) + \* then a process found t timely at its proposal round (pr) + => \E q \in Corr: + LET propRecvTime == proposalReceptionTime[pr, q] IN + ( + /\ beginRound[pr, q] <= propRecvTime + /\ beginRound[pr+1, q] >= propRecvTime + /\ IsTimely(propRecvTime, t) + ) + +IsFirstProposedInRound(prop, src, r) == + \E msg \in msgsPropose[r]: + /\ msg.proposal = prop + /\ msg.src = src + \* If a proposal is reused this changes from Nil to a valid round + /\ msg.validRound = NilRound + +TimeLiveness == +\A r \in Rounds \ {MaxRound}, v \in ValidValues: + LET p == Proposer[r] IN + p \in Corr \* Correct process is proposer in round r + => + \E t \in Timestamps: + LET prop == Proposal(v,t,r) IN + ( + /\ IsFirstProposedInRound(prop, p, r) \* p proposes v with some timestamp t in round r + /\ LET tOffset == t + Delay + Precision IN + /\ firstBeginRound[r] <= t + /\ t <= lastBeginRound[r] + /\ lastBeginRound[r] <= tOffset + /\ tOffset <= firstBeginRound[r+1] + ) => + \A q \in Corr: + \* q eventually decides prop + LET dq == decision[q] IN + dq /= NilDecision => dq[1] = prop + + +\* a conjunction of all invariants +Inv == + /\ AgreementOnValue + /\ ConsensusValidValue + /\ ConsensusTimeValid + /\ TimeLiveness + +============================================================================= diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/MC.out b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/MC.out new file mode 100644 index 00000000000..51e2808a338 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/MC.out @@ -0,0 +1,789 @@ +@!@!@STARTMSG 2262:0 @!@!@ +Created by Apalache on Wed May 18 11:06:20 UTC 2022 +@!@!@ENDMSG 2262 @!@!@ +@!@!@STARTMSG 2110:1 @!@!@ +Invariant is violated. +@!@!@ENDMSG 2110 @!@!@ +@!@!@STARTMSG 2121:1 @!@!@ +The behavior up to this point is: +@!@!@ENDMSG 2121 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +1: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "Init" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) +/\ evidence = {} +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) +/\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "None">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, -1>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, -1>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PROPOSE">> }) +/\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) +/\ validValue = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"None", -1, -1>>>> }) + +@!@!@ENDMSG 2217 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +2: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "ReceiveProposal" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) +/\ evidence = {} +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) +/\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "None">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, -1>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PROPOSE">> }) +/\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) +/\ validValue = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"None", -1, -1>>>> }) + +@!@!@ENDMSG 2217 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +3: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "UponProposalInPropose" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) +/\ evidence = {[proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1]} +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) +/\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "None">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, -1>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PREVOTE">> }) +/\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) +/\ validValue = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"None", -1, -1>>>> }) + +@!@!@ENDMSG 2217 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +4: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "ReceiveProposal" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) +/\ evidence = {[proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1]} +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) +/\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "None">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PREVOTE">> }) +/\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) +/\ validValue = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"None", -1, -1>>>> }) + +@!@!@ENDMSG 2217 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +5: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "UponProposalInPrevoteOrCommitAndPrevote" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) +/\ evidence = { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2] } +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) +/\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "v0">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PRECOMMIT">> }) +/\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) +/\ validValue = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +@!@!@ENDMSG 2217 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +6: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "UponProposalInPropose" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) +/\ evidence = { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) +/\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "v0">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "PREVOTE">>, <<"c2", "PRECOMMIT">> }) +/\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) +/\ validValue = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +@!@!@ENDMSG 2217 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +7: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "UponProposalInPrecommitNoDecision" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, <<"c2", <<<<"v0", 3, 0>>, 0>>>> +}) +/\ evidence = { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) +/\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "v0">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "PREVOTE">>, <<"c2", "DECIDED">> }) +/\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) +/\ validValue = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +@!@!@ENDMSG 2217 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +8: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "UponProposalInPrevoteOrCommitAndPrevote" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, <<"c2", <<<<"v0", 3, 0>>, 0>>>> +}) +/\ evidence = { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ lockedValue = SetAsFun({ <<"c1", "v1">>, <<"c2", "v0">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "PRECOMMIT">>, <<"c2", "DECIDED">> }) +/\ validRound = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ validValue = SetAsFun({ <<"c1", <<"v1", 2, 0>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +@!@!@ENDMSG 2217 @!@!@ +@!@!@STARTMSG 2217:4 @!@!@ +9: +/\ Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) +/\ action = "UponProposalInPrecommitNoDecision" +/\ beginRound = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) +/\ decision = SetAsFun({ <<"c1", <<<<"v1", 2, 0>>, 0>>>>, <<"c2", <<<<"v0", 3, 0>>, 0>>>> }) +/\ evidence = { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } +/\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) +/\ lockedRound = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ lockedValue = SetAsFun({ <<"c1", "v1">>, <<"c2", "v0">> }) +/\ msgsPrecommit = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, round |-> 2, src |-> "f3", type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, round |-> 3, src |-> "f4", type |-> "PRECOMMIT"]} + >> }) +/\ msgsPrevote = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ msgsPropose = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) +/\ proposalReceptionTime = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) +/\ realTime = 0 +/\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ step = SetAsFun({ <<"c1", "DECIDED">>, <<"c2", "DECIDED">> }) +/\ validRound = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) +/\ validValue = SetAsFun({ <<"c1", <<"v1", 2, 0>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +@!@!@ENDMSG 2217 @!@!@ diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.itf.json b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.itf.json new file mode 100644 index 00000000000..232cc28dbf5 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.itf.json @@ -0,0 +1,5910 @@ +{ + "#meta": { + "format": "ITF", + "format-description": "https://apalache.informal.systems/docs/adr/015adr-trace.html", + "description": "Created by Apalache on Wed May 18 11:06:20 UTC 2022" + }, + "params": [ + "Proposer" + ], + "vars": [ + "decision", + "msgsPrecommit", + "beginRound", + "msgsPrevote", + "action", + "lockedRound", + "msgsPropose", + "validRound", + "step", + "lockedValue", + "validValue", + "realTime", + "round", + "evidence", + "proposalReceptionTime", + "localClock" + ], + "states": [ + { + "#meta": { + "index": 0 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "Init", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + -1 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "None" + ], + [ + "c2", + "None" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "PROPOSE" + ], + [ + "c2", + "PROPOSE" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + -1 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ] + ] + } + }, + { + "#meta": { + "index": 1 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "ReceiveProposal", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + -1 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "None" + ], + [ + "c2", + "None" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "PROPOSE" + ], + [ + "c2", + "PROPOSE" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + -1 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ] + ] + } + }, + { + "#meta": { + "index": 2 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "UponProposalInPropose", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + -1 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "None" + ], + [ + "c2", + "None" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "PROPOSE" + ], + [ + "c2", + "PREVOTE" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + -1 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ] + ] + } + }, + { + "#meta": { + "index": 3 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "ReceiveProposal", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + -1 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "None" + ], + [ + "c2", + "None" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "PROPOSE" + ], + [ + "c2", + "PREVOTE" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + -1 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ] + ] + } + }, + { + "#meta": { + "index": 4 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "UponProposalInPrevoteOrCommitAndPrevote", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + } + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + 0 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "None" + ], + [ + "c2", + "v0" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "PROPOSE" + ], + [ + "c2", + "PRECOMMIT" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + 0 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + "v0", + 3, + 0 + ] + } + ] + ] + } + }, + { + "#meta": { + "index": 5 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "UponProposalInPropose", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + 0 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "None" + ], + [ + "c2", + "v0" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "PREVOTE" + ], + [ + "c2", + "PRECOMMIT" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + 0 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + "v0", + 3, + 0 + ] + } + ] + ] + } + }, + { + "#meta": { + "index": 6 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "UponProposalInPrecommitNoDecision", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "v0", + 3, + 0 + ] + }, + 0 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + 0 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "None" + ], + [ + "c2", + "v0" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "PREVOTE" + ], + [ + "c2", + "DECIDED" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + -1 + ], + [ + "c2", + 0 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "None", + -1, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + "v0", + 3, + 0 + ] + } + ] + ] + } + }, + { + "#meta": { + "index": 7 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "UponProposalInPrevoteOrCommitAndPrevote", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "None", + -1, + -1 + ] + }, + -1 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "v0", + 3, + 0 + ] + }, + 0 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "v1" + ], + [ + "c2", + "v0" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "PRECOMMIT" + ], + [ + "c2", + "DECIDED" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "v1", + 2, + 0 + ] + } + ], + [ + "c2", + { + "#tup": [ + "v0", + 3, + 0 + ] + } + ] + ] + } + }, + { + "#meta": { + "index": 8 + }, + "Proposer": { + "#map": [ + [ + 0, + "f4" + ], + [ + 1, + "f4" + ], + [ + 2, + "f4" + ], + [ + 3, + "f4" + ] + ] + }, + "action": "UponProposalInPrecommitNoDecision", + "beginRound": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + 7 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + 7 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + 7 + ] + ] + }, + "decision": { + "#map": [ + [ + "c1", + { + "#tup": [ + { + "#tup": [ + "v1", + 2, + 0 + ] + }, + 0 + ] + } + ], + [ + "c2", + { + "#tup": [ + { + "#tup": [ + "v0", + 3, + 0 + ] + }, + 0 + ] + } + ] + ] + }, + "evidence": { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + }, + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + }, + "localClock": { + "#map": [ + [ + "c1", + 3 + ], + [ + "c2", + 2 + ] + ] + }, + "lockedRound": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "lockedValue": { + "#map": [ + [ + "c1", + "v1" + ], + [ + "c2", + "v0" + ] + ] + }, + "msgsPrecommit": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PRECOMMIT" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 3, + 2 + ] + }, + "round": 2, + "src": "f3", + "type": "PRECOMMIT" + } + ] + } + ], + [ + 3, + { + "#set": [ + { + "id": { + "#tup": [ + "v2", + 7, + 3 + ] + }, + "round": 3, + "src": "f4", + "type": "PRECOMMIT" + } + ] + } + ] + ] + }, + "msgsPrevote": { + "#map": [ + [ + 0, + { + "#set": [ + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "c2", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "c1", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f3", + "type": "PREVOTE" + }, + { + "id": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PREVOTE" + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "msgsPropose": { + "#map": [ + [ + 0, + { + "#set": [ + { + "proposal": { + "#tup": [ + "v0", + 3, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": 2 + }, + { + "proposal": { + "#tup": [ + "v1", + 2, + 0 + ] + }, + "round": 0, + "src": "f4", + "type": "PROPOSAL", + "validRound": -1 + } + ] + } + ], + [ + 1, + { + "#set": [ + + ] + } + ], + [ + 2, + { + "#set": [ + + ] + } + ], + [ + 3, + { + "#set": [ + + ] + } + ] + ] + }, + "proposalReceptionTime": { + "#map": [ + [ + { + "#tup": [ + 0, + "c1" + ] + }, + 3 + ], + [ + { + "#tup": [ + 2, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c1" + ] + }, + -1 + ], + [ + { + "#tup": [ + 2, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 1, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 3, + "c2" + ] + }, + -1 + ], + [ + { + "#tup": [ + 0, + "c2" + ] + }, + 2 + ], + [ + { + "#tup": [ + 3, + "c1" + ] + }, + -1 + ] + ] + }, + "realTime": 0, + "round": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "step": { + "#map": [ + [ + "c1", + "DECIDED" + ], + [ + "c2", + "DECIDED" + ] + ] + }, + "validRound": { + "#map": [ + [ + "c1", + 0 + ], + [ + "c2", + 0 + ] + ] + }, + "validValue": { + "#map": [ + [ + "c1", + { + "#tup": [ + "v1", + 2, + 0 + ] + } + ], + [ + "c2", + { + "#tup": [ + "v0", + 3, + 0 + ] + } + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.json b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.json new file mode 100644 index 00000000000..0314da0e5f0 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.json @@ -0,0 +1,34833 @@ +{ + "name": "ApalacheIR", + "version": "1.0", + "description": "https://apalache.informal.systems/docs/adr/005adr-json.html", + "modules": [ + { + "kind": "TlaModule", + "name": "counterexample", + "declarations": [ + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "ConstInit", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State0", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "Init" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSE" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSE" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State1", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "ReceiveProposal" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSE" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSE" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State2", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "UponProposalInPropose" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSE" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State3", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "ReceiveProposal" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSE" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State4", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "UponProposalInPrevoteOrCommitAndPrevote" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSE" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State5", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "UponProposalInPropose" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State6", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "UponProposalInPrecommitNoDecision" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "DECIDED" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State7", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "UponProposalInPrevoteOrCommitAndPrevote" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "DECIDED" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "State8", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Untyped", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "Proposer" + }, + { + "type": "(Int -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "action" + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "UponProposalInPrecommitNoDecision" + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "beginRound" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "(Str -> <<<>, Int>>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, Int>>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + }, + { + "type": "<>, Int>>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "evidence" + }, + { + "type": "Set([id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "[id: <>, proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "localClock" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "lockedValue" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrecommit" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PRECOMMIT" + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPrevote" + }, + { + "type": "(Int -> Set([id: <>, round: Int, src: Str, type: Str]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f3" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + }, + { + "type": "[id: <>, round: Int, src: Str, type: Str]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "id" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PREVOTE" + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([id: <>, round: Int, src: Str, type: Str])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "msgsPropose" + }, + { + "type": "(Int -> Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int]))", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>, round: Int, src: Str, type: Str, validRound: Int])>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "[proposal: <>, round: Int, src: Str, type: Str, validRound: Int]", + "kind": "OperEx", + "oper": "RECORD", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "proposal" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "round" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "src" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "f4" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "type" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "PROPOSAL" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "validRound" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + }, + { + "type": "<>, round: Int, src: Str, type: Str, validRound: Int])>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Set([proposal: <>, round: Int, src: Str, type: Str, validRound: Int])", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "proposalReceptionTime" + }, + { + "type": "(<> -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<<<>, Int>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 1 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "realTime" + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "round" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "step" + }, + { + "type": "(Str -> Str)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "DECIDED" + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "DECIDED" + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validRound" + }, + { + "type": "(Str -> Int)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Untyped", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "Untyped", + "kind": "NameEx", + "name": "validValue" + }, + { + "type": "(Str -> <>)", + "kind": "OperEx", + "oper": "Apalache!SetAsFun", + "args": [ + { + "type": "Set(<>>>)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 2 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + }, + { + "type": "<>>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + }, + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + }, + { + "type": "Untyped", + "kind": "TlaOperDecl", + "name": "InvariantViolation", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "Bool", + "kind": "OperEx", + "oper": "Apalache!Skolem", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "EXISTS3", + "args": [ + { + "type": "Str", + "kind": "NameEx", + "name": "p$41" + }, + { + "type": "Set(Str)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "Apalache!Skolem", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "EXISTS3", + "args": [ + { + "type": "Str", + "kind": "NameEx", + "name": "q$14" + }, + { + "type": "Set(Str)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c1" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "c2" + } + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "AND", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "NOT", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "FUN_APP", + "args": [ + { + "type": "(Str -> <<<>, Int>>)", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "Str", + "kind": "NameEx", + "name": "p$41" + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "NOT", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "FUN_APP", + "args": [ + { + "type": "(Str -> <<<>, Int>>)", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "Str", + "kind": "NameEx", + "name": "q$14" + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "None" + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": -1 + } + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "FORALL3", + "args": [ + { + "type": "Str", + "kind": "NameEx", + "name": "v$9" + }, + { + "type": "Set(Str)", + "kind": "OperEx", + "oper": "SET_ENUM", + "args": [ + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v0" + } + }, + { + "type": "Str", + "kind": "ValEx", + "value": { + "kind": "TlaStr", + "value": "v1" + } + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "FORALL3", + "args": [ + { + "type": "Int", + "kind": "NameEx", + "name": "t$9" + }, + { + "type": "Set(Int)", + "kind": "OperEx", + "oper": "INT_RANGE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 7 + } + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "FORALL3", + "args": [ + { + "type": "Int", + "kind": "NameEx", + "name": "pr$4" + }, + { + "type": "Set(Int)", + "kind": "OperEx", + "oper": "INT_RANGE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "FORALL3", + "args": [ + { + "type": "Int", + "kind": "NameEx", + "name": "r1$2" + }, + { + "type": "Set(Int)", + "kind": "OperEx", + "oper": "INT_RANGE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "FORALL3", + "args": [ + { + "type": "Int", + "kind": "NameEx", + "name": "r2$2" + }, + { + "type": "Set(Int)", + "kind": "OperEx", + "oper": "INT_RANGE", + "args": [ + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 0 + } + }, + { + "type": "Int", + "kind": "ValEx", + "value": { + "kind": "TlaInt", + "value": 3 + } + } + ] + }, + { + "type": "Bool", + "kind": "LetInEx", + "body": { + "type": "Bool", + "kind": "OperEx", + "oper": "OR", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "NOT", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "FUN_APP", + "args": [ + { + "type": "(Str -> <<<>, Int>>)", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "Str", + "kind": "NameEx", + "name": "p$41" + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "OPER_APP", + "args": [ + { + "type": "(() => <>)", + "kind": "NameEx", + "name": "prop$7" + } + ] + }, + { + "type": "Int", + "kind": "NameEx", + "name": "r1$2" + } + ] + } + ] + } + ] + }, + { + "type": "Bool", + "kind": "OperEx", + "oper": "NOT", + "args": [ + { + "type": "Bool", + "kind": "OperEx", + "oper": "EQ", + "args": [ + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "FUN_APP", + "args": [ + { + "type": "(Str -> <<<>, Int>>)", + "kind": "NameEx", + "name": "decision" + }, + { + "type": "Str", + "kind": "NameEx", + "name": "q$14" + } + ] + }, + { + "type": "<<<>, Int>>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "<>", + "kind": "OperEx", + "oper": "OPER_APP", + "args": [ + { + "type": "(() => <>)", + "kind": "NameEx", + "name": "prop$7" + } + ] + }, + { + "type": "Int", + "kind": "NameEx", + "name": "r2$2" + } + ] + } + ] + } + ] + } + ] + }, + "decls": [ + { + "type": "(() => <>)", + "kind": "TlaOperDecl", + "name": "prop$7", + "formalParams": [ + + ], + "isRecursive": false, + "body": { + "type": "<>", + "kind": "OperEx", + "oper": "TUPLE", + "args": [ + { + "type": "Str", + "kind": "NameEx", + "name": "v$9" + }, + { + "type": "Int", + "kind": "NameEx", + "name": "t$9" + }, + { + "type": "Int", + "kind": "NameEx", + "name": "pr$4" + } + ] + } + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.tla b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.tla new file mode 100644 index 00000000000..5250a2d544a --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.tla @@ -0,0 +1,1174 @@ +---------------------------- MODULE counterexample ---------------------------- + +EXTENDS MC_PBT_2C_2F + +(* Constant initialization state *) +ConstInit == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + +(* Initial state *) +State0 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "Init" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) + /\ evidence = {} + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) + /\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "None">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, -1>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, -1>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PROPOSE">> }) + /\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"None", -1, -1>>>> }) + +(* Transition 3 to State1 *) +State1 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "ReceiveProposal" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) + /\ evidence = {} + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) + /\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "None">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, -1>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PROPOSE">> }) + /\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"None", -1, -1>>>> }) + +(* Transition 12 to State2 *) +State2 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "UponProposalInPropose" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) + /\ evidence + = {[proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1]} + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) + /\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "None">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, -1>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PREVOTE">> }) + /\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"None", -1, -1>>>> }) + +(* Transition 3 to State3 *) +State3 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "ReceiveProposal" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) + /\ evidence + = {[proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1]} + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) + /\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "None">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PREVOTE">> }) + /\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", -1>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"None", -1, -1>>>> }) + +(* Transition 9 to State4 *) +State4 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "UponProposalInPrevoteOrCommitAndPrevote" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) + /\ evidence + = { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2] } + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) + /\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "v0">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "PROPOSE">>, <<"c2", "PRECOMMIT">> }) + /\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +(* Transition 12 to State5 *) +State5 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "UponProposalInPropose" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"None", -1, -1>>, -1>>>> }) + /\ evidence + = { [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) + /\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "v0">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "c1", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "PREVOTE">>, <<"c2", "PRECOMMIT">> }) + /\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +(* Transition 5 to State6 *) +State6 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "UponProposalInPrecommitNoDecision" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"v0", 3, 0>>, 0>>>> }) + /\ evidence + = { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) + /\ lockedValue = SetAsFun({ <<"c1", "None">>, <<"c2", "v0">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "c1", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "PREVOTE">>, <<"c2", "DECIDED">> }) + /\ validRound = SetAsFun({ <<"c1", -1>>, <<"c2", 0>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"None", -1, -1>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +(* Transition 9 to State7 *) +State7 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "UponProposalInPrevoteOrCommitAndPrevote" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"None", -1, -1>>, -1>>>>, + <<"c2", <<<<"v0", 3, 0>>, 0>>>> }) + /\ evidence + = { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ lockedValue = SetAsFun({ <<"c1", "v1">>, <<"c2", "v0">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "c1", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "c1", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "PRECOMMIT">>, <<"c2", "DECIDED">> }) + /\ validRound = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"v1", 2, 0>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +(* Transition 5 to State8 *) +State8 == + Proposer = SetAsFun({ <<0, "f4">>, <<1, "f4">>, <<2, "f4">>, <<3, "f4">> }) + /\ action = "UponProposalInPrecommitNoDecision" + /\ beginRound + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, 7>>, + <<<<1, "c1">>, 7>>, + <<<<2, "c2">>, 7>>, + <<<<1, "c2">>, 7>>, + <<<<3, "c2">>, 7>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, 7>> }) + /\ decision + = SetAsFun({ <<"c1", <<<<"v1", 2, 0>>, 0>>>>, + <<"c2", <<<<"v0", 3, 0>>, 0>>>> }) + /\ evidence + = { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "c2", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "c1", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f3", type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, round |-> 0, src |-> "f4", type |-> "PREVOTE"], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1], + [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + /\ localClock = SetAsFun({ <<"c1", 3>>, <<"c2", 2>> }) + /\ lockedRound = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ lockedValue = SetAsFun({ <<"c1", "v1">>, <<"c2", "v0">> }) + /\ msgsPrecommit + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "c1", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PRECOMMIT"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PRECOMMIT"] } + >>, + <<1, {}>>, + << + 2, {[id |-> <<"v2", 3, 2>>, + round |-> 2, + src |-> "f3", + type |-> "PRECOMMIT"]} + >>, + << + 3, {[id |-> <<"v2", 7, 3>>, + round |-> 3, + src |-> "f4", + type |-> "PRECOMMIT"]} + >> }) + /\ msgsPrevote + = SetAsFun({ << + 0, { [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "c2", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "c1", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f3", + type |-> "PREVOTE"], + [id |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PREVOTE"] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ msgsPropose + = SetAsFun({ << + 0, { [proposal |-> <<"v0", 3, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> 2], + [proposal |-> <<"v1", 2, 0>>, + round |-> 0, + src |-> "f4", + type |-> "PROPOSAL", + validRound |-> -1] } + >>, + <<1, {}>>, + <<2, {}>>, + <<3, {}>> }) + /\ proposalReceptionTime + = SetAsFun({ <<<<0, "c1">>, 3>>, + <<<<2, "c1">>, -1>>, + <<<<1, "c1">>, -1>>, + <<<<2, "c2">>, -1>>, + <<<<1, "c2">>, -1>>, + <<<<3, "c2">>, -1>>, + <<<<0, "c2">>, 2>>, + <<<<3, "c1">>, -1>> }) + /\ realTime = 0 + /\ round = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ step = SetAsFun({ <<"c1", "DECIDED">>, <<"c2", "DECIDED">> }) + /\ validRound = SetAsFun({ <<"c1", 0>>, <<"c2", 0>> }) + /\ validValue + = SetAsFun({ <<"c1", <<"v1", 2, 0>>>>, <<"c2", <<"v0", 3, 0>>>> }) + +(* The following formula holds true in the last state and violates the invariant *) +InvariantViolation == + Skolem((\E p$41 \in { "c1", "c2" }: + Skolem((\E q$14 \in { "c1", "c2" }: + (~(decision[p$41] = <<<<"None", -1, -1>>, -1>>) + /\ ~(decision[q$14] = <<<<"None", -1, -1>>, -1>>)) + /\ (\A v$9 \in { "v0", "v1" }: + \A t$9 \in 0 .. 7: + \A pr$4 \in 0 .. 3: + \A r1$2 \in 0 .. 3: + \A r2$2 \in 0 .. 3: + LET prop_si_7 == <> IN + ~(decision[p$41] = <<(prop_si_7), r1$2>>) + \/ ~(decision[q$14] = <<(prop_si_7), r2$2>>)))))) + +================================================================================ +(* Created by Apalache on Wed May 18 11:06:20 UTC 2022 *) +(* https://github.com/informalsystems/apalache *) diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/log0.smt b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/log0.smt new file mode 100644 index 00000000000..5c0edf996ed --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/log0.smt @@ -0,0 +1,5 @@ +Logging is disabled (Z3SolverContext.debug = false). Activate with --debug. +;; sat.random_seed = 0 +;; smt.random_seed = 0 +;; fp.spacer.random_seed = 0 +;; sls.random_seed = 0 diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/run.txt b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/run.txt new file mode 100644 index 00000000000..ed35549f316 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_2C_2F.tla/run.txt @@ -0,0 +1 @@ + check --length=8 --inv=Inv --cinit=CInit --discard-disabled=false MC_PBT_2C_2F.tla diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_3C_1F.tla/log0.smt b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_3C_1F.tla/log0.smt new file mode 100644 index 00000000000..5c0edf996ed --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_3C_1F.tla/log0.smt @@ -0,0 +1,5 @@ +Logging is disabled (Z3SolverContext.debug = false). Activate with --debug. +;; sat.random_seed = 0 +;; smt.random_seed = 0 +;; fp.spacer.random_seed = 0 +;; sls.random_seed = 0 diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_3C_1F.tla/run.txt b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_3C_1F.tla/run.txt new file mode 100644 index 00000000000..734b5aeac62 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/MC_PBT_3C_1F.tla/run.txt @@ -0,0 +1 @@ + check --length=8 --inv=Inv --cinit=CInit --discard-disabled=false MC_PBT_3C_1F.tla diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/machine.txt b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/machine.txt new file mode 100644 index 00000000000..2352d9db16a --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_data/May2022/machine.txt @@ -0,0 +1,34 @@ +Architecture: x86_64 +CPU op-mode(s): 32-bit, 64-bit +Byte Order: Little Endian +Address sizes: 40 bits physical, 48 bits virtual +CPU(s): 4 +On-line CPU(s) list: 0-3 +Thread(s) per core: 1 +Core(s) per socket: 4 +Socket(s): 1 +NUMA node(s): 1 +Vendor ID: GenuineIntel +CPU family: 6 +Model: 85 +Model name: Intel(R) Xeon(R) Gold 6248 CPU @ 2.50GHz +Stepping: 7 +CPU MHz: 2494.140 +BogoMIPS: 4988.28 +Virtualization: VT-x +Hypervisor vendor: KVM +Virtualization type: full +L1d cache: 128 KiB +L1i cache: 128 KiB +L2 cache: 16 MiB +NUMA node0 CPU(s): 0-3 +Vulnerability Itlb multihit: KVM: Mitigation: Split huge pages +Vulnerability L1tf: Not affected +Vulnerability Mds: Not affected +Vulnerability Meltdown: Not affected +Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp +Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization +Vulnerability Spectre v2: Mitigation; Enhanced IBRS, IBPB conditional, RSB filling +Vulnerability Srbds: Not affected +Vulnerability Tsx async abort: Not affected +Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single ssbd ibrs ibpb ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 pku ospke avx512_vnni arch_capabilities diff --git a/spec/consensus/proposer-based-timestamp/tla/experiment_log.md b/spec/consensus/proposer-based-timestamp/tla/experiment_log.md new file mode 100644 index 00000000000..70d40805cfd --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/experiment_log.md @@ -0,0 +1,9 @@ +# Experiment Log +This file summarizes the history of Apalache experiments for the PBTS specification. + +| Date | Commit | Command | Runtime [h:min:s] | Machine | Notes | +|---|---|---|---|---|---| +| May 11, 2022 | cd48156f662af8fc325a6478dfa34de6be0e36c8 | [run.txt](./experiment_data/May2022/MC_PBT_3C_1F.tla/run.txt) | 74:39:2 | [machine.txt](./experiment_data/May2022/machine.txt) | No invariant violation in 8 steps | +| May 16, 2022 | cd48156f662af8fc325a6478dfa34de6be0e36c8 | [run.txt](./experiment_data/May2022/MC_PBT_2C_2F.tla/run.txt) | 48:31:29 | [machine.txt](./experiment_data/May2022/machine.txt) | [Counterexample](experiment_data/May2022/MC_PBT_2C_2F.tla/counterexample.tla) found (expected) | + + diff --git a/spec/consensus/proposer-based-timestamp/tla/runApalache.sh b/spec/consensus/proposer-based-timestamp/tla/runApalache.sh new file mode 100755 index 00000000000..dfd0a8f07be --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/runApalache.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Works in all cases except running from jar on Windows +EXE=$APALACHE_HOME/bin/apalache-mc + +CMD=${1:-typecheck} +N=${2:-10} +MC=${3:-true} +DD=${4:-false} + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CFG=$SCRIPT_DIR/.apalache.cfg + + +if [[ $1 == "check" ]]; then + FLAGS="--length=$N --inv=Inv --cinit=CInit --discard-disabled=$DD" +else + FLAGS="" +fi + +if ! [[ -f "$CFG" ]]; then + echo "out-dir: \"$SCRIPT_DIR/_apalache-out\"" >> $CFG + echo "write-intermediate: true" >> $CFG +fi + +if [[ "$MC" = false ]]; then + # Run 2c2f + $EXE $CMD $FLAGS MC_PBT_2C_2F.tla +else + # Run 3c1f + $EXE $CMD $FLAGS MC_PBT_3C_1F.tla +fi + + + diff --git a/spec/consensus/proposer-based-timestamp/tla/typedefs.tla b/spec/consensus/proposer-based-timestamp/tla/typedefs.tla new file mode 100644 index 00000000000..72e76df54b6 --- /dev/null +++ b/spec/consensus/proposer-based-timestamp/tla/typedefs.tla @@ -0,0 +1,39 @@ +-------------------- MODULE typedefs --------------------------- +(* + @typeAlias: PROCESS = Str; + @typeAlias: VALUE = Str; + @typeAlias: STEP = Str; + @typeAlias: ROUND = Int; + @typeAlias: ACTION = Str; + @typeAlias: TRACE = Seq(Str); + @typeAlias: TIME = Int; + @typeAlias: PROPOSAL = <>; + @typeAlias: DECISION = <>; + @typeAlias: PROPMESSAGE = + [ + type: STEP, + src: PROCESS, + round: ROUND, + proposal: PROPOSAL, + validRound: ROUND + ]; + @typeAlias: PREMESSAGE = + [ + type: STEP, + src: PROCESS, + round: ROUND, + id: PROPOSAL + ]; + @typeAlias: MESSAGE = + [ + type: STEP, + src: PROCESS, + round: ROUND, + proposal: PROPOSAL, + validRound: ROUND, + id: PROPOSAL + ]; +*) +TypeAliases == TRUE + +============================================================================= \ No newline at end of file diff --git a/spec/consensus/proposer-based-timestamp/pbts-algorithm_001_draft.md b/spec/consensus/proposer-based-timestamp/v1/pbts-algorithm_001_draft.md similarity index 95% rename from spec/consensus/proposer-based-timestamp/pbts-algorithm_001_draft.md rename to spec/consensus/proposer-based-timestamp/v1/pbts-algorithm_001_draft.md index b42b3ab2f1f..82a50291a67 100644 --- a/spec/consensus/proposer-based-timestamp/pbts-algorithm_001_draft.md +++ b/spec/consensus/proposer-based-timestamp/v1/pbts-algorithm_001_draft.md @@ -1,4 +1,6 @@ -# Proposer-Based Time - Part II +# PBTS: Protocol Specification (first draft) + +This specification is **OUTDATED**. Please refer to the [new version][algorithm]. ## Updated Consensus Algorithm @@ -150,11 +152,11 @@ upon ⟨PROPOSAL, h_p, r, (v,t), ∗⟩ from proposer(h_p, r) AND 2f + 1 ⟨PREC **All other rules remains unchanged.** -Back to [main document][main]. - -[main]: ./pbts_001_draft.md - -[arXiv]: https://arxiv.org/abs/1807.04938 +Back to [main document][main_v1]. +[main_v1]: ./pbts_001_draft.md +[algorithm]: ../pbts-algorithm.md +[algorithm_v1]: ./pbts-algorithm_001_draft.md +[arXiv]: https://arxiv.org/abs/1807.04938 diff --git a/spec/consensus/proposer-based-timestamp/pbts-sysmodel_001_draft.md b/spec/consensus/proposer-based-timestamp/v1/pbts-sysmodel_001_draft.md similarity index 95% rename from spec/consensus/proposer-based-timestamp/pbts-sysmodel_001_draft.md rename to spec/consensus/proposer-based-timestamp/v1/pbts-sysmodel_001_draft.md index 8fee14252ee..803b5cd4acd 100644 --- a/spec/consensus/proposer-based-timestamp/pbts-sysmodel_001_draft.md +++ b/spec/consensus/proposer-based-timestamp/v1/pbts-sysmodel_001_draft.md @@ -1,4 +1,6 @@ -# Proposer-Based Time - Part I +# PBTS: System Model and Properties (first draft) + +This specification is **OUTDATED**. Please refer to the [new version][sysmodel]. ## System Model @@ -182,10 +184,14 @@ Let `b` be a block with a valid commit that contains at least one `precommit` me > "triggered the `PRECOMMIT`" implies that the data in `m` and `b` are "matching", that is, `m` proposed the values that are actually stored in `b`. -Back to [main document][main]. +Back to [main document][main_v1]. + +[main_v1]: ./pbts_001_draft.md + +[algorithm_v1]: ./pbts-algorithm_001_draft.md -[main]: ./pbts_001_draft.md +[sysmodel]: ../pbts-sysmodel.md [arXiv]: https://arxiv.org/abs/1807.04938 -[CMBC-FM-2THIRDS-link]: https://github.com/cometbft/cometbft/blob/main/spec/light-client/verification/verification_002_draft.md#cmbc-fm-2thirds1 +[CMBC-FM-2THIRDS-link]: ../../../light-client/verification/verification_002_draft.md#cmbc-fm-2thirds1 diff --git a/spec/consensus/proposer-based-timestamp/pbts_001_draft.md b/spec/consensus/proposer-based-timestamp/v1/pbts_001_draft.md similarity index 94% rename from spec/consensus/proposer-based-timestamp/pbts_001_draft.md rename to spec/consensus/proposer-based-timestamp/v1/pbts_001_draft.md index bcb01d73640..bc0a8882493 100644 --- a/spec/consensus/proposer-based-timestamp/pbts_001_draft.md +++ b/spec/consensus/proposer-based-timestamp/v1/pbts_001_draft.md @@ -1,4 +1,4 @@ -# Proposer-Based Time +# Proposer-Based Time (first draft) ## Current BFTTime @@ -21,7 +21,7 @@ In CometBFT, the first version of how time is computed and stored in a block wor 1. **Liveness.** The liveness of the protocol: 1. does not depend on clock synchronization, 1. depends on bounded message delays. -1. **Relation to real time.** There is no clock synchronizaton, which implies that there is **no relation** between the computed block `time` and real time. +1. **Relation to real time.** There is no clock synchronization, which implies that there is **no relation** between the computed block `time` and real time. 1. **Aggregate signatures.** As the `precommit` messages contain the local times, all these `precommit` messages typically differ in the time field, which **prevents** the use of aggregate signatures. ## Suggested Proposer-Based Time @@ -249,21 +249,20 @@ For analyzing real-time safety (Point 5), we use a system parameter `ACCURACY`, This specification describes the changes needed to be done to the Tendermint consensus algorithm as described in the [arXiv paper][arXiv] and the simplified specification in [TLA+][tlatender], and makes precise the underlying assumptions and the required properties. -- [Part I - System Model and Properties][sysmodel] -- [Part II - Protocol specification][algorithm] +- [Part I - System Model and Properties][sysmodel_v1] +- [Part II - Protocol specification][algorithm_v1] - [TLA+ Specification][proposertla] -[arXiv]: https://arxiv.org/abs/1807.04938 +[algorithm_v1]: ./pbts-algorithm_001_draft.md -[tlatender]: ../../light-client/accountability/README.md +[tlatender]: ../../../light-client/accountability/README.md [bfttime]: ../bft-time.md [lcspec]: ../../light-client/README.md -[algorithm]: ./pbts-algorithm_001_draft.md - -[sysmodel]: ./pbts-sysmodel_001_draft.md +[sysmodel_v1]: ./pbts-sysmodel_001_draft.md +[proposertla]: ../tla/TendermintPBT_001_draft.tla -[proposertla]: ./tla/TendermintPBT_001_draft.tla +[arXiv]: https://arxiv.org/abs/1807.04938 diff --git a/spec/consensus/proposer-selection.md b/spec/consensus/proposer-selection.md index f9f0ff4ace1..e5142bd3a97 100644 --- a/spec/consensus/proposer-selection.md +++ b/spec/consensus/proposer-selection.md @@ -179,7 +179,7 @@ In order to prevent this, when a new validator is added, its initial priority is where P is the total voting power of the set including V. -Curent implementation uses the penalty factor of 1.125 because it provides a small punishment that is efficient to calculate. See [here](https://github.com/tendermint/tendermint/pull/2785#discussion_r235038971) for more details. +Current implementation uses the penalty factor of 1.125 because it provides a small punishment that is efficient to calculate. See [here](https://github.com/tendermint/tendermint/pull/2785#discussion_r235038971) for more details. If we consider the validator set where p3 has just been added: diff --git a/spec/consensus/readme.md b/spec/consensus/readme.md index 9dbee537e11..48aac8c52f1 100644 --- a/spec/consensus/readme.md +++ b/spec/consensus/readme.md @@ -14,8 +14,8 @@ Specification of the consensus protocol implemented in CometBFT. - [Consensus Paper](./consensus-paper) - Latex paper on [arxiv](https://arxiv.org/abs/1807.04938) describing the Tendermint consensus algorithm, adopted in CometBFT, with proofs of safety and termination. -- [BFT Time](./bft-time.md) - How the timestamp in a CometBFT - block header is computed in a Byzantine Fault Tolerant manner +- [Time](./time.md) - How the timestamp in a CometBFT + block header is produced in a Byzantine Fault Tolerant manner - [Creating Proposal](./creating-proposal.md) - How a proposer creates a block proposal for consensus - [Light Client Protocol](./light-client) - A protocol for light weight consensus diff --git a/spec/consensus/signing.md b/spec/consensus/signing.md index 38afe35022b..8304b8e9879 100644 --- a/spec/consensus/signing.md +++ b/spec/consensus/signing.md @@ -30,14 +30,30 @@ All signed messages must correspond to one of these types. ## Timestamp -Timestamp validation is subtle and there are currently no bounds placed on the -timestamp included in a proposal or vote. It is expected that validators will honestly -report their local clock time. The median of all timestamps -included in a commit is used as the timestamp for the next block height. +Both `Proposal` and `Vote` messages include a `Timestamp` field of +[Time](../core/data_structures.md#time) data type. +Timestamp validation is subtle and there are currently no validations on the +timestamp included in a received `Proposal` or `Vote`. +As a general rule, it is expected that validators report in the Timestamp field their +local clock time. Timestamps are expected to be strictly monotonic for a given validator, though -this is not currently enforced. - +this is not enforced. + +Some timestamps, however, are used by the algorithms adopted for computing +[block times](./time.md): + +- [BFT Time](./bft-time.md): the `Timestamp` field of `Precommit` vote messages + is used to compute the `Time` for the next proposed block. + Correct validators are expected to report their local clock time, provided + that the time is higher than the current block's time. + Otherwise, the reported time is the current block's time plus 1ms. + +- [PBTS](./proposer-based-timestamp/README.md): the `Timestamp` field of a + `Proposal` message must match the proposed `Block.Time`. + Otherwise, the `Proposal` will be rejected by correct validators. + There are no requirements for `Vote.Timestamp` values. + ## ChainID ChainID is an unstructured string with a max length of 50-bytes. @@ -62,9 +78,9 @@ type PartSetHeader struct { ``` To be included in a valid vote or proposal, BlockID must either represent a `nil` block, or a complete one. -We introduce two methods, `BlockID.IsZero()` and `BlockID.IsComplete()` for these cases, respectively. +We introduce two methods, `BlockID.IsNil()` and `BlockID.IsComplete()` for these cases, respectively. -`BlockID.IsZero()` returns true for BlockID `b` if each of the following +`BlockID.IsNil()` returns true for BlockID `b` if each of the following are true: ```go @@ -133,7 +149,7 @@ A vote is valid if each of the following lines evaluates to true for vote `v`: v.Type == 0x1 || v.Type == 0x2 v.Height > 0 v.Round >= 0 -v.BlockID.IsZero() || v.BlockID.IsComplete() +v.BlockID.IsNil() || v.BlockID.IsComplete() ``` In other words, a vote is valid for signing if it contains the type of a Prevote @@ -151,7 +167,7 @@ these basic validation rules. Signers must be careful not to sign conflicting messages, also known as "double signing" or "equivocating". CometBFT has mechanisms to publish evidence of validators that signed conflicting votes, so they can be punished -by the application. Note CometBFT does not currently handle evidence of conflciting proposals, though it may in the future. +by the application. Note CometBFT does not currently handle evidence of conflicting proposals, though it may in the future. ### State @@ -207,8 +223,8 @@ In other words, a vote should only be signed if it's: This means that once a validator signs a prevote for a given height and round, the only other message it can sign for that height and round is a precommit. And once a validator signs a precommit for a given height and round, it must not sign any other message for that same height and round. -Note this includes votes for `nil`, ie. where `BlockID.IsZero()` is true. If a -signer has already signed a vote where `BlockID.IsZero()` is true, it cannot +Note this includes votes for `nil`, ie. where `BlockID.IsNil()` is true. If a +signer has already signed a vote where `BlockID.IsNil()` is true, it cannot sign another vote with the same type for the same height and round where `BlockID.IsComplete()` is true. Thus only a single vote of a particular type (ie. 0x01 or 0x02) can be signed for the same height and round. diff --git a/spec/consensus/time.md b/spec/consensus/time.md new file mode 100644 index 00000000000..c1294100621 --- /dev/null +++ b/spec/consensus/time.md @@ -0,0 +1,89 @@ +--- +order: 2 +--- +# Time + +CometBFT provides a Byzantine fault-tolerant source of time. + +Time in CometBFT is defined with the [`Time`][spec-time] field of the +block [`Header`][spec-header]. + +## Properties + +The Time produced by CometBFT satisfies the following properties: + +- **Time Monotonicity**: time is monotonically increasing. More precisely, given + two block headers `H1` of height `h1` and `H2` of height `h2`, + it is guaranteed that if `h2 > h1` then `H2.Time > H1.Time`. + +- **Byzantine Fault Tolerance**: malicious nodes or nodes with inaccurate clocks should not be able + to arbitrarily increase or decrease the block Time. + In other words, the Time of blocks should be defined by correct nodes. + +In addition, the Time produced by CometBFT is expected, by external observers, to provide: + +- **Relation to real time**: block times bear some resemblance to real time. + In other words, block times should represent, within some reasonable accuracy, + the actual clock time at which blocks were produced. + More formally, lets `t` be the clock time at which a block with header `H` + was first proposed. + Then there exists a, possibly unknown but reasonably small, bound `ACCURACY` + so that `|H.Time - t| < ACCURACY`. + +## Implementations + +CometBFT implements two algorithms for computing block times: + +- [BFT Time][bft-time]: the algorithm adopted in versions up to `v0.38.x`; + available, in legacy mode, in version `v1.x`. + +- [Proposer-Based Timestamps (PBTS)][pbts-spec]: introduced in version `v1.x`, + as a replacement for BFT Time. + +Users are strongly encouraged to adopt PBTS in new chains or switch to PBTS +when upgrading existing chains. + +### Comparison + +The table below compares BFT Time and PBTS algorithms in terms of the above enumerated properties: + +| Algorithm | Time Monotonicity | Byzantine Fault Tolerance | Relation to real time | +|-----------|:-----------------:|:---------------------------------:|-----------------------------------------------------------------------------------------------| +| BFT Time | Guaranteed | Tolerates `< 1/3` Byzantine nodes | Best effort and **not guaranteed**. | +| PBTS | Guaranteed | Tolerates `< 2/3` Byzantine nodes | Guaranteed with `ACCURACY` determined by the consensus parameters `PRECISION` and `MSGDELAY`. | + +Note that by Byzantine nodes we consider both malicious nodes, that purposely +try to increase or decrease block times, and nodes that produce or propose +inaccurate block times because they rely on inaccurate local clocks. + +For more details, refer to the specification of [BFT Time][bft-time] and [Proposer-Based Timestamps][pbts-spec]. + +## Adopting PBTS + +The Proposer-Based Timestamp (PBTS) algorithm is the recommended algorithm for +producing block times. + +As of CometBFT `v1.x`, however, PBTS is not enabled by default, neither for new +chains using default values for genesis parameters, nor for chains upgrading to +newer CometBFT versions, for backwards compatibility reasons. + +Enabling PBTS requires configuring some consensus parameters: + +- From `SynchronyParams`, the `Precision` and `MessageDelay` parameters. + They correspond, respectively, to the `PRECISION` and `MSGDELAY` parameters + adopted in the PBTS specification. +- From `FeatureParams`, the `PbtsEnableHeight` parameter, which defines the + height from which PBTS will be adopted. + While it is set to `0` (default) or in heights previous to + `PbtsEnableHeight`, BFT Time is adopted. + +Refer to the [consensus parameters specification][spec-params] for more details, +or to the [PBTS user documentation]() for a more pragmatic description of the +algorithm and recommendations on how to properly configure its parameters. + +[spec-time]: ../core/data_structures.md#time +[spec-header]: ../core/data_structures.md#header +[bft-time]: ./bft-time.md +[pbts-spec]: ./proposer-based-timestamp/README.md +[spec-params]: ../core/data_structures.md#consensusparams +[pbts-doc]: https://github.com/cometbft/cometbft/blob/feature/pbts/docs/explanation/core/proposer-based-timestamps.md diff --git a/spec/core/data_structures.md b/spec/core/data_structures.md index a5be15626b4..b978bb3ad7a 100644 --- a/spec/core/data_structures.md +++ b/spec/core/data_structures.md @@ -9,38 +9,43 @@ Here we describe the data structures in the CometBFT blockchain and the rules fo The CometBFT blockchain consists of a short list of data types: - [Data Structures](#data-structures) - - [Block](#block) - - [Execution](#execution) - - [Header](#header) - - [Version](#version) - - [BlockID](#blockid) - - [PartSetHeader](#partsetheader) - - [Part](#part) - - [Time](#time) - - [Data](#data) - - [Commit](#commit) - - [CommitSig](#commitsig) - - [BlockIDFlag](#blockidflag) - - [Vote](#vote) - - [CanonicalVote](#canonicalvote) - - [Proposal](#proposal) - - [SignedMsgType](#signedmsgtype) - - [Signature](#signature) - - [EvidenceList](#evidencelist) - - [Evidence](#evidence) - - [DuplicateVoteEvidence](#duplicatevoteevidence) - - [LightClientAttackEvidence](#lightclientattackevidence) - - [LightBlock](#lightblock) - - [SignedHeader](#signedheader) - - [ValidatorSet](#validatorset) - - [Validator](#validator) - - [Address](#address) - - [ConsensusParams](#consensusparams) - - [BlockParams](#blockparams) - - [EvidenceParams](#evidenceparams) - - [ValidatorParams](#validatorparams) - - [VersionParams](#versionparams) - - [Proof](#proof) + - [Block](#block) + - [Execution](#execution) + - [Header](#header) + - [Version](#version) + - [BlockID](#blockid) + - [PartSetHeader](#partsetheader) + - [Part](#part) + - [Time](#time) + - [Data](#data) + - [Commit](#commit) + - [ExtendedCommit](#extendedcommit) + - [CommitSig](#commitsig) + - [ExtendedCommitSig](#extendedcommitsig) + - [BlockIDFlag](#blockidflag) + - [Vote](#vote) + - [CanonicalVote](#canonicalvote) + - [CanonicalVoteExtension](#canonicalvoteextension) + - [Proposal](#proposal) + - [SignedMsgType](#signedmsgtype) + - [Signature](#signature) + - [EvidenceList](#evidencelist) + - [Evidence](#evidence) + - [DuplicateVoteEvidence](#duplicatevoteevidence) + - [LightClientAttackEvidence](#lightclientattackevidence) + - [LightBlock](#lightblock) + - [SignedHeader](#signedheader) + - [ValidatorSet](#validatorset) + - [Validator](#validator) + - [Address](#address) + - [Proof](#proof) + - [ConsensusParams](#consensusparams) + - [BlockParams](#blockparams) + - [EvidenceParams](#evidenceparams) + - [ValidatorParams](#validatorparams) + - [ABCIParams](#abciparams) + - [VersionParams](#versionparams) + - [SynchronyParams](#synchronyparams) ## Block @@ -72,7 +77,7 @@ set (TODO). Execute is defined as: ```go 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, + // Function 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) @@ -119,22 +124,22 @@ The steps to validate a new block are: A block header contains metadata about the block and about the consensus, as well as commitments to the data in the current block, the previous block, and the results returned by the application: -| Name | Type | Description | Validation | -|-------------------|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Version | [Version](#version) | Version defines the application and protocol version being used. | Must adhere to the validation rules of [Version](#version) | -| ChainID | String | ChainID is the ID of the chain. This must be unique to your chain. | ChainID must be less than 50 bytes. | -| Height | uint64 | Height is the height for this header. | Must be > 0, >= initialHeight, and == previous Height+1 | -| Time | [Time](#time) | The timestamp is equal to the weighted median of validators present in the last commit. Read more on time in the [BFT-time section](../consensus/bft-time.md). Note: the timestamp of a vote must be greater by at least one millisecond than that of the block being voted on. | Time must be >= previous header timestamp + consensus parameters TimeIotaMs. The timestamp of the first block must be equal to the genesis time (since there's no votes to compute the median). | -| LastBlockID | [BlockID](#blockid) | BlockID of the previous block. | Must adhere to the validation rules of [blockID](#blockid). The first block has `block.Header.LastBlockID == BlockID{}`. | -| LastCommitHash | slice of bytes (`[]byte`) | MerkleRoot of the lastCommit's signatures. The signatures represent the validators that committed to the last block. The first block has an empty slices of bytes for the hash. | Must be of length 32 | -| DataHash | slice of bytes (`[]byte`) | MerkleRoot of the hash of transactions. **Note**: The transactions are hashed before being included in the merkle tree, the leaves of the Merkle tree are the hashes, not the transactions themselves. | Must be of length 32 | -| ValidatorHash | slice of bytes (`[]byte`) | MerkleRoot of the current validator set. The validators are first sorted by voting power (descending), then by address (ascending) prior to computing the MerkleRoot. | Must be of length 32 | -| NextValidatorHash | slice of bytes (`[]byte`) | MerkleRoot of the next validator set. The validators are first sorted by voting power (descending), then by address (ascending) prior to computing the MerkleRoot. | Must be of length 32 | -| ConsensusHash | slice of bytes (`[]byte`) | Hash of the protobuf encoded consensus parameters. | Must be of length 32 | -| AppHash | slice of bytes (`[]byte`) | Arbitrary byte array returned by the application after executing and commiting the previous block. It serves as the basis for validating any merkle proofs that comes from the ABCI application and represents the state of the actual application rather than the state of the blockchain itself. The first block's `block.Header.AppHash` is given by `ResponseInitChain.app_hash`. | This hash is determined by the application, CometBFT can not perform validation on it. | -| LastResultHash | slice of bytes (`[]byte`) | `LastResultsHash` is the root hash of a Merkle tree built from `ResponseDeliverTx` responses (`Log`,`Info`, `Codespace` and `Events` fields are ignored). | Must be of length 32. The first block has `block.Header.ResultsHash == MerkleRoot(nil)`, i.e. the hash of an empty input, for RFC-6962 conformance. | -| EvidenceHash | slice of bytes (`[]byte`) | MerkleRoot of the evidence of Byzantine behavior included in this block. | Must be of length 32 | -| ProposerAddress | slice of bytes (`[]byte`) | Address of the original proposer of the block. Validator must be in the current validatorSet. | Must be of length 20 | +| Name | Type | Description | Validation | +|-------------------|---------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Version | [Version](#version) | Version defines the application and protocol version being used. | Must adhere to the validation rules of [Version](#version) | +| ChainID | String | ChainID is the ID of the chain. This must be unique to your chain. | ChainID must be less than 50 bytes. | +| Height | uint64 | Height is the height for this header. | Must be > 0, >= initialHeight, and == previous Height+1 | +| Time | [Time](#time) | The timestamp can be computed using [PBTS][pbts] or [BFT Time][bfttime] algorithms. In case of PBTS, it is the time at which the proposer has produced the block (the value of its local clock). In case of BFT Time, it is equal to the weighted median of timestamps present in the previous commit. | Time must be larger than the Time of the previous block header. The timestamp of the first block should not be smaller than the genesis time. When BFT Time is used, it should match the genesis time (since there's no votes to compute the median with). | +| LastBlockID | [BlockID](#blockid) | BlockID of the previous block. | Must adhere to the validation rules of [blockID](#blockid). The first block has `block.Header.LastBlockID == BlockID{}`. | +| LastCommitHash | slice of bytes (`[]byte`) | MerkleRoot of the lastCommit's signatures. The signatures represent the validators that committed to the last block. The first block has an empty slices of bytes for the hash. | Must be of length 32 | +| DataHash | slice of bytes (`[]byte`) | MerkleRoot of the hash of transactions. **Note**: The transactions are hashed before being included in the merkle tree, the leaves of the Merkle tree are the hashes, not the transactions themselves. | Must be of length 32 | +| ValidatorHash | slice of bytes (`[]byte`) | MerkleRoot of the current validator set. The validators are first sorted by voting power (descending), then by address (ascending) prior to computing the MerkleRoot. | Must be of length 32 | +| NextValidatorHash | slice of bytes (`[]byte`) | MerkleRoot of the next validator set. The validators are first sorted by voting power (descending), then by address (ascending) prior to computing the MerkleRoot. | Must be of length 32 | +| ConsensusHash | slice of bytes (`[]byte`) | Hash of the protobuf encoded consensus parameters. | Must be of length 32 | +| AppHash | slice of bytes (`[]byte`) | Arbitrary byte array returned by the application after executing and committing the previous block. It serves as the basis for validating any merkle proofs that comes from the ABCI application and represents the state of the actual application rather than the state of the blockchain itself. The first block's `block.Header.AppHash` is given by `InitChainResponse.app_hash`. | This hash is determined by the application, CometBFT can not perform validation on it. | +| LastResultHash | slice of bytes (`[]byte`) | `LastResultsHash` is the root hash of a Merkle tree built from `DeliverTxResponse` responses (`Log`,`Info`, `Codespace` and `Events` fields are ignored). | Must be of length 32. The first block has `block.Header.ResultsHash == MerkleRoot(nil)`, i.e. the hash of an empty input, for RFC-6962 conformance. | +| EvidenceHash | slice of bytes (`[]byte`) | MerkleRoot of the evidence of Byzantine behavior included in this block. | Must be of length 32 | +| ProposerAddress | slice of bytes (`[]byte`) | Address of the original proposer of the block. Validator must be in the current validatorSet. | Must be of length 20 | ## Version @@ -171,14 +176,15 @@ Part defines a part of a block. In CometBFT blocks are broken into `parts` for g | Name | Type | Description | Validation | |-------|-----------------|-----------------------------------|----------------------| -| index | int32 | Total amount of parts for a block | Must be > 0 | +| index | int32 | Total amount of parts for a block | Must be >= 0 | | bytes | bytes | MerkleRoot of a serialized block | Must be of length 32 | | proof | [Proof](#proof) | MerkleRoot of a serialized block | Must be of length 32 | ## Time -CometBFT uses the [Google.Protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) +CometBFT uses the [Google.Protobuf.Timestamp](https://protobuf.dev/reference/protobuf/google.protobuf/#timestamp) format, which uses two integers, one 64 bit integer for Seconds and a 32 bit integer for Nanoseconds. +Time is aligned with the Coordinated Universal Time (UTC). ## Data @@ -192,12 +198,14 @@ Data is just a wrapper for a list of transactions, where transactions are arbitr Commit is a simple wrapper for a list of signatures, with one for each validator. It also contains the relevant BlockID, height and round: -| Name | Type | Description | Validation | -|------------|----------------------------------|----------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------| -| Height | int64 | Height at which this commit was created. | Must be > 0 | -| Round | int32 | Round that the commit corresponds to. | Must be > 0 | -| BlockID | [BlockID](#blockid) | The blockID of the corresponding block. | Must adhere to the validation rules of [BlockID](#blockid). | -| Signatures | Array of [CommitSig](#commitsig) | Array of commit signatures that correspond to current validator set. | Length of signatures must be > 0 and adhere to the validation of each individual [Commitsig](#commitsig) | +| Name | Type | Description | Validation | +|------------|----------------------------------|----------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------| +| Height | int64 | Height at which this commit was created. | Must be >= 0. | +| Round | int32 | Round that the commit corresponds to. | Must be >= 0. | +| BlockID | [BlockID](#blockid) | The blockID of the corresponding block. | If Height > 0, then it cannot be the [BlockID](#blockid) of a nil block. | +| Signatures | Array of [CommitSig](#commitsig) | Array of commit signatures that correspond to current validator set. | If Height > 0, then the length of signatures must be > 0 and adhere to the validation of each individual [Commitsig](#commitsig). | + + ## ExtendedCommit @@ -206,8 +214,8 @@ In addition, it contains the verified vote extensions, one for each non-`nil` vo | Name | Type | Description | Validation | |--------------------|------------------------------------------|-------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------| -| Height | int64 | Height at which this commit was created. | Must be > 0 | -| Round | int32 | Round that the commit corresponds to. | Must be > 0 | +| Height | int64 | Height at which this commit was created. | Must be >= 0 | +| Round | int32 | Round that the commit corresponds to. | Must be >= 0 | | BlockID | [BlockID](#blockid) | The blockID of the corresponding block. | Must adhere to the validation rules of [BlockID](#blockid). | | ExtendedSignatures | Array of [ExtendedCommitSig](#commitsig) | The current validator set's commit signatures, extension, and extension signatures. | Length of signatures must be > 0 and adhere to the validation of each individual [ExtendedCommitSig](#extendedcommitsig) | @@ -265,8 +273,8 @@ The vote includes information about the validator signing it. When stored in the | Name | Type | Description | Validation | |--------------------|---------------------------------|------------------------------------------------------------------------------------------|------------------------------------------| | Type | [SignedMsgType](#signedmsgtype) | The type of message the vote refers to | Must be `PrevoteType` or `PrecommitType` | -| Height | int64 | Height for which this vote was created for | Must be > 0 | -| Round | int32 | Round that the commit corresponds to. | Must be > 0 | +| Height | int64 | Height for which this vote was created for | Must be > 0 | +| Round | int32 | Round that the commit corresponds to. | Must be >= 0 | | BlockID | [BlockID](#blockid) | The blockID of the corresponding block. | | | Timestamp | [Time](#time) | Timestamp represents the time at which a validator signed. | | | ValidatorAddress | bytes | Address of the validator | Length must be equal to 20 | @@ -284,8 +292,8 @@ and uses a different ordering of the fields. | Name | Type | Description | Validation | |-----------|---------------------------------|-----------------------------------------|------------------------------------------| | Type | [SignedMsgType](#signedmsgtype) | The type of message the vote refers to | Must be `PrevoteType` or `PrecommitType` | -| Height | int64 | Height in which the vote was provided. | Must be > 0 | -| Round | int64 | Round in which the vote was provided. | Must be > 0 | +| Height | int64 | Height in which the vote was provided. | Must be > 0 | +| Round | int64 | Round in which the vote was provided. | Must be >= 0 | | BlockID | string | ID of the block the vote refers to. | | | Timestamp | string | Time of the vote. | | | ChainID | string | ID of the blockchain running consensus. | | @@ -318,25 +326,25 @@ This is the structure to marshall in order to obtain the bytes to sign or verify | Name | Type | Description | Validation | |-----------|--------|---------------------------------------------|----------------------| | Extension | bytes | Vote extension provided by the Application. | Can have zero length | -| Height | int64 | Height in which the extension was provided. | Must be > 0 | -| Round | int64 | Round in which the extension was provided. | Must be > 0 | +| Height | int64 | Height in which the extension was provided. | Must be >= 0 | +| Round | int64 | Round in which the extension was provided. | Must be >= 0 | | ChainID | string | ID of the blockchain running consensus. | | ## Proposal Proposal contains height and round for which this proposal is made, BlockID as a unique identifier of proposed block, timestamp, and POLRound (a so-called Proof-of-Lock (POL) round) that is needed for -termination of the consensus. If POLRound >= 0, then BlockID corresponds to the block that -is locked in POLRound. The message is signed by the validator private key. +termination of the consensus. If POLRound >= 0, then BlockID corresponds to the block that was +or could have been locked in POLRound. The message is signed by the validator private key. | Name | Type | Description | Validation | |-----------|---------------------------------|---------------------------------------------------------------------------------------|---------------------------------------------------------| -| Type | [SignedMsgType](#signedmsgtype) | Represents a Proposal [SignedMsgType](#signedmsgtype) | Must be `ProposalType` [signedMsgType](#signedmsgtype) | -| Height | uint64 | Height for which this vote was created for | Must be > 0 | -| Round | int32 | Round that the commit corresponds to. | Must be > 0 | -| POLRound | int64 | Proof of lock | Must be > 0 | +| Type | [SignedMsgType](#signedmsgtype) | Represents a Proposal [SignedMsgType](#signedmsgtype). | Must be `ProposalType` | +| Height | uint64 | Height for which this vote was created for | Must be >= 0 | +| Round | int32 | Round that the commit corresponds to. | Must be >= 0 | +| POLRound | int64 | Proof of lock round. | Must be >= -1 | | BlockID | [BlockID](#blockid) | The blockID of the corresponding block. | [BlockID](#blockid) | -| Timestamp | [Time](#time) | Timestamp represents the time at which a validator signed. | [Time](#time) | +| Timestamp | [Time](#time) | Timestamp represents the time at which the block was produced. | [Time](#time) | | Signature | slice of bytes (`[]byte`) | Signature by the validator if they participated in consensus for the associated bock. | Length of signature must be > 0 and < 64 | ## SignedMsgType @@ -455,47 +463,106 @@ func SumTruncated(bz []byte) []byte { } ``` +## Proof + +| Name | Type | Description | Field Number | +|-----------|----------------|-----------------------------------------------|:------------:| +| total | int64 | Total number of items. | 1 | +| index | int64 | Index item to prove. | 2 | +| leaf_hash | bytes | Hash of item value. | 3 | +| aunts | repeated bytes | Hashes from leaf's sibling to a root's child. | 4 | + ## ConsensusParams -| Name | Type | Description | Field Number | -|-----------|-------------------------------------|------------------------------------------------------------------------------|--------------| -| block | [BlockParams](#blockparams) | Parameters limiting the size of a block and time between consecutive blocks. | 1 | -| evidence | [EvidenceParams](#evidenceparams) | Parameters limiting the validity of evidence of byzantine behavior. | 2 | -| validator | [ValidatorParams](#validatorparams) | Parameters limiting the types of public keys validators can use. | 3 | -| version | [BlockParams](#blockparams) | The ABCI application version. | 4 | +| Name | Type | Description | Field Number | +|-----------|-------------------------------------|-------------------------------------------------------------------------|:------------:| +| block | [BlockParams](#blockparams) | Parameters limiting the block and gas. | 1 | +| evidence | [EvidenceParams](#evidenceparams) | Parameters determining the validity of evidences of Byzantine behavior. | 2 | +| validator | [ValidatorParams](#validatorparams) | Parameters limiting the types of public keys validators can use. | 3 | +| version | [VersionParams](#versionparams) | The version of specific components of CometBFT. | 4 | +| synchrony | [SynchronyParams](#synchronyparams) | Parameters determining the validity of block timestamps. | 6 | +| feature | [FeatureParams](#featureparms) | Parameters for configuring the height from which features are enabled. | 7 | ### BlockParams -| Name | Type | Description | Field Number | -|--------------|-------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| -| max_bytes | int64 | Max size of a block, in bytes. | 1 | -| max_gas | int64 | Max sum of `GasWanted` in a proposed block. NOTE: blocks that violate this may be committed if there are Byzantine proposers. It's the application's responsibility to handle this when processing a block! | 2 | +| Name | Type | Description | Field Number | +|-----------|-------|---------------------------------------------------------|:------------:| +| max_bytes | int64 | Maximum size of a block, in bytes. | 1 | +| max_gas | int64 | Maximum gas wanted by transactions included in a block. | 2 | + +The `max_bytes` parameter must be greater or equal to -1, and cannot be greater +than the hard-coded maximum block size, which is 100MB. +If set to -1, the limit is the hard-coded maximum block size. + +The `max_gas` parameter must be greater or equal to -1. +If set to -1, no limit is enforced. + +Blocks that violate `max_gas` were potentially proposed by Byzantine validators. +CometBFT does not enforce the maximum wanted gas for committed blocks. +It is responsibility of the application handling blocks whose wanted gas exceeds +the configured `max_gas` when processing the block. ### EvidenceParams -| Name | Type | Description | Field Number | -|--------------------|------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------| -| max_age_num_blocks | int64 | Max age of evidence, in blocks. | 1 | -| max_age_duration | [google.protobuf.Duration](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Duration) | Max age of evidence, in time. It should correspond with an app's "unbonding period" or other similar mechanism for handling [Nothing-At-Stake attacks](https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed). | 2 | -| max_bytes | int64 | maximum size in bytes of total evidence allowed to be entered into a block | 3 | +| Name | Type | Description | Field Number | +|--------------------|--------------------------------------------|----------------------------------------------------------------------|:------------:| +| max_age_num_blocks | int64 | Max age of evidence, in blocks. | 1 | +| max_age_duration | [google.protobuf.Duration][proto-duration] | Max age of evidence, in time. | 2 | +| max_bytes | int64 | Maximum size in bytes of evidence allowed to be included in a block. | 3 | + +The recommended value of `max_age_duration` parameter should correspond to +the application's "unbonding period" or other similar mechanism for handling +[Nothing-At-Stake attacks](https://github.com/ethereum/wiki/wiki/Proof-of-Stake-FAQ#what-is-the-nothing-at-stake-problem-and-how-can-it-be-fixed). + +The recommended formula for calculating `max_age_num_blocks` is `max_age_duration / {average block time}`. ### ValidatorParams | Name | Type | Description | Field Number | -|---------------|-----------------|-----------------------------------------------------------------------|--------------| +|---------------|-----------------|-----------------------------------------------------------------------|:------------:| | pub_key_types | repeated string | List of accepted public key types. Uses same naming as `PubKey.Type`. | 1 | +The `pub_key_types` parameter uses ABCI public keys naming, not Amino names. + ### VersionParams -| Name | Type | Description | Field Number | -|-------------|--------|-------------------------------|--------------| -| app_version | uint64 | The ABCI application version. | 1 | +| Name | Type | Description | Field Number | +|------|--------|-------------------------------|:------------:| +| app | uint64 | The ABCI application version. | 1 | -## Proof +The `app` parameter was named `app_version` in CometBFT 0.34. -| Name | Type | Description | Field Number | -|-----------|----------------|-----------------------------------------------|--------------| -| total | int64 | Total number of items. | 1 | -| index | int64 | Index item to prove. | 2 | -| leaf_hash | bytes | Hash of item value. | 3 | -| aunts | repeated bytes | Hashes from leaf's sibling to a root's child. | 4 | +### ABCIParams + +| Name | Type | Description | Field Number | +|-------------------------------|-------|---------------------------------------------------|:------------:| +| vote_extensions_enable_height | int64 | The height where vote extensions will be enabled. | 1 | + +The `ABCIParams` type has been **deprecated** from CometBFT `v1.0`. + +### FeatureParams + +| Name | Type | Description | Field Number | +|-------------------------------|-------|-------------------------------------------------------------------|:------------:| +| vote_extensions_enable_height | int64 | First height during which vote extensions will be enabled. | 1 | +| pbts_enable_height | int64 | Height at which Proposer-Based Timestamps (PBTS) will be enabled. | 2 | + +From the configured height, and for all subsequent heights, the corresponding +feature will be enabled. +Cannot be set to heights lower or equal to the current blockchain height. +A value of 0 indicates that the feature is disabled. + +### SynchronyParams + +| Name | Type | Description | Field Number | +|---------------|--------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|:------------:| +| precision | [google.protobuf.Duration][proto-duration] | Bound for how skewed a proposer's clock may be from any validator on the network while still producing valid proposals. | 1 | +| message_delay | [google.protobuf.Duration][proto-duration] | Bound for how long a proposal message may take to reach all validators on a network and still be considered valid. | 2 | + +These parameters are part of the Proposer-Based Timestamps (PBTS) algorithm. +For more information on the relationship of the synchrony parameters to +block timestamps validity, refer to the [PBTS specification][pbts]. + +[pbts]: ../consensus/proposer-based-timestamp/README.md +[bfttime]: ../consensus/bft-time.md +[proto-duration]: https://protobuf.dev/reference/protobuf/google.protobuf/#duration diff --git a/spec/core/encoding.md b/spec/core/encoding.md index 0c2fdb1f63e..cf4c3909665 100644 --- a/spec/core/encoding.md +++ b/spec/core/encoding.md @@ -19,7 +19,7 @@ For details on varints, see the [protobuf spec](https://developers.google.com/protocol-buffers/docs/encoding#varints). For example, the byte-array `[0xA, 0xB]` would be encoded as `0x020A0B`, -while a byte-array containing 300 entires beginning with `[0xA, 0xB, ...]` would +while a byte-array containing 300 entries beginning with `[0xA, 0xB, ...]` would be encoded as `0xAC020A0B...` where `0xAC02` is the UVarint encoding of 300. ## Hashing @@ -41,7 +41,7 @@ include details of the private keys beyond their type and name. ### Key Types -Each type specifies it's own pubkey, address, and signature format. +Each type specifies its own pubkey, address, and signature format. #### Ed25519 @@ -171,7 +171,7 @@ func getSplitPoint(k int) { ... } func MerkleRoot(items [][]byte) []byte{ switch len(items) { case 0: - return empthHash() + return emptyHash() case 1: return leafHash(items[0]) default: diff --git a/spec/core/state.md b/spec/core/state.md index 1dbb020001c..4b7aa44a9ea 100644 --- a/spec/core/state.md +++ b/spec/core/state.md @@ -51,11 +51,11 @@ be found in [data structures](./data_structures.md) ## Execution -State gets updated at the end of executing a block. Of specific interest is `ResponseEndBlock` and -`ResponseCommit` +State gets updated at the end of executing a block. Of specific interest is `EndBlockResponse` and +`CommitResponse` ```go -type ResponseEndBlock struct { +type EndBlockResponse struct { ValidatorUpdates []ValidatorUpdate `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates,proto3" json:"validator_updates"` ConsensusParamUpdates *types1.ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates,proto3" json:"consensus_param_updates,omitempty"` Events []Event `protobuf:"bytes,3,rep,name=events,proto3" json:"events,omitempty"` @@ -74,7 +74,7 @@ type ValidatorUpdate struct { and ```go -type ResponseCommit struct { +type CommitResponse struct { // reserve 1 Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` RetainHeight int64 `protobuf:"varint,3,opt,name=retain_height,json=retainHeight,proto3" json:"retain_height,omitempty"` @@ -84,7 +84,7 @@ type ResponseCommit struct { `ValidatorUpdates` are used to add and remove validators to the current set as well as update validator power. Setting validator power to 0 in `ValidatorUpdate` will cause the validator to be removed. `ConsensusParams` are safely copied across (i.e. if a field is nil it gets ignored) and the -`Data` from the `ResponseCommit` is used as the `AppHash` +`Data` from the `CommitResponse` is used as the `AppHash` ## Version @@ -104,6 +104,12 @@ The total size of a block is limited in bytes by the `ConsensusParams.Block.MaxB Proposed blocks must be less than this size, and will be considered invalid otherwise. +The Application may set `ConsensusParams.Block.MaxBytes` to -1. +In that case, the actual block limit is set to 100 MB, +and CometBFT will provide all transactions in the mempool as part of `PrepareProposal`. +The application has to be careful to return a list of transactions in `PrepareProposalResponse` +whose size is less than or equal to `PrepareProposalRequest.MaxTxBytes`. + Blocks should additionally be limited by the amount of "gas" consumed by the transactions in the block, though this is not yet implemented. @@ -121,5 +127,5 @@ implemented to mitigate spam attacks. ## Validator -Validators from genesis file and `ResponseEndBlock` must have pubkeys of type ∈ +Validators from genesis file and `EndBlockResponse` must have pubkeys of type ∈ `ConsensusParams.Validator.PubKeyTypes`. diff --git a/spec/ivy-proofs/accountable_safety_2.ivy b/spec/ivy-proofs/accountable_safety_2.ivy index 7fb928909a3..599933ccc13 100644 --- a/spec/ivy-proofs/accountable_safety_2.ivy +++ b/spec/ivy-proofs/accountable_safety_2.ivy @@ -6,7 +6,7 @@ include abstract_tendermint # Here we prove the second accountability property: no well-behaved node is # ever observed to violate the accountability properties. -# The proof is done in two steps: first we prove the the abstract specification +# The proof is done in two steps: first we prove the abstract specification # satisfies the property, and then we show by refinement that this property # also holds in the concrete specification. diff --git a/spec/ivy-proofs/classic_safety.ivy b/spec/ivy-proofs/classic_safety.ivy index b422a2c175f..f5315733104 100644 --- a/spec/ivy-proofs/classic_safety.ivy +++ b/spec/ivy-proofs/classic_safety.ivy @@ -10,7 +10,7 @@ include abstract_tendermint # Here we prove the classic safety property: assuming that every two quorums # have a well-behaved node in common, no two well-behaved nodes ever disagree. -# The proof is done in two steps: first we prove the the abstract specification +# The proof is done in two steps: first we prove the abstract specification # satisfies the property, and then we show by refinement that this property # also holds in the concrete specification. diff --git a/spec/ivy-proofs/tendermint_test.ivy b/spec/ivy-proofs/tendermint_test.ivy index 1299fc086d3..35ac6300f2c 100644 --- a/spec/ivy-proofs/tendermint_test.ivy +++ b/spec/ivy-proofs/tendermint_test.ivy @@ -26,7 +26,7 @@ isolate protocol = { # Finally, call the action: #``` scenarios.scenario_1 # Note that Ivy will check at runtime that all action preconditions are -# satisfied. For example, runing the scenario twice will cause a violation of +# satisfied. For example, running the scenario twice will cause a violation of # the precondition of the `start` action, because a node cannot start twice # (see `require ~_has_started` in action `start`). diff --git a/spec/light-client/accountability/README.md b/spec/light-client/accountability/README.md index 64b475bec71..75563df708c 100644 --- a/spec/light-client/accountability/README.md +++ b/spec/light-client/accountability/README.md @@ -231,7 +231,7 @@ Execution Consequences: -* The validators in F1 will be detectable by the the fork accountability mechanisms. +* The validators in F1 will be detectable by the fork accountability mechanisms. * The validators in F2 cannot be detected using this mechanism. Only in case they signed something which conflicts with the application this can be used against them. Otherwise they do not do anything incorrect. * This case is not covered by the report as it only assumes at most 2/3 of faulty validators. diff --git a/spec/light-client/accountability/Synopsis.md b/spec/light-client/accountability/Synopsis.md index e8cf15bfa36..9488aad876e 100644 --- a/spec/light-client/accountability/Synopsis.md +++ b/spec/light-client/accountability/Synopsis.md @@ -4,7 +4,7 @@ A TLA+ specification of a simplified Tendermint consensus algorithm, tuned for fork accountability. The simplifications are as follows: -- the procotol runs for one height, that is, one-shot consensus +- the protocol runs for one height, that is, one-shot consensus - this specification focuses on safety, so timeouts are modelled with with non-determinism diff --git a/spec/light-client/accountability/TendermintAccInv_004_draft.tla b/spec/light-client/accountability/TendermintAccInv_004_draft.tla index e23f69cbae7..bbab81369d7 100644 --- a/spec/light-client/accountability/TendermintAccInv_004_draft.tla +++ b/spec/light-client/accountability/TendermintAccInv_004_draft.tla @@ -164,7 +164,7 @@ TwoThirdsPrevotes(vr, v) == Cardinality(PV) >= THRESHOLD2 \* if a process sends a PREVOTE, then there are three possibilities: -\* 1) the process is faulty, 2) the PREVOTE cotains Nil, +\* 1) the process is faulty, 2) the PREVOTE contains Nil, \* 3) there is a proposal in an earlier (valid) round and two thirds of PREVOTES IfSentPrevoteThenReceivedProposalOrTwoThirds(r) == \A mpv \in msgsPrevote[r]: @@ -254,7 +254,7 @@ NoEquivocationByCorrect(r, msgs) == \/ m.src /= p \/ m.id = v -\* a proposer nevers sends two values +\* a proposer never sends two values \* @type: ($round, $round -> Set($proposeMsg)) => Bool; ProposalsByProposer(r, msgs) == \* if the proposer is not faulty, it sends only one value diff --git a/spec/light-client/attacks/Blockchain_003_draft.tla b/spec/light-client/attacks/Blockchain_003_draft.tla index 6b725d83d6b..064a41973af 100644 --- a/spec/light-client/attacks/Blockchain_003_draft.tla +++ b/spec/light-client/attacks/Blockchain_003_draft.tla @@ -35,7 +35,7 @@ BlockHeaders == [ (* in the implementation, only the hashes of V and NextV are stored in a block, as V and NextV are stored in the application state *) VS: SUBSET AllNodes, - \* the validators of this bloc. We store the validators instead of the hash. + \* the validators of this block. We store the validators instead of the hash. NextVS: SUBSET AllNodes \* the validators of the next block. We store the next validators instead of the hash. ] diff --git a/spec/light-client/attacks/isolate-attackers_001_draft.md b/spec/light-client/attacks/isolate-attackers_001_draft.md index a130dfb6fbf..803bf87e294 100644 --- a/spec/light-client/attacks/isolate-attackers_001_draft.md +++ b/spec/light-client/attacks/isolate-attackers_001_draft.md @@ -135,7 +135,7 @@ func violatesTMValidity(ref Header, ev Header) boolean ``` - Implementation remarks - - checks whether the evidence header `ev` violates the validity property of Tendermint consensus algorithm, by checking agains a reference header + - checks whether the evidence header `ev` violates the validity property of Tendermint consensus algorithm, by checking against a reference header - Expected precondition - `ref.Height == ev.Height` - Expected postcondition diff --git a/spec/light-client/detection/Blockchain_003_draft.tla b/spec/light-client/detection/Blockchain_003_draft.tla index c57bc469382..ef04dfc4d0b 100644 --- a/spec/light-client/detection/Blockchain_003_draft.tla +++ b/spec/light-client/detection/Blockchain_003_draft.tla @@ -35,7 +35,7 @@ BlockHeaders == [ (* in the implementation, only the hashes of V and NextV are stored in a block, as V and NextV are stored in the application state *) VS: SUBSET AllNodes, - \* the validators of this bloc. We store the validators instead of the hash. + \* the validators of this block. We store the validators instead of the hash. NextVS: SUBSET AllNodes \* the validators of the next block. We store the next validators instead of the hash. ] diff --git a/spec/light-client/detection/LCDetector_003_draft.tla b/spec/light-client/detection/LCDetector_003_draft.tla index cdc492b3661..aed0ea8fcd5 100644 --- a/spec/light-client/detection/LCDetector_003_draft.tla +++ b/spec/light-client/detection/LCDetector_003_draft.tla @@ -11,7 +11,7 @@ * * - the light client has its own local clock that can drift from the reference clock * within the envelope [refClock - CLOCK_DRIFT, refClock + CLOCK_DRIFT]. - * The local clock may increase as well as decrease in the the envelope + * The local clock may increase as well as decrease in the envelope * (similar to clock synchronization). * * - the ratio of the faulty validators is set as the parameter. diff --git a/spec/light-client/detection/detection_001_reviewed.md b/spec/light-client/detection/detection_001_reviewed.md index faa89d53aa8..aa51844272a 100644 --- a/spec/light-client/detection/detection_001_reviewed.md +++ b/spec/light-client/detection/detection_001_reviewed.md @@ -621,7 +621,7 @@ func AttackDetector(root LightBlock, primary_trace []LightBlock) for each secondary in Secondaries { // we replay the primary trace with the secondary, in // order to generate evidence that we can submit to the - // secodary. We return the evidence + the trace the + // secondary. We return the evidence + the trace the // secondary told us that spans the evidence at its local store EvidenceForSecondary, newroot, secondary_trace, result := @@ -678,7 +678,7 @@ func CreateEvidenceForPeer(peer PeerID, root LightBlock, trace LightStore) auxLS, result := VerifyToTarget(peer, common, trace[i].Header.Height) if result != ResultSuccess { - // something went wrong; peer did not provide a verifyable block + // something went wrong; peer did not provide a verifiable block return (nil, nil, nil, FaultyPeer) } else { diff --git a/spec/light-client/detection/draft-functions.md b/spec/light-client/detection/draft-functions.md index f983fded124..2962ba90540 100644 --- a/spec/light-client/detection/draft-functions.md +++ b/spec/light-client/detection/draft-functions.md @@ -33,7 +33,7 @@ func checkMisbehaviorAndUpdateState(cs: ClientState, PoF: LightNodeProofOfFork) *0 < i < length(PoF.PrimaryTrace)* - supports(PoF.TrustedBlock, PoF.SecondaryTrace[1], t) - supports(PoF.SecondaryTrace[i], PoF.SecondaryTrace[i+1], t) for - *0 < i < length(PoF.SecondaryTrace)* + *0 < i < length(PoF.SecondaryTrace)* - Expected postcondition - set cs.FrozenHeight to min(cs.FrozenHeight, PoF.TrustedBlock.Header.Height) - Error condition @@ -120,9 +120,9 @@ func SubmitIBCProofOfFork( else { // the ibc component does not have the TrustedBlock and might // even be on yet a different branch. We have to compute a PoF - // that the ibc component can verifiy based on its current + // that the ibc component can verify based on its current // knowledge - + ibcLightBlock, lblock, _, result := commonRoot(lightStore, ibc, PoF.TrustedBlock) if result = Success { @@ -169,7 +169,7 @@ LightBlock) (LightBlock, LightBlock, LightStore, Result) { lblock.Height - 1); // this function does not exist yet. Alternatively, we may // request all transactions that installed headers via CosmosSDK - + for { h, result = max(ibcHeights) @@ -194,7 +194,7 @@ LightBlock) (LightBlock, LightBlock, LightStore, Result) { - a lightBlock b1 from the IBC component, and - a lightBlock b2 from the local lightStore with height less than - lblock.Header.Hight, s.t. b1 supports b2, and + lblock.Header.Height, s.t. b1 supports b2, and - a lightstore with the blocks downloaded from the ibc component @@ -237,7 +237,7 @@ func extendPoF (root LightBlock, - let prefix = connector + lightStore.Subtrace(connector.Header.Height, PoF.TrustedBlock.Header.Height-1) + - PoF.TrustedBlock + PoF.TrustedBlock - newPoF.PrimaryTrace = prefix + PoF.PrimaryTrace - newPoF.SecondaryTrace = prefix + PoF.SecondaryTrace @@ -259,7 +259,7 @@ func DetectIBCFork(ibc IBCComponent, lightStore LightStore) (LightNodeProofOfFor lb, result = LightClient.Main(primary, lightStore, cs.Header.Height) // [LCV-FUNC-IBCMAIN.1] **TODO** decide what to do following the outcome of Issue #499 - + // I guess here we have to get into the light client } @@ -281,7 +281,7 @@ func DetectIBCFork(ibc IBCComponent, lightStore LightStore) (LightNodeProofOfFor **TODO:** finish conditions - Implementation remark - - we ask the handler for the lastest check. Cross-check with the + - we ask the handler for the latest check. Cross-check with the chain. In case they deviate we generate PoF. - we assume IBC component is correct. It has verified the consensus state diff --git a/spec/light-client/detection/req-ibc-detection.md b/spec/light-client/detection/req-ibc-detection.md index ceffef1f84e..e271c8be672 100644 --- a/spec/light-client/detection/req-ibc-detection.md +++ b/spec/light-client/detection/req-ibc-detection.md @@ -17,7 +17,7 @@ In the following, I distilled what I considered relevant from | IBC Term | Cosmos Spec Term | Comment | |----------|-------------------------| --------| | `CommitmentRoot` | AppState | app hash | -| `ConsensusState` | Lightblock | not all fields are there. NextValidator is definitly needed | +| `ConsensusState` | Lightblock | not all fields are there. NextValidator is definitely needed | | `ClientState` | latest light block + configuration parameters (e.g., trusting period + `frozenHeight` | NextValidators missing; what is `proofSpecs`?| | `frozenHeight` | height of fork | set when a fork is detected | | "would-have-been-fooled" | light node fork detection | light node may submit proof of fork to IBC component to halt it | diff --git a/spec/light-client/supervisor/supervisor_001_draft.md b/spec/light-client/supervisor/supervisor_001_draft.md index 28ea997c750..44268672850 100644 --- a/spec/light-client/supervisor/supervisor_001_draft.md +++ b/spec/light-client/supervisor/supervisor_001_draft.md @@ -439,7 +439,7 @@ func Sequential-Supervisor (initdata LCInitData) (Error) { - Implementation remark - infinite loop unless a light client attack is detected - In typical implementations (e.g., the one in Rust), - there are mutliple input actions: + there are multiple input actions: `VerifytoLatest`, `LatestTrusted`, and `GetStatus`. The information can be easily obtained from the lightstore, so that we do not treat these requests explicitly here but just consider @@ -474,8 +474,8 @@ we want to maintain [LCV-INV-TP.1] from the beginning. > it may increase trust, when one cross-checks the initial light > block. However, if a peer provides a conflicting > lightblock, the question is to distinguish the case of a -> [bogus](https://informal.systems) block (upon which operation should proceed) from a -> [light client attack](https://informal.systems) (upon which operation should stop). In +> bogus block (upon which operation should proceed) from a +> light client attack (upon which operation should stop). In > case of a bogus block, the lightclient might be forced to do > backwards verification until the blocks are out of the trusting > period, to make sure no previous validator set could have generated @@ -580,7 +580,7 @@ func VerifyAndDetect (lightStore LightStore, targetHeight Height) } // get the lightblock with maximum height smaller than targetHeight - // would typically be the heighest, if we always move forward + // would typically be the heights, if we always move forward root_of_trust, r2 = lightStore.LatestPrevious(targetHeight); if r2 = false { diff --git a/spec/light-client/verification/Blockchain_002_draft.tla b/spec/light-client/verification/Blockchain_002_draft.tla index df22b346dc4..2a9712decfc 100644 --- a/spec/light-client/verification/Blockchain_002_draft.tla +++ b/spec/light-client/verification/Blockchain_002_draft.tla @@ -35,7 +35,7 @@ BlockHeaders == [ (* in the implementation, only the hashes of V and NextV are stored in a block, as V and NextV are stored in the application state *) VS: SUBSET AllNodes, - \* the validators of this bloc. We store the validators instead of the hash. + \* the validators of this block. We store the validators instead of the hash. NextVS: SUBSET AllNodes \* the validators of the next block. We store the next validators instead of the hash. ] diff --git a/spec/light-client/verification/Blockchain_003_draft.tla b/spec/light-client/verification/Blockchain_003_draft.tla index c57bc469382..8db2ba71bba 100644 --- a/spec/light-client/verification/Blockchain_003_draft.tla +++ b/spec/light-client/verification/Blockchain_003_draft.tla @@ -6,17 +6,23 @@ voting powers, introduce multiple copies of the same validator (do not forget to give them unique names though). *) -EXTENDS Integers, FiniteSets +EXTENDS Integers, FiniteSets, typedefs Min(a, b) == IF a < b THEN a ELSE b CONSTANT + \* a set of all nodes that can act as validators (correct and faulty) + \* + \* @type: Set($node); AllNodes, - (* a set of all nodes that can act as validators (correct and faulty) *) + \* a maximal height that can be ever reached (modelling artifact) + \* + \* @type: Int; ULTIMATE_HEIGHT, - (* a maximal height that can be ever reached (modelling artifact) *) + \* the period within which the validators are trusted + \* + \* @type: Int; TRUSTING_PERIOD - (* the period within which the validators are trusted *) Heights == 1..ULTIMATE_HEIGHT (* possible heights *) @@ -35,7 +41,7 @@ BlockHeaders == [ (* in the implementation, only the hashes of V and NextV are stored in a block, as V and NextV are stored in the application state *) VS: SUBSET AllNodes, - \* the validators of this bloc. We store the validators instead of the hash. + \* the validators of this block. We store the validators instead of the hash. NextVS: SUBSET AllNodes \* the validators of the next block. We store the next validators instead of the hash. ] @@ -44,14 +50,17 @@ BlockHeaders == [ LightBlocks == [header: BlockHeaders, Commits: Commits] VARIABLES + \* the current global time in integer units as perceived by the reference chain + \* @type: Int; refClock, - (* the current global time in integer units as perceived by the reference chain *) + \* A sequence of BlockHeaders, which gives us a bird view of the blockchain + \* @type: Int -> $header; blockchain, - (* A sequence of BlockHeaders, which gives us a bird view of the blockchain. *) + \* A set of faulty nodes, which can act as validators. + \* We assume that the set of faulty processes is non-decreasing. + \* If a process has recovered, it should connect using a different id. + \* @type: Set($node); Faulty - (* A set of faulty nodes, which can act as validators. We assume that the set - of faulty processes is non-decreasing. If a process has recovered, it should - connect using a different id. *) (* all variables, to be used with UNCHANGED *) vars == <> @@ -59,21 +68,11 @@ vars == <> (* The set of all correct nodes in a state *) Corr == AllNodes \ Faulty -(* APALACHE annotations *) -a <: b == a \* type annotation - -NT == STRING -NodeSet(S) == S <: {NT} -EmptyNodeSet == NodeSet({}) - -BT == [height |-> Int, time |-> Int, lastCommit |-> {NT}, VS |-> {NT}, NextVS |-> {NT}] - -LBT == [header |-> BT, Commits |-> {NT}] -(* end of APALACHE annotations *) - (****************************** BLOCKCHAIN ************************************) -(* the header is still within the trusting period *) +\* the header is still within the trusting period +\* +\* @type: $header => Bool; InTrustingPeriod(header) == refClock < header.time + TRUSTING_PERIOD @@ -97,6 +96,8 @@ TwoThirds(pVS, pNodes) == - pVS is a set of all validators, maybe including Faulty, intersecting with it, etc. - pMaxFaultRatio is a pair <> that limits the ratio a / b of the faulty validators from above (exclusive) + + @type: (Set($node), Set($node), <>) => Bool; *) FaultyValidatorsFewerThan(pFaultyNodes, pVS, maxRatio) == LET FN == pFaultyNodes \intersect pVS \* faulty nodes in pNodes @@ -108,7 +109,9 @@ FaultyValidatorsFewerThan(pFaultyNodes, pVS, maxRatio) == LET TP == CP + FP IN FP * maxRatio[2] < TP * maxRatio[1] -(* Can a block be produced by a correct peer, or an authenticated Byzantine peer *) +\* Can a block be produced by a correct peer, or an authenticated Byzantine peer +\* +\* @type: (Int, $lightHeader) => Bool; IsLightBlockAllowedByDigitalSignatures(ht, block) == \/ block.header = blockchain[ht] \* signed by correct and faulty (maybe) \/ /\ block.Commits \subseteq Faulty @@ -122,6 +125,8 @@ IsLightBlockAllowedByDigitalSignatures(ht, block) == Parameters: - pMaxFaultyRatioExclusive is a pair <> that bound the number of faulty validators in each block by the ratio a / b (exclusive) + + @type: <> => Bool; *) InitToHeight(pMaxFaultyRatioExclusive) == /\ Faulty \in SUBSET AllNodes \* some nodes may fail @@ -133,7 +138,7 @@ InitToHeight(pMaxFaultyRatioExclusive) == \* the genesis starts on day 1 /\ timestamp[1] = 1 /\ vs[1] = AllNodes - /\ lastCommit[1] = EmptyNodeSet + /\ lastCommit[1] = {} /\ \A h \in Heights \ {1}: /\ lastCommit[h] \subseteq vs[h - 1] \* the non-validators cannot commit /\ TwoThirds(vs[h - 1], lastCommit[h]) \* the commit has >2/3 of validator votes diff --git a/spec/light-client/verification/Blockchain_A_1.tla b/spec/light-client/verification/Blockchain_A_1.tla index cf8f45967b2..21d6b539f85 100644 --- a/spec/light-client/verification/Blockchain_A_1.tla +++ b/spec/light-client/verification/Blockchain_A_1.tla @@ -35,7 +35,7 @@ BlockHeaders == [ (* in the implementation, only the hashes of V and NextV are stored in a block, as V and NextV are stored in the application state *) VS: SUBSET AllNodes, - \* the validators of this bloc. We store the validators instead of the hash. + \* the validators of this block. We store the validators instead of the hash. NextVS: SUBSET AllNodes \* the validators of the next block. We store the next validators instead of the hash. ] diff --git a/spec/light-client/verification/LCVerificationApi_003_draft.tla b/spec/light-client/verification/LCVerificationApi_003_draft.tla index 8ab5e8259cb..31a29b3b3a0 100644 --- a/spec/light-client/verification/LCVerificationApi_003_draft.tla +++ b/spec/light-client/verification/LCVerificationApi_003_draft.tla @@ -2,30 +2,43 @@ (** * The common interface of the light client verification and detection. *) -EXTENDS Integers, FiniteSets +EXTENDS Integers, FiniteSets, typedefs \* the parameters of Light Client CONSTANTS + \* the period within which the validators are trusted + \* @type: Int; TRUSTING_PERIOD, - (* the period within which the validators are trusted *) + \* the assumed precision of the clock + \* @type: Int; CLOCK_DRIFT, - (* the assumed precision of the clock *) + \* the actual clock drift, which under normal circumstances should not + \* be larger than CLOCK_DRIFT (otherwise, there will be a bug) + \* + \* @type: Int; REAL_CLOCK_DRIFT, - (* the actual clock drift, which under normal circumstances should not - be larger than CLOCK_DRIFT (otherwise, there will be a bug) *) + \* a pair <> that limits that ratio of faulty validator in the blockchain + \* from above (exclusive). Cosmos security model prescribes 1 / 3 + \* @type: <>; FAULTY_RATIO - (* a pair <> that limits that ratio of faulty validator in the blockchain - from above (exclusive). Cosmos security model prescribes 1 / 3. *) VARIABLES - localClock (* current time as measured by the light client *) + \* current time as measured by the light client + \* @type: Int; + localClock -(* the header is still within the trusting period *) +\* The header is still within the trusting period. +\* @type: $header => Bool; InTrustingPeriodLocal(header) == \* note that the assumption about the drift reduces the period of trust localClock < header.time + TRUSTING_PERIOD - CLOCK_DRIFT -(* the header is still within the trusting period, even if the clock can go backwards *) +(* + The header is still within the trusting period, even if the clock can go + backwards. + + @type: $header => Bool; + *) InTrustingPeriodLocalSurely(header) == \* note that the assumption about the drift reduces the period of trust localClock < header.time + TRUSTING_PERIOD - 2 * CLOCK_DRIFT @@ -36,8 +49,10 @@ IsLocalClockWithinDrift(local, global) == /\ local <= global + REAL_CLOCK_DRIFT (** - * Check that the commits in an untrusted block form 1/3 of the next validators - * in a trusted header. + Check that the commits in an untrusted block form 1/3 of the next validators + in a trusted header. + + @type: ($lightHeader, $lightHeader) => Bool; *) SignedByOneThirdOfTrusted(trusted, untrusted) == LET TP == Cardinality(trusted.header.NextVS) @@ -50,6 +65,8 @@ SignedByOneThirdOfTrusted(trusted, untrusted) == the current time into account. [LCV-FUNC-VALID.1::TLA-PRE-UNTIMED.1] + + @type: ($lightHeader, $lightHeader) => Bool; *) ValidAndVerifiedPreUntimed(trusted, untrusted) == LET thdr == trusted.header @@ -76,6 +93,8 @@ ValidAndVerifiedPreUntimed(trusted, untrusted) == Check the precondition of ValidAndVerified, including the time checks. [LCV-FUNC-VALID.1::TLA-PRE.1] + + @type: ($lightHeader, $lightHeader, Bool) => Bool; *) ValidAndVerifiedPre(trusted, untrusted, checkFuture) == LET thdr == trusted.header @@ -124,6 +143,8 @@ ValidAndVerified(trusted, untrusted, checkFuture) == (** The invariant of the light store that is not related to the blockchain + + @type: (Int -> $lightHeader, Int -> Str) => Bool; *) LightStoreInv(fetchedLightBlocks, lightBlockStatus) == \A lh, rh \in DOMAIN fetchedLightBlocks: @@ -148,6 +169,8 @@ LightStoreInv(fetchedLightBlocks, lightBlockStatus) == an instance of Tendermint consensus. [LCV-DIST-SAFE.1::CORRECTNESS-INV.1] + + @type: ($blockchain, Int -> $lightHeader, Int -> Str) => Bool; *) CorrectnessInv(blockchain, fetchedLightBlocks, lightBlockStatus) == \A h \in DOMAIN fetchedLightBlocks: @@ -157,13 +180,18 @@ CorrectnessInv(blockchain, fetchedLightBlocks, lightBlockStatus) == (** * When the light client terminates, there are no failed blocks. * (Otherwise, someone lied to us.) + * + * @type: (Int -> $lightHeader, Int -> Str) => Bool; *) NoFailedBlocksOnSuccessInv(fetchedLightBlocks, lightBlockStatus) == \A h \in DOMAIN fetchedLightBlocks: - lightBlockStatus[h] /= "StateFailed" + lightBlockStatus[h] /= "StateFailed" (** The expected post-condition of VerifyToTarget. + + @type: ($blockchain, Bool, + Int -> $lightHeader, Int -> Str, Int, Int, Str) => Bool; *) VerifyToTargetPost(blockchain, isPeerCorrect, fetchedLightBlocks, lightBlockStatus, diff --git a/spec/light-client/verification/Lightclient_002_draft.tla b/spec/light-client/verification/Lightclient_002_draft.tla index 32c807f6e62..1e5b5671abc 100644 --- a/spec/light-client/verification/Lightclient_002_draft.tla +++ b/spec/light-client/verification/Lightclient_002_draft.tla @@ -155,7 +155,7 @@ LCInit == /\ fetchedLightBlocks = [h \in {TRUSTED_HEIGHT} |-> trustedLightBlock] \* initially, lightBlockStatus is a function of one element, i.e., TRUSTED_HEIGHT /\ lightBlockStatus = [h \in {TRUSTED_HEIGHT} |-> "StateVerified"] - \* the latest verified block the the trusted block + \* the latest verified block the trusted block /\ latestVerified = trustedLightBlock /\ InitMonitor(trustedLightBlock, trustedLightBlock, now, "SUCCESS") diff --git a/spec/light-client/verification/Lightclient_003_draft.tla b/spec/light-client/verification/Lightclient_003_draft.tla index 158146eb1cd..814abdf63f8 100644 --- a/spec/light-client/verification/Lightclient_003_draft.tla +++ b/spec/light-client/verification/Lightclient_003_draft.tla @@ -6,38 +6,60 @@ * https://github.com/informalsystems/tendermint-rs/blob/master/docs/spec/lightclient/verification.md *) -EXTENDS Integers, FiniteSets +EXTENDS Integers, FiniteSets, typedefs \* the parameters of Light Client CONSTANTS + \* an index of the block header that the light client trusts by social consensus + \* @type: Int; TRUSTED_HEIGHT, - (* an index of the block header that the light client trusts by social consensus *) + \* an index of the block header that the light client tries to verify + \* @type: Int; TARGET_HEIGHT, - (* an index of the block header that the light client tries to verify *) + \* the period within which the validators are trusted + \* @type: Int; TRUSTING_PERIOD, - (* the period within which the validators are trusted *) + \* the assumed precision of the clock + \* @type: Int; CLOCK_DRIFT, - (* the assumed precision of the clock *) + \* the actual clock drift, which under normal circumstances should not + \* be larger than CLOCK_DRIFT (otherwise, there will be a bug) + \* + \* @type: Int; REAL_CLOCK_DRIFT, - (* the actual clock drift, which under normal circumstances should not - be larger than CLOCK_DRIFT (otherwise, there will be a bug) *) + \* is primary correct? + \* @type: Bool; IS_PRIMARY_CORRECT, - (* is primary correct? *) + \* a pair <> that limits that ratio of faulty validator in the blockchain + \* from above (exclusive). Cosmos security model prescribes 1 / 3 + \* @type: <>; FAULTY_RATIO - (* a pair <> that limits that ratio of faulty validator in the blockchain - from above (exclusive). Cosmos security model prescribes 1 / 3. *) - -VARIABLES (* see TypeOK below for the variable types *) - localClock, (* the local clock of the light client *) - state, (* the current state of the light client *) - nextHeight, (* the next height to explore by the light client *) - nprobes (* the lite client iteration, or the number of block tests *) + +VARIABLES + \* current time as measured by the light client + \* @type: Int; + localClock, + \* the current state of the light client + \* @type: Str; + state, + \* the next height to explore by the light client + \* @type: Int; + nextHeight, + \* the lite client iteration, or the number of block tests + \* @type: Int; + nprobes (* the light store *) VARIABLES - fetchedLightBlocks, (* a function from heights to LightBlocks *) - lightBlockStatus, (* a function from heights to block statuses *) - latestVerified (* the latest verified block *) + \* a function from heights to LightBlocks + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* a function from heights to block statuses + \* @type: Int -> Str; + lightBlockStatus, + \* the latest verified block + \* @type: $lightHeader; + latestVerified (* the variables of the lite client *) lcvars == < $header; + blockchain, + \* A set of faulty nodes, which can act as validators. + \* We assume that the set of faulty processes is non-decreasing. + \* If a process has recovered, it should connect using a different id. + \* @type: Set($node); + Faulty \* All the variables of Blockchain. For some reason, BC!vars does not work bcvars == <> @@ -114,7 +152,7 @@ LCInit == /\ fetchedLightBlocks = [h \in {TRUSTED_HEIGHT} |-> trustedLightBlock] \* initially, lightBlockStatus is a function of one element, i.e., TRUSTED_HEIGHT /\ lightBlockStatus = [h \in {TRUSTED_HEIGHT} |-> "StateVerified"] - \* the latest verified block the the trusted block + \* the latest verified block the trusted block /\ latestVerified = trustedLightBlock /\ InitMonitor(trustedLightBlock, trustedLightBlock, localClock, "SUCCESS") @@ -141,6 +179,8 @@ FetchLightBlockInto(block, height) == \* add a block into the light store \* \* [LCV-FUNC-UPDATE.1::TLA.1] +\* +\* @type: (Int -> $lightHeader, $lightHeader) => (Int -> $lightHeader); LightStoreUpdateBlocks(lightBlocks, block) == LET ht == block.header.height IN [h \in DOMAIN lightBlocks \union {ht} |-> @@ -149,6 +189,8 @@ LightStoreUpdateBlocks(lightBlocks, block) == \* update the state of a light block \* \* [LCV-FUNC-UPDATE.1::TLA.1] +\* +\* @type: (Int -> Str, Int, Str) => (Int -> Str); LightStoreUpdateStates(statuses, ht, blockState) == [h \in DOMAIN statuses \union {ht} |-> IF h = ht THEN blockState ELSE statuses[h]] @@ -156,6 +198,8 @@ LightStoreUpdateStates(statuses, ht, blockState) == \* Check, whether newHeight is a possible next height for the light client. \* \* [LCV-FUNC-SCHEDULE.1::TLA.1] +\* +\* @type: (Int, $lightHeader, Int, Int) => Bool; CanScheduleTo(newHeight, pLatestVerified, pNextHeight, pTargetHeight) == LET ht == pLatestVerified.header.height IN \/ /\ ht = pNextHeight diff --git a/spec/light-client/verification/Lightclient_A_1.tla b/spec/light-client/verification/Lightclient_A_1.tla index 6274632d019..902108b89d5 100644 --- a/spec/light-client/verification/Lightclient_A_1.tla +++ b/spec/light-client/verification/Lightclient_A_1.tla @@ -134,7 +134,7 @@ LCInit == /\ fetchedLightBlocks = [h \in {TRUSTED_HEIGHT} |-> trustedLightBlock] \* initially, lightBlockStatus is a function of one element, i.e., TRUSTED_HEIGHT /\ lightBlockStatus = [h \in {TRUSTED_HEIGHT} |-> "StateVerified"] - \* the latest verified block the the trusted block + \* the latest verified block the trusted block /\ latestVerified = trustedLightBlock \* block should contain a copy of the block from the reference chain, with a matching commit diff --git a/spec/light-client/verification/MC4_3_correct.tla b/spec/light-client/verification/MC4_3_correct.tla index a27d8de05de..44c10e192f4 100644 --- a/spec/light-client/verification/MC4_3_correct.tla +++ b/spec/light-client/verification/MC4_3_correct.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == TRUE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_3_faulty.tla b/spec/light-client/verification/MC4_3_faulty.tla index 74b278900b6..c1fcb55680c 100644 --- a/spec/light-client/verification/MC4_3_faulty.tla +++ b/spec/light-client/verification/MC4_3_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_4_correct.tla b/spec/light-client/verification/MC4_4_correct.tla index 0a8d96b59cd..d9d87e2be54 100644 --- a/spec/light-client/verification/MC4_4_correct.tla +++ b/spec/light-client/verification/MC4_4_correct.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == TRUE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_4_correct_drifted.tla b/spec/light-client/verification/MC4_4_correct_drifted.tla index 7fefe349ea8..96f1eff85a7 100644 --- a/spec/light-client/verification/MC4_4_correct_drifted.tla +++ b/spec/light-client/verification/MC4_4_correct_drifted.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 30 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == TRUE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_4_faulty.tla b/spec/light-client/verification/MC4_4_faulty.tla index 167fa61fb11..54362a1a4f1 100644 --- a/spec/light-client/verification/MC4_4_faulty.tla +++ b/spec/light-client/verification/MC4_4_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_4_faulty_drifted.tla b/spec/light-client/verification/MC4_4_faulty_drifted.tla index e37c3cb404c..72b0820bb9c 100644 --- a/spec/light-client/verification/MC4_4_faulty_drifted.tla +++ b/spec/light-client/verification/MC4_4_faulty_drifted.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 30 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_5_correct.tla b/spec/light-client/verification/MC4_5_correct.tla index cffb22cc8f4..e7096c20f53 100644 --- a/spec/light-client/verification/MC4_5_correct.tla +++ b/spec/light-client/verification/MC4_5_correct.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == TRUE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_5_faulty.tla b/spec/light-client/verification/MC4_5_faulty.tla index 3d3a002907b..fd59e3832ea 100644 --- a/spec/light-client/verification/MC4_5_faulty.tla +++ b/spec/light-client/verification/MC4_5_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) IS_PRICLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting MARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_6_faulty.tla b/spec/light-client/verification/MC4_6_faulty.tla index 64f164854b7..08c97953261 100644 --- a/spec/light-client/verification/MC4_6_faulty.tla +++ b/spec/light-client/verification/MC4_6_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) IS_PRCLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IMARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC4_7_faulty.tla b/spec/light-client/verification/MC4_7_faulty.tla index dc6a94eb1d4..f757227824e 100644 --- a/spec/light-client/verification/MC4_7_faulty.tla +++ b/spec/light-client/verification/MC4_7_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC5_5_correct.tla b/spec/light-client/verification/MC5_5_correct.tla index 00b4151f7c4..09f2dac8840 100644 --- a/spec/light-client/verification/MC5_5_correct.tla +++ b/spec/light-client/verification/MC5_5_correct.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == TRUE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC5_5_correct_peer_two_thirds_faulty.tla b/spec/light-client/verification/MC5_5_correct_peer_two_thirds_faulty.tla index d4212032fc4..d950a7d7d36 100644 --- a/spec/light-client/verification/MC5_5_correct_peer_two_thirds_faulty.tla +++ b/spec/light-client/verification/MC5_5_correct_peer_two_thirds_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == TRUE +\* @type: <>; FAULTY_RATIO == <<2, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC5_7_faulty.tla b/spec/light-client/verification/MC5_7_faulty.tla index 63461b0c891..d257da1c931 100644 --- a/spec/light-client/verification/MC5_7_faulty.tla +++ b/spec/light-client/verification/MC5_7_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC7_5_faulty.tla b/spec/light-client/verification/MC7_5_faulty.tla index 860f9c0aa8e..64d0032e05e 100644 --- a/spec/light-client/verification/MC7_5_faulty.tla +++ b/spec/light-client/verification/MC7_5_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/MC7_7_faulty.tla b/spec/light-client/verification/MC7_7_faulty.tla index 79e328f141e..b7fe366b3c9 100644 --- a/spec/light-client/verification/MC7_7_faulty.tla +++ b/spec/light-client/verification/MC7_7_faulty.tla @@ -7,19 +7,40 @@ TRUSTING_PERIOD == 1400 \* two weeks, one day is 100 time units :-) CLOCK_DRIFT == 10 \* how much we assume the local clock is drifting REAL_CLOCK_DRIFT == 3 \* how much the local clock is actually drifting IS_PRIMARY_CORRECT == FALSE +\* @type: <>; FAULTY_RATIO == <<1, 3>> \* < 1 / 3 faulty validators VARIABLES - state, nextHeight, fetchedLightBlocks, lightBlockStatus, latestVerified, + \* @type: Str; + state, + \* @type: Int; + nextHeight, + \* @type: Int -> $lightHeader; + fetchedLightBlocks, + \* @type: Int -> Str; + lightBlockStatus, + \* @type: $lightHeader; + latestVerified, + \* @type: Int; nprobes, + \* @type: Int; localClock, - refClock, blockchain, Faulty + \* @type: Int; + refClock, + \* @type: Int -> $header; + blockchain, + \* @type: Set($node); + Faulty (* the light client previous state components, used for monitoring *) VARIABLES + \* @type: $lightHeader; prevVerified, + \* @type: $lightHeader; prevCurrent, + \* @type: Int; prevLocalClock, + \* @type: Str; prevVerdict INSTANCE Lightclient_003_draft diff --git a/spec/light-client/verification/typedefs.tla b/spec/light-client/verification/typedefs.tla new file mode 100644 index 00000000000..5e06de45048 --- /dev/null +++ b/spec/light-client/verification/typedefs.tla @@ -0,0 +1,25 @@ +--------------------------- MODULE typedefs ---------------------------- +(* + // a node id, just a string + @typeAlias: node = Str; + + // a block header + @typeAlias: header = { + height: Int, + time: Int, + lastCommit: Set($node), + VS: Set($node), + NextVS: Set($node) + }; + + // the blockchain is a function of heights to blocks + @typeAlias: blockchain = Int -> $header; + + // a light-client block header + @typeAlias: lightHeader = { + header: $header, + Commits: Set($node) + }; + *) +typedefs == TRUE +======================================================================== diff --git a/spec/light-client/verification/verification_001_published.md b/spec/light-client/verification/verification_001_published.md index 45123d1a29a..8e6e9fbb306 100644 --- a/spec/light-client/verification/verification_001_published.md +++ b/spec/light-client/verification/verification_001_published.md @@ -29,7 +29,7 @@ formalized in TLA+ and model checked. ## Issues that need to be addressed As it is part of the larger light node, its data structures and -functions interact with the fork dectection functionality of the light +functions interact with the fork detection functionality of the light client. As a result of the work on [Pull Request 479](https://github.com/informalsystems/tendermint-rs/pull/479) we established the need for an update in the data structures in [Issue 499](https://github.com/informalsystems/tendermint-rs/issues/499). This diff --git a/spec/light-client/verification/verification_002_draft.md b/spec/light-client/verification/verification_002_draft.md index 4ae3731f825..5744b7166ff 100644 --- a/spec/light-client/verification/verification_002_draft.md +++ b/spec/light-client/verification/verification_002_draft.md @@ -32,7 +32,7 @@ formalized in TLA+ and model checked. ## Issues that are addressed in this revision As it is part of the larger light node, its data structures and -functions interact with the attack dectection functionality of the light +functions interact with the attack detection functionality of the light client. As a result of the work on - [attack detection](https://github.com/tendermint/spec/pull/164) for light nodes diff --git a/spec/light-client/verification/verification_003_draft.md b/spec/light-client/verification/verification_003_draft.md index 6ff8f65419a..35f44b37bf7 100644 --- a/spec/light-client/verification/verification_003_draft.md +++ b/spec/light-client/verification/verification_003_draft.md @@ -1,4 +1,4 @@ -# Light Client Verificaiton +# Light Client Verification #### **[LCV-FUNC-VERIFYCOMMITLIGHT.1]** @@ -29,7 +29,7 @@ height int64, commit *Commit) error { continue } - // If the vals and commit have a 1-to-1 correspondance we can retrieve + // If the vals and commit have a 1-to-1 correspondence we can retrieve // them by index else we need to retrieve them by address if lookUpByIndex { val = vals.Validators[idx] diff --git a/spec/mempool/mempool.md b/spec/mempool/mempool.md new file mode 100644 index 00000000000..543d4d14e42 --- /dev/null +++ b/spec/mempool/mempool.md @@ -0,0 +1,156 @@ +# Mempool + +In this document, we define the notion of **mempool** and characterize its role in **CometBFT**. +First, we provide an overview of what is a mempool, and relate it to other blockchains. +Then, the interactions with the consensus and client application are detailed. +A formalization of the mempool follows. +This formalization is readable in Quint [here](./quint). + +## Overview + +The mempool acts as an entry point to consensus. +It permits to disseminate transactions from one node to another, for their eventual inclusion into a block. +To this end, the mempool maintains a replicated set, or _pool_, of transactions. +Transactions in the mempool are consumed by consensus to create the next proposed block. +Once a new block in the blockchain is decided, the mempool is refreshed. +We shall detail how shortly. + +A transaction can be received from a local client, or a remote disseminating process. +Each transaction is subject to a test by the client application. +This test verifies that the transaction is _valid_. +Such a test provides some form of protection against byzantine agents, whether they be clients or other system nodes. +It also serves to optimize the overall utility of the blockchain. +Validity can be simply syntactical which is stateless, or a more complex verification that is state-dependent. +If the transaction is valid, the local process further propagates it in the system using a gossip (or an anti-entropy) mechanism. + +_In other blockchains._ +The notion of mempool appears in all blockchains, but with varying definitions and/or implementations. +For instance in Ethereum, the mempool contains two types of transactions: processable and pending ones. +To be pending, a transactions must first succeed in a series of tests. +Some of these tests are [syntactic](https://github.com/ethereum/go-ethereum/blob/281e8cd5abaac86ed3f37f98250ff147b3c9fe62/core/txpool/txpool.go#L581) ones (e.g., valid source address), while [others](https://github.com/ethereum/go-ethereum/blob/281e8cd5abaac86ed3f37f98250ff147b3c9fe62/core/txpool/txpool.go#L602) are state-dependent (e.g., enough gas, at most one pending transactions per address, etc). +[Narwhal](https://arxiv.org/abs/2105.11827.pdf) is the mempool abstraction for the Tusk and [Bullshark](https://arxiv.org/pdf/2201.05677) protocols. +It provides strong global guarantees. +In particular, once a transaction is added to the mempool, it is guaranteed to be available at any later point in time. + +## Interactions + +In what follows, we present the interactions of the mempool with other parts of CometBFT. +Some of the specificities of the current implementation (`CListMempool`) are also detailed. + +**RPC server** +To add a new transaction to the mempool, a client submits it through an appropriate RPC endpoint. +This endpoint is offered by some of the system nodes (but not necessarily all of them). + +**Gossip protocol** +Transactions can also be received from other nodes, through a gossiping mechanism. + +**ABCI application** +As pointed out above, the mempool should only store and disseminate valid transactions. +It is up to the [ABCI](./../abci/abci%2B%2B_basic_concepts.md#mempool-methods) (client) application to define whether a transaction is valid. +Transactions received locally are sent to the application to be validated, through the `checkTx` method from the mempool ABCI connection. +Such a check indicates with a flag whether it is the first time (or not) that the transaction is sent for validation. +Transactions that are validated by the application are later added to the mempool. +Transactions tagged as invalid are simply dropped. +The validity of a transaction may depend on the state of the client application. +In particular, some transactions that are valid in some state of the application may later become invalid. +The state of the application is updated when consensus commits a block of transactions. +When this happens, the transactions still in the mempool have to be validated again. +We further detail this mechanism below. + +**Consensus** +The consensus protocol consumes transactions stored in the mempool to build blocks to be proposed. +To this end, consensus requests from the mempool a list of transactions. +A limit on the total number of bytes, or transactions, _may_ be specified. +In the current implementation, the mempool is stored as a list of transactions. +The call returns the longest prefix of the list that matches the imposed limits. +Notice that at this point the transactions returned to consensus are not removed from the mempool. +This comes from the fact that the block is proposed but not decided yet. + +Proposing a block is the prerogative of the nodes acting as validators. +At all the full nodes (validators or not), consensus is responsible for committing blocks of transactions to the blockchain. +Once a block is committed, all the transactions included in the block are removed from the mempool. +This happens with an `update` call to the mempool. +Before doing this call, CometBFT takes a `lock` on the mempool. +Then, it `flush` the connection with the client application. +When `flush` returns, all the pending validation requests are answered and/or dropped. +Both operations aim at preventing any concurrent `checkTx` while the mempool is updated. +At the end of `update`, all the transactions still in the mempool are re-validated (asynchronously) against the new state of the client application. +This procedure is executed with a call to `recheckTxs`. +Finally, consensus removes its lock on the mempool by issuing a call to `unlock`. + +## Formalization + +In what follows, we formalize the notion of mempool. +To this end, we first provide a (brief) definition of what is a ledger, that is a replicated log of transactions. +At a process $p$, we shall write $p.var$ the local variable $var$ at $p$. + +**Ledger.** +We use the standard definition of (BFT) SMR in the context of blockchain, where each process $p$ has a ledger, written $p.ledger$. +At process $p$, the $i$-th entry of the ledger is denoted $p.ledger[i]$. +This entry contains either a null value ($\bot$), or a set of transactions, aka., a block. +The height of the ledger at $p$ is the index of the first null entry; denoted $p.height$. +Operation $submit(txs, i)$ attempts to write the set of transactions $txs$ to the $i$-th entry of the ledger. +The (history) variable $p.submitted[i]$ holds all the transactions (if any) submitted by $p$ at height $i$. +By extension, $p.submitted$ are all the transaction submitted by $p$. +A transaction is committed when it appears in one of the entries of the ledger. +We denote by $p.committed$ the committed transactions at $p$. + +As standard, the ledger ensures that: +* _(Gap-freedom)_ There is no gap between two entries at a correct process: +$\forall i \in \mathbb{N}. \forall p \in Correct. \square(p.ledger[i] \neq \bot \implies (i=0 \vee p.ledger[i-1] \neq \bot))$; +* _(Agreement)_ No two correct processes have different ledger entries; formally: +$\forall i \in \mathbb{N}. \forall p,q \in Correct. \square((p.ledger[i] = \bot) \vee (q.ledger[i] = \bot) \vee (p.ledger[i] = q.ledger[i]))$; +* _(Validity)_ If some transaction appears at an index $i$ at a correct process, then a process submitted it at that index: +$\forall p \in Correct. \exists q \in Processes. \forall i \in \mathbb{N}. \square(tx \in p.ledger[i] \implies tx \in \bigcup_q q.submitted[i]$). +* _(Termination)_ If a correct process submits a block at its current height, eventually its height get incremented: +$\forall p \in Correct. \square((h=p.height \wedge p.submitted[h] \neq \varnothing) \implies \lozenge(p.height>h))$ + +**Mempool.** +A mempool is a replicated set of transactions. +At a process $p$, we write it $p.mempool$. +We also define $p.hmempool$, the (history) variable that tracks all the transactions ever added to the mempool by process $p$. +Below, we list the invariants of the mempool (at a correct process). + +Only the mempool is used as an input for the ledger: +**INV1.** $\forall tx. \forall p \in Correct. \square(tx \in p.submitted \implies tx \in p.hmempool)$ + +Committed transactions are not in the mempool: +**INV2.** $\forall tx. \forall p \in Correct. \square(tx \in p.committed \implies tx \notin p.mempool)$ + +In blockchain, a transaction is (or not) valid in a given state. +That is, a transaction can be valid (or not) at a given height of the ledger. +To model this, consider a transaction $tx$. +Let $p.ledger.valid(tx)$ be such a check at the current height of the ledger at process $p$ (ABCI call). +Our third invariant is that only valid transactions are present in the mempool: +**INV3.** $\forall tx, \forall p \in Correct. \square(tx \in p.mempool \implies p.ledger.valid(tx))$ + +Finally, we require some progress from the mempool. +Namely, if a transaction appears at a correct process then eventually it is committed or forever invalid. +**INV4** $\forall tx. \forall p \in Correct. \square(tx \in p.mempool \implies \lozenge\square(tx \in p.committed \vee \neg p.ledger.valid(tx)))$ + +The above invariant ensures that if a transaction enters the mempool (at a correct process), then it eventually leaves it at a later time. +For this to be true, the client application must ensure that the validity of a transaction converges toward some value. +This means that there exists a height after which $valid(tx)$ always returns the same value. +Such a requirement is termed _eventual non-oscillation_ in the [ABCI](https://github.com/cometbft/cometbft/blob/main/spec/abci/abci%2B%2B_app_requirements.md#mempool-connection-requirements) documentation. +It also appears in [Ethereum](https://github.com/ethereum/go-ethereum/blob/5c51ef8527c47268628fe9be61522816a7f1b395/light/txpool.go#L401) as a transaction is always valid until a transaction from the same address executes with the same or higher nonce. +A simple way to satisfy this for the programmer is by having $valid(tx)$ deterministic and stateless (e.g., a syntactic check). + +**Practical considerations.** +Invariants INV2 and INV3 require to atomically update the mempool when transactions are newly committed. +To maintain such invariants in an implementation, standard thread-safe mechanisms (e.g., monitors and locks) can be used. + +Another practical concern is that INV2 requires to traverse the whole ledger, which might be too expensive. +Instead, we would like to maintain this only over the last $\alpha$ committed transactions, for some parameter $\alpha$. +Given a process $p$, we write $p.lcommitted$ the last $\alpha$ committed transactions at $p$. +Invariant INV2 is replaced with: +**INV2a.** $\forall tx. \forall p \in Correct. \square(tx \in p.lcommitted \implies tx \notin p.mempool)$ + +INV3 requires to have a green light from the client application before adding a transaction to the mempool. +For efficiency, such a validation needs to be made at most $\beta$ times per transaction at each height, for some parameter $\beta$. +Ideally, $\beta$ equals $1$. +In practice, $\beta = f(T)$ for some function $f$ of the maximal number of transactions $T$ submitted between two heights. +Given some transaction $tx$, variable $p.valid[tx]$ tracks the number of times the application was asked at the current height. +A weaker version of INV3 is as follows: +**INV3a.** $\forall tx. \forall p \in Correct. \square(tx \in p.hmempool \implies p.valid[tx] \in [1, \beta])$ + +> For further information regarding the current implementation of the mempool in CometBFT, the reader may consult [this](https://github.com/cometbft/knowledge-base/blob/main/protocols/mempool/v0/mempool-v0.md) document in the knowledge base. diff --git a/spec/mempool/quint/Consensus.qnt b/spec/mempool/quint/Consensus.qnt new file mode 100644 index 00000000000..6c0c1346bc9 --- /dev/null +++ b/spec/mempool/quint/Consensus.qnt @@ -0,0 +1,199 @@ +// -*- mode: Bluespec; -*- +// The common consensus abstraction for blockchain where processes agree on a block (that is, a set of transactions). + +module Consensus{ + + import Spells.* from "Spells" + import System.* from "System" + + type ConsensusState = { + proposed: Process -> Set[Tx], + decided: Process -> Set[Tx] + } + + pure def newConsensus(P: Set[Process]): ConsensusState = { + proposed: P.mapBy(p => Set()), + decided: P.mapBy(p => Set()) + } + + //// helpers + + pure def processes(state: ConsensusState): Set[Process] = { + state.proposed.keys() + } + + pure def hasProposed(state: ConsensusState, p: Process): bool = { + state.proposed.get(p).size() > 0 + } + + pure def hasDecided(state: ConsensusState, p: Process): bool = { + state.decided.get(p).size() > 0 + } + + pure def isProposed(state: ConsensusState, t: Tx): bool = { + state.proposed.keys().filter(p => state.proposed.get(p).contains(t)).size() > 0 + } + + pure def isDecided(state: ConsensusState, t: Tx): bool = { + state.decided.keys().filter(p => state.decided.get(p).contains(t)).size() > 0 + } + + pure def hasDecision(state: ConsensusState): bool = { + state.decided.keys().filter(p => state.decided.get(p).size()>0).size() > 0 + } + + pure def decisionOf(state: ConsensusState, p: Process): Set[Tx] = { + state.decided.get(p) + } + + pure def proposalOf(state: ConsensusState, p: Process): Set[Tx] = { + state.proposed.get(p) + } + + pure def getProposed(state: ConsensusState): Set[Tx] = { + flatten(mapValues(state.proposed)) + } + + pure def getDecided(state: ConsensusState): Set[Tx] = { + flatten(mapValues(state.decided)) + } + + // this function is useful when comparing two instances of consensus over time + // (as e.g., in the stability invariant of the ledger) + // state0 is superseded by state1 when all the processes have made more progress in state1 than in state0. + pure def isSupersededBy(state0: ConsensusState, state1: ConsensusState): bool = { + and { + state0.processes() == state1.processes(), + state0.processes().forall( + p => not(state0.hasDecided(p) and not(state1.hasDecided(p))) + ) + } + } + + //// preconditions + + pure def mayPropose(state: ConsensusState, p: Process, txs: Set[Tx]): bool = { + state.processes().contains(p) and not(state.hasProposed(p)) and txs.size() != 0 + } + + pure def mayDecide(state: ConsensusState, p: Process): bool = { + processes(state).contains(p) and size(state.getProposed()) > 0 and not(state.hasDecided(p)) + } + + //// transitions + + pure def propose(state: ConsensusState, p: Process, txs: Set[Tx]): ConsensusState = { + val newProposed = state.proposed.set(p, txs) + {proposed: newProposed, ...state} + } + + // decide any of the proposed values + pure def decide(state: ConsensusState, p: Process): ConsensusState = { + val proposal = state.proposed.get(setChooseSome(state.proposed.keys().filter(x => state.proposed.get(x).size()>0))) + val decisions = state.decided.keys().filter(x => state.decided.get(x).size()>0) + val decision = if (decisions.size()>0) {state.decided.get(setChooseSome(decisions))} else {proposal} + val newDecided = state.decided.set(p, decision) + {decided: newDecided, ...state} + } + + //// state machine + + var _consensus: ConsensusState + + action consensusInit = all { + _consensus' = newConsensus(PROCESSES) + } + + action consensusDoPropose = all { + nondet p = oneOf(PROCESSES) + nondet txs = oneOf(nonEmptyPowerset(TXS)) + all { + require(_consensus.mayPropose(p, txs)), + _consensus' = _consensus.propose(p, txs) + } + } + + action consensusDoDecide = all { + nondet p = oneOf(PROCESSES) + all { + require(_consensus.mayDecide(p)), + _consensus' = _consensus.decide(p) + } + } + + action consensusStep = any { + consensusDoPropose, + consensusDoDecide + } + + // 5. invariants + + // Validity: a process may only decide proposed values + pure def consensusValidityInv(state: ConsensusState): bool = { + state.processes().forall( + p => or { + not(state.hasDecided(p)), + state.proposed.keys().filter(q => state.proposed.get(q) == state.decided.get(p)).size()>0 + } + ) + } + + // Agreement: no two processes decide different values + pure def consensusAgreementInv(state: ConsensusState): bool = { + size(mapValues(state.decided).filter(x => x.size()>0)) <= 1 + } + + // Irrevocability: a decision always remains the same + // temporal consensusIrrevocabilityInv = { + // _consensus.processes().forall( + // p => always(not(_consensus.hasDecided(p)) or _consensus.decisionOf(p) == next(_consensus).decisionOf(p)) + // ) + // } + // FIXME. cannot be verified yet + + val consensusInvariant = { + and { + consensusAgreementInv(_consensus), + consensusValidityInv(_consensus) + } + } + + // 6. tests + + run proposeTwiceErrorTest = { + nondet p = oneOf(PROCESSES) + nondet txs = oneOf(nonEmptyPowerset(TXS)) + consensusInit + .then( + all { + _consensus.propose(p, txs).mayPropose(p, txs), + _consensus' = _consensus + }) + .fail() + } + + run decideNonProposedErrorTest = { + consensusInit + .then( + all { + _consensus.mayDecide(oneOf(PROCESSES)), + _consensus' = _consensus + }) + .fail() + } + + run decideProposedSuccessTest = { + nondet p = oneOf(PROCESSES) + nondet q = oneOf(PROCESSES) + nondet txs0 = oneOf(nonEmptyPowerset(TXS)) + nondet txs1 = oneOf(nonEmptyPowerset(TXS)) + consensusInit + .then(_consensus' = _consensus.propose(p, txs0).propose(q, txs1)) + .then( + all { + _consensus' = _consensus, + _consensus.mayDecide(p) and _consensus.decide(p).hasDecided(p) + }) + } + +} diff --git a/spec/mempool/quint/Ledger.qnt b/spec/mempool/quint/Ledger.qnt new file mode 100644 index 00000000000..c6c0bd28ac6 --- /dev/null +++ b/spec/mempool/quint/Ledger.qnt @@ -0,0 +1,188 @@ +// -*- mode: Bluespec; -*- +// A Ledger is a replicated log of blocks. +// The specification below considers that +// - replication is made with consensus (see Consensus.qnt) +// - idempotence is not granted (that is, two log entries might have transactions in common). + +module Ledger{ + + import Spells.* from "Spells" + import System.* from "System" + import Consensus.* from "Consensus" + + type LedgerState = { + log: List[ConsensusState], + } + + pure def newLedger(P: Set[Process]): LedgerState = { + log: List(newConsensus(P)) + } + + //// helpers + + // index of the first null entry + pure def height(state: LedgerState): int = { + length(state.log.select(s => s.hasDecision())) + } + + pure def heightOf(state: LedgerState, p: Process): int = { + length(state.log.select(s => s.hasDecided(p))) + } + + pure def entry(state: LedgerState, p: Process, i: int): Set[Tx] = { + state.log[i].decisionOf(p) + } + + pure def lastEntry(state: LedgerState, p: Process): Set[Tx] = { + entry(state, p, state.heightOf(p)-1) + } + + pure def getSubmittedFor(state: LedgerState, p: Process): Set[Tx] = { + 0.to(state.heightOf(p)).fold(Set(), (s, i) => s.union(state.log[i].proposalOf(p))) + } + + pure def getCommittedFor(state: LedgerState, p: Process): Set[Tx] = { + 0.to(state.heightOf(p)).fold(Set(), (s, i) => s.union(state.log[i].decisionOf(p))) + } + + pure def isSubmitted(state: LedgerState, t: Tx): bool = { + 0.to(state.height()).exists(h => state.log[h].isProposed(t)) + } + + pure def isCommitted(state: LedgerState, t: Tx): bool = { + if (state.height()==0) false else 0.to(state.height()-1).exists(i => state.log[i].isDecided(t)) + } + + pure def isCommittedFor(state: LedgerState, p: Process, t: Tx): bool = { + if (state.heightOf(p)==0) false else 0.to(state.heightOf(p)-1).exists(h => state.log[h].isDecided(t)) + } + + //// preconditions + + pure def maySubmit(state: LedgerState, p: Process, txs: Set[Tx]): bool = { + state.log[state.heightOf(p)].mayPropose(p, txs) + } + + pure def mayCommit(state: LedgerState, p: Process): bool = { + state.log[state.heightOf(p)].mayDecide(p) + } + + //// transitions + + pure def submit(state: LedgerState, p: Process, txs: Set[Tx]): LedgerState = { + val currentConsensus = state.log[heightOf(state,p)] + val nextLog = state.log.replaceAt(heightOf(state,p), currentConsensus.propose(p, txs)) + {log: nextLog, ...state} + } + + pure def commit(state: LedgerState, p: Process): LedgerState = { + val currentConsensus = state.log[state.heightOf(p)] + val nextLog = if (state.heightOf(p) == state.height()) { + state.log.append(newConsensus(processes(state.log[0]))) + } else { + state.log + } + {log: nextLog.replaceAt(heightOf(state,p), currentConsensus.decide(p)), ...state} + } + + //// state machine + + var _ledger: LedgerState + + action ledgerInit = all { + _ledger' = newLedger(PROCESSES) + } + + action ledgerDoSubmit = all { + nondet p = oneOf(PROCESSES) + nondet txs = oneOf(nonEmptyPowerset(TXS)) + all { + require(_ledger.maySubmit(p, txs)), + _ledger' = _ledger.submit(p, txs) + } + } + + action ledgerDoCommit = all { + nondet p = oneOf(PROCESSES) + all { + require(_ledger.mayCommit(p)), + _ledger' = _ledger.commit(p) + } + } + + action ledgerStep = any { + ledgerDoSubmit, + ledgerDoCommit + } + + //// invariants + + // Validity: every non-null entry is submitted. + pure def ledgerValidityInv(state: LedgerState): bool = { + 0.to(state.height()).forall(h => consensusValidityInv(state.log[h])) + } + + // Total Order: for any two processes, entries are prefix one from another. + pure def ledgerOrdertInv(state: LedgerState): bool = { + 0.to(state.height()-1).forall(h => consensusAgreementInv(state.log[h])) + } + + // Stability: for every process, its entry always grows. + // temporal ledgerStabilityInv = { + // and { + // _ledger.height() <= next(_ledger.height()), + // 0.to(_ledger.height()).forall(h => _ledger.log[h].isSupersededBy(next(_ledger.log[h]))) + // } + // } + // FIXME. cannot be verified yet + + val ledgerInvariant = { + and { + ledgerValidityInv(_ledger), + ledgerOrdertInv(_ledger) + } + } + + //// tests + + run submitTwiceErrorTest = { + nondet p = oneOf(PROCESSES) + nondet txs = oneOf(nonEmptyPowerset(TXS)) + ledgerInit + .then( + all { + _ledger.submit(p, txs).maySubmit(p, txs), + _ledger'=_ledger + } + ) + .fail() + } + + run commitNonSubmittedErrorTest = { + nondet p = oneOf(PROCESSES) + ledgerInit + .then( + all { + _ledger.mayCommit(p), + _ledger'=_ledger + } + ) + .fail() + } + + run commitSubmittedSuccessTest = { + nondet p = oneOf(PROCESSES) + nondet q = oneOf(PROCESSES) + nondet txs0 = oneOf(nonEmptyPowerset(TXS)) + nondet txs1 = oneOf(nonEmptyPowerset(TXS)) + ledgerInit + .then(_ledger' = _ledger.submit(p, txs0).submit(q, txs1)) + .then( + all { + _ledger.mayCommit(p) and heightOf(_ledger.commit(p), p)==1, + _ledger'=_ledger + } + ) + } + +} diff --git a/spec/mempool/quint/Mempool.qnt b/spec/mempool/quint/Mempool.qnt new file mode 100644 index 00000000000..2850d385c59 --- /dev/null +++ b/spec/mempool/quint/Mempool.qnt @@ -0,0 +1,195 @@ +// -*- mode: Bluespec; -*- +// A mempool is a replicated set of transactions which is used as an input by a ledger. +// Below, we follow the specification given here: +// https://github.com/cometbft/knowledge-base/blob/main/protocols/mempool-overview.md + +module ABCI { + + import System.* from "System" + import Ledger.* from "Ledger" + + pure def isValid(l: LedgerState, p: Process, t: Tx): bool = { + true + } + +} + +module Mempool { + + import Spells.* from "Spells" + import System.* from "System" + import Ledger.* from "Ledger" + import ABCI.* + + type MempoolState = { + mempool: Process -> Set[Tx], + hmempool: Process -> Set[Tx], // history variable + ledger: LedgerState + } + + pure def newMempoolState(P: Set[Process]): MempoolState = { + ledger: newLedger(P), + mempool: P.mapBy(p => Set()), + hmempool: P.mapBy(p => Set()) + } + + //// helpers + + pure def txsAvailable(st: MempoolState, p: Process): Set[Tx] = { + st.mempool.get(p) + } + + pure def txsSize(st: MempoolState, p: Process): int = { + st.mempool.get(p).size() + } + + pure def reap(st: MempoolState, p: Process, max: int): Set[Tx] = { + setSubsetOfAtMost(st.mempool.get(p), max) + } + + pure def txsOf(st: MempoolState, p: Process): Set[Tx] = { + st.mempool.get(p) + } + + pure def isValidAndNotCommittedFor(ledger: LedgerState, p: Process, tx: Tx): bool = { + isValid(ledger, p, tx) and not(ledger.getCommittedFor(p).contains(tx)) + } + + //// conditions + + pure def mayRcvFromClientAt(st: MempoolState, p: Process, txs: Set[Tx]): bool = { + and { + not(txs.subseteq(st.txsOf(p))), // to avoid stuttering + txs.forall(tx => isValidAndNotCommittedFor(st.ledger, p, tx)) + } + } + + pure def mayRcvFromProcessAt(st: MempoolState, p: Process, q: Process, txs: Set[Tx]): bool = { + and { + p != q, + not(txs.subseteq(st.txsOf(q))), // to avoid stuttering + not(st.ledger.heightOf(p) < st.ledger.heightOf(q)), + } + } + + pure def maySubmitToLedger(st: MempoolState, p: Process, txs: Set[Tx]) : bool = { + and { + txs.forall(t => st.ledger.isValid(p, t)), + st.ledger.maySubmit(p, txs) + } + } + + //// transitions + + pure def add(st: MempoolState, p: Process, txs: Set[Tx]): MempoolState = { + val nmempool = st.mempool.set(p, st.mempool.get(p).union(txs)) + val nhmempool = st.hmempool.set(p, st.hmempool.get(p).union(txs)) + {mempool: nmempool, hmempool: nhmempool, ...st} + } + + pure def commitThenUpdate(st: MempoolState, p: Process): MempoolState = { + val nledger = st.ledger.commit(p) + val nmempool = st.mempool.set(p, st.mempool.get(p).filter(tx => isValidAndNotCommittedFor(nledger, p, tx))) + {mempool: nmempool, ledger: nledger, ...st} + } + + //// state machine + + var _state: MempoolState + + action init : bool = all { + all { + _state' = newMempoolState(PROCESSES) + } + } + + action doClientThenAdd(p: Process, txs: Set[Tx]): bool = all { + all { + require(_state.mayRcvFromClientAt(p, txs)), + _state' = _state.add(p, txs) + } + } + + action doSubmit(p: Process): bool = all { + val txs = reap(_state, p, 1) + all { + require(_state.maySubmitToLedger(p, txs)), + _state' = {ledger: _state.ledger.submit(p, txs), ..._state} + } + } + + action doCommitThenUpdate(p: Process): bool = all { + all { + require(_state.ledger.mayCommit(p)), + _state' = _state.commitThenUpdate(p) + } + } + + action doGossipThenAdd(p: Process, q: Process): bool = all { + val txs = _state.txsOf(p) // all txs at once + all { + require(_state.mayRcvFromProcessAt(p, q, txs)), + _state' = _state.add(p, txs) + } + } + + action step: bool = { + nondet p = oneOf(PROCESSES) + nondet q = oneOf(PROCESSES) + nondet txs = Set(oneOf(TXS)) // one at a time + any { + doClientThenAdd(p,txs), + doSubmit(p), + doCommitThenUpdate(p), + doGossipThenAdd(p,q) + } + } + + //// invariants + + // INV1. the mempool is used as an input for the ledger + val inv1 = { + PROCESSES.forall(p => _state.ledger.getSubmittedFor(p).subseteq(_state.hmempool.get(p))) + } + + // INV2. committed transactions are not in the mempool + val inv2 = { + PROCESSES.forall(p => 0.to(_state.ledger.heightOf(p)-1).forall(i => _state.ledger.entry(p, i).intersect(_state.txsOf(p)).size()==0)) + } + + // INV3. every transaction in the mempool is valid + val inv3 = { + PROCESSES.forall(p => _state.txsOf(p).forall(t => _state.ledger.isValid(p, t))) + } + + // INV4. every transaction that appears in the mempool is eventually committed or forever invalid + // temporal inv4 = { + // PROCESSES.forall(p => mempool.get(p).forall(tx => eventually(ledger.isCommittedFor(p, tx) or always(not(ledger.isValid(p, tx)))))) + // } + // FIXME. cannot be verified yet + + // Instead, we use the (simpler) invariant below + // INV4b. every transaction in hmempool is always committed or if valid still in the mempool + val inv4() = { + PROCESSES.forall(p => _state.hmempool.get(p).forall(tx => _state.ledger.isCommittedFor(p, tx) or not(_state.ledger.isValid(p, tx)) or _state.txsOf(p).contains(tx))) + } + + val allInv = and { + inv1, + inv2, + inv3, + inv4 + } + + //// tests + + run moveHeightOnceTest = { + nondet p = oneOf(PROCESSES) + nondet txs = Set(oneOf(TXS)) + init + .then(doClientThenAdd(p,txs)) + .then(doSubmit(p)) + .then(doCommitThenUpdate(p)) + } + +} diff --git a/spec/mempool/quint/Spells.qnt b/spec/mempool/quint/Spells.qnt new file mode 100644 index 00000000000..54908430447 --- /dev/null +++ b/spec/mempool/quint/Spells.qnt @@ -0,0 +1,25 @@ +// -*- mode: Bluespec; -*- +module Spells{ + pure def require(cond: bool): bool = cond + + pure def setEqualsOrOneEmpty(s: Set[x], t: Set[x]): bool = { + (s.size()==0 or t.size()==0) or s == t + } + + pure def setSubsetOfAtMost(s: Set[x], max: int): Set[x] = { + if (max>=size(s)) s else oneOf(s.powerset().filter(u => size(u)==max)) + } + + pure def mapValues(m: x -> y): Set[y] = { + m.keys().fold(Set(), (s, i) => s.union(Set(m.get(i)))) + } + + pure def setChooseSome(s: Set[x]): x = { + head(s.fold(List(), (t,x) => t.append(x))) + } + + pure def nonEmptyPowerset(s: Set[x]): Set[Set[x]] = { + s.powerset().exclude(Set(Set())) + } + +} diff --git a/spec/mempool/quint/System.qnt b/spec/mempool/quint/System.qnt new file mode 100644 index 00000000000..c2cb1028945 --- /dev/null +++ b/spec/mempool/quint/System.qnt @@ -0,0 +1,9 @@ +// -*- mode: Bluespec; -*- +module System{ + type Process = str + type Tx = str + type Block = Set[Tx] + + pure val PROCESSES=Set("alice", "bob", "charlie") + pure val TXS=Set("T0", "T1", "T2") +} diff --git a/spec/mempool/quint/test.sh b/spec/mempool/quint/test.sh new file mode 100755 index 00000000000..4e6b2dc95ad --- /dev/null +++ b/spec/mempool/quint/test.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +quint test Mempool.qnt +quint run --init consensusInit --step consensusStep --invariant consensusInvariant Consensus.qnt +quint run --init ledgerInit --step ledgerStep --invariant ledgerInvariant Ledger.qnt +quint run --max-steps 30 --invariant allInv --out-itf out.itf Mempool.qnt diff --git a/spec/p2p/README.md b/spec/p2p/README.md new file mode 100644 index 00000000000..29efd8ecadf --- /dev/null +++ b/spec/p2p/README.md @@ -0,0 +1,46 @@ +--- +order: 1 +parent: + title: P2P + order: 6 +--- + +# Peer-to-Peer Communication + +A CometBFT network is composed of multiple CometBFT instances, hereafter called +`nodes`, that interact by exchanging messages. + +The CometBFT protocols are designed under the assumption of a partially-connected network model. +This means that a node is not assumed to be directly connected to every other +node in the network. +Instead, each node is directly connected to only a subset of other nodes, +hereafter called its `peers`. + +The peer-to-peer (p2p) communication layer is then the component of CometBFT that: + +1. establishes connections between nodes in a CometBFT network +2. manages the communication between a node and the connected peers +3. intermediates the exchange of messages between peers in CometBFT protocols + +The specification the p2p layer is a work in progress, +tracked by [issue #19](https://github.com/cometbft/cometbft/issues/19). +The current content is organized as follows: + +- [`implementation`](./implementation/README.md): documents the current state + of the implementation of the p2p layer, covering the main components of the + `p2p` package. The documentation covers, in a fairly comprehensive way, + the items 1. and 2. from the list above. +- [`reactor-api`](./reactor-api/README.md): specifies the API offered by the + p2p layer to the protocol layer, through the `Reactor` abstraction. + This is a high-level specification (i.e., it should not be implementation-specific) + of the p2p layer API, covering item 3. from the list above. +- [`legacy-docs`](./legacy-docs/): We keep older documentation in + the `legacy-docs` directory, as overall, it contains useful information. + However, part of this content is redundant, + being more comprehensively covered in more recent documents, + and some implementation details might be outdated + (see [issue #981](https://github.com/cometbft/cometbft/issues/981)). + +In addition to this content, some unfinished, work in progress, and auxiliary +material can be found in the +[knowledge-base](https://github.com/cometbft/knowledge-base/tree/main/p2p) repository. diff --git a/spec/p2p/images/p2p-reactors.png b/spec/p2p/images/p2p-reactors.png new file mode 100644 index 00000000000..5515976c10c Binary files /dev/null and b/spec/p2p/images/p2p-reactors.png differ diff --git a/spec/p2p/v0.34/img/p2p_state.png b/spec/p2p/images/p2p_state.png similarity index 100% rename from spec/p2p/v0.34/img/p2p_state.png rename to spec/p2p/images/p2p_state.png diff --git a/spec/p2p/implementation/README.md b/spec/p2p/implementation/README.md new file mode 100644 index 00000000000..e44c9e7740f --- /dev/null +++ b/spec/p2p/implementation/README.md @@ -0,0 +1,38 @@ +# Implementation of the p2p layer + +This section documents the implementation of the peer-to-peer (p2p) +communication layer in CometBFT. + +The documentation was [produced](https://github.com/tendermint/tendermint/pull/9348) +using the `v0.34.*` releases +and the branch [`v0.34.x`](https://github.com/cometbft/cometbft/tree/v0.34.x) +of this repository as reference. +As there were no substantial changes in the p2p implementation, the +documentation also applies to the releases `v0.37.*` and `v0.38.*` [^v35]. + +[^v35]: The releases `v0.35.*` and `v0.36.*`, which included a major + refactoring of the p2p layer implementation, were [discontinued][v35postmorten]. + +[v35postmorten]: https://interchain-io.medium.com/discontinuing-tendermint-v0-35-a-postmortem-on-the-new-networking-layer-3696c811dabc + +## Contents + +The documentation follows the organization of the +[`p2p` package](https://github.com/cometbft/cometbft/tree/v0.34.x/p2p), +which implements the following abstractions: + +- [Transport](./transport.md): establishes secure and authenticated + connections with peers; +- [Switch](./switch.md): responsible for dialing peers and accepting + connections from peers, for managing established connections, and for + routing messages between the reactors and peers, + that is, between local and remote instances of the CometBFT protocols; +- [PEX Reactor](./pex.md): due to the several roles of this component, the + documentation is split in several parts: + - [Peer Exchange protocol](./pex-protocol.md): enables nodes to exchange peer addresses, thus implementing a peer discovery service; + - [Address Book](./addressbook.md): stores discovered peer addresses and + quality metrics associated to peers with which the node has interacted; + - [Peer Manager](./peer_manager.md): defines when and to which peers a node + should dial, in order to establish outbound connections; +- [Types](./types.md) and [Configuration](./configuration.md) provide a list of + existing types and configuration parameters used by the p2p package. diff --git a/spec/p2p/v0.34/addressbook.md b/spec/p2p/implementation/addressbook.md similarity index 99% rename from spec/p2p/v0.34/addressbook.md rename to spec/p2p/implementation/addressbook.md index 8fd2cc3a2c8..26b9504214b 100644 --- a/spec/p2p/v0.34/addressbook.md +++ b/spec/p2p/implementation/addressbook.md @@ -303,7 +303,7 @@ The `MarkBad` method marks a peer as bad and bans it for a period of time. This method is only invoked within the PEX reactor, with a banning time of 24 hours, for the following reasons: -- A peer misbehaves in the [PEX protocol](pex-protocol.md#misbehavior) +- A peer misbehaves in the [PEX protocol](./pex-protocol.md#misbehavior) - When the `maxAttemptsToDial` limit (`16`) is reached for a peer - If an `ErrSwitchAuthenticationFailure` error is returned when dialing a peer diff --git a/spec/p2p/v0.34/configuration.md b/spec/p2p/implementation/configuration.md similarity index 61% rename from spec/p2p/v0.34/configuration.md rename to spec/p2p/implementation/configuration.md index 53ac3183db5..9f172c22c81 100644 --- a/spec/p2p/v0.34/configuration.md +++ b/spec/p2p/implementation/configuration.md @@ -6,41 +6,39 @@ This document contains configurable parameters a node operator can use to tune t | --- | --- | ---| | ListenAddress | "tcp://0.0.0.0:26656" | Address to listen for incoming connections (0.0.0.0:0 means any interface, any port) | | ExternalAddress | "" | Address to advertise to peers for them to dial | -| [Seeds](pex-protocol.md#seed-nodes) | empty | Comma separated list of seed nodes to connect to (ID@host:port )| -| [Persistent peers](peer_manager.md#persistent-peers) | empty | Comma separated list of nodes to keep persistent connections to (ID@host:port ) | -| UPNP | false | UPNP port forwarding enabled | -| [AddrBook](addressbook.md) | defaultAddrBookPath | Path do address book | +| [Seeds](./pex-protocol.md#seed-nodes) | empty | Comma separated list of seed nodes to connect to (ID@host:port )| +| [Persistent peers](./peer_manager.md#persistent-peers) | empty | Comma separated list of nodes to keep persistent connections to (ID@host:port ) | +| [AddrBook](./addressbook.md) | defaultAddrBookPath | Path do address book | | AddrBookStrict | true | Set true for strict address routability rules and false for private or local networks | -| [MaxNumInboundPeers](switch.md#accepting-peers) | 40 | Maximum number of inbound peers | -| [MaxNumOutboundPeers](peer_manager.md#ensure-peers) | 10 | Maximum number of outbound peers to connect to, excluding persistent peers | -| [UnconditionalPeers](switch.md#accepting-peers) | empty | These are IDs of the peers which are allowed to be (re)connected as both inbound or outbound regardless of whether the node reached `max_num_inbound_peers` or `max_num_outbound_peers` or not. | +| [MaxNumInboundPeers](./switch.md#accepting-peers) | 40 | Maximum number of inbound peers | +| [MaxNumOutboundPeers](./peer_manager.md#ensure-peers) | 10 | Maximum number of outbound peers to connect to, excluding persistent peers | +| [UnconditionalPeers](./switch.md#accepting-peers) | empty | These are IDs of the peers which are allowed to be (re)connected as both inbound or outbound regardless of whether the node reached `max_num_inbound_peers` or `max_num_outbound_peers` or not. | | PersistentPeersMaxDialPeriod| 0 * time.Second | Maximum pause when redialing a persistent peer (if zero, exponential backoff is used) | | FlushThrottleTimeout |100 * time.Millisecond| Time to wait before flushing messages out on the connection | | MaxPacketMsgPayloadSize | 1024 | Maximum size of a message packet payload, in bytes | | SendRate | 5120000 (5 mB/s) | Rate at which packets can be sent, in bytes/second | | RecvRate | 5120000 (5 mB/s) | Rate at which packets can be received, in bytes/second| -| [PexReactor](pex.md) | true | Set true to enable the peer-exchange reactor | +| [PexReactor](./pex.md) | true | Set true to enable the peer-exchange reactor | | SeedMode | false | Seed mode, in which node constantly crawls the network and looks for. Does not work if the peer-exchange reactor is disabled. | | PrivatePeerIDs | empty | Comma separated list of peer IDsthat we do not add to the address book or gossip to other peers. They stay private to us. | | AllowDuplicateIP | false | Toggle to disable guard against peers connecting from the same ip.| -| [HandshakeTimeout](transport.md#connection-upgrade) | 20 * time.Second | Timeout for handshake completion between peers | -| [DialTimeout](switch.md#dialing-peers) | 3 * time.Second | Timeout for dialing a peer | +| [HandshakeTimeout](./transport.md#connection-upgrade) | 20 * time.Second | Timeout for handshake completion between peers | +| [DialTimeout](./switch.md#dialing-peers) | 3 * time.Second | Timeout for dialing a peer | These parameters can be set using the `$CMTHOME/config/config.toml` file. A subset of them can also be changed via command line using the following command line flags: -| Parameter | Flag| Example| -| --- | --- | ---| +| Parameter | Flag | Example | +| --- | --- | --- | | Listen address| `p2p.laddr` | "tcp://0.0.0.0:26656" | | Seed nodes | `p2p.seeds` | `--p2p.seeds “id100000000000000000000000000000000@1.2.3.4:26656,id200000000000000000000000000000000@2.3.4.5:4444”` | | Persistent peers | `p2p.persistent_peers` | `--p2p.persistent_peers “id100000000000000000000000000000000@1.2.3.4:26656,id200000000000000000000000000000000@2.3.4.5:26656”` | | Unconditional peers | `p2p.unconditional_peer_ids` | `--p2p.unconditional_peer_ids “id100000000000000000000000000000000,id200000000000000000000000000000000”` | - | UPNP | `p2p.upnp` | `--p2p.upnp` | - | PexReactor | `p2p.pex` | `--p2p.pex` | - | Seed mode | `p2p.seed_mode` | `--p2p.seed_mode` | - | Private peer ids | `p2p.private_peer_ids` | `--p2p.private_peer_ids “id100000000000000000000000000000000,id200000000000000000000000000000000”` | +| PexReactor | `p2p.pex` | `--p2p.pex` | +| Seed mode | `p2p.seed_mode` | `--p2p.seed_mode` | +| Private peer ids | `p2p.private_peer_ids` | `--p2p.private_peer_ids “id100000000000000000000000000000000,id200000000000000000000000000000000”` | - **Note on persistent peers** + **Note on persistent peers** If `persistent_peers_max_dial_period` is set greater than zero, the pause between each dial to each persistent peer will not exceed `persistent_peers_max_dial_period` diff --git a/spec/p2p/v0.34/peer_manager.md b/spec/p2p/implementation/peer_manager.md similarity index 93% rename from spec/p2p/v0.34/peer_manager.md rename to spec/p2p/implementation/peer_manager.md index ba2e75ef323..2deb82a4dc6 100644 --- a/spec/p2p/v0.34/peer_manager.md +++ b/spec/p2p/implementation/peer_manager.md @@ -124,19 +124,19 @@ This is not done in the p2p package, but it is part of the procedure to set up a The picture below is a first attempt of illustrating the life cycle of an outbound peer: - + A peer can be in the following states: -- Candidate peers: peer addresses stored in the address boook, that can be +- Candidate peers: peer addresses stored in the address book, that can be retrieved via the [`PickAddress`](./addressbook.md#pick-address) method -- [Dialing](switch.md#dialing-peers): peer addresses that are currently being +- [Dialing](./switch.md#dialing-peers): peer addresses that are currently being dialed. This state exists to ensure that a single dialing routine exist per peer. -- [Reconnecting](switch.md#reconnect-to-peer): persistent peers to which a node +- [Reconnecting](./switch.md#reconnect-to-peer): persistent peers to which a node is currently reconnecting, as a previous connection attempt has failed. - Connected peers: peers that a node has successfully dialed, added as outbound peers. -- [Bad peers](addressbook.md#bad-peers): peers marked as bad in the address - book due to exhibited [misbehavior](pex-protocol.md#misbehavior). +- [Bad peers](./addressbook.md#bad-peers): peers marked as bad in the address + book due to exhibited [misbehavior](./pex-protocol.md#misbehavior). Peers can be reinstated after being marked as bad. ## Pending of documentation diff --git a/spec/p2p/v0.34/pex-protocol.md b/spec/p2p/implementation/pex-protocol.md similarity index 98% rename from spec/p2p/v0.34/pex-protocol.md rename to spec/p2p/implementation/pex-protocol.md index ed88993026c..760a56bd9dc 100644 --- a/spec/p2p/v0.34/pex-protocol.md +++ b/spec/p2p/implementation/pex-protocol.md @@ -78,7 +78,7 @@ Sending a PEX response to a peer that has not requested peer addresses is also considered a misbehavior. So, if a PEX response is received from a peer that is not registered in the `requestsSent` set, a `ErrUnsolicitedList` error is produced. -This leads the peer to be disconnected and [marked as a bad peer](addressbook.md#bad-peers). +This leads the peer to be disconnected and [marked as a bad peer](./addressbook.md#bad-peers). ## Providing Addresses @@ -102,7 +102,7 @@ The `receiveRequest` method is responsible for verifying this condition. The node keeps a `lastReceivedRequests` map with the time of the last PEX request received from every peer. If the interval between successive requests is less than the minimum accepted -one, the peer is disconnected and [marked as a bad peer](addressbook.md#bad-peers). +one, the peer is disconnected and [marked as a bad peer](./addressbook.md#bad-peers). An exception is made for the first two PEX requests received from a peer. > The probably reason is that, when a new peer is added, the two conditions for @@ -150,7 +150,7 @@ peers, the seed node sends a PEX request. Dialing a selected peer address can fail for multiple reasons. The seed node might have attempted to dial the peer too many times. -In this case, the peer address is marked as [bad in the address book](addressbook.md#bad-peers). +In this case, the peer address is marked as [bad in the address book](./addressbook.md#bad-peers). The seed node might have attempted to dial the peer recently, without success, and the exponential `backoffDuration` has not yet passed. Or the current connection attempt might fail, which is registered in the address book. diff --git a/spec/p2p/v0.34/pex.md b/spec/p2p/implementation/pex.md similarity index 98% rename from spec/p2p/v0.34/pex.md rename to spec/p2p/implementation/pex.md index 8243eaa559d..8f49e84af74 100644 --- a/spec/p2p/v0.34/pex.md +++ b/spec/p2p/implementation/pex.md @@ -106,6 +106,6 @@ A node receives two type of messages as part of the PEX protocol: - `PexRequest`: a request for addresses received from a peer, handled as described [here](./pex-protocol.md#providing-addresses) -- `PexAddrs`: a list of addresses received from a peer, as a reponse to a PEX +- `PexAddrs`: a list of addresses received from a peer, as a response to a PEX request sent by the node, as described [here](./pex-protocol.md#responses) diff --git a/spec/p2p/v0.34/switch.md b/spec/p2p/implementation/switch.md similarity index 95% rename from spec/p2p/v0.34/switch.md rename to spec/p2p/implementation/switch.md index 1d50108f2b9..4497fef96e2 100644 --- a/spec/p2p/v0.34/switch.md +++ b/spec/p2p/implementation/switch.md @@ -50,11 +50,11 @@ The `DialPeersAsync` method receives a list of peer addresses (strings) and dials all of them in parallel. It is invoked in two situations: -- In the [setup](https://github.com/cometbft/cometbft/blob/29c5a062d23aaef653f11195db55c45cd9e02715/node/node.go#L985) of a node, to establish connections with every configured - persistent peer +- In the [setup](https://github.com/cometbft/cometbft/blob/v0.34.x/node/node.go#L987) +of a node, to establish connections with every configured persistent peer - In the RPC package, to implement two unsafe RPC commands, not used in production: - [`DialSeeds`](https://github.com/cometbft/cometbft/blob/29c5a062d23aaef653f11195db55c45cd9e02715/rpc/core/net.go#L47) and - [`DialPeers`](https://github.com/cometbft/cometbft/blob/29c5a062d23aaef653f11195db55c45cd9e02715/rpc/core/net.go#L87) + [`DialSeeds`](https://github.com/cometbft/cometbft/blob/v0.34.x/rpc/core/net.go#L47) and + [`DialPeers`](https://github.com/cometbft/cometbft/blob/v0.34.x/rpc/core/net.go#L87) The received list of peer addresses to dial is parsed into `NetAddress` instances. In case of parsing errors, the method returns. An exception is made for diff --git a/spec/p2p/v0.34/transport.md b/spec/p2p/implementation/transport.md similarity index 95% rename from spec/p2p/v0.34/transport.md rename to spec/p2p/implementation/transport.md index 457fa1e1cbb..20d4db87a43 100644 --- a/spec/p2p/v0.34/transport.md +++ b/spec/p2p/implementation/transport.md @@ -43,9 +43,9 @@ The `NetAddress` method exports the listen address configured for the transport. The maximum number of simultaneous incoming connections accepted by the listener is bound to `MaxNumInboundPeer` plus the configured number of unconditional peers, using the `MultiplexTransportMaxIncomingConnections` option, -in the node [initialization](https://github.com/cometbft/cometbft/blob/29c5a062d23aaef653f11195db55c45cd9e02715/node/node.go#L563). +in the node [initialization](https://github.com/cometbft/cometbft/blob/v0.34.x/node/node.go#L563). -This method is called when a node is [started](https://github.com/cometbft/cometbft/blob/29c5a062d23aaef653f11195db55c45cd9e02715/node/node.go#L972). +This method is called when a node is [started](https://github.com/cometbft/cometbft/blob/v0.34.x/node/node.go#L974). In case of errors, the `acceptPeers` routine is not started and the error is returned. ## Accept @@ -191,7 +191,7 @@ an `ErrRejected` error with reason `isIncompatible` is returned. The `Close` method closes the TCP listener created by the `Listen` method, and sends a signal for interrupting the `acceptPeers` routine. -This method is called when a node is [stopped](https://github.com/cometbft/cometbft/blob/46badfabd9d5491c78283a0ecdeb695e21785508/node/node.go#L1019). +This method is called when a node is [stopped](https://github.com/cometbft/cometbft/blob/v0.34.x/node/node.go#L1023). ## Cleanup @@ -216,7 +216,7 @@ For this reason, this method is not invoked with a started transport. > Note that the default list of supported channel IDs, including the default reactors, > is provided to the transport as its original `NodeInfo` record. -[peer-sts]: https://github.com/cometbft/cometbft/blob/main/spec/p2p/peer.md#authenticated-encryption-handshake -[peer-handshake]:https://github.com/cometbft/cometbft/blob/main/spec/p2p/peer.md#cometbft-version-handshake +[peer-sts]: ../legacy-docs/peer.md#authenticated-encryption-handshake +[peer-handshake]: ../legacy-docs/peer.md#cometbft-version-handshake [sts-paper]: https://link.springer.com/article/10.1007/BF00124891 [sts-paper-pdf]: https://github.com/tendermint/tendermint/blob/0.1/docs/sts-final.pdf diff --git a/spec/p2p/v0.34/types.md b/spec/p2p/implementation/types.md similarity index 96% rename from spec/p2p/v0.34/types.md rename to spec/p2p/implementation/types.md index 6d71da03fb7..19a15ae36be 100644 --- a/spec/p2p/v0.34/types.md +++ b/spec/p2p/implementation/types.md @@ -116,7 +116,7 @@ Interface `IPeerSet` offers methods to access a table of [`Peer`](#peergo) insta Type `PeerSet` implements a thread-safe table of [`Peer`](#peergo) instances, used by the [switch](#switchgo). -The switch provides limited access to this table by returing a `IPeerSet` +The switch provides limited access to this table by returning a `IPeerSet` instance, used by the [PEX reactor](#pex_reactorgo). ### `switch.go` @@ -231,9 +231,3 @@ Go documentation of `Metric` type: > // See cometbft/docs/architecture/adr-006-trust-metric.md for details Not imported by any other CometBFT source file. - -## Package `p2p.upnp` - -This package implementation was taken from "taipei-torrent". - -It is used by the `probe-upnp` command of the CometBFT binary. diff --git a/spec/p2p/config.md b/spec/p2p/legacy-docs/config.md similarity index 83% rename from spec/p2p/config.md rename to spec/p2p/legacy-docs/config.md index 4b191e821a4..a087f8e1d53 100644 --- a/spec/p2p/config.md +++ b/spec/p2p/legacy-docs/config.md @@ -17,14 +17,6 @@ and upon incoming connection shares some peers and disconnects. Dials these seeds when we need more peers. They should return a list of peers and then disconnect. If we already have enough peers in the address book, we may never need to dial them. -## Bootstrap Peers - -`--p2p.bootstrap_peers “id100000000000000000000000000000000@1.2.3.4:26656,id200000000000000000000000000000000@2.3.4.5:26656”` - -A list of peers to be added to the addressbook upon startup to ensure that the node has some peers to initially dial. -Unlike persistent peers, these addresses don't have any extra privileges. The node may not necessarily connect on redial -these peers. - ## Persistent Peers `--p2p.persistent_peers “id100000000000000000000000000000000@1.2.3.4:26656,id200000000000000000000000000000000@2.3.4.5:26656”` diff --git a/spec/p2p/connection.md b/spec/p2p/legacy-docs/connection.md similarity index 98% rename from spec/p2p/connection.md rename to spec/p2p/legacy-docs/connection.md index 158d9d4fa5b..b208011ab2f 100644 --- a/spec/p2p/connection.md +++ b/spec/p2p/legacy-docs/connection.md @@ -103,7 +103,7 @@ switch := NewSwitch([]Reactor{MyReactor{}}) ... // Send a random message to all outbound connections -for _, peer := range switch.Peers().List() { +for _, peer := range switch.Peers().Copy() { if peer.IsOutbound() { peer.Send(MyChannelID, "Here's a random message") } diff --git a/spec/p2p/messages/README.md b/spec/p2p/legacy-docs/messages/README.md similarity index 100% rename from spec/p2p/messages/README.md rename to spec/p2p/legacy-docs/messages/README.md diff --git a/spec/p2p/messages/block-sync.md b/spec/p2p/legacy-docs/messages/block-sync.md similarity index 92% rename from spec/p2p/messages/block-sync.md rename to spec/p2p/legacy-docs/messages/block-sync.md index b00c3062c57..49afcc417ed 100644 --- a/spec/p2p/messages/block-sync.md +++ b/spec/p2p/legacy-docs/messages/block-sync.md @@ -39,8 +39,8 @@ It also contains an extended commit _iff_ vote extensions are enabled at the blo | Name | Type | Description | Field Number | |-----------|----------------------------------------------------------------|---------------------------------|--------------| -| Block | [Block](../../core/data_structures.md#block) | Requested Block | 1 | -| ExtCommit | [ExtendedCommit](../../core/data_structures.md#extendedcommit) | Sender's LastCommit information | 2 | +| Block | [Block](../../../core/data_structures.md#block) | Requested Block | 1 | +| ExtCommit | [ExtendedCommit](../../../core/data_structures.md#extendedcommit) | Sender's LastCommit information | 2 | ### StatusRequest diff --git a/spec/p2p/messages/consensus.md b/spec/p2p/legacy-docs/messages/consensus.md similarity index 89% rename from spec/p2p/messages/consensus.md rename to spec/p2p/legacy-docs/messages/consensus.md index ebb7fab7fca..aae0cdbe132 100644 --- a/spec/p2p/messages/consensus.md +++ b/spec/p2p/legacy-docs/messages/consensus.md @@ -24,7 +24,7 @@ next block in the blockchain should be. | Name | Type | Description | Field Number | |----------|----------------------------------------------------|----------------------------------------|--------------| -| proposal | [Proposal](../../core/data_structures.md#proposal) | Proposed Block to come to consensus on | 1 | +| proposal | [Proposal](../../../core/data_structures.md#proposal) | Proposed Block to come to consensus on | 1 | ### Vote @@ -38,7 +38,7 @@ message is signed by the validator private key. | Name | Type | Description | Field Number | |------|--------------------------------------------|---------------------------|--------------| -| vote | [Vote](../../core/data_structures.md#vote) | Vote for a proposed Block | 1 | +| vote | [Vote](../../../core/data_structures.md#vote) | Vote for a proposed Block | 1 | ### BlockPart @@ -49,7 +49,7 @@ and the block part. |--------|--------------------------------------------|----------------------------------------|--------------| | height | int64 | Height of corresponding block. | 1 | | round | int32 | Round of voting to finalize the block. | 2 | -| part | [Part](../../core/data_structures.md#part) | A part of the block. | 3 | +| part | [Part](../../../core/data_structures.md#part) | A part of the block. | 3 | ### NewRoundStep @@ -79,7 +79,7 @@ In case the block is also committed, then IsCommit flag is set to true. |-----------------------|--------------------------------------------------------------|----------------------------------------|--------------| | height | int64 | Height of corresponding block | 1 | | round | int32 | Round of voting to finalize the block. | 2 | -| block_part_set_header | [PartSetHeader](../../core/data_structures.md#partsetheader) | | 3 | +| block_part_set_header | [PartSetHeader](../../../core/data_structures.md#partsetheader) | | 3 | | block_parts | int32 | | 4 | | is_commit | bool | | 5 | @@ -104,7 +104,7 @@ round, vote type and the index of the validator that is the originator of the co |--------|------------------------------------------------------------------|----------------------------------------|--------------| | height | int64 | Height of corresponding block | 1 | | round | int32 | Round of voting to finalize the block. | 2 | -| type | [SignedMessageType](../../core/data_structures.md#signedmsgtype) | | 3 | +| type | [SignedMessageType](../../../core/data_structures.md#signedmsgtype) | | 3 | | index | int32 | | 4 | ### VoteSetMaj23 @@ -116,7 +116,7 @@ It contains height, round, vote type and the BlockID. |--------|------------------------------------------------------------------|----------------------------------------|--------------| | height | int64 | Height of corresponding block | 1 | | round | int32 | Round of voting to finalize the block. | 2 | -| type | [SignedMessageType](../../core/data_structures.md#signedmsgtype) | | 3 | +| type | [SignedMessageType](../../../core/data_structures.md#signedmsgtype) | | 3 | ### VoteSetBits @@ -128,8 +128,8 @@ the votes a process has. |----------|------------------------------------------------------------------|----------------------------------------|--------------| | height | int64 | Height of corresponding block | 1 | | round | int32 | Round of voting to finalize the block. | 2 | -| type | [SignedMessageType](../../core/data_structures.md#signedmsgtype) | | 3 | -| block_id | [BlockID](../../core/data_structures.md#blockid) | | 4 | +| type | [SignedMessageType](../../../core/data_structures.md#signedmsgtype) | | 3 | +| block_id | [BlockID](../../../core/data_structures.md#blockid) | | 4 | | votes | BitArray | Round of voting to finalize the block. | 5 | ### Message diff --git a/spec/p2p/messages/evidence.md b/spec/p2p/legacy-docs/messages/evidence.md similarity index 78% rename from spec/p2p/messages/evidence.md rename to spec/p2p/legacy-docs/messages/evidence.md index 34fc40a9155..7db104b3477 100644 --- a/spec/p2p/messages/evidence.md +++ b/spec/p2p/legacy-docs/messages/evidence.md @@ -16,8 +16,8 @@ Evidence has one channel. The channel identifier is listed below. ### EvidenceList -EvidenceList consists of a list of verified evidence. This evidence will already have been propagated throughout the network. EvidenceList is used in two places, as a p2p message and within the block [block](../../core/data_structures.md#block) as well. +EvidenceList consists of a list of verified evidence. This evidence will already have been propagated throughout the network. EvidenceList is used in two places, as a p2p message and within the block [block](../../../core/data_structures.md#block) as well. | Name | Type | Description | Field Number | |----------|-------------------------------------------------------------|------------------------|--------------| -| evidence | repeated [Evidence](../../core/data_structures.md#evidence) | List of valid evidence | 1 | +| evidence | repeated [Evidence](../../../core/data_structures.md#evidence) | List of valid evidence | 1 | diff --git a/spec/p2p/messages/mempool.md b/spec/p2p/legacy-docs/messages/mempool.md similarity index 94% rename from spec/p2p/messages/mempool.md rename to spec/p2p/legacy-docs/messages/mempool.md index 8f3925cad51..3425b13169d 100644 --- a/spec/p2p/messages/mempool.md +++ b/spec/p2p/legacy-docs/messages/mempool.md @@ -14,7 +14,7 @@ Mempool has one channel. The channel identifier is listed below. ## Message Types There is currently only one message that Mempool broadcasts and receives over -the p2p gossip network (via the reactor): `TxsMessage` +the p2p gossip network (via the reactor): `Txs` ### Txs diff --git a/spec/p2p/messages/pex.md b/spec/p2p/legacy-docs/messages/pex.md similarity index 100% rename from spec/p2p/messages/pex.md rename to spec/p2p/legacy-docs/messages/pex.md diff --git a/spec/p2p/messages/state-sync.md b/spec/p2p/legacy-docs/messages/state-sync.md similarity index 93% rename from spec/p2p/messages/state-sync.md rename to spec/p2p/legacy-docs/messages/state-sync.md index cfc958e08da..05f60e0182a 100644 --- a/spec/p2p/messages/state-sync.md +++ b/spec/p2p/legacy-docs/messages/state-sync.md @@ -89,9 +89,9 @@ if necessary. The light block at the height of the snapshot will be used to veri | Name | Type | Description | Field Number | |---------------|---------------------------------------------------------|--------------------------------------|--------------| -| light_block | [LightBlock](../../core/data_structures.md#lightblock) | Light block at the height requested | 1 | +| light_block | [LightBlock](../../../core/data_structures.md#lightblock) | Light block at the height requested | 1 | -State sync will use [light client verification](../../../spec/light-client/verification/README.md) to verify +State sync will use [light client verification](../../../light-client/verification/README.md) to verify the light blocks. If no state sync is in progress (i.e. during normal operation), any unsolicited response messages @@ -108,12 +108,12 @@ In order to build the state, the state provider will request the params at the h ### ParamsResponse -A reciever to the request will use the state store to fetch the consensus params at that height and return it to the sender. +A receiver to the request will use the state store to fetch the consensus params at that height and return it to the sender. | Name | Type | Description | Field Number | |----------|--------|---------------------------------|--------------| | height | uint64 | Height of the consensus params | 1 | -| consensus_params | [ConsensusParams](../../core/data_structures.md#ConsensusParams) | Consensus params at the height requested | 2 | +| consensus_params | [ConsensusParams](../../../core/data_structures.md#ConsensusParams) | Consensus params at the height requested | 2 | ### Message diff --git a/spec/p2p/node.md b/spec/p2p/legacy-docs/node.md similarity index 100% rename from spec/p2p/node.md rename to spec/p2p/legacy-docs/node.md diff --git a/spec/p2p/peer.md b/spec/p2p/legacy-docs/peer.md similarity index 100% rename from spec/p2p/peer.md rename to spec/p2p/legacy-docs/peer.md diff --git a/spec/p2p/reactor-api/README.md b/spec/p2p/reactor-api/README.md new file mode 100644 index 00000000000..401805c4b90 --- /dev/null +++ b/spec/p2p/reactor-api/README.md @@ -0,0 +1,43 @@ +# Reactors + +Reactor is the generic name for a component that employs the p2p communication layer. + +This section documents the interaction of the p2p communication layer with the +reactors. +The diagram below summarizes this interaction, namely the **northbound interface** +of the p2p communication layer, representing some relevant event flows: + + + +Each of the protocols running a CometBFT node implements a reactor and registers +the implementation with the p2p layer. +The p2p layer provides network events to the registered reactors, the main +two being new connections with peers and received messages. +The reactors provide to the p2p layer messages to be sent to +peers and commands to control the operation of the p2p layer. + +It is worth noting that the components depicted in the diagram below run +multiple routines and that the illustrated actions happen in parallel. +For instance, the connection establishment routines run in parallel, invoking +the depicted `AddPeer` method concurrently. +Once a connection is fully established, each `Peer` instance runs a send and a +receive routines. +The send routine collects messages from multiple reactors to a peer, packaging +then into raw messages which are transmitted to the peer. +The receive routine processes incoming messages and forwards them to the +destination reactors, invoking the depicted `Receive` methods. +In addition, the reactors run multiple routines for interacting +with the peers (for example, to send messages to them) or with the `Switch`. + +The remaining of the documentation is organized as follows: + +- [Reactor API](./reactor.md): documents the [`p2p.Reactor`][reactor-interface] + interface and specifies the behaviour of the p2p layer when interacting with + a reactor. + In other words, the interaction of the p2p layer with the protocol layer (bottom-up). + +- [P2P API](./p2p-api.md): documents the interface provided by the p2p + layer to the reactors, through the `Switch` and `Peer` abstractions. + In other words, the interaction of the protocol layer with the p2p layer (top-down). + +[reactor-interface]: ../../../p2p/base_reactor.go diff --git a/spec/p2p/reactor-api/p2p-api.md b/spec/p2p/reactor-api/p2p-api.md new file mode 100644 index 00000000000..15edcdd8615 --- /dev/null +++ b/spec/p2p/reactor-api/p2p-api.md @@ -0,0 +1,312 @@ +# API for Reactors + +This document describes the API provided by the p2p layer to the protocol +layer, namely to the registered reactors. + +This API consists of two interfaces: the one provided by the `Switch` instance, +and the ones provided by multiple `Peer` instances, one per connected peer. +The `Switch` instance is provided to every reactor as part of the reactor's +[registration procedure][reactor-registration]. +The multiple `Peer` instances are provided to every registered reactor whenever +a [new connection with a peer][reactor-addpeer] is established. + +> **Note** +> +> The practical reasons that lead to the interface to be provided in two parts, +> `Switch` and `Peer` instances are discussed in more datail in the +> [knowledge-base repository](https://github.com/cometbft/knowledge-base/blob/main/p2p/reactors/switch-peer.md). + +## `Switch` API + +The [`Switch`][switch-type] is the central component of the p2p layer +implementation. It manages all the reactors running in a node and keeps track +of the connections with peers. +The table below summarizes the interaction of the standard reactors with the `Switch`: + +| `Switch` API method | consensus | block sync | state sync | mempool | evidence | PEX | +|--------------------------------------------|-----------|------------|------------|---------|-----------|-------| +| `Peers() IPeerSet` | x | x | | | | x | +| `NumPeers() (int, int, int)` | | x | | | | x | +| `Broadcast(Envelope) chan bool` | x | x | x | | | | +| `MarkPeerAsGood(Peer)` | x | | | | | | +| `StopPeerForError(Peer, interface{})` | x | x | x | x | x | x | +| `StopPeerGracefully(Peer)` | | | | | | x | +| `Reactor(string) Reactor` | | x | | | | | + +The above list is not exhaustive as it does not include all the `Switch` methods +invoked by the PEX reactor, a special component that should be considered part +of the p2p layer. This document does not cover the operation of the PEX reactor +as a connection manager. + +### Peers State + +The first two methods in the switch API allow reactors to query the state of +the p2p layer: the set of connected peers. + + func (sw *Switch) Peers() IPeerSet + +The `Peers()` method returns the current set of connected peers. The returned +`IPeerSet` is concurrency-safe. Observe that the `Peer` handlers returned by +this method were previously [added to the reactor][reactor-addpeer] via the +`InitPeer(Peer)` method, but not yet removed via the `RemovePeer(Peer)` method. +Thus, a priori, reactors should already have this information. + + func (sw *Switch) NumPeers() (outbound, inbound, dialing int) + +The `NumPeers()` method returns the current number of connected peers, +distinguished between `outbound` and `inbound` peers. An `outbound` peer is a +peer the node has dialed to, while an `inbound` peer is a peer the node has +accepted a connection from. Note that `unconditional` peers are not being +counted here. + +The third field `dialing` reports the number of peers to which the node is +currently attempting to connect, so not (yet) connected peers. + +> **Note** +> +> The third field returned by `NumPeers()`, the number of peers in `dialing` +> state, is not an information that should regard the protocol layer. +> In fact, with the exception of the PEX reactor, which can be considered part +> of the p2p layer implementation, no standard reactor actually uses this +> information, that could be removed when this interface is refactored. + +### Broadcast + +The switch provides, mostly for historical or retro-compatibility reasons, +a method for sending a message to all connected peers: + + func (sw *Switch) Broadcast(e Envelope) chan bool + +The `Broadcast()` method is not blocking and returns a channel of booleans. +For every connected `Peer`, it starts a background thread for sending the +message to that peer, using the `Peer.Send()` method +(which is blocking, as detailed in [Send Methods](#send-methods)). +The result of each unicast send operation (success or failure) is added to the +returned channel, which is closed when all operations are completed. + +> **Note** +> +> - The current _implementation_ of the `Switch.Broadcast(Envelope)` method is +> not efficient, as the marshalling of the provided message is performed as +> part of the `Peer.Send(Envelope)` helper method, that is, once per +> connected peer. +> - The return value of the broadcast method is not considered by any of the +> standard reactors that employ the method. One of the reasons is that is +> not possible to associate each of the boolean outputs added to the +> returned channel to a peer. + +### Vetting Peers + +The p2p layer relies on the registered reactors to gauge the _quality_ of peers. +The following method can be invoked by a reactor to inform the p2p layer that a +peer has presented a "good" behaviour. +This information is registered in the node's address book and influences the +operation of the Peer Exchange (PEX) protocol, as node discovery adopts a bias +towards "good" peers: + + func (sw *Switch) MarkPeerAsGood(peer Peer) + +At the moment, it is up to the consensus reactor to vet a peer. +In the current logic, a peer is marked as good whenever the consensus protocol +collects a multiple of `votesToContributeToBecomeGoodPeer = 10000` useful votes +or `blocksToContributeToBecomeGoodPeer = 10000` useful block parts from that peer. +By "useful", the consensus implementation considers messages that are valid and +that are received by the node when the node is expected for such information, +which excludes duplicated or late received messages. + +> **Note** +> +> The switch doesn't currently provide a method to mark a peer as a bad peer. +> In fact, the peer quality management is really implemented in the current +> version of the p2p layer. +> This topic is being discussed in the [knowledge-base repository](https://github.com/cometbft/knowledge-base/blob/main/p2p/reactors/peer-quality.md). + +### Stopping Peers + +Reactors can instruct the p2p layer to disconnect from a peer. +Using the p2p layer's nomenclature, the reactor requests a peer to be stopped. +The peer's send and receive routines are in fact stopped, interrupting the +communication with the peer. +The `Peer` is then [removed from every registered reactor][reactor-removepeer], +using the `RemovePeer(Peer)` method, and from the set of connected peers. + + func (sw *Switch) StopPeerForError(peer Peer, reason interface{}) + +All the standard reactors employ the above method for disconnecting from a peer +in case of errors. +These are errors that occur when processing a message received from a `Peer`. +The produced `error` is provided to the method as the `reason`. + +The `StopPeerForError()` method has an important *caveat*: if the peer to be +stopped is configured as a _persistent peer_, the switch will attempt +reconnecting to that same peer. +While this behaviour makes sense when the method is invoked by other components +of the p2p layer (e.g., in the case of communication errors), it does not make +sense when it is invoked by a reactor. + +> **Note** +> +> A more comprehensive discussion regarding this topic can be found on the +> [knowledge-base repository](https://github.com/cometbft/knowledge-base/blob/main/p2p/reactors/stop-peer.md). + + func (sw *Switch) StopPeerGracefully(peer Peer) + +The second method instructs the switch to disconnect from a peer for no +particular reason. +This method is only adopted by the PEX reactor of a node operating in _seed mode_, +as seed nodes disconnect from a peer after exchanging peer addresses with it. + +### Reactors Table + +The switch keeps track of all registered reactors, indexed by unique reactor names. +A reactor can therefore use the switch to access another `Reactor` from its `name`: + + func (sw *Switch) Reactor(name string) Reactor + +This method is currently only used by the Block Sync reactor to access the +Consensus reactor implementation, from which it uses the exported +`SwitchToConsensus()` method. +While available, this inter-reactor interaction approach is discouraged and +should be avoided, as it violates the assumption that reactors are independent. + + +## `Peer` API + +The [`Peer`][peer-interface] interface represents a connected peer. +A `Peer` instance encapsulates a multiplex connection that implements the +actual communication (sending and receiving messages) with a peer. +When a connection is established with a peer, the `Switch` provides the +corresponding `Peer` instance to all registered reactors. +From this point, reactors can use the methods of the new `Peer` instance. + +The table below summarizes the interaction of the standard reactors with +connected peers, with the `Peer` methods used by them: + +| `Peer` API method | consensus | block sync | state sync | mempool | evidence | PEX | +|--------------------------------------------|-----------|------------|------------|---------|-----------|-------| +| `ID() ID` | x | x | x | x | x | x | +| `IsRunning() bool` | x | | | x | x | | +| `Quit() <-chan struct{}` | | | | x | x | | +| `Get(string) interface{}` | x | | | x | x | | +| `Set(string, interface{})` | x | | | | | | +| `Send(Envelope) bool` | x | x | x | x | x | x | +| `TrySend(Envelope) bool` | x | x | | | | | + +The above list is not exhaustive as it does not include all the `Peer` methods +invoked by the PEX reactor, a special component that should be considered part +of the p2p layer. This document does not cover the operation of the PEX reactor +as a connection manager. + +### Identification + +Nodes in the p2p network are configured with a unique cryptographic key pair. +The public part of this key pair is verified when establishing a connection +with the peer, as part of the authentication handshake, and constitutes the +peer's `ID`: + + func (p Peer) ID() p2p.ID + +Observe that each time the node connects to a peer (e.g., after disconnecting +from it), a new (distinct) `Peer` handler is provided to the reactors via +`InitPeer(Peer)` method. +In fact, the `Peer` handler is associated to a _connection_ with a peer, not to +the actual _node_ in the network. +To keep track of actual peers, the unique peer `p2p.ID` provided by the above +method should be employed. + +### Peer state + +The switch starts the peer's send and receive routines before adding the peer +to every registered reactor using the `AddPeer(Peer)` method. +The reactors then usually start routines to interact with the new connected +peer using the received `Peer` handler. +For these routines it is useful to check whether the peer is still connected +and its send and receive routines are still running: + + func (p Peer) IsRunning() bool + func (p Peer) Quit() <-chan struct{} + +The above two methods provide the same information about the state of a `Peer` +instance in two different ways. +Both of them are defined in the [`Service`][service-interface] interface. +The `IsRunning()` method is synchronous and returns whether the peer has been +started and has not been stopped. +The `Quit()` method returns a channel that is closed when the peer is stopped; +it is an asynchronous state query. + +### Key-value store + +Each `Peer` instance provides a synchronized key-value store that allows +sharing peer-specific state between reactors: + + + func (p Peer) Get(key string) interface{} + func (p Peer) Set(key string, data interface{}) + +This key-value store can be seen as an asynchronous mechanism to exchange the +state of a peer between reactors. +In the current use-case of this mechanism, the Consensus reactor populates the +key-value store with a `PeerState` instance for each connected peer. +The Consensus reactor routines interacting with a peer read and update the +shared peer state. +The Evidence and Mempool reactors, in their turn, periodically query the +key-value store of each peer for retrieving, in particular, the last height +reported by the peer. +This information, produced by the Consensus reactor, influences the interaction +of these two reactors with their peers. + +> **Note** +> +> More details of how this key-value store is used to share state between reactors can be found on the +> [knowledge-base repository](https://github.com/cometbft/knowledge-base/blob/main/p2p/reactors/peer-kvstore.md). + +### Send methods + +Finally, a `Peer` instance allows a reactor to send messages to companion +reactors running at that peer. +This is ultimately the goal of the switch when it provides `Peer` instances to +the registered reactors. +There are two methods for sending messages: + + func (p Peer) Send(e Envelope) bool + func (p Peer) TrySend(e Envelope) bool + +The two message-sending methods receive an `Envelope`, whose content should be +set as follows: + +- `ChannelID`: the channel the message should be sent through, which defines + the reactor that will process the message; +- `Src`: this field represents the source of an incoming message, which is + irrelevant for outgoing messages; +- `Message`: the actual message's payload, which is marshalled using protocol buffers. + +The two message-sending methods attempt to add the message (`e.Payload`) to the +send queue of the peer's destination channel (`e.ChannelID`). +There is a send queue for each registered channel supported by the peer, and +each send queue has a capacity. +The capacity of the send queues for each channel are [configured][reactor-channels] +by reactors via the corresponding `ChannelDescriptor`. + +The two message-sending methods return whether it was possible to enqueue +the marshalled message to the channel's send queue. +The most common reason for these methods to return `false` is the channel's +send queue being full. +Further reasons for returning `false` are: the peer being stopped, providing a +non-registered channel ID, or errors when marshalling the message's payload. + +The difference between the two message-sending methods is _when_ they return `false`. +The `Send()` method is a _blocking_ method, it returns `false` if the message +could not be enqueued, because the channel's send queue is still full, after a +10-second _timeout_. +The `TrySend()` method is a _non-blocking_ method, it _immediately_ returns +`false` when the channel's send queue is full. + +[peer-interface]: ../../../p2p/peer.go +[service-interface]: ../../../libs/service/service.go +[switch-type]: ../../../p2p/switch.go + +[reactor-interface]: ../../../p2p/base_reactor.go +[reactor-registration]: ./reactor.md#registration +[reactor-channels]: ./reactor.md#registration +[reactor-addpeer]: ./reactor.md#peer-management +[reactor-removepeer]: ./reactor.md#stop-peer diff --git a/spec/p2p/reactor-api/reactor.md b/spec/p2p/reactor-api/reactor.md new file mode 100644 index 00000000000..5f23e2ae011 --- /dev/null +++ b/spec/p2p/reactor-api/reactor.md @@ -0,0 +1,230 @@ +# Reactor API + +A component has to implement the [`p2p.Reactor` interface][reactor-interface] +in order to use communication services provided by the p2p layer. +This interface is currently the main source of documentation for a reactor. + +The goal of this document is to specify the behaviour of the p2p communication +layer when interacting with a reactor. +So while the [`Reactor interface`][reactor-interface] declares the methods +invoked and determines what the p2p layer expects from a reactor, +this documentation focuses on the **temporal behaviour** that a reactor implementation +should expect from the p2p layer. (That is, in which orders the functions may be called) + +This specification is accompanied by the [`reactor.qnt`](./reactor.qnt) file, +a more comprehensive model of the reactor's operation written in +[Quint][quint-repo], an executable specification language. +The methods declared in the [`Reactor`][reactor-interface] interface are +modeled in Quint, in the form of `pure def` methods, providing some examples of +how they should be implemented. +The behaviour of the p2p layer when interacting with a reactor, by invoking the +interface methods, is modeled in the form of state transitions, or `action`s in +the Quint nomenclature. + +## Overview + +The following _grammar_ is a simplified representation of the expected sequence of calls +from the p2p layer to a reactor. +Note that the grammar represents events referring to a _single reactor_, while +the p2p layer supports the execution of multiple reactors. +For a more detailed representation of the sequence of calls from the p2p layer +to reactors, please refer to the companion Quint model. + +While useful to provide an overview of the operation of a reactor, +grammars have some limitations in terms of the behaviour they can express. +For instance, the following grammar only represents the management of _a single peer_, +namely of a peer with a given ID which can connect, disconnect, and reconnect +multiple times to the node. +The p2p layer and every reactor should be able to handle multiple distinct peers in parallel. +This means that multiple occurrences of non-terminal `peer-management` of the +grammar below can "run" independently and in parallel, each one referring and +producing events associated to a different peer: + +```abnf +start = registration on-start *peer-management on-stop +registration = get-channels set-switch + +; Refers to a single peer, a reactor must support multiple concurrent peers +peer-management = init-peer start-peer stop-peer +start-peer = [*receive] (connected-peer / start-error) +connected-peer = add-peer *receive +stop-peer = [peer-error] remove-peer + +; Service interface +on-start = %s"OnStart()" +on-stop = %s"OnStop()" +; Reactor interface +get-channels = %s"GetChannels()" +set-switch = %s"SetSwitch(*Switch)" +init-peer = %s"InitPeer(Peer)" +add-peer = %s"AddPeer(Peer)" +remove-peer = %s"RemovePeer(Peer, reason)" +receive = %s"Receive(Envelope)" + +; Errors, for reference +start-error = %s"log(Error starting peer)" +peer-error = %s"log(Stopping peer for error)" +``` + +The grammar is written in case-sensitive Augmented Backus–Naur form (ABNF, +specified in [IETF RFC 7405](https://datatracker.ietf.org/doc/html/rfc7405)). +It is inspired on the grammar produced to specify the interaction of CometBFT +with an ABCI application, available [here](../../abci/abci%2B%2B_comet_expected_behavior.md). + +## Registration + +To become a reactor, a component has first to implement the +[`Reactor`][reactor-interface] interface, +then to register the implementation with the p2p layer, using the +`Switch.AddReactor(name string, reactor Reactor)` method, +with a global unique `name` for the reactor. + +The registration must happen before the node, in general, and the p2p layer, +in particular, are started. +In other words, there is no support for registering a reactor on a running node: +reactors must be registered as part of the setup of a node. + +```abnf +registration = get-channels set-switch +``` + +The p2p layer retrieves from the reactor a list of channels the reactor is +responsible for, using the `GetChannels()` method. +The reactor implementation should thereafter expect the delivery of every +message received by the p2p layer in the informed channels. + +The second method `SetSwitch(Switch)` concludes the handshake between the +reactor and the p2p layer. +The `Switch` is the main component of the p2p layer, being responsible for +establishing connections with peers and routing messages. +The `Switch` instance provides a number of methods for all registered reactors, +documented in the companion [API for Reactors](./p2p-api.md#switch-api) document. + +## Service interface + +A reactor must implement the [`Service`](../../../libs/service/service.go) interface, +in particular, a startup `OnStart()` and a shutdown `OnStop()` methods: + +```abnf +start = registration on-start *peer-management on-stop +``` + +As part of the startup of a node, all registered reactors are started by the p2p layer. +And when the node is shut down, all registered reactors are stopped by the p2p layer. +Observe that the `Service` interface specification establishes that a service +can be started and stopped only once. +So before being started or once stopped by the p2p layer, the reactor should +not expect any interaction. + +## Peer management + +The core of a reactor's operation is the interaction with peers or, more +precisely, with companion reactors operating on the same channels in peers connected to the node. +The grammar extract below represents the interaction of the reactor with a +single peer: + +```abnf +; Refers to a single peer, a reactor must support multiple concurrent peers +peer-management = init-peer start-peer stop-peer +``` + +The p2p layer informs all registered reactors when it establishes a connection +with a `Peer`, using the `InitPeer(Peer)` method. +When this method is invoked, the `Peer` has not yet been started, namely the +routines for sending messages to and receiving messages from the peer are not running. +This method should be used to initialize state or data related to the new +peer, but not to interact with it. + +The next step is to start the communication routines with the new `Peer`. +As detailed in the following, this procedure may or may not succeed. +In any case, the peer is eventually stopped, which concludes the management of +that `Peer` instance. + +## Start peer + +Once `InitPeer(Peer)` is invoked for every registered reactor, the p2p layer starts the peer's +communication routines and adds the `Peer` to the set of connected peers. +If both steps are concluded without errors, the reactor's `AddPeer(Peer)` is invoked: + +```abnf +start-peer = [*receive] (connected-peer / start-error) +connected-peer = add-peer *receive +``` + +In case of errors, a message is logged informing that the p2p layer failed to start the peer. +This is not a common scenario and it is only expected to happen when +interacting with a misbehaving or slow peer. A practical example is reported on this +[issue](https://github.com/tendermint/tendermint/pull/9500). + +It is up to the reactor to define how to process the `AddPeer(Peer)` event. +The typical behavior is to start routines that, given some conditions or events, +send messages to the added peer, using the provided `Peer` instance. +The companion [API for Reactors](./p2p-api.md#peer-api) documents the methods +provided by `Peer` instances, available from when they are added to the reactors. + +## Stop Peer + +The p2p layer informs all registered reactors when it disconnects from a `Peer`, +using the `RemovePeer(Peer, reason)` method: + +```abnf +stop-peer = [peer-error] remove-peer +``` + +This method is invoked after the p2p layer has stopped peer's send and receive routines. +Depending of the `reason` for which the peer was stopped, different log +messages can be produced. +After removing a peer from all reactors, the `Peer` instance is also removed from +the set of connected peers. +This enables the same peer to reconnect and `InitPeer(Peer)` to be invoked for +the new connection. + +From the removal of a `Peer` , the reactor should not receive any further message +from the peer and must not try sending messages to the removed peer. +This usually means stopping the routines that were started by the companion +`Add(Peer)` method. + +## Receive messages + +The main duty of a reactor is to handle incoming messages on the channels it +has registered with the p2p layer. + +The _pre-condition_ for receiving a message from a `Peer` is that the p2p layer +has previously invoked `InitPeer(Peer)`. +This means that the reactor must be able to receive a message from a `Peer` +_before_ `AddPeer(Peer)` is invoked. +This happens because the peer's send and receive routines are started before, +and should be already running when the p2p layer adds the peer to every +registered reactor. + +```abnf +start-peer = [*receive] (connected-peer / start-error) +connected-peer = add-peer *receive +``` + +The most common scenario, however, is to start receiving messages from a peer +after `AddPeer(Peer)` is invoked. +An arbitrary number of messages can be received, until the peer is stopped and +`RemovePeer(Peer)` is invoked. + +When a message is received from a connected peer on any of the channels +registered by the reactor, the p2p layer will deliver the message to the +reactor via the `Receive(Envelope)` method. +The message is packed into an `Envelope` that contains: + +- `ChannelID`: the channel the message belongs to +- `Src`: the source `Peer` handler, from which the message was received +- `Message`: the actual message's payload, unmarshalled using protocol buffers + +Two important observations regarding the implementation of the `Receive` method: + +1. Concurrency: the implementation should consider concurrent invocations of + the `Receive` method carrying messages from different peers, as the + interaction with different peers is independent and messages can be received in parallel. +1. Non-blocking: the implementation of the `Receive` method is expected not to block, + as it is invoked directly by the receive routines. + In other words, while `Receive` does not return, other messages from the + same sender are not delivered to any reactor. + +[reactor-interface]: ../../../p2p/base_reactor.go +[quint-repo]: https://github.com/informalsystems/quint diff --git a/spec/p2p/reactor-api/reactor.qnt b/spec/p2p/reactor-api/reactor.qnt new file mode 100644 index 00000000000..002c57023af --- /dev/null +++ b/spec/p2p/reactor-api/reactor.qnt @@ -0,0 +1,276 @@ +// -*- mode: Bluespec; -*- +/* + * Reactor is responsible for handling incoming messages on one or more + * Channel. Switch calls GetChannels when reactor is added to it. When a new + * peer joins our node, InitPeer and AddPeer are called. RemovePeer is called + * when the peer is stopped. Receive is called when a message is received on a + * channel associated with this reactor. + */ +// Code: https://github.com/cometbft/cometbft/blob/main/p2p/base_reactor.go +module reactor { + + // Unique ID of a node. + type NodeID = str + + /* + * Peer is an interface representing a peer connected on a reactor. + */ + type Peer = { + ID: NodeID, + + // Other fields can be added to represent the p2p operation. + } + + // Byte ID used by channels, must be globally unique. + type Byte = str + + // Channel configuration. + type ChannelDescriptor = { + ID: Byte, + Priority: int, + } + + /* + * Envelope contains a message with sender routing info. + */ + type Envelope = { + Src: Peer, // Sender + Message: str, // Payload + ChannelID: Byte, + } + + // A Routine is used to interact with an active Peer. + type Routine = { + name: str, + peer: Peer, + } + + type ReactorState = { + // Peers that have been initialized but not yet removed. + // The reactor should expect receiving messages from them. + peers: Set[NodeID], + + // The reactor runs multiple routines. + routines: Set[Routine], + + // Values: init -> registered -> running -> stopped + state: str, + + // Name with which the reactor was registered. + name: str, + + // Channels the reactor is responsible for. + channels: Set[ChannelDescriptor], + } + + // Produces a new, uninitialized reactor. + pure def NewReactor(): ReactorState = { + { + peers: Set(), + routines: Set(), + state: "init", + name: "", + channels: Set(), + } + } + + // Pure definitions below represent the `p2p.Reactor` interface methods: + + /* + * GetChannels returns the list of MConnection.ChannelDescriptor. Make sure + * that each ID is unique across all the reactors added to the switch. + */ + pure def GetChannels(s: ReactorState): Set[ChannelDescriptor] = { + s.channels // Static list, configured at initialization. + } + + /* + * SetSwitch allows setting a switch. + */ + pure def SetSwitch(s: ReactorState, switch: bool): ReactorState = { + s.with("state", "registered") + } + + /* + * Start the service. + * If it's already started or stopped, will return an error. + */ + pure def OnStart(s: ReactorState): ReactorState = { + // Startup procedures should come here. + s.with("state", "running") + } + + /* + * Stop the service. + * If it's already stopped, will return an error. + */ + pure def OnStop(s: ReactorState): ReactorState = { + // Shutdown procedures should come here. + s.with("state", "stopped") + } + + /* + * InitPeer is called by the switch before the peer is started. Use it to + * initialize data for the peer (e.g. peer state). + */ + pure def InitPeer(s: ReactorState, peer: Peer): (ReactorState, Peer) = { + // This method can update the received peer, which is returned. + val updatedPeer = peer + (s.with("peers", s.peers.union(Set(peer.ID))), updatedPeer) + } + + /* + * AddPeer is called by the switch after the peer is added and successfully + * started. Use it to start goroutines communicating with the peer. + */ + pure def AddPeer(s: ReactorState, peer: Peer): ReactorState = { + // This method can be used to start routines to handle the peer. + // Below an example of an arbitrary 'ioRoutine' routine. + val startedRoutines = Set( {name: "ioRoutine", peer: peer} ) + s.with("routines", s.routines.union(startedRoutines)) + } + + /* + * RemovePeer is called by the switch when the peer is stopped (due to error + * or other reason). + */ + pure def RemovePeer(s: ReactorState, peer: Peer, reason: str): ReactorState = { + // This method should stop routines created by `AddPeer(Peer)`. + val stoppedRoutines = s.routines.filter(r => r.peer.ID == peer.ID) + s.with("peers", s.peers.exclude(Set(peer.ID))) + .with("routines", s.routines.exclude(stoppedRoutines)) + } + + /* + * Receive is called by the switch when an envelope is received from any connected + * peer on any of the channels registered by the reactor. + */ + pure def Receive(s: ReactorState, e: Envelope): ReactorState = { + // This method should process the message payload: e.Message. + s + } + + // Global state + + // Reactors are uniquely identified by their names. + var reactors: str -> ReactorState + + // Reactor (name) assigned to each channel ID. + var reactorsByCh: Byte -> str + + // Helper action to (only) update the state of a given reactor. + action updateReactorTo(reactor: ReactorState): bool = all { + reactors' = reactors.set(reactor.name, reactor), + reactorsByCh' = reactorsByCh + } + + // State transitions performed by the p2p layer, invoking `p2p.Reactor` methods: + + // Code: Switch.AddReactor(name string, reactor Reactor) + action register(name: str, reactor: ReactorState): bool = all { + reactor.state == "init", + // Assign the reactor as responsible for its channel IDs, which + // should not be already assigned to another reactor. + val chIDs = reactor.GetChannels().map(c => c.ID) + all { + size(chIDs.intersect(reactorsByCh.keys())) == 0, + reactorsByCh' = reactorsByCh.keys().union(chIDs). + mapBy(id => if (id.in(chIDs)) name + else reactorsByCh.get(id)), + }, + // Register the reactor by its name, which must be unique. + not(name.in(reactors.keys())), + reactors' = reactors.put(name, + reactor.SetSwitch(true).with("name", name)) + } + + // Code: Switch.OnStart() + action start(reactor: ReactorState): bool = all { + reactor.state == "registered", + updateReactorTo(reactor.OnStart()) + } + + // Code: Switch.addPeer(p Peer): preamble + action initPeer(reactor: ReactorState, peer: Peer): bool = all { + reactor.state == "running", + not(peer.ID.in(reactor.peers)), + updateReactorTo(reactor.InitPeer(peer)._1) + } + + // Code: Switch.addPeer(p Peer): conclusion + action addPeer(reactor: ReactorState, peer: Peer): bool = all { + reactor.state == "running", + peer.ID.in(reactor.peers), // InitPeer(peer) and not RemovePeer(peer) + reactor.routines.filter(r => r.peer.ID == peer.ID).size() == 0, + updateReactorTo(reactor.AddPeer(peer)) + } + + // Code: Switch.stopAndRemovePeer(peer Peer, reason interface{}) + action removePeer(reactor: ReactorState, peer: Peer, reason: str): bool = all { + reactor.state == "running", + peer.ID.in(reactor.peers), // InitPeer(peer) and not RemovePeer(peer) + // Routines might not be started, namely: not AddPeer(peer) + // Routines could also be already stopped if Peer has erroed. + updateReactorTo(reactor.RemovePeer(peer, reason)) + } + + // Code: Peer type, onReceive := func(chID byte, msgBytes []byte) + action receive(reactor: ReactorState, e: Envelope): bool = all { + reactor.state == "running", + // The message's sender is an active peer + e.Src.ID.in(reactor.peers), + // Reactor is assigned to the message's channel ID + e.ChannelID.in(reactorsByCh.keys()), + reactorsByCh.get(e.ChannelID) == reactor.name, + reactor.GetChannels().exists(c => c.ID == e.ChannelID), + updateReactorTo(reactor.Receive(e)) + } + + // Code: Switch.OnStop() + action stop(reactor: ReactorState): bool = all { + reactor.state == "running", + // Either no peer was added or all peers were removed + reactor.peers.size() == 0, + updateReactorTo(reactor.OnStop()) + } + + // Simulation support + + action init = all { + reactors' = Map(), + reactorsByCh' = Map(), + } + + // Modelled reactor configuration + pure val reactorName = "myReactor" + pure val reactorChannels = Set({ID: "3", Priority: 1}, {ID: "7", Priority: 2}) + + // For retro-compatibility: the state of the modelled reactor + def state(): ReactorState = { + reactors.get(reactorName) + } + + pure val samplePeers = Set({ID: "p1"}, {ID: "p3"}) + pure val sampleChIDs = Set("1", "3", "7") // ChannelID 1 not registered + pure val sampleMsgs = Set("ping", "pong") + + action step = any { + register(reactorName, NewReactor.with("channels", reactorChannels)), + val reactor = reactors.get(reactorName) + any { + reactor.start(), + reactor.stop(), + nondet peer = oneOf(samplePeers) + any { + // Peer-specific actions + reactor.initPeer(peer), + reactor.addPeer(peer), + reactor.removePeer(peer, "no reason"), + reactor.receive({Src: peer, + ChannelID: oneOf(sampleChIDs), + Message: oneOf(sampleMsgs)}), + } + } + } + +} diff --git a/spec/p2p/readme.md b/spec/p2p/readme.md deleted file mode 100644 index e7f57c30263..00000000000 --- a/spec/p2p/readme.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -order: 1 -parent: - title: P2P - order: 6 ---- - -# Peer-to-Peer Communication - -The operation of the p2p adopted in production CometBFT networks is [HERE](./v0.34/). - -> This is part of an ongoing [effort](https://github.com/cometbft/cometbft/issues/19) -> to produce a high-level specification of the operation of the p2p layer. diff --git a/spec/p2p/v0.34/README.md b/spec/p2p/v0.34/README.md deleted file mode 100644 index 017e1001f66..00000000000 --- a/spec/p2p/v0.34/README.md +++ /dev/null @@ -1,70 +0,0 @@ -# Peer-to-Peer Communication - -This document describes the implementation of the peer-to-peer (p2p) -communication layer in CometBFT. - -It is part of an [effort](https://github.com/cometbft/cometbft/issues/19) -to produce a high-level specification of the operation of the p2p layer adopted -in production CometBFT networks. - -This documentation, therefore, considers the releases `0.34.*` of CometBFT, more -specifically, the branch [`v0.34.x`](https://github.com/cometbft/cometbft/tree/v0.34.x) -of this repository. - -## Overview - -A CometBFT network is composed of multiple CometBFT instances, hereafter -called **nodes**, that interact by exchanging messages. - -CometBFT assumes a partially-connected network model. -This means that a node is not assumed to be directly connected to every other -node in the network. -Instead, each node is directly connected to a subset of other nodes in the -network, hereafter called its **peers**. - -The peer-to-peer (p2p) communication layer is responsible for establishing -connections between nodes in a CometBFT network, -for managing the communication between a node and its peers, -and for intermediating the exchange of messages between peers in CometBFT protocols. - -## Contents - -The documentation follows the organization of the `p2p` package of CometBFT, -which implements the following abstractions: - -- [Transport](./transport.md): establishes secure and authenticated - connections with peers; -- [Switch](./switch.md): responsible for dialing peers and accepting - connections from peers, for managing established connections, and for - routing messages between the reactors and peers, - that is, between local and remote instances of the CometBFT protocols; -- [PEX Reactor](./pex.md): a reactor is the implementation of a protocol which - exchanges messages through the p2p layer. The PEX reactor manages the [Address Book](./addressbook.md) and implements both the [PEX protocol](./pex-protocol.md) and the [Peer Manager](./peer_manager.md) role. - - [Peer Exchange protocol](./pex-protocol.md): enables nodes to exchange peer addresses, thus implementing a peer discovery service; - - [Address Book](./addressbook.md): stores discovered peer addresses and - quality metrics associated to peers with which the node has interacted; - - [Peer Manager](./peer_manager.md): defines when and to which peers a node - should dial, in order to establish outbound connections; -- Finally, [Types](./types.md) and [Configuration](./configuration.md) provide - a list of existing types and configuration parameters used by the p2p layer implementation. - -## Further References - -Existing documentation referring to the p2p layer: - -- : p2p-related - configuration flags; overview of connections, peer instances, and reactors; - overview of peer discovery and node types; peer identity, secure connections - and peer authentication handshake. -- : message - types and channel IDs of Block Sync, Mempool, Evidence, State Sync, PEX, and - Consensus reactors. -- : the p2p layer - configuration and operation is documented in several pages. - This content is not necessarily up-to-date, some settings and concepts may - refer to the release `v0.35`, that was [discontinued][v35postmorten]. -- : - peer types, peer discovery, peer management overview, address book and peer - ranking. This documentation refers to the release `v0.35`, that was [discontinued][v35postmorten]. - -[v35postmorten]: https://interchain-io.medium.com/discontinuing-tendermint-v0-35-a-postmortem-on-the-new-networking-layer-3696c811dabc diff --git a/spec/rpc/README.md b/spec/rpc/README.md index ff9ce2ce9e4..a9743bc642d 100644 --- a/spec/rpc/README.md +++ b/spec/rpc/README.md @@ -65,13 +65,13 @@ None ##### HTTP ```sh -curl http://127.0.0.1:26657/health +curl http://127.0.0.1:26657/v1/health ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"health\"}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"health\"}" ``` #### Response @@ -97,13 +97,13 @@ None ##### HTTP ```sh -curl http://127.0.0.1:26657/status +curl http://127.0.0.1:26657/v1/status ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"status\"}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"status\"}" ``` #### Response @@ -166,13 +166,13 @@ None ##### HTTP ```sh -curl http://127.0.0.1:26657/net_info +curl http://127.0.0.1:26657/v1/net_info ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"net_info\"}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"net_info\"}" ``` #### Response @@ -211,15 +211,15 @@ Get block headers. Returned in descending order. May be limited in quantity. ##### HTTP ```sh -curl http://127.0.0.1:26657/blockchain +curl http://127.0.0.1:26657/v1/blockchain -curl http://127.0.0.1:26657/blockchain?minHeight=1&maxHeight=2 +curl http://127.0.0.1:26657/v1/blockchain?minHeight=1&maxHeight=2 ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"blockchain\",\"params\":{\"minHeight\":\"1\", \"maxHeight\":\"2\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"blockchain\",\"params\":{\"minHeight\":\"1\", \"maxHeight\":\"2\"}}" ``` #### Response @@ -285,15 +285,15 @@ Get block at a specified height. ##### HTTP ```sh -curl http://127.0.0.1:26657/block +curl http://127.0.0.1:26657/v1/block -curl http://127.0.0.1:26657/block?height=1 +curl http://127.0.0.1:26657/v1/block?height=1 ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"block\",\"params\":{\"height\":\"1\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"block\",\"params\":{\"height\":\"1\"}}" ``` #### Response @@ -400,13 +400,13 @@ curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\ ##### HTTP ```sh -curl http://127.0.0.1:26657/block_by_hash?hash=0xD70952032620CC4E2737EB8AC379806359D8E0B17B0488F627997A0B043ABDED +curl http://127.0.0.1:26657/v1/block_by_hash?hash=0xD70952032620CC4E2737EB8AC379806359D8E0B17B0488F627997A0B043ABDED ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"block_by_hash\",\"params\":{\"hash\":\"0xD70952032620CC4E2737EB8AC379806359D8E0B17B0488F627997A0B043ABDED\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"block_by_hash\",\"params\":{\"hash\":\"0xD70952032620CC4E2737EB8AC379806359D8E0B17B0488F627997A0B043ABDED\"}}" ``` #### Response @@ -513,16 +513,16 @@ curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\ ##### HTTP ```sh -curl http://127.0.0.1:26657/block_results +curl http://127.0.0.1:26657/v1/block_results -curl http://127.0.0.1:26657/block_results?height=1 +curl http://127.0.0.1:26657/v1/block_results?height=1 ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"block_results\",\"params\":{\"height\":\"1\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"block_results\",\"params\":{\"height\":\"1\"}}" ``` #### Response @@ -620,16 +620,16 @@ curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\ ##### HTTP ```sh -curl http://127.0.0.1:26657/commit +curl http://127.0.0.1:26657/v1/commit -curl http://127.0.0.1:26657/commit?height=1 +curl http://127.0.0.1:26657/v1/commit?height=1 ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"commit\",\"params\":{\"height\":\"1\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"commit\",\"params\":{\"height\":\"1\"}}" ``` #### Response @@ -703,13 +703,13 @@ curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\ ##### HTTP ```sh -curl http://127.0.0.1:26657/validators +curl http://127.0.0.1:26657/v1/validators ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"validators\",\"params\":{\"height\":\"1\", \"page\":\"1\", \"per_page\":\"20\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"validators\",\"params\":{\"height\":\"1\", \"page\":\"1\", \"per_page\":\"20\"}}" ``` #### Response @@ -747,13 +747,13 @@ will return an error: use `genesis_chunked` instead. ##### HTTP ```sh -curl http://127.0.0.1:26657/genesis +curl http://127.0.0.1:26657/v1/genesis ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"genesis\"}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"genesis\"}" ``` #### Response @@ -802,7 +802,7 @@ curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\ ### GenesisChunked -Get the genesis document in a chunks to support easily transfering larger documents. +Get the genesis document in a chunks to support easily transferring larger documents. #### Parameters @@ -814,13 +814,13 @@ Get the genesis document in a chunks to support easily transfering larger docume ##### HTTP ```sh -curl http://127.0.0.1:26657/genesis_chunked?chunk=0 +curl http://127.0.0.1:26657/v1/genesis_chunked?chunk=0 ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"genesis_chunked\",\"params\":{\"chunk\":0}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"genesis_chunked\",\"params\":{\"chunk\":0}}" ``` #### Response @@ -850,13 +850,13 @@ Get the consensus parameters. ##### HTTP ```sh -curl http://127.0.0.1:26657/consensus_params +curl http://127.0.0.1:26657/v1/consensus_params ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"consensus_params\"}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"consensus_params\"}" ``` #### Response @@ -899,13 +899,13 @@ Get a list of unconfirmed transactions. ##### HTTP ```sh -curl http://127.0.0.1:26657/unconfirmed_txs +curl http://127.0.0.1:26657/v1/unconfirmed_txs ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"unconfirmed_txs\, \"params\":{\"limit\":\"20\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"unconfirmed_txs\, \"params\":{\"limit\":\"20\"}}" ``` #### Response @@ -938,13 +938,13 @@ None ##### HTTP ```sh -curl http://127.0.0.1:26657/num_unconfirmed_txs +curl http://127.0.0.1:26657/v1/num_unconfirmed_txs ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"num_unconfirmed_txs\"}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"num_unconfirmed_txs\"}" ``` #### Response @@ -973,13 +973,13 @@ curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\ ##### HTTP ```sh -curl http://127.0.0.1:26657/num_unconfirmed_txs +curl http://127.0.0.1:26657/v1/num_unconfirmed_txs ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"num_unconfirmed_txs\"}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"num_unconfirmed_txs\"}" ``` #### Response @@ -1024,13 +1024,13 @@ Returns with the response from CheckTx. Does not wait for DeliverTx result. ##### HTTP ```sh -curl http://127.0.0.1:26657/broadcast_tx_sync?tx=encoded_tx +curl http://127.0.0.1:26657/v1/broadcast_tx_sync?tx=encoded_tx ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"broadcast_tx_sync\",\"params\":{\"tx\":\"a/encoded_tx/c\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"broadcast_tx_sync\",\"params\":{\"tx\":\"a/encoded_tx/c\"}}" ``` #### Response @@ -1063,13 +1063,13 @@ Returns right away, with no response. Does not wait for CheckTx nor DeliverTx re ##### HTTP ```sh -curl http://127.0.0.1:26657/broadcast_tx_async?tx=encoded_tx +curl http://127.0.0.1:26657/v1/broadcast_tx_async?tx=encoded_tx ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"broadcast_tx_async\",\"params\":{\"tx\":\"a/encoded_tx/c\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"broadcast_tx_async\",\"params\":{\"tx\":\"a/encoded_tx/c\"}}" ``` #### Response @@ -1102,13 +1102,13 @@ Checks the transaction without executing it. ##### HTTP ```sh -curl http://127.0.0.1:26657/check_tx?tx=encoded_tx +curl http://127.0.0.1:26657/v1/check_tx?tx=encoded_tx ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"check_tx\",\"params\":{\"tx\":\"a/encoded_tx/c\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"check_tx\",\"params\":{\"tx\":\"a/encoded_tx/c\"}}" ``` #### Response @@ -1157,13 +1157,13 @@ None ##### HTTP ```sh -curl http://127.0.0.1:26657/abci_info +curl http://127.0.0.1:26657/v1/abci_info ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"abci_info\"}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"abci_info\"}" ``` #### Response @@ -1188,23 +1188,23 @@ Query the application for some information. #### Parameters -- `path (string)`: Path to the data. This is defined by the application. -- `data (string)`: The data requested -- `height (integer)`: Height at which the data is being requested for. -- `prove (bool)`: Include proofs of the transactions inclusion in the block +- `path (string)`: A request path for the application to interpret analogously to a [URI path component](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) in e.g. routing. +- `data (string)`: Request parameters for the application to interpret analogously to a [URI query component](https://www.rfc-editor.org/rfc/rfc3986#section-3.4), expressed as hexadecimal-serialized bytes. +- `height (integer)`: The block height against which to query. +- `prove (bool)`: Return Merkle proof with response if possible. #### Request ##### HTTP ```sh -curl http://127.0.0.1:26657/abci_query?path="a/b/c"=IHAVENOIDEA&height=1&prove=true +curl 'http://127.0.0.1:26657/v1/abci_query?path="/store/foo/key"&data=0x636f6d6574626674&height=1&prove=true' ``` ##### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"abci_query\",\"params\":{\"path\":\"a/b/c\", \"height\":\"1\", \"bool\":\"true\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"abci_query\",\"params\":{\"path\":\"/store/foo/key\", \"data\":\"636f6d6574626674\", \"height\":\"1\", \"prove\":\"true\"}}" ``` #### Response @@ -1217,8 +1217,8 @@ curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\ "log": "exists", "height": "0", "proof": "010114FED0DAD959F36091AD761C922ABA3CBF1D8349990101020103011406AA2262E2F448242DF2C2607C3CDC705313EE3B0001149D16177BC71E445476174622EA559715C293740C", - "value": "61626364", - "key": "61626364", + "key": "Y29tZXRiZnQ=", + "value": "cm9ja3M=", "index": "-1", "code": "0" } @@ -1243,13 +1243,13 @@ Broadcast evidence of the misbehavior. ##### HTTP ```sh -curl http://localhost:26657/broadcast_evidence?evidence=JSON_EVIDENCE_encoded +curl http://localhost:26657/v1/broadcast_evidence?evidence=JSON_EVIDENCE_encoded ``` #### JSONRPC ```sh -curl -X POST https://localhost:26657 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"broadcast_evidence\",\"params\":{\"evidence\":\"JSON_EVIDENCE_encoded\"}}" +curl -X POST https://localhost:26657/v1 -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"broadcast_evidence\",\"params\":{\"evidence\":\"JSON_EVIDENCE_encoded\"}}" ``` #### Response diff --git a/state/indexer/block/kv/util.go b/state/indexer/block/kv/util.go deleted file mode 100644 index 9ccb84720fa..00000000000 --- a/state/indexer/block/kv/util.go +++ /dev/null @@ -1,193 +0,0 @@ -package kv - -import ( - "encoding/binary" - "fmt" - "strconv" - - "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 { - return true - } - } - - return false -} - -func int64FromBytes(bz []byte) int64 { - v, _ := binary.Varint(bz) - return v -} - -func int64ToBytes(i int64) []byte { - buf := make([]byte, binary.MaxVarintLen64) - n := binary.PutVarint(buf, i) - return buf[:n] -} - -func heightKey(height int64) ([]byte, error) { - return orderedcode.Append( - nil, - types.BlockHeightKey, - height, - ) -} - -func eventKey(compositeKey, typ, eventValue string, height int64, eventSeq int64) ([]byte, error) { - return orderedcode.Append( - nil, - compositeKey, - eventValue, - height, - typ, - eventSeq, - ) -} - -func parseValueFromPrimaryKey(key []byte) (string, error) { - var ( - compositeKey string - height int64 - ) - - remaining, err := orderedcode.Parse(string(key), &compositeKey, &height) - if err != nil { - return "", fmt.Errorf("failed to parse event key: %w", err) - } - - if len(remaining) != 0 { - return "", fmt.Errorf("unexpected remainder in key: %s", remaining) - } - - return strconv.FormatInt(height, 10), nil -} - -func parseValueFromEventKey(key []byte) (string, error) { - var ( - compositeKey, typ, eventValue string - height int64 - ) - - _, 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 { - 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 eventSeq, nil -} - -// 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 { - 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 -} - -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/block/null/null.go b/state/indexer/block/null/null.go deleted file mode 100644 index 2af842c74a8..00000000000 --- a/state/indexer/block/null/null.go +++ /dev/null @@ -1,27 +0,0 @@ -package null - -import ( - "context" - "errors" - - "github.com/cometbft/cometbft/libs/pubsub/query" - "github.com/cometbft/cometbft/state/indexer" - "github.com/cometbft/cometbft/types" -) - -var _ indexer.BlockIndexer = (*BlockerIndexer)(nil) - -// TxIndex implements a no-op block indexer. -type BlockerIndexer struct{} - -func (idx *BlockerIndexer) Has(height int64) (bool, error) { - return false, errors.New(`indexing is disabled (set 'tx_index = "kv"' in config)`) -} - -func (idx *BlockerIndexer) Index(types.EventDataNewBlockEvents) error { - return nil -} - -func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, error) { - return []int64{}, nil -} diff --git a/state/indexer/mocks/block_indexer.go b/state/indexer/mocks/block_indexer.go deleted file mode 100644 index c17a6532247..00000000000 --- a/state/indexer/mocks/block_indexer.go +++ /dev/null @@ -1,97 +0,0 @@ -// Code generated by mockery. DO NOT EDIT. - -package mocks - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" - - query "github.com/cometbft/cometbft/libs/pubsub/query" - - types "github.com/cometbft/cometbft/types" -) - -// BlockIndexer is an autogenerated mock type for the BlockIndexer type -type BlockIndexer struct { - mock.Mock -} - -// Has provides a mock function with given fields: height -func (_m *BlockIndexer) Has(height int64) (bool, error) { - ret := _m.Called(height) - - var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(int64) (bool, error)); ok { - return rf(height) - } - if rf, ok := ret.Get(0).(func(int64) bool); ok { - r0 = rf(height) - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(height) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Index provides a mock function with given fields: _a0 -func (_m *BlockIndexer) Index(_a0 types.EventDataNewBlockEvents) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(types.EventDataNewBlockEvents) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Search provides a mock function with given fields: ctx, q -func (_m *BlockIndexer) Search(ctx context.Context, q *query.Query) ([]int64, error) { - ret := _m.Called(ctx, q) - - var r0 []int64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *query.Query) ([]int64, error)); ok { - return rf(ctx, q) - } - if rf, ok := ret.Get(0).(func(context.Context, *query.Query) []int64); ok { - r0 = rf(ctx, q) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]int64) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *query.Query) error); ok { - r1 = rf(ctx, q) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTNewBlockIndexer interface { - mock.TestingT - Cleanup(func()) -} - -// NewBlockIndexer creates a new instance of BlockIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBlockIndexer(t mockConstructorTestingTNewBlockIndexer) *BlockIndexer { - mock := &BlockIndexer{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/state/indexer/sink/psql/psql.go b/state/indexer/sink/psql/psql.go deleted file mode 100644 index 79c641b0790..00000000000 --- a/state/indexer/sink/psql/psql.go +++ /dev/null @@ -1,251 +0,0 @@ -// Package psql implements an event sink backed by a PostgreSQL database. -package psql - -import ( - "context" - "database/sql" - "errors" - "fmt" - "strings" - "time" - - "github.com/cosmos/gogoproto/proto" - - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" - "github.com/cometbft/cometbft/types" -) - -const ( - tableBlocks = "blocks" - tableTxResults = "tx_results" - tableEvents = "events" - tableAttributes = "attributes" - driverName = "postgres" -) - -// EventSink is an indexer backend providing the tx/block index services. This -// implementation stores records in a PostgreSQL database using the schema -// defined in state/indexer/sink/psql/schema.sql. -type EventSink struct { - store *sql.DB - chainID string -} - -// NewEventSink constructs an event sink associated with the PostgreSQL -// database specified by connStr. Events written to the sink are attributed to -// the specified chainID. -func NewEventSink(connStr, chainID string) (*EventSink, error) { - db, err := sql.Open(driverName, connStr) - if err != nil { - return nil, err - } - - return &EventSink{ - store: db, - chainID: chainID, - }, nil -} - -// DB returns the underlying Postgres connection used by the sink. -// This is exported to support testing. -func (es *EventSink) DB() *sql.DB { return es.store } - -// runInTransaction executes query in a fresh database transaction. -// If query reports an error, the transaction is rolled back and the -// error from query is reported to the caller. -// Otherwise, the result of committing the transaction is returned. -func runInTransaction(db *sql.DB, query func(*sql.Tx) error) error { - dbtx, err := db.Begin() - if err != nil { - return err - } - if err := query(dbtx); err != nil { - _ = dbtx.Rollback() // report the initial error, not the rollback - return err - } - return dbtx.Commit() -} - -// queryWithID executes the specified SQL query with the given arguments, -// expecting a single-row, single-column result containing an ID. If the query -// succeeds, the ID from the result is returned. -func queryWithID(tx *sql.Tx, query string, args ...interface{}) (uint32, error) { - var id uint32 - if err := tx.QueryRow(query, args...).Scan(&id); err != nil { - return 0, err - } - return id, nil -} - -// insertEvents inserts a slice of events and any indexed attributes of those -// events into the database associated with dbtx. -// -// If txID > 0, the event is attributed to the transaction with that -// ID; otherwise it is recorded as a block event. -func insertEvents(dbtx *sql.Tx, blockID, txID uint32, evts []abci.Event) error { - // Populate the transaction ID field iff one is defined (> 0). - var txIDArg interface{} - if txID > 0 { - txIDArg = txID - } - - // Add each event to the events table, and retrieve its row ID to use when - // adding any attributes the event provides. - for _, evt := range evts { - // Skip events with an empty type. - if evt.Type == "" { - continue - } - - eid, err := queryWithID(dbtx, ` -INSERT INTO `+tableEvents+` (block_id, tx_id, type) VALUES ($1, $2, $3) - RETURNING rowid; -`, blockID, txIDArg, evt.Type) - if err != nil { - return err - } - - // Add any attributes flagged for indexing. - for _, attr := range evt.Attributes { - if !attr.Index { - continue - } - compositeKey := evt.Type + "." + attr.Key - if _, err := dbtx.Exec(` -INSERT INTO `+tableAttributes+` (event_id, key, composite_key, value) - VALUES ($1, $2, $3, $4); -`, eid, attr.Key, compositeKey, attr.Value); err != nil { - return err - } - } - } - return nil -} - -// makeIndexedEvent constructs an event from the specified composite key and -// value. If the key has the form "type.name", the event will have a single -// attribute with that name and the value; otherwise the event will have only -// a type and no attributes. -func makeIndexedEvent(compositeKey, value string) abci.Event { - i := strings.Index(compositeKey, ".") - if i < 0 { - return abci.Event{Type: compositeKey} - } - return abci.Event{Type: compositeKey[:i], Attributes: []abci.EventAttribute{ - {Key: compositeKey[i+1:], Value: value, Index: true}, - }} -} - -// IndexBlockEvents indexes the specified block header, part of the -// indexer.EventSink interface. -func (es *EventSink) IndexBlockEvents(h types.EventDataNewBlockEvents) error { - ts := time.Now().UTC() - - return runInTransaction(es.store, func(dbtx *sql.Tx) error { - // Add the block to the blocks table and report back its row ID for use - // in indexing the events for the block. - blockID, err := queryWithID(dbtx, ` -INSERT INTO `+tableBlocks+` (height, chain_id, created_at) - VALUES ($1, $2, $3) - ON CONFLICT DO NOTHING - RETURNING rowid; -`, h.Height, es.chainID, ts) - if err == sql.ErrNoRows { - return nil // we already saw this block; quietly succeed - } else if err != nil { - return fmt.Errorf("indexing block header: %w", err) - } - - // Insert the special block meta-event for height. - if err := insertEvents(dbtx, blockID, 0, []abci.Event{ - makeIndexedEvent(types.BlockHeightKey, fmt.Sprint(h.Height)), - }); err != nil { - return fmt.Errorf("block meta-events: %w", err) - } - // Insert all the block events. Order is important here, - if err := insertEvents(dbtx, blockID, 0, h.Events); err != nil { - return fmt.Errorf("finalizeblock events: %w", err) - } - return nil - }) -} - -func (es *EventSink) IndexTxEvents(txrs []*abci.TxResult) error { - ts := time.Now().UTC() - - for _, txr := range txrs { - // Encode the result message in protobuf wire format for indexing. - resultData, err := proto.Marshal(txr) - if err != nil { - return fmt.Errorf("marshaling tx_result: %w", err) - } - - // Index the hash of the underlying transaction as a hex string. - txHash := fmt.Sprintf("%X", types.Tx(txr.Tx).Hash()) - - if err := runInTransaction(es.store, func(dbtx *sql.Tx) error { - // Find the block associated with this transaction. The block header - // must have been indexed prior to the transactions belonging to it. - blockID, err := queryWithID(dbtx, ` -SELECT rowid FROM `+tableBlocks+` WHERE height = $1 AND chain_id = $2; -`, txr.Height, es.chainID) - if err != nil { - return fmt.Errorf("finding block ID: %w", err) - } - - // Insert a record for this tx_result and capture its ID for indexing events. - txID, err := queryWithID(dbtx, ` -INSERT INTO `+tableTxResults+` (block_id, index, created_at, tx_hash, tx_result) - VALUES ($1, $2, $3, $4, $5) - ON CONFLICT DO NOTHING - RETURNING rowid; -`, blockID, txr.Index, ts, txHash, resultData) - if err == sql.ErrNoRows { - return nil // we already saw this transaction; quietly succeed - } else if err != nil { - return fmt.Errorf("indexing tx_result: %w", err) - } - - // Insert the special transaction meta-events for hash and height. - if err := insertEvents(dbtx, blockID, txID, []abci.Event{ - makeIndexedEvent(types.TxHashKey, txHash), - makeIndexedEvent(types.TxHeightKey, fmt.Sprint(txr.Height)), - }); err != nil { - return fmt.Errorf("indexing transaction meta-events: %w", err) - } - // Index any events packaged with the transaction. - if err := insertEvents(dbtx, blockID, txID, txr.Result.Events); err != nil { - return fmt.Errorf("indexing transaction events: %w", err) - } - return nil - - }); err != nil { - return err - } - } - return nil -} - -// SearchBlockEvents is not implemented by this sink, and reports an error for all queries. -func (es *EventSink) SearchBlockEvents(ctx context.Context, q *query.Query) ([]int64, error) { - return nil, errors.New("block search is not supported via the postgres event sink") -} - -// SearchTxEvents is not implemented by this sink, and reports an error for all queries. -func (es *EventSink) SearchTxEvents(ctx context.Context, q *query.Query) ([]*abci.TxResult, error) { - return nil, errors.New("tx search is not supported via the postgres event sink") -} - -// GetTxByHash is not implemented by this sink, and reports an error for all queries. -func (es *EventSink) GetTxByHash(hash []byte) (*abci.TxResult, error) { - return nil, errors.New("getTxByHash is not supported via the postgres event sink") -} - -// HasBlock is not implemented by this sink, and reports an error for all queries. -func (es *EventSink) HasBlock(h int64) (bool, error) { - return false, errors.New("hasBlock is not supported via the postgres event sink") -} - -// Stop closes the underlying PostgreSQL database. -func (es *EventSink) Stop() error { return es.store.Close() } diff --git a/state/metrics.gen.go b/state/metrics.gen.go deleted file mode 100644 index 554beefb691..00000000000 --- a/state/metrics.gen.go +++ /dev/null @@ -1,46 +0,0 @@ -// Code generated by metricsgen. DO NOT EDIT. - -package state - -import ( - "github.com/go-kit/kit/metrics/discard" - prometheus "github.com/go-kit/kit/metrics/prometheus" - stdprometheus "github.com/prometheus/client_golang/prometheus" -) - -func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { - labels := []string{} - for i := 0; i < len(labelsAndValues); i += 2 { - labels = append(labels, labelsAndValues[i]) - } - return &Metrics{ - BlockProcessingTime: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "block_processing_time", - Help: "Time spent processing FinalizeBlock", - - Buckets: stdprometheus.LinearBuckets(1, 10, 10), - }, labels).With(labelsAndValues...), - ConsensusParamUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "consensus_param_updates", - Help: "Number of consensus parameter updates returned by the application since process start.", - }, labels).With(labelsAndValues...), - ValidatorSetUpdates: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: namespace, - Subsystem: MetricsSubsystem, - Name: "validator_set_updates", - Help: "Number of validator set updates returned by the application since process start.", - }, labels).With(labelsAndValues...), - } -} - -func NopMetrics() *Metrics { - return &Metrics{ - BlockProcessingTime: discard.NewHistogram(), - ConsensusParamUpdates: discard.NewCounter(), - ValidatorSetUpdates: discard.NewCounter(), - } -} diff --git a/state/metrics.go b/state/metrics.go deleted file mode 100644 index 9015ed1dd2b..00000000000 --- a/state/metrics.go +++ /dev/null @@ -1,29 +0,0 @@ -package state - -import ( - "github.com/go-kit/kit/metrics" -) - -const ( - // MetricsSubsystem is a subsystem shared by all metrics exposed by this - // package. - MetricsSubsystem = "state" -) - -//go:generate go run ../scripts/metricsgen -struct=Metrics - -// Metrics contains metrics exposed by this package. -type Metrics struct { - // Time spent processing FinalizeBlock - BlockProcessingTime metrics.Histogram `metrics_buckettype:"lin" metrics_bucketsizes:"1, 10, 10"` - - // ConsensusParamUpdates is the total number of times the application has - // updated the consensus params since process start. - //metrics:Number of consensus parameter updates returned by the application since process start. - ConsensusParamUpdates metrics.Counter - - // ValidatorSetUpdates is the total number of times the application has - // updated the validator set since process start. - //metrics:Number of validator set updates returned by the application since process start. - ValidatorSetUpdates metrics.Counter -} diff --git a/state/mocks/store.go b/state/mocks/store.go deleted file mode 100644 index 8e8d1e35fee..00000000000 --- a/state/mocks/store.go +++ /dev/null @@ -1,276 +0,0 @@ -// Code generated by mockery. DO NOT EDIT. - -package mocks - -import ( - abcitypes "github.com/cometbft/cometbft/abci/types" - mock "github.com/stretchr/testify/mock" - - state "github.com/cometbft/cometbft/state" - - types "github.com/cometbft/cometbft/types" -) - -// Store is an autogenerated mock type for the Store type -type Store struct { - mock.Mock -} - -// Bootstrap provides a mock function with given fields: _a0 -func (_m *Store) Bootstrap(_a0 state.State) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(state.State) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Close provides a mock function with given fields: -func (_m *Store) Close() error { - ret := _m.Called() - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Load provides a mock function with given fields: -func (_m *Store) Load() (state.State, error) { - ret := _m.Called() - - var r0 state.State - var r1 error - if rf, ok := ret.Get(0).(func() (state.State, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() state.State); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(state.State) - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoadConsensusParams provides a mock function with given fields: _a0 -func (_m *Store) LoadConsensusParams(_a0 int64) (types.ConsensusParams, error) { - ret := _m.Called(_a0) - - var r0 types.ConsensusParams - var r1 error - if rf, ok := ret.Get(0).(func(int64) (types.ConsensusParams, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(int64) types.ConsensusParams); ok { - r0 = rf(_a0) - } else { - r0 = ret.Get(0).(types.ConsensusParams) - } - - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoadFinalizeBlockResponse provides a mock function with given fields: _a0 -func (_m *Store) LoadFinalizeBlockResponse(_a0 int64) (*abcitypes.ResponseFinalizeBlock, error) { - ret := _m.Called(_a0) - - var r0 *abcitypes.ResponseFinalizeBlock - var r1 error - if rf, ok := ret.Get(0).(func(int64) (*abcitypes.ResponseFinalizeBlock, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(int64) *abcitypes.ResponseFinalizeBlock); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*abcitypes.ResponseFinalizeBlock) - } - } - - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoadFromDBOrGenesisDoc provides a mock function with given fields: _a0 -func (_m *Store) LoadFromDBOrGenesisDoc(_a0 *types.GenesisDoc) (state.State, error) { - ret := _m.Called(_a0) - - var r0 state.State - var r1 error - if rf, ok := ret.Get(0).(func(*types.GenesisDoc) (state.State, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(*types.GenesisDoc) state.State); ok { - r0 = rf(_a0) - } else { - r0 = ret.Get(0).(state.State) - } - - if rf, ok := ret.Get(1).(func(*types.GenesisDoc) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoadFromDBOrGenesisFile provides a mock function with given fields: _a0 -func (_m *Store) LoadFromDBOrGenesisFile(_a0 string) (state.State, error) { - ret := _m.Called(_a0) - - var r0 state.State - var r1 error - if rf, ok := ret.Get(0).(func(string) (state.State, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(string) state.State); ok { - r0 = rf(_a0) - } else { - r0 = ret.Get(0).(state.State) - } - - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoadLastFinalizeBlockResponse provides a mock function with given fields: _a0 -func (_m *Store) LoadLastFinalizeBlockResponse(_a0 int64) (*abcitypes.ResponseFinalizeBlock, error) { - ret := _m.Called(_a0) - - var r0 *abcitypes.ResponseFinalizeBlock - var r1 error - if rf, ok := ret.Get(0).(func(int64) (*abcitypes.ResponseFinalizeBlock, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(int64) *abcitypes.ResponseFinalizeBlock); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*abcitypes.ResponseFinalizeBlock) - } - } - - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// LoadValidators provides a mock function with given fields: _a0 -func (_m *Store) LoadValidators(_a0 int64) (*types.ValidatorSet, error) { - ret := _m.Called(_a0) - - var r0 *types.ValidatorSet - var r1 error - if rf, ok := ret.Get(0).(func(int64) (*types.ValidatorSet, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(int64) *types.ValidatorSet); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ValidatorSet) - } - } - - if rf, ok := ret.Get(1).(func(int64) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PruneStates provides a mock function with given fields: _a0, _a1, _a2 -func (_m *Store) PruneStates(_a0 int64, _a1 int64, _a2 int64) error { - ret := _m.Called(_a0, _a1, _a2) - - var r0 error - if rf, ok := ret.Get(0).(func(int64, int64, int64) error); ok { - r0 = rf(_a0, _a1, _a2) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Save provides a mock function with given fields: _a0 -func (_m *Store) Save(_a0 state.State) error { - ret := _m.Called(_a0) - - var r0 error - if rf, ok := ret.Get(0).(func(state.State) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// SaveFinalizeBlockResponse provides a mock function with given fields: _a0, _a1 -func (_m *Store) SaveFinalizeBlockResponse(_a0 int64, _a1 *abcitypes.ResponseFinalizeBlock) error { - ret := _m.Called(_a0, _a1) - - var r0 error - if rf, ok := ret.Get(0).(func(int64, *abcitypes.ResponseFinalizeBlock) error); ok { - r0 = rf(_a0, _a1) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -type mockConstructorTestingTNewStore interface { - mock.TestingT - Cleanup(func()) -} - -// NewStore creates a new instance of Store. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewStore(t mockConstructorTestingTNewStore) *Store { - mock := &Store{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/state/store.go b/state/store.go deleted file mode 100644 index 5b0dee2afd6..00000000000 --- a/state/store.go +++ /dev/null @@ -1,708 +0,0 @@ -package state - -import ( - "errors" - "fmt" - - "github.com/cosmos/gogoproto/proto" - - dbm "github.com/cometbft/cometbft-db" - - abci "github.com/cometbft/cometbft/abci/types" - cmtmath "github.com/cometbft/cometbft/libs/math" - cmtos "github.com/cometbft/cometbft/libs/os" - cmtstate "github.com/cometbft/cometbft/proto/tendermint/state" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - "github.com/cometbft/cometbft/types" -) - -const ( - // persist validators every valSetCheckpointInterval blocks to avoid - // LoadValidators taking too much time. - // https://github.com/tendermint/tendermint/pull/3438 - // 100000 results in ~ 100ms to get 100 validators (see BenchmarkLoadValidators) - valSetCheckpointInterval = 100000 -) - -//------------------------------------------------------------------------ - -func calcValidatorsKey(height int64) []byte { - return []byte(fmt.Sprintf("validatorsKey:%v", height)) -} - -func calcConsensusParamsKey(height int64) []byte { - return []byte(fmt.Sprintf("consensusParamsKey:%v", height)) -} - -func calcABCIResponsesKey(height int64) []byte { - return []byte(fmt.Sprintf("abciResponsesKey:%v", height)) -} - -//---------------------- - -var lastABCIResponseKey = []byte("lastABCIResponseKey") - -//go:generate ../scripts/mockery_generate.sh Store - -// Store defines the state store interface -// -// It is used to retrieve current state and save and load ABCI responses, -// validators and consensus parameters -type Store interface { - // LoadFromDBOrGenesisFile loads the most recent state. - // If the chain is new it will use the genesis file from the provided genesis file path as the current state. - LoadFromDBOrGenesisFile(string) (State, error) - // LoadFromDBOrGenesisDoc loads the most recent state. - // If the chain is new it will use the genesis doc as the current state. - LoadFromDBOrGenesisDoc(*types.GenesisDoc) (State, error) - // Load loads the current state of the blockchain - Load() (State, error) - // LoadValidators loads the validator set at a given height - LoadValidators(int64) (*types.ValidatorSet, error) - // LoadFinalizeBlockResponse loads the abciResponse for a given height - LoadFinalizeBlockResponse(int64) (*abci.ResponseFinalizeBlock, error) - // LoadLastABCIResponse loads the last abciResponse for a given height - LoadLastFinalizeBlockResponse(int64) (*abci.ResponseFinalizeBlock, error) - // LoadConsensusParams loads the consensus params for a given height - LoadConsensusParams(int64) (types.ConsensusParams, error) - // Save overwrites the previous state with the updated one - Save(State) error - // SaveFinalizeBlockResponse saves ABCIResponses for a given height - SaveFinalizeBlockResponse(int64, *abci.ResponseFinalizeBlock) error - // Bootstrap is used for bootstrapping state when not starting from a initial height. - Bootstrap(State) error - // PruneStates takes the height from which to start pruning and which height stop at - PruneStates(int64, int64, int64) error - // Close closes the connection with the database - Close() error -} - -// dbStore wraps a db (github.com/cometbft/cometbft-db) -type dbStore struct { - db dbm.DB - - StoreOptions -} - -type StoreOptions struct { - // DiscardABCIResponses determines whether or not the store - // retains all ABCIResponses. If DiscardABCIResponses is enabled, - // the store will maintain only the response object from the latest - // height. - DiscardABCIResponses bool -} - -var _ Store = (*dbStore)(nil) - -// NewStore creates the dbStore of the state pkg. -func NewStore(db dbm.DB, options StoreOptions) Store { - return dbStore{db, options} -} - -// LoadStateFromDBOrGenesisFile loads the most recent state from the database, -// or creates a new one from the given genesisFilePath. -func (store dbStore) LoadFromDBOrGenesisFile(genesisFilePath string) (State, error) { - state, err := store.Load() - if err != nil { - return State{}, err - } - if state.IsEmpty() { - var err error - state, err = MakeGenesisStateFromFile(genesisFilePath) - if err != nil { - return state, err - } - } - - return state, nil -} - -// LoadStateFromDBOrGenesisDoc loads the most recent state from the database, -// or creates a new one from the given genesisDoc. -func (store dbStore) LoadFromDBOrGenesisDoc(genesisDoc *types.GenesisDoc) (State, error) { - state, err := store.Load() - if err != nil { - return State{}, err - } - - if state.IsEmpty() { - var err error - state, err = MakeGenesisState(genesisDoc) - if err != nil { - return state, err - } - } - - return state, nil -} - -// LoadState loads the State from the database. -func (store dbStore) Load() (State, error) { - return store.loadState(stateKey) -} - -func (store dbStore) loadState(key []byte) (state State, err error) { - buf, err := store.db.Get(key) - if err != nil { - return state, err - } - if len(buf) == 0 { - return state, nil - } - - sp := new(cmtstate.State) - - err = proto.Unmarshal(buf, sp) - if err != nil { - // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED - cmtos.Exit(fmt.Sprintf(`LoadState: Data has been corrupted or its spec has changed: - %v\n`, err)) - } - - sm, err := FromProto(sp) - if err != nil { - return state, err - } - return *sm, nil -} - -// Save persists the State, the ValidatorsInfo, and the ConsensusParamsInfo to the database. -// This flushes the writes (e.g. calls SetSync). -func (store dbStore) Save(state State) error { - return store.save(state, stateKey) -} - -func (store dbStore) save(state State, key []byte) error { - nextHeight := state.LastBlockHeight + 1 - // If first block, save validators for the block. - if nextHeight == 1 { - nextHeight = state.InitialHeight - // This extra logic due to validator set changes being delayed 1 block. - // It may get overwritten due to InitChain validator updates. - if err := store.saveValidatorsInfo(nextHeight, nextHeight, state.Validators); err != nil { - return err - } - } - // Save next validators. - if err := store.saveValidatorsInfo(nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators); err != nil { - return err - } - - // Save next consensus params. - if err := store.saveConsensusParamsInfo(nextHeight, - state.LastHeightConsensusParamsChanged, state.ConsensusParams); err != nil { - return err - } - err := store.db.SetSync(key, state.Bytes()) - if err != nil { - return err - } - - return nil -} - -// BootstrapState saves a new state, used e.g. by state sync when starting from non-zero height. -func (store dbStore) Bootstrap(state State) error { - height := state.LastBlockHeight + 1 - if height == 1 { - height = state.InitialHeight - } - - if height > 1 && !state.LastValidators.IsNilOrEmpty() { - if err := store.saveValidatorsInfo(height-1, height-1, state.LastValidators); err != nil { - return err - } - } - - if err := store.saveValidatorsInfo(height, height, state.Validators); err != nil { - return err - } - - if err := store.saveValidatorsInfo(height+1, height+1, state.NextValidators); err != nil { - return err - } - - if err := store.saveConsensusParamsInfo(height, - state.LastHeightConsensusParamsChanged, state.ConsensusParams); err != nil { - return err - } - - return store.db.SetSync(stateKey, state.Bytes()) -} - -// PruneStates deletes states between the given heights (including from, excluding to). It is not -// guaranteed to delete all states, since the last checkpointed state and states being pointed to by -// e.g. `LastHeightChanged` must remain. The state at to must also exist. -// -// The from parameter is necessary since we can't do a key scan in a performant way due to the key -// encoding not preserving ordering: https://github.com/tendermint/tendermint/issues/4567 -// This will cause some old states to be left behind when doing incremental partial prunes, -// specifically older checkpoints and LastHeightChanged targets. -func (store dbStore) PruneStates(from int64, to int64, evidenceThresholdHeight int64) error { - if from <= 0 || to <= 0 { - return fmt.Errorf("from height %v and to height %v must be greater than 0", from, to) - } - if from >= to { - return fmt.Errorf("from height %v must be lower than to height %v", from, to) - } - - valInfo, err := loadValidatorsInfo(store.db, min(to, evidenceThresholdHeight)) - if err != nil { - return fmt.Errorf("validators at height %v not found: %w", to, err) - } - paramsInfo, err := store.loadConsensusParamsInfo(to) - if err != nil { - return fmt.Errorf("consensus params at height %v not found: %w", to, err) - } - - keepVals := make(map[int64]bool) - if valInfo.ValidatorSet == nil { - keepVals[valInfo.LastHeightChanged] = true - keepVals[lastStoredHeightFor(to, valInfo.LastHeightChanged)] = true // keep last checkpoint too - } - keepParams := make(map[int64]bool) - if paramsInfo.ConsensusParams.Equal(&cmtproto.ConsensusParams{}) { - keepParams[paramsInfo.LastHeightChanged] = true - } - - batch := store.db.NewBatch() - defer batch.Close() - pruned := uint64(0) - - // We have to delete in reverse order, to avoid deleting previous heights that have validator - // sets and consensus params that we may need to retrieve. - for h := to - 1; h >= from; h-- { - // For heights we keep, we must make sure they have the full validator set or consensus - // params, otherwise they will panic if they're retrieved directly (instead of - // indirectly via a LastHeightChanged pointer). - if keepVals[h] { - v, err := loadValidatorsInfo(store.db, h) - if err != nil || v.ValidatorSet == nil { - vip, err := store.LoadValidators(h) - if err != nil { - return err - } - - pvi, err := vip.ToProto() - if err != nil { - return err - } - - v.ValidatorSet = pvi - v.LastHeightChanged = h - - bz, err := v.Marshal() - if err != nil { - return err - } - err = batch.Set(calcValidatorsKey(h), bz) - if err != nil { - return err - } - } - } else if h < evidenceThresholdHeight { - err = batch.Delete(calcValidatorsKey(h)) - if err != nil { - return err - } - } - // else we keep the validator set because we might need - // it later on for evidence verification - - if keepParams[h] { - p, err := store.loadConsensusParamsInfo(h) - if err != nil { - return err - } - - if p.ConsensusParams.Equal(&cmtproto.ConsensusParams{}) { - params, err := store.LoadConsensusParams(h) - if err != nil { - return err - } - p.ConsensusParams = params.ToProto() - - p.LastHeightChanged = h - bz, err := p.Marshal() - if err != nil { - return err - } - - err = batch.Set(calcConsensusParamsKey(h), bz) - if err != nil { - return err - } - } - } else { - err = batch.Delete(calcConsensusParamsKey(h)) - if err != nil { - return err - } - } - - err = batch.Delete(calcABCIResponsesKey(h)) - if err != nil { - return err - } - pruned++ - - // avoid batches growing too large by flushing to database regularly - if pruned%1000 == 0 && pruned > 0 { - err := batch.Write() - if err != nil { - return err - } - batch.Close() - batch = store.db.NewBatch() - defer batch.Close() - } - } - - err = batch.WriteSync() - if err != nil { - return err - } - - return nil -} - -//------------------------------------------------------------------------ - -// TxResultsHash returns the root hash of a Merkle tree of -// ExecTxResulst responses (see ABCIResults.Hash) -// -// See merkle.SimpleHashFromByteSlices -func TxResultsHash(txResults []*abci.ExecTxResult) []byte { - return types.NewResults(txResults).Hash() -} - -// LoadFinalizeBlockResponse loads the DiscardABCIResponses for the given height from the -// database. If the node has D set to true, ErrABCIResponsesNotPersisted -// is persisted. If not found, ErrNoABCIResponsesForHeight is returned. -func (store dbStore) LoadFinalizeBlockResponse(height int64) (*abci.ResponseFinalizeBlock, error) { - if store.DiscardABCIResponses { - return nil, ErrFinalizeBlockResponsesNotPersisted - } - - buf, err := store.db.Get(calcABCIResponsesKey(height)) - if err != nil { - return nil, err - } - if len(buf) == 0 { - return nil, ErrNoABCIResponsesForHeight{height} - } - - resp := new(abci.ResponseFinalizeBlock) - err = resp.Unmarshal(buf) - if err != nil { - // The data might be of the legacy ABCI response type, so - // we try to unmarshal that - legacyResp := new(cmtstate.LegacyABCIResponses) - rerr := legacyResp.Unmarshal(buf) - if rerr != nil { - // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED - cmtos.Exit(fmt.Sprintf(`LoadFinalizeBlockResponse: Data has been corrupted or its spec has - changed: %v\n`, err)) - } - // The state store contains the old format. Migrate to - // the new ResponseFinalizeBlock format. Note that the - // new struct expects the AppHash which we don't have. - return responseFinalizeBlockFromLegacy(legacyResp), nil - } - - // TODO: ensure that buf is completely read. - - return resp, nil -} - -// LoadLastFinalizeBlockResponses loads the FinalizeBlockResponses from the most recent height. -// The height parameter is used to ensure that the response corresponds to the latest height. -// If not, an error is returned. -// -// This method is used for recovering in the case that we called the Commit ABCI -// method on the application but crashed before persisting the results. -func (store dbStore) LoadLastFinalizeBlockResponse(height int64) (*abci.ResponseFinalizeBlock, error) { - bz, err := store.db.Get(lastABCIResponseKey) - if err != nil { - return nil, err - } - - if len(bz) == 0 { - return nil, errors.New("no last ABCI response has been persisted") - } - - info := new(cmtstate.ABCIResponsesInfo) - err = info.Unmarshal(bz) - if err != nil { - cmtos.Exit(fmt.Sprintf(`LoadLastFinalizeBlockResponse: Data has been corrupted or its spec has - changed: %v\n`, err)) - } - - // Here we validate the result by comparing its height to the expected height. - if height != info.GetHeight() { - return nil, fmt.Errorf("expected height %d but last stored abci responses was at height %d", height, info.GetHeight()) - } - - // It is possible if this is called directly after an upgrade that - // ResponseFinalizeBlock is nil. In which case we use the legacy - // ABCI responses - if info.ResponseFinalizeBlock == nil { - // sanity check - if info.LegacyAbciResponses == nil { - panic("state store contains last abci response but it is empty") - } - return responseFinalizeBlockFromLegacy(info.LegacyAbciResponses), nil - } - - return info.ResponseFinalizeBlock, nil -} - -// SaveFinalizeBlockResponse persists the ResponseFinalizeBlock to the database. -// This is useful in case we crash after app.Commit and before s.Save(). -// Responses are indexed by height so they can also be loaded later to produce -// Merkle proofs. -// -// CONTRACT: height must be monotonically increasing every time this is called. -func (store dbStore) SaveFinalizeBlockResponse(height int64, resp *abci.ResponseFinalizeBlock) error { - var dtxs []*abci.ExecTxResult - // strip nil values, - for _, tx := range resp.TxResults { - if tx != nil { - dtxs = append(dtxs, tx) - } - } - resp.TxResults = dtxs - - // If the flag is false then we save the ABCIResponse. This can be used for the /BlockResults - // query or to reindex an event using the command line. - if !store.DiscardABCIResponses { - bz, err := resp.Marshal() - if err != nil { - return err - } - if err := store.db.Set(calcABCIResponsesKey(height), bz); err != nil { - return err - } - } - - // We always save the last ABCI response for crash recovery. - // This overwrites the previous saved ABCI Response. - response := &cmtstate.ABCIResponsesInfo{ - ResponseFinalizeBlock: resp, - Height: height, - } - bz, err := response.Marshal() - if err != nil { - return err - } - - return store.db.SetSync(lastABCIResponseKey, bz) -} - -//----------------------------------------------------------------------------- - -// LoadValidators loads the ValidatorSet for a given height. -// Returns ErrNoValSetForHeight if the validator set can't be found for this height. -func (store dbStore) LoadValidators(height int64) (*types.ValidatorSet, error) { - valInfo, err := loadValidatorsInfo(store.db, height) - if err != nil { - return nil, ErrNoValSetForHeight{height} - } - if valInfo.ValidatorSet == nil { - lastStoredHeight := lastStoredHeightFor(height, valInfo.LastHeightChanged) - valInfo2, err := loadValidatorsInfo(store.db, lastStoredHeight) - if err != nil || valInfo2.ValidatorSet == nil { - return nil, - fmt.Errorf("couldn't find validators at height %d (height %d was originally requested): %w", - lastStoredHeight, - height, - err, - ) - } - - vs, err := types.ValidatorSetFromProto(valInfo2.ValidatorSet) - if err != nil { - return nil, err - } - - vs.IncrementProposerPriority(cmtmath.SafeConvertInt32(height - lastStoredHeight)) // mutate - vi2, err := vs.ToProto() - if err != nil { - return nil, err - } - - valInfo2.ValidatorSet = vi2 - valInfo = valInfo2 - } - - vip, err := types.ValidatorSetFromProto(valInfo.ValidatorSet) - if err != nil { - return nil, err - } - - return vip, nil -} - -func lastStoredHeightFor(height, lastHeightChanged int64) int64 { - checkpointHeight := height - height%valSetCheckpointInterval - return cmtmath.MaxInt64(checkpointHeight, lastHeightChanged) -} - -// CONTRACT: Returned ValidatorsInfo can be mutated. -func loadValidatorsInfo(db dbm.DB, height int64) (*cmtstate.ValidatorsInfo, error) { - buf, err := db.Get(calcValidatorsKey(height)) - if err != nil { - return nil, err - } - - if len(buf) == 0 { - return nil, errors.New("value retrieved from db is empty") - } - - v := new(cmtstate.ValidatorsInfo) - err = v.Unmarshal(buf) - if err != nil { - // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED - cmtos.Exit(fmt.Sprintf(`LoadValidators: Data has been corrupted or its spec has changed: - %v\n`, err)) - } - // TODO: ensure that buf is completely read. - - return v, nil -} - -// saveValidatorsInfo persists the validator set. -// -// `height` is the effective height for which the validator is responsible for -// signing. It should be called from s.Save(), right before the state itself is -// persisted. -func (store dbStore) saveValidatorsInfo(height, lastHeightChanged int64, valSet *types.ValidatorSet) error { - if lastHeightChanged > height { - return errors.New("lastHeightChanged cannot be greater than ValidatorsInfo height") - } - valInfo := &cmtstate.ValidatorsInfo{ - LastHeightChanged: lastHeightChanged, - } - // Only persist validator set if it was updated or checkpoint height (see - // valSetCheckpointInterval) is reached. - if height == lastHeightChanged || height%valSetCheckpointInterval == 0 { - pv, err := valSet.ToProto() - if err != nil { - return err - } - valInfo.ValidatorSet = pv - } - - bz, err := valInfo.Marshal() - if err != nil { - return err - } - - err = store.db.Set(calcValidatorsKey(height), bz) - if err != nil { - return err - } - - return nil -} - -//----------------------------------------------------------------------------- - -// ConsensusParamsInfo represents the latest consensus params, or the last height it changed - -// LoadConsensusParams loads the ConsensusParams for a given height. -func (store dbStore) LoadConsensusParams(height int64) (types.ConsensusParams, error) { - var ( - empty = types.ConsensusParams{} - emptypb = cmtproto.ConsensusParams{} - ) - paramsInfo, err := store.loadConsensusParamsInfo(height) - if err != nil { - return empty, fmt.Errorf("could not find consensus params for height #%d: %w", height, err) - } - - if paramsInfo.ConsensusParams.Equal(&emptypb) { - paramsInfo2, err := store.loadConsensusParamsInfo(paramsInfo.LastHeightChanged) - if err != nil { - return empty, fmt.Errorf( - "couldn't find consensus params at height %d as last changed from height %d: %w", - paramsInfo.LastHeightChanged, - height, - err, - ) - } - - paramsInfo = paramsInfo2 - } - - return types.ConsensusParamsFromProto(paramsInfo.ConsensusParams), nil -} - -func (store dbStore) loadConsensusParamsInfo(height int64) (*cmtstate.ConsensusParamsInfo, error) { - buf, err := store.db.Get(calcConsensusParamsKey(height)) - if err != nil { - return nil, err - } - if len(buf) == 0 { - return nil, errors.New("value retrieved from db is empty") - } - - paramsInfo := new(cmtstate.ConsensusParamsInfo) - if err = paramsInfo.Unmarshal(buf); err != nil { - // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED - cmtos.Exit(fmt.Sprintf(`LoadConsensusParams: Data has been corrupted or its spec has changed: - %v\n`, err)) - } - // TODO: ensure that buf is completely read. - - return paramsInfo, nil -} - -// saveConsensusParamsInfo persists the consensus params for the next block to disk. -// It should be called from s.Save(), right before the state itself is persisted. -// If the consensus params did not change after processing the latest block, -// only the last height for which they changed is persisted. -func (store dbStore) saveConsensusParamsInfo(nextHeight, changeHeight int64, params types.ConsensusParams) error { - paramsInfo := &cmtstate.ConsensusParamsInfo{ - LastHeightChanged: changeHeight, - } - - if changeHeight == nextHeight { - paramsInfo.ConsensusParams = params.ToProto() - } - bz, err := paramsInfo.Marshal() - if err != nil { - return err - } - - err = store.db.Set(calcConsensusParamsKey(nextHeight), bz) - if err != nil { - return err - } - - return nil -} - -func (store dbStore) Close() error { - return store.db.Close() -} - -func min(a int64, b int64) int64 { - if a < b { - return a - } - return b -} - -// responseFinalizeBlockFromLegacy is a convenience function that takes the old abci responses and morphs -// it to the finalize block response. Note that the app hash is missing -func responseFinalizeBlockFromLegacy(legacyResp *cmtstate.LegacyABCIResponses) *abci.ResponseFinalizeBlock { - return &abci.ResponseFinalizeBlock{ - TxResults: legacyResp.DeliverTxs, - ValidatorUpdates: legacyResp.EndBlock.ValidatorUpdates, - ConsensusParamUpdates: legacyResp.EndBlock.ConsensusParamUpdates, - Events: append(legacyResp.BeginBlock.Events, legacyResp.EndBlock.Events...), - // NOTE: AppHash is missing in the response but will - // be caught and filled in consensus/replay.go - } -} diff --git a/state/store_test.go b/state/store_test.go deleted file mode 100644 index a7688fe6b5e..00000000000 --- a/state/store_test.go +++ /dev/null @@ -1,352 +0,0 @@ -package state_test - -import ( - "fmt" - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - dbm "github.com/cometbft/cometbft-db" - - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/crypto" - "github.com/cometbft/cometbft/crypto/ed25519" - "github.com/cometbft/cometbft/internal/test" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtstate "github.com/cometbft/cometbft/proto/tendermint/state" - sm "github.com/cometbft/cometbft/state" - "github.com/cometbft/cometbft/types" -) - -func TestStoreLoadValidators(t *testing.T) { - stateDB := dbm.NewMemDB() - stateStore := sm.NewStore(stateDB, sm.StoreOptions{ - DiscardABCIResponses: false, - }) - val, _ := types.RandValidator(true, 10) - vals := types.NewValidatorSet([]*types.Validator{val}) - - // 1) LoadValidators loads validators using a height where they were last changed - err := sm.SaveValidatorsInfo(stateDB, 1, 1, vals) - require.NoError(t, err) - err = sm.SaveValidatorsInfo(stateDB, 2, 1, vals) - require.NoError(t, err) - loadedVals, err := stateStore.LoadValidators(2) - require.NoError(t, err) - assert.NotZero(t, loadedVals.Size()) - - // 2) LoadValidators loads validators using a checkpoint height - - err = sm.SaveValidatorsInfo(stateDB, sm.ValSetCheckpointInterval, 1, vals) - require.NoError(t, err) - - loadedVals, err = stateStore.LoadValidators(sm.ValSetCheckpointInterval) - require.NoError(t, err) - assert.NotZero(t, loadedVals.Size()) -} - -func BenchmarkLoadValidators(b *testing.B) { - const valSetSize = 100 - - config := test.ResetTestRoot("state_") - defer os.RemoveAll(config.RootDir) - dbType := dbm.BackendType(config.DBBackend) - stateDB, err := dbm.NewDB("state", dbType, config.DBDir()) - require.NoError(b, err) - stateStore := sm.NewStore(stateDB, sm.StoreOptions{ - DiscardABCIResponses: false, - }) - state, err := stateStore.LoadFromDBOrGenesisFile(config.GenesisFile()) - if err != nil { - b.Fatal(err) - } - - state.Validators = genValSet(valSetSize) - state.NextValidators = state.Validators.CopyIncrementProposerPriority(1) - err = stateStore.Save(state) - require.NoError(b, err) - - for i := 10; i < 10000000000; i *= 10 { // 10, 100, 1000, ... - i := i - if err := sm.SaveValidatorsInfo(stateDB, - int64(i), state.LastHeightValidatorsChanged, state.NextValidators); err != nil { - b.Fatal(err) - } - - b.Run(fmt.Sprintf("height=%d", i), func(b *testing.B) { - for n := 0; n < b.N; n++ { - _, err := stateStore.LoadValidators(int64(i)) - if err != nil { - b.Fatal(err) - } - } - }) - } -} - -func TestPruneStates(t *testing.T) { - testcases := map[string]struct { - makeHeights int64 - pruneFrom int64 - pruneTo int64 - evidenceThresholdHeight int64 - expectErr bool - expectVals []int64 - expectParams []int64 - expectABCI []int64 - }{ - "error on pruning from 0": {100, 0, 5, 100, true, nil, nil, nil}, - "error when from > to": {100, 3, 2, 2, true, nil, nil, nil}, - "error when from == to": {100, 3, 3, 3, true, nil, nil, nil}, - "error when to does not exist": {100, 1, 101, 101, true, nil, nil, nil}, - "prune all": {100, 1, 100, 100, false, []int64{93, 100}, []int64{95, 100}, []int64{100}}, - "prune some": { - 10, 2, 8, 8, false, - []int64{1, 3, 8, 9, 10}, - []int64{1, 5, 8, 9, 10}, - []int64{1, 8, 9, 10}, - }, - "prune across checkpoint": { - 100001, 1, 100001, 100001, false, - []int64{99993, 100000, 100001}, - []int64{99995, 100001}, - []int64{100001}, - }, - "prune when evidence height < height": {20, 1, 18, 17, false, []int64{13, 17, 18, 19, 20}, []int64{15, 18, 19, 20}, []int64{18, 19, 20}}, - } - for name, tc := range testcases { - tc := tc - t.Run(name, func(t *testing.T) { - db := dbm.NewMemDB() - stateStore := sm.NewStore(db, sm.StoreOptions{ - DiscardABCIResponses: false, - }) - pk := ed25519.GenPrivKey().PubKey() - - // Generate a bunch of state data. Validators change for heights ending with 3, and - // parameters when ending with 5. - validator := &types.Validator{Address: cmtrand.Bytes(crypto.AddressSize), VotingPower: 100, PubKey: pk} - validatorSet := &types.ValidatorSet{ - Validators: []*types.Validator{validator}, - Proposer: validator, - } - valsChanged := int64(0) - paramsChanged := int64(0) - - for h := int64(1); h <= tc.makeHeights; h++ { - if valsChanged == 0 || h%10 == 2 { - valsChanged = h + 1 // Have to add 1, since NextValidators is what's stored - } - if paramsChanged == 0 || h%10 == 5 { - paramsChanged = h - } - - state := sm.State{ - InitialHeight: 1, - LastBlockHeight: h - 1, - Validators: validatorSet, - NextValidators: validatorSet, - ConsensusParams: types.ConsensusParams{ - Block: types.BlockParams{MaxBytes: 10e6}, - }, - LastHeightValidatorsChanged: valsChanged, - LastHeightConsensusParamsChanged: paramsChanged, - } - - if state.LastBlockHeight >= 1 { - state.LastValidators = state.Validators - } - - err := stateStore.Save(state) - require.NoError(t, err) - - err = stateStore.SaveFinalizeBlockResponse(h, &abci.ResponseFinalizeBlock{ - TxResults: []*abci.ExecTxResult{ - {Data: []byte{1}}, - {Data: []byte{2}}, - {Data: []byte{3}}, - }, - }) - require.NoError(t, err) - } - - // Test assertions - err := stateStore.PruneStates(tc.pruneFrom, tc.pruneTo, tc.evidenceThresholdHeight) - if tc.expectErr { - require.Error(t, err) - return - } - require.NoError(t, err) - - expectVals := sliceToMap(tc.expectVals) - expectParams := sliceToMap(tc.expectParams) - expectABCI := sliceToMap(tc.expectABCI) - - for h := int64(1); h <= tc.makeHeights; h++ { - vals, err := stateStore.LoadValidators(h) - if expectVals[h] { - require.NoError(t, err, "validators height %v", h) - require.NotNil(t, vals) - } else { - require.Error(t, err, "validators height %v", h) - require.Equal(t, sm.ErrNoValSetForHeight{Height: h}, err) - } - - params, err := stateStore.LoadConsensusParams(h) - if expectParams[h] { - require.NoError(t, err, "params height %v", h) - require.NotEmpty(t, params) - } else { - require.Error(t, err, "params height %v", h) - require.Empty(t, params) - } - - abci, err := stateStore.LoadFinalizeBlockResponse(h) - if expectABCI[h] { - require.NoError(t, err, "abci height %v", h) - require.NotNil(t, abci) - } else { - require.Error(t, err, "abci height %v", h) - require.Equal(t, sm.ErrNoABCIResponsesForHeight{Height: h}, err) - } - } - }) - } -} - -func TestTxResultsHash(t *testing.T) { - txResults := []*abci.ExecTxResult{ - {Code: 32, Data: []byte("Hello"), Log: "Huh?"}, - } - - root := sm.TxResultsHash(txResults) - - // root should be Merkle tree root of ExecTxResult responses - results := types.NewResults(txResults) - assert.Equal(t, root, results.Hash()) - - // test we can prove first ExecTxResult - proof := results.ProveResult(0) - bz, err := results[0].Marshal() - require.NoError(t, err) - assert.NoError(t, proof.Verify(root, bz)) -} - -func sliceToMap(s []int64) map[int64]bool { - m := make(map[int64]bool, len(s)) - for _, i := range s { - m[i] = true - } - return m -} - -func TestLastFinalizeBlockResponses(t *testing.T) { - // create an empty state store. - t.Run("Not persisting responses", func(t *testing.T) { - stateDB := dbm.NewMemDB() - stateStore := sm.NewStore(stateDB, sm.StoreOptions{ - DiscardABCIResponses: false, - }) - responses, err := stateStore.LoadFinalizeBlockResponse(1) - require.Error(t, err) - require.Nil(t, responses) - // stub the abciresponses. - response1 := &abci.ResponseFinalizeBlock{ - TxResults: []*abci.ExecTxResult{ - {Code: 32, Data: []byte("Hello"), Log: "Huh?"}, - }, - } - // create new db and state store and set discard abciresponses to false. - stateDB = dbm.NewMemDB() - stateStore = sm.NewStore(stateDB, sm.StoreOptions{DiscardABCIResponses: false}) - height := int64(10) - // save the last abci response. - err = stateStore.SaveFinalizeBlockResponse(height, response1) - require.NoError(t, err) - // search for the last finalize block response and check if it has saved. - lastResponse, err := stateStore.LoadLastFinalizeBlockResponse(height) - require.NoError(t, err) - // check to see if the saved response height is the same as the loaded height. - assert.Equal(t, lastResponse, response1) - // use an incorret height to make sure the state store errors. - _, err = stateStore.LoadLastFinalizeBlockResponse(height + 1) - assert.Error(t, err) - // check if the abci response didnt save in the abciresponses. - responses, err = stateStore.LoadFinalizeBlockResponse(height) - require.NoError(t, err, responses) - require.Equal(t, response1, responses) - }) - - t.Run("persisting responses", func(t *testing.T) { - stateDB := dbm.NewMemDB() - height := int64(10) - // stub the second abciresponse. - response2 := &abci.ResponseFinalizeBlock{ - TxResults: []*abci.ExecTxResult{ - {Code: 44, Data: []byte("Hello again"), Log: "????"}, - }, - } - // create a new statestore with the responses on. - stateStore := sm.NewStore(stateDB, sm.StoreOptions{ - DiscardABCIResponses: true, - }) - // save an additional response. - err := stateStore.SaveFinalizeBlockResponse(height+1, response2) - require.NoError(t, err) - // check to see if the response saved by calling the last response. - lastResponse2, err := stateStore.LoadLastFinalizeBlockResponse(height + 1) - require.NoError(t, err) - // check to see if the saved response height is the same as the loaded height. - assert.Equal(t, response2, lastResponse2) - // should error as we are no longer saving the response. - _, err = stateStore.LoadFinalizeBlockResponse(height + 1) - assert.Equal(t, sm.ErrFinalizeBlockResponsesNotPersisted, err) - }) -} - -func TestFinalizeBlockRecoveryUsingLegacyABCIResponses(t *testing.T) { - var ( - height int64 = 10 - lastABCIResponseKey = []byte("lastABCIResponseKey") - memDB = dbm.NewMemDB() - cp = types.DefaultConsensusParams().ToProto() - legacyResp = cmtstate.ABCIResponsesInfo{ - LegacyAbciResponses: &cmtstate.LegacyABCIResponses{ - BeginBlock: &cmtstate.ResponseBeginBlock{ - Events: []abci.Event{{ - Type: "begin_block", - Attributes: []abci.EventAttribute{{ - Key: "key", - Value: "value", - }}, - }}, - }, - DeliverTxs: []*abci.ExecTxResult{{ - Events: []abci.Event{{ - Type: "tx", - Attributes: []abci.EventAttribute{{ - Key: "key", - Value: "value", - }}, - }}, - }}, - EndBlock: &cmtstate.ResponseEndBlock{ - ConsensusParamUpdates: &cp, - }, - }, - Height: height, - } - ) - bz, err := legacyResp.Marshal() - require.NoError(t, err) - // should keep this in parity with state/store.go - require.NoError(t, memDB.Set(lastABCIResponseKey, bz)) - stateStore := sm.NewStore(memDB, sm.StoreOptions{DiscardABCIResponses: false}) - resp, err := stateStore.LoadLastFinalizeBlockResponse(height) - require.NoError(t, err) - require.Equal(t, resp.ConsensusParamUpdates, &cp) - require.Equal(t, resp.Events, legacyResp.LegacyAbciResponses.BeginBlock.Events) - require.Equal(t, resp.TxResults[0], legacyResp.LegacyAbciResponses.DeliverTxs[0]) -} diff --git a/state/txindex/mocks/tx_indexer.go b/state/txindex/mocks/tx_indexer.go deleted file mode 100644 index fb50fd96dd9..00000000000 --- a/state/txindex/mocks/tx_indexer.go +++ /dev/null @@ -1,114 +0,0 @@ -// Code generated by mockery. DO NOT EDIT. - -package mocks - -import ( - context "context" - - query "github.com/cometbft/cometbft/libs/pubsub/query" - mock "github.com/stretchr/testify/mock" - - txindex "github.com/cometbft/cometbft/state/txindex" - - types "github.com/cometbft/cometbft/abci/types" -) - -// TxIndexer is an autogenerated mock type for the TxIndexer type -type TxIndexer struct { - mock.Mock -} - -// AddBatch provides a mock function with given fields: b -func (_m *TxIndexer) AddBatch(b *txindex.Batch) error { - ret := _m.Called(b) - - var r0 error - if rf, ok := ret.Get(0).(func(*txindex.Batch) error); ok { - r0 = rf(b) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Get provides a mock function with given fields: hash -func (_m *TxIndexer) Get(hash []byte) (*types.TxResult, error) { - ret := _m.Called(hash) - - var r0 *types.TxResult - var r1 error - if rf, ok := ret.Get(0).(func([]byte) (*types.TxResult, error)); ok { - return rf(hash) - } - if rf, ok := ret.Get(0).(func([]byte) *types.TxResult); ok { - r0 = rf(hash) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.TxResult) - } - } - - if rf, ok := ret.Get(1).(func([]byte) error); ok { - r1 = rf(hash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Index provides a mock function with given fields: result -func (_m *TxIndexer) Index(result *types.TxResult) error { - ret := _m.Called(result) - - var r0 error - if rf, ok := ret.Get(0).(func(*types.TxResult) error); ok { - r0 = rf(result) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Search provides a mock function with given fields: ctx, q -func (_m *TxIndexer) Search(ctx context.Context, q *query.Query) ([]*types.TxResult, error) { - ret := _m.Called(ctx, q) - - var r0 []*types.TxResult - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *query.Query) ([]*types.TxResult, error)); ok { - return rf(ctx, q) - } - if rf, ok := ret.Get(0).(func(context.Context, *query.Query) []*types.TxResult); ok { - r0 = rf(ctx, q) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*types.TxResult) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *query.Query) error); ok { - r1 = rf(ctx, q) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTNewTxIndexer interface { - mock.TestingT - Cleanup(func()) -} - -// NewTxIndexer creates a new instance of TxIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewTxIndexer(t mockConstructorTestingTNewTxIndexer) *TxIndexer { - mock := &TxIndexer{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/state/txindex/null/null.go b/state/txindex/null/null.go deleted file mode 100644 index 3e881e826fa..00000000000 --- a/state/txindex/null/null.go +++ /dev/null @@ -1,34 +0,0 @@ -package null - -import ( - "context" - "errors" - - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" - "github.com/cometbft/cometbft/state/txindex" -) - -var _ txindex.TxIndexer = (*TxIndex)(nil) - -// TxIndex acts as a /dev/null. -type TxIndex struct{} - -// Get on a TxIndex is disabled and panics when invoked. -func (txi *TxIndex) Get(hash []byte) (*abci.TxResult, error) { - return nil, errors.New(`indexing is disabled (set 'tx_index = "kv"' in config)`) -} - -// AddBatch is a noop and always returns nil. -func (txi *TxIndex) AddBatch(batch *txindex.Batch) error { - return nil -} - -// Index is a noop and always returns nil. -func (txi *TxIndex) Index(result *abci.TxResult) error { - return nil -} - -func (txi *TxIndex) Search(ctx context.Context, q *query.Query) ([]*abci.TxResult, error) { - return []*abci.TxResult{}, nil -} diff --git a/test/README.md b/test/README.md index 7437fd2d753..9928c0da1d9 100644 --- a/test/README.md +++ b/test/README.md @@ -1,7 +1,11 @@ # CometBFT Tests -The unit tests (ie. the `go test` s) can be run with `make test`. -The integration tests can be run with `make test_integrations`. +## Unit tests +The unit tests (ie. `go test`) can be run with `make test` from the root directory of the repository. + +## Integration tests + +The integration tests can be run with `make test_integrations` from the root directory of the repository. Running the integrations test will build a docker container with local version of CometBFT and run the following tests in docker containers: @@ -13,6 +17,44 @@ and run the following tests in docker containers: - persistence tests - crash cometbft at each of many predefined points, restart, and ensure it syncs properly with the app +## End-to-end tests + +You can run e2e nightly tests locally by running +``` +make -j2 docker generator runner && ./build/generator -g 5 -d networks/nightly/ -p && ./run-multiple.sh networks/nightly/*-group*-*.toml +``` +from the root directory of the repository. + +Please refer to the [README.MD](e2e/README.md) in the `e2e` folder for more information. + +## `localnet` tests +During development you might need a local network that runs modified code. + +1. Build a linux binary with the code modifications +``` +make build-linux +``` + +2. Run a local network with four nodes +``` +make localnet-start +``` +This command will build a `localnet` docker image and run it using Docker Compose. + +3. You can send arbitrary transactions on your local network by building and running the `loadtime` application. +``` +make -C test/loadtime build +test/loadtime/build/load -c 2 --broadcast-tx-method sync -T 1200 --endpoints ws://127.0.0.1:26657/websocket +``` +Refer to the [README.md](loadtime/README.md) for more information. + +4. You can also monitor your network using Prometheus and Grafana. +``` +make monitoring-start +``` +Refer to the [README.md](monitoring/README.md) for more information. + + ## Fuzzing [Fuzzing](https://en.wikipedia.org/wiki/Fuzzing) of various system inputs. diff --git a/test/app/counter_test.sh b/test/app/counter_test.sh index 3af2b885f18..5c459fd1e3d 100755 --- a/test/app/counter_test.sh +++ b/test/app/counter_test.sh @@ -2,10 +2,6 @@ export GO111MODULE=on -if [[ "$GRPC_BROADCAST_TX" == "" ]]; then - GRPC_BROADCAST_TX="" -fi - set -u ##################### @@ -24,7 +20,7 @@ function getCode() { fi if [[ $(echo $R | jq 'has("code")') == "true" ]]; then - # this wont actually work if theres an error ... + # this won't actually work if there's an error ... echo "$R" | jq ".code" else # protobuf auto adds `omitempty` to everything so code OK and empty data/log @@ -34,15 +30,6 @@ function getCode() { fi } -# build grpc client if needed -if [[ "$GRPC_BROADCAST_TX" != "" ]]; then - if [ -f test/app/grpc_client ]; then - rm test/app/grpc_client - fi - echo "... building grpc_client" - go build -mod=readonly -o test/app/grpc_client test/app/grpc_client.go -fi - function sendTx() { TX=$1 set +u @@ -51,18 +38,12 @@ function sendTx() { SHOULD_ERR=false fi set -u - if [[ "$GRPC_BROADCAST_TX" == "" ]]; then - RESPONSE=$(curl -s localhost:26657/broadcast_tx_commit?tx=0x"$TX") - IS_ERR=$(echo "$RESPONSE" | jq 'has("error")') - ERROR=$(echo "$RESPONSE" | jq '.error') - ERROR=$(echo "$ERROR" | tr -d '"') # remove surrounding quotes + RESPONSE=$(curl -s localhost:26657/broadcast_tx_commit?tx=0x"$TX") + IS_ERR=$(echo "$RESPONSE" | jq 'has("error")') + ERROR=$(echo "$RESPONSE" | jq '.error') + ERROR=$(echo "$ERROR" | tr -d '"') # remove surrounding quotes - RESPONSE=$(echo "$RESPONSE" | jq '.result') - else - RESPONSE=$(./test/app/grpc_client "$TX") - IS_ERR=false - ERROR="" - fi + RESPONSE=$(echo "$RESPONSE" | jq '.result') echo "RESPONSE" echo "$RESPONSE" diff --git a/test/app/grpc_client.go b/test/app/grpc_client.go deleted file mode 100644 index 00b5668d58d..00000000000 --- a/test/app/grpc_client.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "encoding/hex" - "fmt" - "os" - - "context" - - cmtjson "github.com/cometbft/cometbft/libs/json" - coregrpc "github.com/cometbft/cometbft/rpc/grpc" -) - -var grpcAddr = "tcp://localhost:36656" - -func main() { - args := os.Args - if len(args) == 1 { - fmt.Println("Must enter a transaction to send (hex)") - os.Exit(1) - } - tx := args[1] - txBytes, err := hex.DecodeString(tx) - if err != nil { - fmt.Println("Invalid hex", err) - os.Exit(1) - } - - clientGRPC := coregrpc.StartGRPCClient(grpcAddr) - res, err := clientGRPC.BroadcastTx(context.Background(), &coregrpc.RequestBroadcastTx{Tx: txBytes}) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - bz, err := cmtjson.Marshal(res) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - fmt.Println(string(bz)) -} diff --git a/test/docker/Dockerfile b/test/docker/Dockerfile index 3dd11ce7ead..0f5ea361274 100644 --- a/test/docker/Dockerfile +++ b/test/docker/Dockerfile @@ -1,9 +1,9 @@ -FROM golang:1.15 +FROM golang:1.22 # Grab deps (jq, hexdump, xxd, killall) RUN apt-get update && \ apt-get install -y --no-install-recommends \ - jq bsdmainutils vim-common psmisc netcat curl + jq bsdmainutils vim-common psmisc netcat-traditional curl # Setup CometBFT repo ENV REPO $GOPATH/src/github.com/cometbft/cometbft @@ -14,9 +14,6 @@ WORKDIR $REPO # TODO: rewrite to only copy Makefile & other files? COPY . $REPO -# Install the vendored dependencies -# docker caching prevents reinstall on code change! -RUN make tools # install ABCI CLI RUN make install_abci diff --git a/test/e2e/Makefile b/test/e2e/Makefile index 794572d8428..f440218f27f 100644 --- a/test/e2e/Makefile +++ b/test/e2e/Makefile @@ -1,20 +1,38 @@ -COMETBFT_BUILD_OPTIONS += badgerdb,boltdb,cleveldb,rocksdb +COMETBFT_BUILD_OPTIONS += badgerdb,rocksdb,pebbledb,clock_skew,bls12381 +IMAGE_TAG=cometbft/e2e-node:local-version include ../../common.mk all: docker generator runner -docker: +fast: docker-fast generator runner + +# This will set up a container with all required dependencies for compiling, copy all the source +# code to the container, and compile the binary inside it. +docker: docker-clean @echo "Building E2E Docker image" - @docker build \ - --tag cometbft/e2e-node:local-version \ - -f docker/Dockerfile ../.. + @docker build --tag $(IMAGE_TAG) -f docker/Dockerfile ../.. + +docker-debug: docker-clean + @echo "Building E2E Docker image for debugging" + @docker build --tag $(IMAGE_TAG) -f docker/Dockerfile.debug ../.. + +# This will compile a binary to be executed in a container, set up a slim container, and copy only +# the binary to it. +docker-fast: docker-clean + @echo "Compiling binary for slim E2E Docker image" + @CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o build/node ./node + @echo "Building slim E2E Docker image" + @docker build --tag $(IMAGE_TAG) -f docker/Dockerfile.fast . + +docker-clean: + @docker rmi $(IMAGE_TAG) 2>/dev/null; true # We need to build support for database backends into the app in # order to build a binary with a CometBFT node in it (for built-in # ABCI testing). node: - go build $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o build/node ./node + go build -race $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o build/node ./node generator: go build -o build/generator ./generator @@ -22,4 +40,15 @@ generator: runner: go build -o build/runner ./runner -.PHONY: all node docker generator runner +lint: + @echo "--> Running linter for E2E" + @go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run + +grammar-gen: + go run github.com/goccmack/gogll/v3@latest -o pkg/grammar/grammar-auto pkg/grammar/abci_grammar.md + +clean: docker-clean + rm -drf build/ + rm -drf data/ + +.PHONY: all fast node docker docker-debug docker-fast docker-clean generator runner lint grammar-gen clean diff --git a/test/e2e/README.md b/test/e2e/README.md index 9427aa9934a..4c1af624a1e 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -9,6 +9,27 @@ make This creates and runs a testnet named `ci` under `networks/ci/`. +To generate the testnet files in a different directory, run: +```sh +./build/runner -f networks/ci.toml -d networks/foo/bar/ +``` + +### Fast compiling + +If you need to run experiments on a testnet, you will probably want to compile the code multiple +times and `make` could be slow. This is because `make` builds an image by first copying all the +source code into it and then compiling the binary from inside. This is needed if, for example, you +want to create a binary that uses a different database (as in `networks/ci.toml`), or to emulate +latencies by running the Python script. + +If you just need to (re-)compile and run the binary without any extra building options, you can use +`make fast`, which will first compile the code and then make a slim Docker image with the binary. +For example: +```sh +make fast +./build/runner -f networks/simple.toml +``` + ## Conceptual Overview End-to-end testnets are used to test Tendermint functionality as a user would use it, by spinning up a set of nodes with various configurations and making sure the nodes and network behave correctly. The background for the E2E test suite is outlined in [RFC-001](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-066-e2e-testing.md). @@ -68,7 +89,7 @@ generator. For example: # the CometBFT version in the current local code (as specified in # ../../version/version.go). # -# In the example below, if the local version.TMCoreSemVer value is "v0.34.24", +# In the example below, if the local version value is "v0.34.24", # for example, and the latest official release is v0.34.23, then 1/3rd of the # network will run v0.34.23 and the remaining 2/3rds will run the E2E node built # from the local code. @@ -125,6 +146,8 @@ To run tests manually, set the `E2E_MANIFEST` environment variable to the path o E2E_MANIFEST=networks/ci.toml go test -v ./tests/... ``` +If the testnet files are located in a custom directory, you need to set it in the `E2E_TESTNET_DIR` environment variable. + Optionally, `E2E_NODE` specifies the name of a single testnet node to test. These environment variables can also be specified in `tests/e2e_test.go` to run tests from an editor or IDE: @@ -134,6 +157,7 @@ func init() { // This can be used to manually specify a testnet manifest and/or node to // run tests against. The testnet must have been started by the runner first. os.Setenv("E2E_MANIFEST", "networks/ci.toml") + os.Setenv("E2E_TESTNET_DIR", "networks/foo") os.Setenv("E2E_NODE", "validator01") } ``` diff --git a/test/e2e/app/app.go b/test/e2e/app/app.go index 8992695f67c..5ec8197bc80 100644 --- a/test/e2e/app/app.go +++ b/test/e2e/app/app.go @@ -3,26 +3,30 @@ package app import ( "bytes" "context" + "crypto/rand" "encoding/base64" "encoding/binary" "encoding/hex" "errors" "fmt" - "math/rand" + "math/big" "os" "path/filepath" "strconv" "strings" "time" + gogo "github.com/cosmos/gogoproto/types" + "github.com/cometbft/cometbft/abci/example/kvstore" abci "github.com/cometbft/cometbft/abci/types" + cryptoproto "github.com/cometbft/cometbft/api/cometbft/crypto/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" + "github.com/cometbft/cometbft/internal/protoio" "github.com/cometbft/cometbft/libs/log" - "github.com/cometbft/cometbft/libs/protoio" - cryptoproto "github.com/cometbft/cometbft/proto/tendermint/crypto" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmttypes "github.com/cometbft/cometbft/types" "github.com/cometbft/cometbft/version" ) @@ -33,6 +37,7 @@ const ( prefixReservedKey string = "reservedTxKey_" suffixChainID string = "ChainID" suffixVoteExtHeight string = "VoteExtensionsHeight" + suffixPbtsHeight string = "PbtsHeight" suffixInitialHeight string = "InitialHeight" ) @@ -96,6 +101,34 @@ type Config struct { CheckTxDelay time.Duration `toml:"check_tx_delay"` FinalizeBlockDelay time.Duration `toml:"finalize_block_delay"` VoteExtensionDelay time.Duration `toml:"vote_extension_delay"` + + // Vote extension padding size, to simulate different vote extension sizes. + VoteExtensionSize uint `toml:"vote_extension_size"` + + // VoteExtensionsEnableHeight configures the first height during which + // the chain will use and require vote extension data to be present + // in precommit messages. + VoteExtensionsEnableHeight int64 `toml:"vote_extensions_enable_height"` + + // VoteExtensionsUpdateHeight configures the height at which consensus + // param VoteExtensionsEnableHeight will be set. + // -1 denotes it is set at genesis. + // 0 denotes it is set at InitChain. + VoteExtensionsUpdateHeight int64 `toml:"vote_extensions_update_height"` + + // Flag for enabling and disabling logging of ABCI requests. + ABCIRequestsLoggingEnabled bool `toml:"abci_requests_logging_enabled"` + + // PbtsEnableHeight configures the first height during which + // the chain will start using Proposer-Based Timestamps (PBTS) + // to create and validate new blocks. + PbtsEnableHeight int64 `toml:"pbts_enable_height"` + + // PbtsUpdateHeight configures the height at which consensus + // param PbtsEnableHeight will be set. + // -1 denotes it is set at genesis. + // 0 denotes it is set at InitChain. + PbtsUpdateHeight int64 `toml:"pbts_update_height"` } func DefaultConfig(dir string) *Config { @@ -116,8 +149,12 @@ func NewApplication(cfg *Config) (*Application, error) { if err != nil { return nil, err } + + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + logger.Info("Application started!") + return &Application{ - logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)), + logger: logger, state: state, snapshots: snapshots, cfg: cfg, @@ -125,18 +162,58 @@ func NewApplication(cfg *Config) (*Application, error) { } // Info implements ABCI. -func (app *Application) Info(_ context.Context, req *abci.RequestInfo) (*abci.ResponseInfo, error) { - return &abci.ResponseInfo{ +func (app *Application) Info(context.Context, *abci.InfoRequest) (*abci.InfoResponse, error) { + r := &abci.Request{Value: &abci.Request_Info{Info: &abci.InfoRequest{}}} + if err := app.logABCIRequest(r); err != nil { + return nil, err + } + + height, hash := app.state.Info() + return &abci.InfoResponse{ Version: version.ABCIVersion, AppVersion: appVersion, - LastBlockHeight: int64(app.state.Height), - LastBlockAppHash: app.state.Hash, + LastBlockHeight: int64(height), + LastBlockAppHash: hash, }, nil } +func (app *Application) updateFeatureEnableHeights(currentHeight int64) *cmtproto.ConsensusParams { + params := &cmtproto.ConsensusParams{ + Feature: &cmtproto.FeatureParams{}, + } + retNil := true + if app.cfg.VoteExtensionsUpdateHeight == currentHeight { + app.logger.Info("enabling vote extensions on the fly", + "current_height", currentHeight, + "enable_height", app.cfg.VoteExtensionsEnableHeight) + params.Feature.VoteExtensionsEnableHeight = &gogo.Int64Value{Value: app.cfg.VoteExtensionsEnableHeight} + retNil = false + app.logger.Info("updating VoteExtensionsHeight in app_state", "height", app.cfg.VoteExtensionsEnableHeight) + app.state.Set(prefixReservedKey+suffixVoteExtHeight, strconv.FormatInt(app.cfg.VoteExtensionsEnableHeight, 10)) + } + if app.cfg.PbtsUpdateHeight == currentHeight { + app.logger.Info("enabling PBTS on the fly", + "current_height", currentHeight, + "enable_height", app.cfg.PbtsEnableHeight) + params.Feature.PbtsEnableHeight = &gogo.Int64Value{Value: app.cfg.PbtsEnableHeight} + retNil = false + app.logger.Info("updating PBTS Height in app_state", "height", app.cfg.PbtsEnableHeight) + app.state.Set(prefixReservedKey+suffixPbtsHeight, strconv.FormatInt(app.cfg.PbtsEnableHeight, 10)) + } + if retNil { + return nil + } + return params +} + // Info implements ABCI. -func (app *Application) InitChain(_ context.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) { - var err error +func (app *Application) InitChain(_ context.Context, req *abci.InitChainRequest) (*abci.InitChainResponse, error) { + r := &abci.Request{Value: &abci.Request_InitChain{InitChain: &abci.InitChainRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + app.state.initialHeight = uint64(req.InitialHeight) if len(req.AppStateBytes) > 0 { err = app.state.Import(0, req.AppStateBytes) @@ -146,11 +223,13 @@ func (app *Application) InitChain(_ context.Context, req *abci.RequestInitChain) } app.logger.Info("setting ChainID in app_state", "chainId", req.ChainId) app.state.Set(prefixReservedKey+suffixChainID, req.ChainId) - app.logger.Info("setting VoteExtensionsHeight in app_state", "height", req.ConsensusParams.Abci.VoteExtensionsEnableHeight) - app.state.Set(prefixReservedKey+suffixVoteExtHeight, strconv.FormatInt(req.ConsensusParams.Abci.VoteExtensionsEnableHeight, 10)) + app.logger.Info("setting VoteExtensionsHeight in app_state", "height", req.ConsensusParams.Feature.VoteExtensionsEnableHeight.GetValue()) + app.state.Set(prefixReservedKey+suffixVoteExtHeight, strconv.FormatInt(req.ConsensusParams.Feature.VoteExtensionsEnableHeight.GetValue(), 10)) + app.logger.Info("setting PBTS Height in app_state", "height", req.ConsensusParams.Feature.PbtsEnableHeight.GetValue()) + app.state.Set(prefixReservedKey+suffixPbtsHeight, strconv.FormatInt(req.ConsensusParams.Feature.PbtsEnableHeight.GetValue(), 10)) app.logger.Info("setting initial height in app_state", "initial_height", req.InitialHeight) app.state.Set(prefixReservedKey+suffixInitialHeight, strconv.FormatInt(req.InitialHeight, 10)) - //Get validators from genesis + // Get validators from genesis if req.Validators != nil { for _, val := range req.Validators { val := val @@ -159,8 +238,12 @@ func (app *Application) InitChain(_ context.Context, req *abci.RequestInitChain) } } } - resp := &abci.ResponseInitChain{ - AppHash: app.state.Hash, + + params := app.updateFeatureEnableHeights(0) + + resp := &abci.InitChainResponse{ + ConsensusParams: params, + AppHash: app.state.GetHash(), } if resp.Validators, err = app.validatorUpdates(0); err != nil { return nil, err @@ -169,10 +252,17 @@ func (app *Application) InitChain(_ context.Context, req *abci.RequestInitChain) } // CheckTx implements ABCI. -func (app *Application) CheckTx(_ context.Context, req *abci.RequestCheckTx) (*abci.ResponseCheckTx, error) { +func (app *Application) CheckTx(_ context.Context, req *abci.CheckTxRequest) (*abci.CheckTxResponse, error) { + r := &abci.Request{Value: &abci.Request_CheckTx{CheckTx: &abci.CheckTxRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + key, _, err := parseTx(req.Tx) if err != nil || key == prefixReservedKey { - return &abci.ResponseCheckTx{ + //nolint:nilerr + return &abci.CheckTxResponse{ Code: kvstore.CodeTypeEncodingError, Log: err.Error(), }, nil @@ -182,12 +272,18 @@ func (app *Application) CheckTx(_ context.Context, req *abci.RequestCheckTx) (*a time.Sleep(app.cfg.CheckTxDelay) } - return &abci.ResponseCheckTx{Code: kvstore.CodeTypeOK, GasWanted: 1}, nil + return &abci.CheckTxResponse{Code: kvstore.CodeTypeOK, GasWanted: 1}, nil } // FinalizeBlock implements ABCI. -func (app *Application) FinalizeBlock(_ context.Context, req *abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) { - var txs = make([]*abci.ExecTxResult, len(req.Txs)) +func (app *Application) FinalizeBlock(_ context.Context, req *abci.FinalizeBlockRequest) (*abci.FinalizeBlockResponse, error) { + r := &abci.Request{Value: &abci.Request_FinalizeBlock{FinalizeBlock: &abci.FinalizeBlockRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + + txs := make([]*abci.ExecTxResult, len(req.Txs)) for i, tx := range req.Txs { key, value, err := parseTx(tx) @@ -202,19 +298,32 @@ func (app *Application) FinalizeBlock(_ context.Context, req *abci.RequestFinali txs[i] = &abci.ExecTxResult{Code: kvstore.CodeTypeOK} } + for _, ev := range req.Misbehavior { + app.logger.Info("Misbehavior. Slashing validator", + "validator_address", ev.GetValidator().Address, + "type", ev.GetType(), + "height", ev.GetHeight(), + "time", ev.GetTime(), + "total_voting_power", ev.GetTotalVotingPower(), + ) + } + valUpdates, err := app.validatorUpdates(uint64(req.Height)) if err != nil { panic(err) } + params := app.updateFeatureEnableHeights(req.Height) + if app.cfg.FinalizeBlockDelay != 0 { time.Sleep(app.cfg.FinalizeBlockDelay) } - return &abci.ResponseFinalizeBlock{ - TxResults: txs, - ValidatorUpdates: valUpdates, - AppHash: app.state.Finalize(), + return &abci.FinalizeBlockResponse{ + TxResults: txs, + ValidatorUpdates: valUpdates, + AppHash: app.state.Finalize(), + ConsensusParamUpdates: params, Events: []abci.Event{ { Type: "val_updates", @@ -234,7 +343,13 @@ func (app *Application) FinalizeBlock(_ context.Context, req *abci.RequestFinali } // Commit implements ABCI. -func (app *Application) Commit(_ context.Context, _ *abci.RequestCommit) (*abci.ResponseCommit, error) { +func (app *Application) Commit(_ context.Context, _ *abci.CommitRequest) (*abci.CommitResponse, error) { + r := &abci.Request{Value: &abci.Request_Commit{Commit: &abci.CommitRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + height, err := app.state.Commit() if err != nil { panic(err) @@ -254,50 +369,81 @@ func (app *Application) Commit(_ context.Context, _ *abci.RequestCommit) (*abci. if app.cfg.RetainBlocks > 0 { retainHeight = int64(height - app.cfg.RetainBlocks + 1) } - return &abci.ResponseCommit{ + return &abci.CommitResponse{ RetainHeight: retainHeight, }, nil } // Query implements ABCI. -func (app *Application) Query(_ context.Context, req *abci.RequestQuery) (*abci.ResponseQuery, error) { - return &abci.ResponseQuery{ - Height: int64(app.state.Height), +func (app *Application) Query(_ context.Context, req *abci.QueryRequest) (*abci.QueryResponse, error) { + r := &abci.Request{Value: &abci.Request_Query{Query: &abci.QueryRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + + value, height := app.state.Query(string(req.Data)) + return &abci.QueryResponse{ + Height: int64(height), Key: req.Data, - Value: []byte(app.state.Get(string(req.Data))), + Value: []byte(value), }, nil } // ListSnapshots implements ABCI. -func (app *Application) ListSnapshots(_ context.Context, req *abci.RequestListSnapshots) (*abci.ResponseListSnapshots, error) { +func (app *Application) ListSnapshots(context.Context, *abci.ListSnapshotsRequest) (*abci.ListSnapshotsResponse, error) { + r := &abci.Request{Value: &abci.Request_ListSnapshots{ListSnapshots: &abci.ListSnapshotsRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + snapshots, err := app.snapshots.List() if err != nil { panic(err) } - return &abci.ResponseListSnapshots{Snapshots: snapshots}, nil + return &abci.ListSnapshotsResponse{Snapshots: snapshots}, nil } // LoadSnapshotChunk implements ABCI. -func (app *Application) LoadSnapshotChunk(_ context.Context, req *abci.RequestLoadSnapshotChunk) (*abci.ResponseLoadSnapshotChunk, error) { +func (app *Application) LoadSnapshotChunk(_ context.Context, req *abci.LoadSnapshotChunkRequest) (*abci.LoadSnapshotChunkResponse, error) { + r := &abci.Request{Value: &abci.Request_LoadSnapshotChunk{LoadSnapshotChunk: &abci.LoadSnapshotChunkRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + chunk, err := app.snapshots.LoadChunk(req.Height, req.Format, req.Chunk) if err != nil { panic(err) } - return &abci.ResponseLoadSnapshotChunk{Chunk: chunk}, nil + return &abci.LoadSnapshotChunkResponse{Chunk: chunk}, nil } // OfferSnapshot implements ABCI. -func (app *Application) OfferSnapshot(_ context.Context, req *abci.RequestOfferSnapshot) (*abci.ResponseOfferSnapshot, error) { +func (app *Application) OfferSnapshot(_ context.Context, req *abci.OfferSnapshotRequest) (*abci.OfferSnapshotResponse, error) { + r := &abci.Request{Value: &abci.Request_OfferSnapshot{OfferSnapshot: &abci.OfferSnapshotRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + if app.restoreSnapshot != nil { panic("A snapshot is already being restored") } app.restoreSnapshot = req.Snapshot app.restoreChunks = [][]byte{} - return &abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT}, nil + return &abci.OfferSnapshotResponse{Result: abci.OFFER_SNAPSHOT_RESULT_ACCEPT}, nil } // ApplySnapshotChunk implements ABCI. -func (app *Application) ApplySnapshotChunk(_ context.Context, req *abci.RequestApplySnapshotChunk) (*abci.ResponseApplySnapshotChunk, error) { +func (app *Application) ApplySnapshotChunk(_ context.Context, req *abci.ApplySnapshotChunkRequest) (*abci.ApplySnapshotChunkResponse, error) { + r := &abci.Request{Value: &abci.Request_ApplySnapshotChunk{ApplySnapshotChunk: &abci.ApplySnapshotChunkRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + if app.restoreSnapshot == nil { panic("No restore in progress") } @@ -314,14 +460,16 @@ func (app *Application) ApplySnapshotChunk(_ context.Context, req *abci.RequestA app.restoreSnapshot = nil app.restoreChunks = nil } - return &abci.ResponseApplySnapshotChunk{Result: abci.ResponseApplySnapshotChunk_ACCEPT}, nil + return &abci.ApplySnapshotChunkResponse{Result: abci.APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT}, nil } // PrepareProposal will take the given transactions and attempt to prepare a // proposal from them when it's our turn to do so. If the current height has // vote extension enabled, this method will use vote extensions from the previous // height, passed from CometBFT as parameters to construct a special transaction -// whose value is the sum of all of the vote extensions from the previous round. +// whose value is the sum of all of the vote extensions from the previous round, +// if voteExtensionSize has not been specified or the sum of all vote extensions +// sizes, if a size has been specified. // // Additionally, we verify the vote extension signatures passed from CometBFT and // include all data necessary for such verification in the special transaction's @@ -336,13 +484,19 @@ func (app *Application) ApplySnapshotChunk(_ context.Context, req *abci.RequestA // The special vote extension-generated transaction must fit within an empty block // and takes precedence over all other transactions coming from the mempool. func (app *Application) PrepareProposal( - _ context.Context, req *abci.RequestPrepareProposal) (*abci.ResponsePrepareProposal, error) { + _ context.Context, req *abci.PrepareProposalRequest, +) (*abci.PrepareProposalResponse, error) { + r := &abci.Request{Value: &abci.Request_PrepareProposal{PrepareProposal: &abci.PrepareProposalRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } _, areExtensionsEnabled := app.checkHeightAndExtensions(true, req.Height, "PrepareProposal") txs := make([][]byte, 0, len(req.Txs)+1) var totalBytes int64 - extTxPrefix := fmt.Sprintf("%s=", voteExtensionKey) + extTxPrefix := voteExtensionKey + "=" sum, err := app.verifyAndSum(areExtensionsEnabled, req.Height, &req.LocalLastCommit, "prepare_proposal") if err != nil { panic(fmt.Errorf("failed to sum and verify in PrepareProposal; err %w", err)) @@ -354,7 +508,7 @@ func (app *Application) PrepareProposal( } extCommitHex := hex.EncodeToString(extCommitBytes) extTx := []byte(fmt.Sprintf("%s%d|%s", extTxPrefix, sum, extCommitHex)) - extTxLen := int64(len(extTx)) + extTxLen := cmttypes.ComputeProtoSizeForTxs([]cmttypes.Tx{extTx}) app.logger.Info("preparing proposal with special transaction from vote extensions", "extTxLen", extTxLen) if extTxLen > req.MaxTxBytes { panic(fmt.Errorf("serious problem in the e2e app configuration; "+ @@ -376,10 +530,11 @@ func (app *Application) PrepareProposal( app.logger.Error("detected tx that should not come from the mempool", "tx", tx) continue } - if totalBytes+int64(len(tx)) > req.MaxTxBytes { + txLen := cmttypes.ComputeProtoSizeForTxs([]cmttypes.Tx{tx}) + if totalBytes+txLen > req.MaxTxBytes { break } - totalBytes += int64(len(tx)) + totalBytes += txLen // Coherence: No need to call parseTx, as the check is stateless and has been performed by CheckTx txs = append(txs, tx) } @@ -388,32 +543,38 @@ func (app *Application) PrepareProposal( time.Sleep(app.cfg.PrepareProposalDelay) } - return &abci.ResponsePrepareProposal{Txs: txs}, nil + return &abci.PrepareProposalResponse{Txs: txs}, nil } // ProcessProposal implements part of the Application interface. // It accepts any proposal that does not contain a malformed transaction. // NOTE It is up to real Applications to effect punitive behavior in the cases ProcessProposal -// returns ResponseProcessProposal_REJECT, as it is evidence of misbehavior. -func (app *Application) ProcessProposal(_ context.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) { +// returns PROCESS_PROPOSAL_STATUS_REJECT, as it is evidence of misbehavior. +func (app *Application) ProcessProposal(_ context.Context, req *abci.ProcessProposalRequest) (*abci.ProcessProposalResponse, error) { + r := &abci.Request{Value: &abci.Request_ProcessProposal{ProcessProposal: &abci.ProcessProposalRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + _, areExtensionsEnabled := app.checkHeightAndExtensions(true, req.Height, "ProcessProposal") for _, tx := range req.Txs { k, v, err := parseTx(tx) if err != nil { app.logger.Error("malformed transaction in ProcessProposal", "tx", tx, "err", err) - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + return &abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_REJECT}, nil } switch { case areExtensionsEnabled && k == voteExtensionKey: // Additional check for vote extension-related txs if err := app.verifyExtensionTx(req.Height, v); err != nil { app.logger.Error("vote extension transaction failed verification, rejecting proposal", k, v, "err", err) - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + return &abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_REJECT}, nil } case strings.HasPrefix(k, prefixReservedKey): app.logger.Error("key prefix %q is reserved and cannot be used in transactions, rejecting proposal", k) - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, nil + return &abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_REJECT}, nil } } @@ -421,7 +582,7 @@ func (app *Application) ProcessProposal(_ context.Context, req *abci.RequestProc time.Sleep(app.cfg.ProcessProposalDelay) } - return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil + return &abci.ProcessProposalResponse{Status: abci.PROCESS_PROPOSAL_STATUS_ACCEPT}, nil } // ExtendVote will produce vote extensions in the form of random numbers to @@ -431,25 +592,41 @@ func (app *Application) ProcessProposal(_ context.Context, req *abci.RequestProc // a new transaction will be proposed that updates a special value in the // key/value store ("extensionSum") with the sum of all of the numbers collected // from the vote extensions. -func (app *Application) ExtendVote(_ context.Context, req *abci.RequestExtendVote) (*abci.ResponseExtendVote, error) { +func (app *Application) ExtendVote(_ context.Context, req *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) { + r := &abci.Request{Value: &abci.Request_ExtendVote{ExtendVote: &abci.ExtendVoteRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + appHeight, areExtensionsEnabled := app.checkHeightAndExtensions(false, req.Height, "ExtendVote") if !areExtensionsEnabled { panic(fmt.Errorf("received call to ExtendVote at height %d, when vote extensions are disabled", appHeight)) } - ext := make([]byte, binary.MaxVarintLen64) - // We don't care that these values are generated by a weak random number - // generator. It's just for test purposes. - //nolint:gosec // G404: Use of weak random number generator - num := rand.Int63n(voteExtensionMaxVal) - extLen := binary.PutVarint(ext, num) - if app.cfg.VoteExtensionDelay != 0 { time.Sleep(app.cfg.VoteExtensionDelay) } - app.logger.Info("generated vote extension", "num", num, "ext", fmt.Sprintf("%x", ext[:extLen]), "height", appHeight) - return &abci.ResponseExtendVote{ + var ext []byte + var extLen int + if app.cfg.VoteExtensionSize != 0 { + ext = make([]byte, app.cfg.VoteExtensionSize) + if _, err := rand.Read(ext); err != nil { + panic(fmt.Errorf("could not extend vote. Len:%d", len(ext))) + } + extLen = len(ext) + } else { + ext = make([]byte, 8) + num, err := rand.Int(rand.Reader, big.NewInt(voteExtensionMaxVal)) + if err != nil { + panic(fmt.Errorf("could not extend vote. Len:%d", len(ext))) + } + extLen = binary.PutVarint(ext, num.Int64()) + } + + app.logger.Info("generated vote extension", "height", appHeight, "vote_extension", hex.EncodeToString(ext[:4]), "len", extLen) + return &abci.ExtendVoteResponse{ VoteExtension: ext[:extLen], }, nil } @@ -457,7 +634,13 @@ func (app *Application) ExtendVote(_ context.Context, req *abci.RequestExtendVot // VerifyVoteExtension simply validates vote extensions from other validators // without doing anything about them. In this case, it just makes sure that the // vote extension is a well-formed integer value. -func (app *Application) VerifyVoteExtension(_ context.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) { +func (app *Application) VerifyVoteExtension(_ context.Context, req *abci.VerifyVoteExtensionRequest) (*abci.VerifyVoteExtensionResponse, error) { + r := &abci.Request{Value: &abci.Request_VerifyVoteExtension{VerifyVoteExtension: &abci.VerifyVoteExtensionRequest{}}} + err := app.logABCIRequest(r) + if err != nil { + return nil, err + } + appHeight, areExtensionsEnabled := app.checkHeightAndExtensions(false, req.Height, "VerifyVoteExtension") if !areExtensionsEnabled { panic(fmt.Errorf("received call to VerifyVoteExtension at height %d, when vote extensions are disabled", appHeight)) @@ -465,16 +648,16 @@ func (app *Application) VerifyVoteExtension(_ context.Context, req *abci.Request // We don't allow vote extensions to be optional if len(req.VoteExtension) == 0 { app.logger.Error("received empty vote extension") - return &abci.ResponseVerifyVoteExtension{ - Status: abci.ResponseVerifyVoteExtension_REJECT, + return &abci.VerifyVoteExtensionResponse{ + Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT, }, nil } - num, err := parseVoteExtension(req.VoteExtension) + num, err := parseVoteExtension(app.cfg, req.VoteExtension) if err != nil { - app.logger.Error("failed to parse vote extension", "vote_extension", req.VoteExtension, "err", err) - return &abci.ResponseVerifyVoteExtension{ - Status: abci.ResponseVerifyVoteExtension_REJECT, + app.logger.Error("failed to parse vote extension", "vote_extension", hex.EncodeToString(req.VoteExtension[:4]), "err", err) + return &abci.VerifyVoteExtensionResponse{ + Status: abci.VERIFY_VOTE_EXTENSION_STATUS_REJECT, }, nil } @@ -482,9 +665,9 @@ func (app *Application) VerifyVoteExtension(_ context.Context, req *abci.Request time.Sleep(app.cfg.VoteExtensionDelay) } - app.logger.Info("verified vote extension value", "height", req.Height, "vote_extension", req.VoteExtension, "num", num) - return &abci.ResponseVerifyVoteExtension{ - Status: abci.ResponseVerifyVoteExtension_ACCEPT, + app.logger.Info("verified vote extension value", "height", req.Height, "vote_extension", hex.EncodeToString(req.VoteExtension[:4]), "num", num) + return &abci.VerifyVoteExtensionResponse{ + Status: abci.VERIFY_VOTE_EXTENSION_STATUS_ACCEPT, }, nil } @@ -493,7 +676,7 @@ func (app *Application) Rollback() error { } func (app *Application) getAppHeight() int64 { - initialHeightStr := app.state.Get(prefixReservedKey + suffixInitialHeight) + initialHeightStr, height := app.state.Query(prefixReservedKey + suffixInitialHeight) if len(initialHeightStr) == 0 { panic("initial height not set in database") } @@ -502,7 +685,7 @@ func (app *Application) getAppHeight() int64 { panic(fmt.Errorf("malformed initial height %q in database", initialHeightStr)) } - appHeight := int64(app.state.Height) + appHeight := int64(height) if appHeight == 0 { appHeight = initialHeight - 1 } @@ -554,14 +737,13 @@ func (app *Application) storeValidator(valUpdate *abci.ValidatorUpdate) error { // validatorUpdates generates a validator set update. func (app *Application) validatorUpdates(height uint64) (abci.ValidatorUpdates, error) { - updates := app.cfg.ValidatorUpdates[fmt.Sprintf("%v", height)] + updates := app.cfg.ValidatorUpdates[strconv.FormatUint(height, 10)] if len(updates) == 0 { return nil, nil } valUpdates := abci.ValidatorUpdates{} for keyString, power := range updates { - keyBytes, err := base64.StdEncoding.DecodeString(keyString) if err != nil { return nil, fmt.Errorf("invalid base64 pubkey value %q: %w", keyString, err) @@ -575,8 +757,21 @@ func (app *Application) validatorUpdates(height uint64) (abci.ValidatorUpdates, return valUpdates, nil } +// logAbciRequest log the request using the app's logger. +func (app *Application) logABCIRequest(req *abci.Request) error { + if !app.cfg.ABCIRequestsLoggingEnabled { + return nil + } + s, err := GetABCIRequestString(req) + if err != nil { + return err + } + app.logger.Info(s) + return nil +} + // parseTx parses a tx in 'key=value' format into a key and value. -func parseTx(tx []byte) (string, string, error) { +func parseTx(tx []byte) (key, value string, err error) { parts := bytes.Split(tx, []byte("=")) if len(parts) != 2 { return "", "", fmt.Errorf("invalid tx format: %q", string(tx)) @@ -638,7 +833,7 @@ func (app *Application) verifyAndSum( } cve := cmtproto.CanonicalVoteExtension{ Extension: vote.VoteExtension, - Height: currentHeight - 1, //the vote extension was signed in the previous height + Height: currentHeight - 1, // the vote extension was signed in the previous height Round: int64(extCommit.Round), ChainId: chainID, } @@ -647,7 +842,7 @@ func (app *Application) verifyAndSum( return 0, fmt.Errorf("error when marshaling signed bytes: %w", err) } - //... and verify + // ... and verify valAddr := crypto.Address(vote.Validator.Address).String() pubKeyHex := app.state.Get(prefixReservedKey + valAddr) if len(pubKeyHex) == 0 { @@ -670,7 +865,7 @@ func (app *Application) verifyAndSum( return 0, errors.New("received vote with invalid signature") } - extValue, err := parseVoteExtension(vote.VoteExtension) + extValue, err := parseVoteExtension(app.cfg, vote.VoteExtension) // The extension's format should have been verified in VerifyVoteExtension if err != nil { return 0, fmt.Errorf("failed to parse vote extension: %w", err) @@ -692,15 +887,15 @@ func (app *Application) verifyAndSum( return sum, nil } -// verifyExtensionTx parses and verifies the payload of a vote extension-generated tx +// verifyExtensionTx parses and verifies the payload of a vote extension-generated tx. func (app *Application) verifyExtensionTx(height int64, payload string) error { parts := strings.Split(payload, "|") if len(parts) != 2 { - return fmt.Errorf("invalid payload format") + return errors.New("invalid payload format") } expSumStr := parts[0] if len(expSumStr) == 0 { - return fmt.Errorf("sum cannot be empty in vote extension payload") + return errors.New("sum cannot be empty in vote extension payload") } expSum, err := strconv.Atoi(expSumStr) @@ -710,17 +905,17 @@ func (app *Application) verifyExtensionTx(height int64, payload string) error { extCommitHex := parts[1] if len(extCommitHex) == 0 { - return fmt.Errorf("extended commit data cannot be empty in vote extension payload") + return errors.New("extended commit data cannot be empty in vote extension payload") } extCommitBytes, err := hex.DecodeString(extCommitHex) if err != nil { - return fmt.Errorf("could not hex-decode vote extension payload") + return errors.New("could not hex-decode vote extension payload") } var extCommit abci.ExtendedCommitInfo if extCommit.Unmarshal(extCommitBytes) != nil { - return fmt.Errorf("unable to unmarshal extended commit") + return errors.New("unable to unmarshal extended commit") } sum, err := app.verifyAndSum(true, height, &extCommit, "process_proposal") @@ -728,25 +923,29 @@ func (app *Application) verifyExtensionTx(height int64, payload string) error { return fmt.Errorf("failed to sum and verify in process proposal: %w", err) } - //Final check that the proposer behaved correctly + // Final check that the proposer behaved correctly if int64(expSum) != sum { return fmt.Errorf("sum is not consistent with vote extension payload: %d!=%d", expSum, sum) } return nil } -// parseVoteExtension attempts to parse the given extension data into a positive -// integer value. -func parseVoteExtension(ext []byte) (int64, error) { - num, errVal := binary.Varint(ext) - if errVal == 0 { - return 0, errors.New("vote extension is too small to parse") - } - if errVal < 0 { - return 0, errors.New("vote extension value is too large") - } - if num >= voteExtensionMaxVal { - return 0, fmt.Errorf("vote extension value must be smaller than %d (was %d)", voteExtensionMaxVal, num) +// If extension size was not specified, then parseVoteExtension attempts to parse +// the given extension data into a positive integer. +// Otherwise it is the size of the extension. +func parseVoteExtension(cfg *Config, ext []byte) (int64, error) { + if cfg.VoteExtensionSize == 0 { + num, errVal := binary.Varint(ext) + if errVal == 0 { + return 0, errors.New("vote extension is too small to parse") + } + if errVal < 0 { + return 0, errors.New("vote extension value is too large") + } + if num >= voteExtensionMaxVal { + return 0, fmt.Errorf("vote extension value must be smaller than %d (was %d)", voteExtensionMaxVal, num) + } + return num, nil } - return num, nil + return int64(len(ext)), nil } diff --git a/test/e2e/app/log_abci.go b/test/e2e/app/log_abci.go new file mode 100644 index 00000000000..26b12e4bf3c --- /dev/null +++ b/test/e2e/app/log_abci.go @@ -0,0 +1,45 @@ +package app + +import ( + "encoding/base64" + "fmt" + "strings" + + "github.com/cosmos/gogoproto/proto" + + abci "github.com/cometbft/cometbft/abci/types" +) + +const AbciReq = "abci-req" + +// GetRequestString gets the string representation of the request that will be logged by the application. +func GetABCIRequestString(req *abci.Request) (string, error) { + b, err := proto.Marshal(req) + if err != nil { + return "", err + } + reqStr := base64.StdEncoding.EncodeToString(b) + return AbciReq + reqStr + AbciReq, nil +} + +// GetABCIRequestFromString parse string and try to get a string of a Request created by GetRequestString. +func GetABCIRequestFromString(s string) (*abci.Request, error) { + if !strings.Contains(s, AbciReq) { + return nil, nil + } + parts := strings.Split(s, AbciReq) + if len(parts) != 3 || len(parts[1]) == 0 { + return nil, fmt.Errorf("string %q passed to GetRequestFromString does not have a good format", s) + } + req := &abci.Request{} + reqStr := parts[1] + b, err := base64.StdEncoding.DecodeString(reqStr) + if err != nil { + return nil, err + } + err = proto.Unmarshal(b, req) + if err != nil { + return nil, err + } + return req, nil +} diff --git a/test/e2e/app/log_abci_test.go b/test/e2e/app/log_abci_test.go new file mode 100644 index 00000000000..fbeea6a2503 --- /dev/null +++ b/test/e2e/app/log_abci_test.go @@ -0,0 +1,38 @@ +package app + +import ( + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/cometbft/cometbft/abci/types" +) + +// Tests for logging each type of requests. +func TestLogging(t *testing.T) { + reqs := []*abci.Request{ + {Value: &abci.Request_Echo{Echo: &abci.EchoRequest{}}}, + {Value: &abci.Request_Flush{Flush: &abci.FlushRequest{}}}, + {Value: &abci.Request_Info{Info: &abci.InfoRequest{}}}, + {Value: &abci.Request_InitChain{InitChain: &abci.InitChainRequest{}}}, + {Value: &abci.Request_Query{Query: &abci.QueryRequest{}}}, + {Value: &abci.Request_FinalizeBlock{FinalizeBlock: &abci.FinalizeBlockRequest{}}}, + {Value: &abci.Request_CheckTx{CheckTx: &abci.CheckTxRequest{}}}, + {Value: &abci.Request_Commit{Commit: &abci.CommitRequest{}}}, + {Value: &abci.Request_ListSnapshots{ListSnapshots: &abci.ListSnapshotsRequest{}}}, + {Value: &abci.Request_OfferSnapshot{OfferSnapshot: &abci.OfferSnapshotRequest{}}}, + {Value: &abci.Request_LoadSnapshotChunk{LoadSnapshotChunk: &abci.LoadSnapshotChunkRequest{}}}, + {Value: &abci.Request_ApplySnapshotChunk{ApplySnapshotChunk: &abci.ApplySnapshotChunkRequest{}}}, + {Value: &abci.Request_PrepareProposal{PrepareProposal: &abci.PrepareProposalRequest{}}}, + {Value: &abci.Request_ProcessProposal{ProcessProposal: &abci.ProcessProposalRequest{}}}, + {Value: &abci.Request_ExtendVote{ExtendVote: &abci.ExtendVoteRequest{}}}, + {Value: &abci.Request_VerifyVoteExtension{VerifyVoteExtension: &abci.VerifyVoteExtensionRequest{}}}, + } + for _, r := range reqs { + s, err := GetABCIRequestString(r) + require.NoError(t, err) + rr, err := GetABCIRequestFromString(s) + require.NoError(t, err) + require.Equal(t, r, rr) + } +} diff --git a/test/e2e/app/snapshots.go b/test/e2e/app/snapshots.go index fb0ce82b09a..a5886cf4f53 100644 --- a/test/e2e/app/snapshots.go +++ b/test/e2e/app/snapshots.go @@ -15,7 +15,7 @@ import ( const ( snapshotChunkSize = 1e6 - // Keep only the most recent 10 snapshots. Older snapshots are pruned + // Keep only the most recent 10 snapshots. Older snapshots are pruned. maxSnapshotCount = 10 ) @@ -31,7 +31,7 @@ type SnapshotStore struct { // NewSnapshotStore creates a new snapshot store. func NewSnapshotStore(dir string) (*SnapshotStore, error) { store := &SnapshotStore{dir: dir} - if err := os.MkdirAll(dir, 0755); err != nil { + if err := os.MkdirAll(dir, 0o755); err != nil { return nil, err } if err := store.loadMetadata(); err != nil { @@ -84,17 +84,17 @@ func (s *SnapshotStore) saveMetadata() error { func (s *SnapshotStore) Create(state *State) (abci.Snapshot, error) { s.Lock() defer s.Unlock() - bz, err := state.Export() + bz, height, stateHash, err := state.Export() if err != nil { return abci.Snapshot{}, err } snapshot := abci.Snapshot{ - Height: state.Height, + Height: height, Format: 1, - Hash: hashItems(state.Values, state.Height), + Hash: stateHash, Chunks: byteChunks(bz), } - err = os.WriteFile(filepath.Join(s.dir, fmt.Sprintf("%v.json", state.Height)), bz, 0o644) //nolint:gosec + err = os.WriteFile(filepath.Join(s.dir, fmt.Sprintf("%v.json", height)), bz, 0o644) //nolint:gosec if err != nil { return abci.Snapshot{}, err } @@ -106,7 +106,7 @@ func (s *SnapshotStore) Create(state *State) (abci.Snapshot, error) { return snapshot, nil } -// Prune removes old snapshots ensuring only the most recent n snapshots remain +// Prune removes old snapshots ensuring only the most recent n snapshots remain. func (s *SnapshotStore) Prune(n int) error { s.Lock() defer s.Unlock() diff --git a/test/e2e/app/state.go b/test/e2e/app/state.go index a10a5cbf39c..0b142d390e1 100644 --- a/test/e2e/app/state.go +++ b/test/e2e/app/state.go @@ -17,14 +17,21 @@ const ( prevStateFileName = "prev_app_state.json" ) +// Intermediate type used exclusively in serialization/deserialization of +// State, such that State need not expose any of its internal values publicly. +type serializedState struct { + Height uint64 `json:"height"` + Values map[string]string `json:"values"` + Hash []byte `json:"hash"` +} + // State is the application state. type State struct { sync.RWMutex - Height uint64 - Values map[string]string - Hash []byte + height uint64 + values map[string]string + hash []byte - // private fields aren't marshaled to disk. currentFile string // app saves current and previous state for rollback functionality previousFile string @@ -35,12 +42,12 @@ type State struct { // NewState creates a new state. func NewState(dir string, persistInterval uint64) (*State, error) { state := &State{ - Values: make(map[string]string), + values: make(map[string]string), currentFile: filepath.Join(dir, stateFileName), previousFile: filepath.Join(dir, prevStateFileName), persistInterval: persistInterval, } - state.Hash = hashItems(state.Values, state.Height) + state.hash = hashItems(state.values, state.height) err := state.load() switch { case errors.Is(err, os.ErrNotExist): @@ -56,18 +63,16 @@ func (s *State) load() error { bz, err := os.ReadFile(s.currentFile) if err != nil { // if the current state doesn't exist then we try recover from the previous state - if errors.Is(err, os.ErrNotExist) { - bz, err = os.ReadFile(s.previousFile) - if err != nil { - return fmt.Errorf("failed to read both current and previous state (%q): %w", - s.previousFile, err) - } - } else { + if !errors.Is(err, os.ErrNotExist) { return fmt.Errorf("failed to read state from %q: %w", s.currentFile, err) } + bz, err = os.ReadFile(s.previousFile) + if err != nil { + return fmt.Errorf("failed to read both current and previous state (%q): %w", + s.previousFile, err) + } } - err = json.Unmarshal(bz, s) - if err != nil { + if err := json.Unmarshal(bz, s); err != nil { return fmt.Errorf("invalid state data in %q: %w", s.currentFile, err) } return nil @@ -97,11 +102,39 @@ func (s *State) save() error { return os.Rename(newFile, s.currentFile) } +// GetHash provides a thread-safe way of accessing a copy of the current state +// hash. +func (s *State) GetHash() []byte { + s.RLock() + defer s.RUnlock() + hash := make([]byte, len(s.hash)) + copy(hash, s.hash) + return hash +} + +// Info returns both the height and hash simultaneously, and is used in the +// ABCI Info call. +func (s *State) Info() (uint64, []byte) { + s.RLock() + defer s.RUnlock() + height := s.height + hash := make([]byte, len(s.hash)) + copy(hash, s.hash) + return height, hash +} + // Export exports key/value pairs as JSON, used for state sync snapshots. -func (s *State) Export() ([]byte, error) { +// Additionally returns the current height and hash of the state. +func (s *State) Export() ([]byte, uint64, []byte, error) { s.RLock() defer s.RUnlock() - return json.Marshal(s.Values) + bz, err := json.Marshal(s.values) + if err != nil { + return nil, 0, nil, err + } + height := s.height + stateHash := hashItems(s.values, height) + return bz, height, stateHash, nil } // Import imports key/value pairs from JSON bytes, used for InitChain.AppStateBytes and @@ -114,9 +147,9 @@ func (s *State) Import(height uint64, jsonBytes []byte) error { if err != nil { return fmt.Errorf("failed to decode imported JSON data: %w", err) } - s.Height = height - s.Values = values - s.Hash = hashItems(values, height) + s.height = height + s.values = values + s.hash = hashItems(values, height) return s.save() } @@ -124,7 +157,7 @@ func (s *State) Import(height uint64, jsonBytes []byte) error { func (s *State) Get(key string) string { s.RLock() defer s.RUnlock() - return s.Values[key] + return s.values[key] } // Set sets a value. Setting an empty value is equivalent to deleting it. @@ -132,39 +165,49 @@ func (s *State) Set(key, value string) { s.Lock() defer s.Unlock() if value == "" { - delete(s.Values, key) + delete(s.values, key) } else { - s.Values[key] = value + s.values[key] = value } } -// Finalize is called after applying a block, updating the height and returning the new app_hash +// Query is used in the ABCI Query call, and provides both the current height +// and the value associated with the given key. +func (s *State) Query(key string) (string, uint64) { + s.RLock() + defer s.RUnlock() + height := s.height + value := s.values[key] + return value, height +} + +// Finalize is called after applying a block, updating the height and returning the new app_hash. func (s *State) Finalize() []byte { s.Lock() defer s.Unlock() switch { - case s.Height > 0: - s.Height++ + case s.height > 0: + s.height++ case s.initialHeight > 0: - s.Height = s.initialHeight + s.height = s.initialHeight default: - s.Height = 1 + s.height = 1 } - s.Hash = hashItems(s.Values, s.Height) - return s.Hash + s.hash = hashItems(s.values, s.height) + return s.hash } // Commit commits the current state. func (s *State) Commit() (uint64, error) { s.Lock() defer s.Unlock() - if s.persistInterval > 0 && s.Height%s.persistInterval == 0 { + if s.persistInterval > 0 && s.height%s.persistInterval == 0 { err := s.save() if err != nil { return 0, err } } - return s.Height, nil + return s.height, nil } func (s *State) Rollback() error { @@ -172,13 +215,32 @@ func (s *State) Rollback() error { if err != nil { return fmt.Errorf("failed to read state from %q: %w", s.previousFile, err) } - err = json.Unmarshal(bz, s) - if err != nil { + if err := json.Unmarshal(bz, s); err != nil { return fmt.Errorf("invalid state data in %q: %w", s.previousFile, err) } return nil } +func (s *State) UnmarshalJSON(b []byte) error { + var ss serializedState + if err := json.Unmarshal(b, &ss); err != nil { + return err + } + s.height = ss.Height + s.values = ss.Values + s.hash = ss.Hash + return nil +} + +func (s *State) MarshalJSON() ([]byte, error) { + ss := &serializedState{ + Height: s.height, + Values: s.values, + Hash: s.hash, + } + return json.Marshal(ss) +} + // hashItems hashes a set of key/value items. func hashItems(items map[string]string, height uint64) []byte { keys := make([]string, 0, len(items)) diff --git a/test/e2e/docker/Dockerfile b/test/e2e/docker/Dockerfile index cff113638f1..878181959f4 100644 --- a/test/e2e/docker/Dockerfile +++ b/test/e2e/docker/Dockerfile @@ -1,17 +1,22 @@ # We need to build in a Linux environment to support C libraries, e.g. RocksDB. # We use Debian instead of Alpine, so that we can use binary database packages # instead of spending time compiling them. -FROM golang:1.20 +FROM cometbft/cometbft-db-testing:latest RUN apt-get -qq update -y && apt-get -qq upgrade -y >/dev/null -RUN apt-get -qq install -y libleveldb-dev librocksdb-dev >/dev/null + +# For the latency-setter script +RUN apt-get -qq install -y iputils-ping iproute2 python3-netifaces >/dev/null +RUN mkdir -p /scripts +COPY test/e2e/pkg/latency/aws-latencies.csv /scripts/ +COPY test/e2e/pkg/latency/latency-setter.py /scripts/ # Set up build directory /src/cometbft -ENV COMETBFT_BUILD_OPTIONS badgerdb,boltdb,cleveldb,rocksdb +ENV COMETBFT_BUILD_OPTIONS badgerdb,rocksdb,pebbledb,clock_skew,bls12381 WORKDIR /src/cometbft # Fetch dependencies separately (for layer caching) -COPY go.mod go.sum ./ +COPY go.mod go.sum api/go.mod api/go.sum ./ RUN go mod download # Build CometBFT and install into /usr/bin/cometbft @@ -25,6 +30,7 @@ RUN cd test/e2e && make node && cp build/node /usr/bin/app WORKDIR /cometbft VOLUME /cometbft ENV CMTHOME=/cometbft +ENV GORACE "halt_on_error=1" EXPOSE 26656 26657 26660 6060 ENTRYPOINT ["/usr/bin/entrypoint"] diff --git a/test/e2e/docker/Dockerfile.debug b/test/e2e/docker/Dockerfile.debug new file mode 100644 index 00000000000..da9a56525dd --- /dev/null +++ b/test/e2e/docker/Dockerfile.debug @@ -0,0 +1,32 @@ +# We need to build in a Linux environment to support C libraries, e.g. RocksDB. +# We use Debian instead of Alpine, so that we can use binary database packages +# instead of spending time compiling them. +FROM cometbft/cometbft-db-testing:latest + +RUN apt-get -qq update -y && apt-get -qq upgrade -y >/dev/null +RUN apt-get -qq install -y zsh vim >/dev/null +RUN go install github.com/go-delve/delve/cmd/dlv@latest + +# Set up build directory /src/cometbft +ENV COMETBFT_BUILD_OPTIONS badgerdb,rocksdb,nostrip,pebbledb,clock_skew,bls12381 +WORKDIR /src/cometbft + +# Fetch dependencies separately (for layer caching) +COPY go.mod go.sum ./ +RUN go mod download + +# Build CometBFT and install into /usr/bin/cometbft +COPY . . +RUN echo $COMETBFT_BUILD_OPTION && make build && cp build/cometbft /usr/bin/cometbft +COPY test/e2e/docker/entrypoint-delve /usr/bin/entrypoint-builtin +RUN cd test/e2e && make node && cp build/node /usr/bin/app + +# Set up runtime directory. We don't use a separate runtime image since we need +# e.g. leveldb and rocksdb which are already installed in the build image. +WORKDIR /cometbft +VOLUME /cometbft +ENV CMTHOME=/cometbft +ENV GORACE "halt_on_error=1" + +EXPOSE 26656 26657 26660 6060 2345 2346 +STOPSIGNAL SIGTERM diff --git a/test/e2e/docker/Dockerfile.fast b/test/e2e/docker/Dockerfile.fast new file mode 100644 index 00000000000..5c29052ce60 --- /dev/null +++ b/test/e2e/docker/Dockerfile.fast @@ -0,0 +1,13 @@ +FROM gcr.io/distroless/static-debian11:debug + +COPY build/node /app +COPY docker/entrypoint-fast /usr/bin/entrypoint-builtin + +WORKDIR /cometbft +VOLUME /cometbft +ENV CMTHOME=/cometbft +ENV GORACE "halt_on_error=1" + +EXPOSE 26656 26657 26660 6060 +ENTRYPOINT ["/usr/bin/entrypoint-builtin"] +STOPSIGNAL SIGTERM diff --git a/test/e2e/docker/entrypoint-builtin-delve b/test/e2e/docker/entrypoint-builtin-delve new file mode 100755 index 00000000000..8667c722e29 --- /dev/null +++ b/test/e2e/docker/entrypoint-builtin-delve @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# Forcibly remove any stray UNIX sockets left behind from previous runs +rm -rf /var/run/privval.sock /var/run/app.sock + +dlv --headless --listen=:2345 --log --log-output=debugger,debuglineerr,gdbwire,lldbout,rpc --accept-multiclient --api-version=2 exec /usr/bin/app -- /cometbft/config/app.toml diff --git a/test/e2e/docker/entrypoint-delve b/test/e2e/docker/entrypoint-delve new file mode 100755 index 00000000000..f21613c6ef7 --- /dev/null +++ b/test/e2e/docker/entrypoint-delve @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Forcibly remove any stray UNIX sockets left behind from previous runs +rm -rf /var/run/privval.sock /var/run/app.sock + +# dlv won't run the app until you connect to it with a client. +# Once the app is run, the signer will try only a few times before stopping, so don't take long to let comet run as well. +dlv --headless --listen=:2345 --log --log-output=debugger,debuglineerr,gdbwire,lldbout,rpc --accept-multiclient --api-version=2 exec /usr/bin/app -- /cometbft/config/app.toml & + +sleep 30 + +dlv --headless --listen=:2346 --log --log-output=debugger,debuglineerr,gdbwire,lldbout,rpc --accept-multiclient --api-version=2 exec /usr/bin/cometbft -- "$@" diff --git a/test/e2e/docker/entrypoint-fast b/test/e2e/docker/entrypoint-fast new file mode 100755 index 00000000000..b2e4f5edb36 --- /dev/null +++ b/test/e2e/docker/entrypoint-fast @@ -0,0 +1,5 @@ +#!/busybox/sh + +rm -rf /var/run/privval.sock /var/run/app.sock +/app /cometbft/config/app.toml # > /dev/null + diff --git a/test/e2e/generator/generate.go b/test/e2e/generator/generate.go index 7733e06c5a3..c081b9c1c75 100644 --- a/test/e2e/generator/generate.go +++ b/test/e2e/generator/generate.go @@ -10,16 +10,17 @@ import ( "time" "github.com/Masterminds/semver/v3" - e2e "github.com/cometbft/cometbft/test/e2e/pkg" - "github.com/cometbft/cometbft/version" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing/object" + + e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/version" ) var ( // testnetCombinations defines global testnet options, where we generate a // separate testnet for each combination (Cartesian product) of options. - testnetCombinations = map[string][]interface{}{ + testnetCombinations = map[string][]any{ "topology": {"single", "quad", "large"}, "initialHeight": {0, 1000}, "initialState": { @@ -33,10 +34,10 @@ var ( } // The following specify randomly chosen values for testnet nodes. - nodeDatabases = uniformChoice{"goleveldb", "cleveldb", "rocksdb", "boltdb", "badgerdb"} + nodeDatabases = uniformChoice{"goleveldb", "rocksdb", "badgerdb", "pebbledb"} ipv6 = uniformChoice{false, true} // FIXME: grpc disabled due to https://github.com/tendermint/tendermint/issues/5439 - nodeABCIProtocols = uniformChoice{"unix", "tcp", "builtin", "builtin_unsync"} // "grpc" + nodeABCIProtocols = uniformChoice{"unix", "tcp", "builtin", "builtin_connsync"} // "grpc" nodePrivvalProtocols = uniformChoice{"file", "unix", "tcp"} nodeBlockSyncs = uniformChoice{"v0"} // "v2" nodeStateSyncs = uniformChoice{false, true} @@ -47,9 +48,10 @@ var ( 2 * int(e2e.EvidenceAgeHeight), 4 * int(e2e.EvidenceAgeHeight), } - evidence = uniformChoice{0, 1, 10} - abciDelays = uniformChoice{"none", "small", "large"} - nodePerturbations = probSetChoice{ + nodeEnableCompanionPruning = uniformChoice{true, false} + evidence = uniformChoice{0, 1, 10} + abciDelays = uniformChoice{"none", "small", "large"} + nodePerturbations = probSetChoice{ "disconnect": 0.1, "pause": 0.1, "kill": 0.1, @@ -59,8 +61,13 @@ var ( lightNodePerturbations = probSetChoice{ "upgrade": 0.3, } - voteExtensionEnableHeightOffset = uniformChoice{int64(0), int64(10), int64(100)} - voteExtensionEnabled = uniformChoice{true, false} + voteExtensionsUpdateHeight = uniformChoice{int64(-1), int64(0), int64(1)} // -1: genesis, 0: InitChain, 1: (use offset) + voteExtensionEnabled = weightedChoice{true: 3, false: 1} + voteExtensionsHeightOffset = uniformChoice{int64(0), int64(10), int64(100)} + voteExtensionSize = uniformChoice{uint(128), uint(512), uint(2048), uint(8192)} // TODO: define the right values depending on experiment results. + pbtsUpdateHeight = uniformChoice{int64(-1), int64(0), int64(1)} // -1: genesis, 0: InitChain, 1: (use offset) + pbtsEnabled = weightedChoice{true: 3, false: 1} + pbtsHeightOffset = uniformChoice{int64(0), int64(10), int64(100)} ) type generateConfig struct { @@ -119,7 +126,7 @@ func Generate(cfg *generateConfig) ([]e2e.Manifest, error) { } // generateTestnet generates a single testnet with the given options. -func generateTestnet(r *rand.Rand, opt map[string]interface{}, upgradeVersion string, prometheus bool) (e2e.Manifest, error) { +func generateTestnet(r *rand.Rand, opt map[string]any, upgradeVersion string, prometheus bool) (e2e.Manifest, error) { manifest := e2e.Manifest{ IPv6: ipv6.Choose(r).(bool), ABCIProtocol: nodeABCIProtocols.Choose(r).(string), @@ -147,11 +154,27 @@ func generateTestnet(r *rand.Rand, opt map[string]interface{}, upgradeVersion st manifest.VoteExtensionDelay = 100 * time.Millisecond manifest.FinalizeBlockDelay = 500 * time.Millisecond } - + manifest.VoteExtensionsUpdateHeight = voteExtensionsUpdateHeight.Choose(r).(int64) + if manifest.VoteExtensionsUpdateHeight == 1 { + manifest.VoteExtensionsUpdateHeight = manifest.InitialHeight + voteExtensionsHeightOffset.Choose(r).(int64) + } if voteExtensionEnabled.Choose(r).(bool) { - manifest.VoteExtensionsEnableHeight = manifest.InitialHeight + voteExtensionEnableHeightOffset.Choose(r).(int64) + baseHeight := max(manifest.VoteExtensionsUpdateHeight+1, manifest.InitialHeight) + manifest.VoteExtensionsEnableHeight = baseHeight + voteExtensionsHeightOffset.Choose(r).(int64) } + manifest.VoteExtensionSize = voteExtensionSize.Choose(r).(uint) + + manifest.PbtsUpdateHeight = pbtsUpdateHeight.Choose(r).(int64) + if manifest.PbtsUpdateHeight == 1 { + manifest.PbtsUpdateHeight = manifest.InitialHeight + pbtsHeightOffset.Choose(r).(int64) + } + if pbtsEnabled.Choose(r).(bool) { + baseHeight := max(manifest.PbtsUpdateHeight+1, manifest.InitialHeight) + manifest.PbtsEnableHeight = baseHeight + pbtsHeightOffset.Choose(r).(int64) + } + + // TODO: Add skew config var numSeeds, numValidators, numFulls, numLightClients int switch opt["topology"].(string) { case "single": @@ -171,7 +194,7 @@ func generateTestnet(r *rand.Rand, opt map[string]interface{}, upgradeVersion st // First we generate seed nodes, starting at the initial height. for i := 1; i <= numSeeds; i++ { manifest.Nodes[fmt.Sprintf("seed%02d", i)] = generateNode( - r, e2e.ModeSeed, 0, manifest.InitialHeight, false) + r, e2e.ModeSeed, 0, false) } // Next, we generate validators. We make sure a BFT quorum of validators start @@ -179,6 +202,7 @@ func generateTestnet(r *rand.Rand, opt map[string]interface{}, upgradeVersion st // the initial validator set, and validator set updates for delayed nodes. nextStartAt := manifest.InitialHeight + 5 quorum := numValidators*2/3 + 1 + var totalWeight int64 for i := 1; i <= numValidators; i++ { startAt := int64(0) if i > quorum { @@ -186,16 +210,34 @@ func generateTestnet(r *rand.Rand, opt map[string]interface{}, upgradeVersion st nextStartAt += 5 } name := fmt.Sprintf("validator%02d", i) - manifest.Nodes[name] = generateNode( - r, e2e.ModeValidator, startAt, manifest.InitialHeight, i <= 2) + manifest.Nodes[name] = generateNode(r, e2e.ModeValidator, startAt, i <= 2) + weight := int64(30 + r.Intn(71)) if startAt == 0 { - (*manifest.Validators)[name] = int64(30 + r.Intn(71)) + (*manifest.Validators)[name] = weight } else { - manifest.ValidatorUpdates[fmt.Sprint(startAt+5)] = map[string]int64{ - name: int64(30 + r.Intn(71)), - } + manifest.ValidatorUpdates[strconv.FormatInt(startAt+5, 10)] = map[string]int64{name: weight} } + totalWeight += weight + } + + // Add clock skew only to processes that accumulate less than 1/3 of voting power. + var accWeight int64 + for i := 1; i <= numValidators; i++ { + name := fmt.Sprintf("validator%02d", i) + startAt := manifest.Nodes[name].StartAt + var weight int64 + if startAt == 0 { + weight = (*manifest.Validators)[name] + } else { + weight = manifest.ValidatorUpdates[strconv.FormatInt(startAt+5, 10)][name] + } + + if accWeight > totalWeight*2/3 { + // Interval: [-500ms, 59s500ms) + manifest.Nodes[name].ClockSkew = time.Duration(int64(r.Float64()*float64(time.Minute))) - 500*time.Millisecond + } + accWeight += weight } // Move validators to InitChain if specified. @@ -216,7 +258,7 @@ func generateTestnet(r *rand.Rand, opt map[string]interface{}, upgradeVersion st nextStartAt += 5 } manifest.Nodes[fmt.Sprintf("full%02d", i)] = generateNode( - r, e2e.ModeFull, startAt, manifest.InitialHeight, false) + r, e2e.ModeFull, startAt, false) } // We now set up peer discovery for nodes. Seed nodes are fully meshed with @@ -279,20 +321,21 @@ func generateTestnet(r *rand.Rand, opt map[string]interface{}, upgradeVersion st // here, since we need to know the overall network topology and startup // sequencing. func generateNode( - r *rand.Rand, mode e2e.Mode, startAt int64, initialHeight int64, forceArchive bool, + r *rand.Rand, mode e2e.Mode, startAt int64, forceArchive bool, ) *e2e.ManifestNode { node := e2e.ManifestNode{ - Version: nodeVersions.Choose(r).(string), - Mode: string(mode), - StartAt: startAt, - Database: nodeDatabases.Choose(r).(string), - PrivvalProtocol: nodePrivvalProtocols.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)), - RetainBlocks: uint64(nodeRetainBlocks.Choose(r).(int)), - Perturb: nodePerturbations.Choose(r), + Version: nodeVersions.Choose(r).(string), + Mode: string(mode), + StartAt: startAt, + Database: nodeDatabases.Choose(r).(string), + PrivvalProtocol: nodePrivvalProtocols.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)), + RetainBlocks: uint64(nodeRetainBlocks.Choose(r).(int)), + EnableCompanionPruning: false, + Perturb: nodePerturbations.Choose(r), } // If this node is forced to be an archive node, retain all blocks and @@ -323,6 +366,12 @@ func generateNode( } } + // Only randomly enable data companion-related pruning on 50% of the full + // nodes and validators. + if mode == e2e.ModeFull || mode == e2e.ModeValidator { + node.EnableCompanionPruning = nodeEnableCompanionPruning.Choose(r).(bool) + } + return &node } @@ -355,11 +404,12 @@ func parseWeightedVersions(s string) (weightedChoice, string, error) { for _, wv := range wvs { parts := strings.Split(strings.TrimSpace(wv), ":") var ver string - if len(parts) == 2 { + switch len(parts) { + case 2: ver = strings.TrimSpace(strings.Join([]string{"cometbft/e2e-node", parts[0]}, ":")) - } else if len(parts) == 3 { + case 3: ver = strings.TrimSpace(strings.Join([]string{parts[0], parts[1]}, ":")) - } else { + default: return nil, "", fmt.Errorf("unexpected weight:version combination: %s", wv) } @@ -400,7 +450,7 @@ func gitRepoLatestReleaseVersion(gitRepoDir string) (string, error) { if err != nil { return "", err } - return findLatestReleaseTag(version.TMCoreSemVer, tags) + return findLatestReleaseTag(version.CMTSemVer, tags) } func findLatestReleaseTag(baseVer string, tags []string) (string, error) { diff --git a/test/e2e/generator/generate_test.go b/test/e2e/generator/generate_test.go index 670f701e4b3..08805494658 100644 --- a/test/e2e/generator/generate_test.go +++ b/test/e2e/generator/generate_test.go @@ -12,7 +12,7 @@ import ( e2e "github.com/cometbft/cometbft/test/e2e/pkg" ) -// TestGenerator tests that only valid manifests are generated +// TestGenerator tests that only valid manifests are generated. func TestGenerator(t *testing.T) { cfg := &generateConfig{ randSource: rand.New(rand.NewSource(randomSeed)), @@ -24,7 +24,7 @@ func TestGenerator(t *testing.T) { t.Run(fmt.Sprintf("Case%04d", idx), func(t *testing.T) { infra, err := e2e.NewDockerInfrastructureData(m) require.NoError(t, err) - _, err = e2e.NewTestnetFromManifest(m, filepath.Join(t.TempDir(), fmt.Sprintf("Case%04d", idx)), infra) + _, err = e2e.NewTestnetFromManifest(m, filepath.Join(t.TempDir(), fmt.Sprintf("Case%04d", idx)), infra, "") require.NoError(t, err) }) } diff --git a/test/e2e/generator/main.go b/test/e2e/generator/main.go index f4f8140c0c1..20690270a95 100644 --- a/test/e2e/generator/main.go +++ b/test/e2e/generator/main.go @@ -35,7 +35,7 @@ func NewCLI() *CLI { Short: "End-to-end testnet generator", SilenceUsage: true, SilenceErrors: true, // we'll output them ourselves in Run() - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { dir, err := cmd.Flags().GetString("dir") if err != nil { return err @@ -67,7 +67,7 @@ func NewCLI() *CLI { } // generate generates manifests in a directory. -func (cli *CLI) generate(dir string, groups int, multiVersion string, prometheus bool) error { +func (*CLI) generate(dir string, groups int, multiVersion string, prometheus bool) error { err := os.MkdirAll(dir, 0o755) if err != nil { return err diff --git a/test/e2e/generator/random.go b/test/e2e/generator/random.go index 4312eb30d70..3614355576e 100644 --- a/test/e2e/generator/random.go +++ b/test/e2e/generator/random.go @@ -20,26 +20,26 @@ import ( // {"foo": 2, "bar": 6} // {"foo": 3, "bar": 4} // {"foo": 3, "bar": 5} -// {"foo": 3, "bar": 6} -func combinations(items map[string][]interface{}) []map[string]interface{} { +// {"foo": 3, "bar": 6}. +func combinations(items map[string][]any) []map[string]any { keys := []string{} for key := range items { keys = append(keys, key) } sort.Strings(keys) - return combiner(map[string]interface{}{}, keys, items) + return combiner(map[string]any{}, keys, items) } // combiner is a utility function for combinations. -func combiner(head map[string]interface{}, pending []string, items map[string][]interface{}) []map[string]interface{} { +func combiner(head map[string]any, pending []string, items map[string][]any) []map[string]any { if len(pending) == 0 { - return []map[string]interface{}{head} + return []map[string]any{head} } key, pending := pending[0], pending[1:] - result := []map[string]interface{}{} + result := []map[string]any{} for _, value := range items[key] { - path := map[string]interface{}{} + path := map[string]any{} for k, v := range head { path[k] = v } @@ -50,9 +50,9 @@ func combiner(head map[string]interface{}, pending []string, items map[string][] } // uniformChoice chooses a single random item from the argument list, uniformly weighted. -type uniformChoice []interface{} +type uniformChoice []any -func (uc uniformChoice) Choose(r *rand.Rand) interface{} { +func (uc uniformChoice) Choose(r *rand.Rand) any { return uc[r.Intn(len(uc))] } @@ -85,11 +85,11 @@ func (usc uniformSetChoice) Choose(r *rand.Rand) []string { } // weightedChoice chooses a single random key from a map of keys and weights. -type weightedChoice map[interface{}]uint +type weightedChoice map[any]uint -func (wc weightedChoice) Choose(r *rand.Rand) interface{} { +func (wc weightedChoice) Choose(r *rand.Rand) any { total := 0 - choices := make([]interface{}, 0, len(wc)) + choices := make([]any, 0, len(wc)) for choice, weight := range wc { total += int(weight) choices = append(choices, choice) diff --git a/test/e2e/generator/random_test.go b/test/e2e/generator/random_test.go index 3fbb19ab5a7..0d7d909acc2 100644 --- a/test/e2e/generator/random_test.go +++ b/test/e2e/generator/random_test.go @@ -7,14 +7,14 @@ import ( ) func TestCombinations(t *testing.T) { - input := map[string][]interface{}{ + input := map[string][]any{ "bool": {false, true}, "int": {1, 2, 3}, "string": {"foo", "bar"}, } c := combinations(input) - assert.Equal(t, []map[string]interface{}{ + assert.Equal(t, []map[string]any{ {"bool": false, "int": 1, "string": "foo"}, {"bool": false, "int": 1, "string": "bar"}, {"bool": false, "int": 2, "string": "foo"}, diff --git a/test/e2e/networks/ci.toml b/test/e2e/networks/ci.toml index 9fded05007a..d8e96e9fa0e 100644 --- a/test/e2e/networks/ci.toml +++ b/test/e2e/networks/ci.toml @@ -3,7 +3,10 @@ ipv6 = true initial_height = 1000 +vote_extensions_update_height = 1004 vote_extensions_enable_height = 1007 +pbts_update_height = 1006 +pbts_enable_height = 1009 evidence = 5 initial_state = { initial01 = "a", initial02 = "b", initial03 = "c" } prepare_proposal_delay = "100ms" @@ -12,6 +15,8 @@ check_tx_delay = "0ms" # The most common case (e.g. Cosmos SDK-based chains). abci_protocol = "builtin" prometheus = true +peer_gossip_intraloop_sleep_duration = "50ms" +abci_tests_enabled = true [validators] validator01 = 100 @@ -41,10 +46,11 @@ perturb = ["restart"] seeds = ["seed01"] snapshot_interval = 5 perturb = ["disconnect"] +clock_skew = "20s" [node.validator02] seeds = ["seed01"] -database = "boltdb" +database = "pebbledb" privval_protocol = "tcp" persist_interval = 0 perturb = ["restart"] @@ -55,6 +61,7 @@ database = "badgerdb" privval_protocol = "unix" persist_interval = 3 retain_blocks = 10 +enable_companion_pruning = true perturb = ["kill"] [node.validator04] @@ -65,7 +72,7 @@ perturb = ["pause"] [node.validator05] start_at = 1005 # Becomes part of the validator set at 1010 persistent_peers = ["validator01", "full01"] -database = "cleveldb" +database = "rocksdb" privval_protocol = "tcp" perturb = ["kill", "pause", "disconnect", "restart"] @@ -74,6 +81,7 @@ start_at = 1010 mode = "full" persistent_peers = ["validator01", "validator02", "validator03", "validator04", "validator05"] retain_blocks = 10 +enable_companion_pruning = true perturb = ["restart"] [node.full02] diff --git a/test/e2e/networks/long.toml b/test/e2e/networks/long.toml index 86c01b2b5f1..953a3ec9dbc 100644 --- a/test/e2e/networks/long.toml +++ b/test/e2e/networks/long.toml @@ -52,7 +52,7 @@ load_tx_connections = 0 mode = "full" version = "cometbft/e2e-node:latest" persistent_peers = ["validator03", "validator01", "validator06"] - database = "boltdb" + database = "pebbledb" privval_protocol = "tcp" start_at = 750 fast_sync = "v0" @@ -69,7 +69,7 @@ load_tx_connections = 0 seeds = ["seed01"] database = "badgerdb" privval_protocol = "unix" - start_at = 0 + start_at = 0 fast_sync = "v0" mempool_version = "v0" state_sync = false @@ -89,7 +89,7 @@ load_tx_connections = 0 state_sync = false persist_interval = 5 snapshot_interval = 0 - retain_blocks = 7 + retain_blocks = 7 perturb = ["upgrade"] send_no_load = false [node.validator01] @@ -128,7 +128,7 @@ load_tx_connections = 0 mode = "validator" version = "cometbft/e2e-node:latest" seeds = ["seed01"] - database = "boltdb" + database = "pebbledb" privval_protocol = "file" start_at = 0 fast_sync = "v0" @@ -144,7 +144,7 @@ load_tx_connections = 0 mode = "validator" version = "cometbft/e2e-node:latest" seeds = ["seed01"] - database = "cleveldb" + database = "rocksdb" privval_protocol = "tcp" start_at = 0 fast_sync = "v0" @@ -160,7 +160,7 @@ load_tx_connections = 0 mode = "validator" version = "cometbft/e2e-node:latest" persistent_peers = ["validator03"] - database = "cleveldb" + database = "rocksdb" privval_protocol = "unix" start_at = 0 fast_sync = "v0" @@ -176,7 +176,7 @@ load_tx_connections = 0 mode = "validator" version = "cometbft/e2e-node:latest" persistent_peers = ["full03", "validator02", "validator03"] - database = "boltdb" + database = "pebbledb" privval_protocol = "tcp" start_at = 5 fast_sync = "v0" @@ -192,7 +192,7 @@ load_tx_connections = 0 mode = "validator" version = "cometbft/e2e-node:latest" seeds = ["seed01"] - database = "cleveldb" + database = "rocksdb" privval_protocol = "file" start_at = 10 fast_sync = "v0" @@ -208,12 +208,12 @@ load_tx_connections = 0 mode = "validator" version = "cometbft/e2e-node:latest" seeds = ["seed01"] - database = "cleveldb" + database = "rocksdb" privval_protocol = "file" start_at = 1000 fast_sync = "v0" mempool_version = "v0" - state_sync = false + state_sync = false persist_interval = 5 snapshot_interval = 3 retain_blocks = 0 @@ -224,7 +224,7 @@ load_tx_connections = 0 mode = "validator" version = "cometbft/e2e-node:latest" seeds = ["seed01"] - database = "cleveldb" + database = "rocksdb" privval_protocol = "file" start_at = 1250 fast_sync = "v0" @@ -240,12 +240,12 @@ load_tx_connections = 0 mode = "validator" version = "cometbft/e2e-node:latest" seeds = ["seed01"] - database = "cleveldb" + database = "rocksdb" privval_protocol = "file" start_at = 1500 fast_sync = "v0" mempool_version = "v0" - state_sync = false + state_sync = false persist_interval = 5 snapshot_interval = 3 retain_blocks = 0 diff --git a/test/e2e/networks/simple.toml b/test/e2e/networks/simple.toml index 96b81f79fe1..3fcd56e5614 100644 --- a/test/e2e/networks/simple.toml +++ b/test/e2e/networks/simple.toml @@ -1,4 +1,71 @@ +prometheus = true +timeout_commit = "300ms" +cache_size = 200000 + +#no pruning old layout +[node.validator00] +seeds = ["seed01"] +discard_abci_responses = true +indexer = "null" +prometheus = true +cache_size = 200000 + +# pruning + compaction new layout [node.validator01] +experimental_db_key_layout = "v2" +discard_abci_responses = true +indexer = "null" +retain_blocks = 100 +compaction_interval = 200 +compact = true +seeds = ["seed01"] +prometheus = true +cache_size = 200000 + +# pruning + compaction old layout [node.validator02] +discard_abci_responses = true +retain_blocks = 100 +indexer = "null" +compact = true +compaction_interval = 200 +seeds = ["seed01"] +prometheus = true +cache_size = 200000 + +# pruning no compaction new layout [node.validator03] +discard_abci_responses = true +experimental_db_key_layout = "v2" +retain_blocks = 100 +indexer = "null" +seeds = ["seed01"] +prometheus = true +cache_size = 200000 + +# no pruning new layout [node.validator04] +experimental_db_key_layout = "v2" +discard_abci_responses = true +indexer = "null" +seeds = ["seed01"] +prometheus = true +persistent_peers = ["validator00"] +cache_size = 200000 + +# pruning no compaction old layout +[node.validator05] +discard_abci_responses = true +retain_blocks = 100 +indexer = "null" +seeds = ["seed01"] +prometheus = true +cache_size = 200000 + +[node.seed01] +discard_abci_responses = true +indexer = "null" +mode = "seed" +prometheus = true +cache_size = 200000 + diff --git a/test/e2e/networks/upgrade.toml b/test/e2e/networks/upgrade.toml new file mode 100644 index 00000000000..70d6f2f0bcb --- /dev/null +++ b/test/e2e/networks/upgrade.toml @@ -0,0 +1,37 @@ +evidence = 10 +vote_extensions_enable_height = 100 +abci_protocol = "tcp" +upgrade_version = "cometbft/e2e-node:local-version" + +# Image cometbft/v0.38.x built with v0.38.x as of feb 27/2024 + +[validators] + validator01 = 50 + validator02 = 50 + validator03 = 50 + validator04 = 50 + +[node] + [node.validator01] + mode = "validator" + version = "cometbft/v0.38.x" + perturb = ["upgrade"] + send_no_load = true + [node.validator02] + mode = "validator" + version = "cometbft/v0.38.x" + persistent_peers = ["validator01"] + perturb = [] + send_no_load = true + [node.validator03] + mode = "validator" + version = "cometbft/v0.38.x" + persistent_peers = ["validator01"] + perturb = [] + send_no_load = true + [node.validator04] + mode = "validator" + version = "cometbft/v0.38.x" + persistent_peers = ["validator01"] + perturb = [] + send_no_load = true diff --git a/test/e2e/networks/varyVESize.toml b/test/e2e/networks/varyVESize.toml new file mode 100644 index 00000000000..5c731ea9913 --- /dev/null +++ b/test/e2e/networks/varyVESize.toml @@ -0,0 +1,83 @@ +ipv6 = false +initial_height = 0 +key_type = "" +evidence = 10 +vote_extensions_enable_height = 1 +abci_protocol = "tcp" +prepare_proposal_delay = "100ms" +process_proposal_delay = "100ms" +check_tx_delay = "0s" +vote_extension_delay = "20ms" +finalize_block_delay = "200ms" +upgrade_version = "" +load_tx_size_bytes = 0 +load_tx_batch_size = 0 +load_tx_connections = 0 +prometheus = false +vote_extension_size = 8192 + +[initial_state] + +[validators] + validator01 = 42 + validator02 = 44 + validator03 = 51 + +[validator_update] + +[node] + [node.validator01] + mode = "validator" + version = "" + database = "rocksdb" + privval_protocol = "unix" + start_at = 0 + block_sync_version = "v0" + state_sync = false + persist_interval = 1 + snapshot_interval = 3 + retain_blocks = 0 + perturb = [] + send_no_load = false + [node.validator02] + mode = "validator" + version = "" + persistent_peers = ["validator01"] + database = "rocksdb" + privval_protocol = "tcp" + start_at = 0 + block_sync_version = "v0" + state_sync = false + persist_interval = 1 + snapshot_interval = 3 + retain_blocks = 0 + perturb = [] + send_no_load = false + [node.validator03] + mode = "validator" + version = "" + persistent_peers = ["validator01"] + database = "goleveldb" + privval_protocol = "tcp" + start_at = 0 + block_sync_version = "v0" + state_sync = false + persist_interval = 0 + snapshot_interval = 3 + retain_blocks = 0 + perturb = [] + send_no_load = false + [node.validator04] + mode = "validator" + version = "" + persistent_peers = ["validator02", "validator01"] + database = "rocksdb" + privval_protocol = "tcp" + start_at = 5000 + block_sync_version = "v0" + state_sync = false + persist_interval = 1 + snapshot_interval = 3 + retain_blocks = 28 + perturb = [] + send_no_load = false diff --git a/test/e2e/node/config.go b/test/e2e/node/config.go index c2cb871d1f1..97cb26b8c6a 100644 --- a/test/e2e/node/config.go +++ b/test/e2e/node/config.go @@ -1,12 +1,13 @@ package main import ( - "errors" "fmt" + "time" "github.com/BurntSushi/toml" "github.com/cometbft/cometbft/test/e2e/app" + cmterrors "github.com/cometbft/cometbft/types/errors" ) // Config is the application configuration. @@ -24,17 +25,53 @@ type Config struct { PrivValKey string `toml:"privval_key"` PrivValState string `toml:"privval_state"` KeyType string `toml:"key_type"` + + PrepareProposalDelay time.Duration `toml:"prepare_proposal_delay"` + ProcessProposalDelay time.Duration `toml:"process_proposal_delay"` + CheckTxDelay time.Duration `toml:"check_tx_delay"` + FinalizeBlockDelay time.Duration `toml:"finalize_block_delay"` + VoteExtensionDelay time.Duration `toml:"vote_extension_delay"` + + VoteExtensionSize uint `toml:"vote_extension_size"` + VoteExtensionsEnableHeight int64 `toml:"vote_extensions_enable_height"` + VoteExtensionsUpdateHeight int64 `toml:"vote_extensions_update_height"` + + ABCIRequestsLoggingEnabled bool `toml:"abci_requests_logging_enabled"` + + ExperimentalKeyLayout string `toml:"experimental_db_key_layout"` + + Compact bool `toml:"compact"` + + CompactionInterval bool `toml:"compaction_interval"` + + DiscardABCIResponses bool `toml:"discard_abci_responses"` + + Indexer string `toml:"indexer"` + + PbtsEnableHeight int64 `toml:"pbts_enable_height"` + PbtsUpdateHeight int64 `toml:"pbts_update_height"` } -// App extracts out the application specific configuration parameters +// App extracts out the application specific configuration parameters. func (cfg *Config) App() *app.Config { return &app.Config{ - Dir: cfg.Dir, - SnapshotInterval: cfg.SnapshotInterval, - RetainBlocks: cfg.RetainBlocks, - KeyType: cfg.KeyType, - ValidatorUpdates: cfg.ValidatorUpdates, - PersistInterval: cfg.PersistInterval, + Dir: cfg.Dir, + SnapshotInterval: cfg.SnapshotInterval, + RetainBlocks: cfg.RetainBlocks, + KeyType: cfg.KeyType, + ValidatorUpdates: cfg.ValidatorUpdates, + PersistInterval: cfg.PersistInterval, + PrepareProposalDelay: cfg.PrepareProposalDelay, + ProcessProposalDelay: cfg.ProcessProposalDelay, + CheckTxDelay: cfg.CheckTxDelay, + FinalizeBlockDelay: cfg.FinalizeBlockDelay, + VoteExtensionDelay: cfg.VoteExtensionDelay, + VoteExtensionSize: cfg.VoteExtensionSize, + VoteExtensionsEnableHeight: cfg.VoteExtensionsEnableHeight, + VoteExtensionsUpdateHeight: cfg.VoteExtensionsUpdateHeight, + ABCIRequestsLoggingEnabled: cfg.ABCIRequestsLoggingEnabled, + PbtsEnableHeight: cfg.PbtsEnableHeight, + PbtsUpdateHeight: cfg.PbtsUpdateHeight, } } @@ -59,9 +96,9 @@ func LoadConfig(file string) (*Config, error) { func (cfg Config) Validate() error { switch { case cfg.ChainID == "": - return errors.New("chain_id parameter is required") - case cfg.Listen == "" && cfg.Protocol != "builtin" && cfg.Protocol != "builtin_unsync": - return errors.New("listen parameter is required") + return cmterrors.ErrRequiredField{Field: "chain_id"} + case cfg.Listen == "" && cfg.Protocol != "builtin" && cfg.Protocol != "builtin_connsync": + return cmterrors.ErrRequiredField{Field: "listen"} default: return nil } diff --git a/test/e2e/node/main.go b/test/e2e/node/main.go index 8d008c475e8..bde7e221de5 100644 --- a/test/e2e/node/main.go +++ b/test/e2e/node/main.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "path/filepath" + "strconv" "strings" "time" @@ -15,9 +16,9 @@ import ( "github.com/cometbft/cometbft/abci/server" "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/crypto/ed25519" + cmtnet "github.com/cometbft/cometbft/internal/net" cmtflags "github.com/cometbft/cometbft/libs/cli/flags" "github.com/cometbft/cometbft/libs/log" - cmtnet "github.com/cometbft/cometbft/libs/net" "github.com/cometbft/cometbft/light" lproxy "github.com/cometbft/cometbft/light/proxy" lrpc "github.com/cometbft/cometbft/light/rpc" @@ -62,7 +63,7 @@ func run(configFile string) error { if err = startSigner(cfg); err != nil { return err } - if cfg.Protocol == "builtin" || cfg.Protocol == "builtin_unsync" { + if cfg.Protocol == "builtin" || cfg.Protocol == "builtin_connsync" { time.Sleep(1 * time.Second) } } @@ -71,7 +72,7 @@ func run(configFile string) error { switch cfg.Protocol { case "socket", "grpc": err = startApp(cfg) - case "builtin", "builtin_unsync": + case "builtin", "builtin_connsync": if cfg.Mode == string(e2e.ModeLight) { err = startLightClient(cfg) } else { @@ -124,15 +125,19 @@ func startNode(cfg *Config) error { } var clientCreator proxy.ClientCreator - if cfg.Protocol == string(e2e.ProtocolBuiltinUnsync) { - clientCreator = proxy.NewUnsyncLocalClientCreator(app) - nodeLogger.Info("Using unsynchronized local client creator") + if cfg.Protocol == string(e2e.ProtocolBuiltinConnSync) { + clientCreator = proxy.NewConnSyncLocalClientCreator(app) + nodeLogger.Info("Using connection-synchronized local client creator") } else { clientCreator = proxy.NewLocalClientCreator(app) nodeLogger.Info("Using default (synchronized) local client creator") } - n, err := node.NewNode(cmtcfg, + if cfg.ExperimentalKeyLayout != "" { + cmtcfg.Storage.ExperimentalKeyLayout = cfg.ExperimentalKeyLayout + } + + n, err := node.NewNode(context.Background(), cmtcfg, privval.LoadOrGenFilePV(cmtcfg.PrivValidatorKeyFile(), cmtcfg.PrivValidatorStateFile()), nodeKey, clientCreator, @@ -171,7 +176,7 @@ func startLightClient(cfg *Config) error { }, providers[0], providers[1:], - dbs.New(lightDB, "light"), + dbs.NewWithDBVersion(lightDB, "light", cfg.ExperimentalKeyLayout), light.Logger(nodeLogger), ) if err != nil { @@ -277,7 +282,7 @@ func setupNode() (*config.Config, log.Logger, *p2p.NodeKey, error) { } // rpcEndpoints takes a list of persistent peers and splits them into a list of rpc endpoints -// using 26657 as the port number +// using 26657 as the port number. func rpcEndpoints(peers string) []string { arr := strings.Split(peers, ",") endpoints := make([]string, len(arr)) @@ -286,7 +291,7 @@ func rpcEndpoints(peers string) []string { hostName := strings.Split(urlString, ":26656")[0] // use RPC port instead port := 26657 - rpcEndpoint := "http://" + hostName + ":" + fmt.Sprint(port) + rpcEndpoint := "http://" + hostName + ":" + strconv.Itoa(port) endpoints[i] = rpcEndpoint } return endpoints diff --git a/test/e2e/pkg/exec/exec.go b/test/e2e/pkg/exec/exec.go new file mode 100644 index 00000000000..b0a3228fac6 --- /dev/null +++ b/test/e2e/pkg/exec/exec.go @@ -0,0 +1,40 @@ +package exec + +import ( + "context" + "fmt" + "os" + osexec "os/exec" +) + +// Command executes a shell command. +func Command(ctx context.Context, args ...string) error { + _, err := CommandOutput(ctx, args...) + return err +} + +// CommandOutput executes a shell command and returns the command's output. +func CommandOutput(ctx context.Context, args ...string) ([]byte, error) { + //nolint: gosec + // G204: Subprocess launched with a potential tainted input or cmd arguments + cmd := osexec.CommandContext(ctx, args[0], args[1:]...) + out, err := cmd.CombinedOutput() + switch err := err.(type) { + case nil: + return out, nil + case *osexec.ExitError: + return nil, fmt.Errorf("failed to run %q:\n%v", args, string(out)) + default: + return nil, err + } +} + +// CommandVerbose executes a shell command while displaying its output. +func CommandVerbose(ctx context.Context, args ...string) error { + //nolint: gosec + // G204: Subprocess launched with a potential tainted input or cmd arguments + cmd := osexec.CommandContext(ctx, args[0], args[1:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/test/e2e/pkg/grammar/README.md b/test/e2e/pkg/grammar/README.md new file mode 100644 index 00000000000..5375a0ec11a --- /dev/null +++ b/test/e2e/pkg/grammar/README.md @@ -0,0 +1,14 @@ +# The ``grammar`` folder structure + +This folder has two subdirectories (`clean-start` and `recovery`), `checker.go` and `checker_test.go` files. + +Both `clean-start` and `recovery` folders have the same structure. They contain files with the context-free grammars +`abci_grammar_clean_start.md` and `abci_grammar_recovery.md`, respectively. In addition, they have a subdirectory, +`grammar-auto`, where the auto-generated code is stored. Namely, running `make grammar-gen` from the `e2e` directory will +invoke the `gogll` program that will use `abci_grammar_clean_start.md` and `abci_grammar_recovery.md` grammars as +input and produce lexer and parser for them. All the code `gogll` generates, is stored in the mentioned `grammar-auto` folder. + +`checker.go` and `checker_test.go` files contain the logic of the `GrammarChecker` abstraction and its tests. The +`GrammarChecker` abstraction is used to check whether a specific set of `abci.Requests` respects the +[ABCI grammar](https://github.com/cometbft/cometbft/blob/main/spec/abci/abci%2B%2B_comet_expected_behavior.md). It achieves this by using lexers +and parsers generated by `gogll`. Namely, the only place where the auto-generated code is used is inside the `func (g *GrammarChecker) verifyRecovery(execution string) []*Error` function. \ No newline at end of file diff --git a/test/e2e/pkg/grammar/abci_grammar.md b/test/e2e/pkg/grammar/abci_grammar.md new file mode 100644 index 00000000000..748d1687f2d --- /dev/null +++ b/test/e2e/pkg/grammar/abci_grammar.md @@ -0,0 +1,75 @@ +``` +package "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto" + +Start : CleanStart | Recovery; + +CleanStart : InitChain ConsensusExec | StateSync ConsensusExec ; +StateSync : StateSyncAttempts SuccessSync | SuccessSync ; +StateSyncAttempts : StateSyncAttempt | StateSyncAttempt StateSyncAttempts ; +StateSyncAttempt : OfferSnapshot ApplyChunks | OfferSnapshot ; +SuccessSync : OfferSnapshot ApplyChunks ; +ApplyChunks : ApplyChunk | ApplyChunk ApplyChunks ; + +Recovery : InitChain ConsensusExec | ConsensusExec ; + +ConsensusExec : ConsensusHeights ; +ConsensusHeights : ConsensusHeight | ConsensusHeight ConsensusHeights ; +ConsensusHeight : ConsensusRounds FinalizeBlock Commit | FinalizeBlock Commit ; +ConsensusRounds : ConsensusRound | ConsensusRound ConsensusRounds ; +ConsensusRound : Proposer | NonProposer ; + +Proposer : GotVotes | ProposerSimple | Extend | GotVotes ProposerSimple | GotVotes Extend | ProposerSimple Extend | GotVotes ProposerSimple Extend ; +ProposerSimple : PrepareProposal | PrepareProposal ProcessProposal ; +NonProposer: GotVotes | ProcessProposal | Extend | GotVotes ProcessProposal | GotVotes Extend | ProcessProposal Extend | GotVotes ProcessProposal Extend ; +Extend : ExtendVote | GotVotes ExtendVote | ExtendVote GotVotes | GotVotes ExtendVote GotVotes ; +GotVotes : GotVote | GotVote GotVotes ; + +InitChain : "init_chain" ; +FinalizeBlock : "finalize_block" ; +Commit : "commit" ; +OfferSnapshot : "offer_snapshot" ; +ApplyChunk : "apply_snapshot_chunk" ; +PrepareProposal : "prepare_proposal" ; +ProcessProposal : "process_proposal" ; +ExtendVote : "extend_vote" ; +GotVote : "verify_vote_extension" ; + +``` + +The original grammar (https://github.com/cometbft/cometbft/blob/main/spec/abci/abci%2B%2B_comet_expected_behavior.md) the grammar above +refers to is below: + +start = clean-start / recovery + +clean-start = ( app-handshake / state-sync ) consensus-exec +app-handshake = info init-chain +state-sync = *state-sync-attempt success-sync info +state-sync-attempt = offer-snapshot *apply-chunk +success-sync = offer-snapshot 1*apply-chunk + +recovery = info [init-chain] consensus-exec + +consensus-exec = (inf)consensus-height +consensus-height = *consensus-round finalize-block commit +consensus-round = proposer / non-proposer + +proposer = *got-vote [prepare-proposal [process-proposal]] [extend] +extend = *got-vote extend-vote *got-vote +non-proposer = *got-vote [process-proposal] [extend] + +init-chain = %s"" +offer-snapshot = %s"" +apply-chunk = %s"" +info = %s"" +prepare-proposal = %s"" +process-proposal = %s"" +extend-vote = %s"" +got-vote = %s"" +finalize-block = %s"" +commit = %s"" + +*Note* We ignore `Info` since it can be triggered by the e2e tests at unpredictable places because of its role in RPC handling from external clients. + + + + diff --git a/test/e2e/pkg/grammar/checker.go b/test/e2e/pkg/grammar/checker.go new file mode 100644 index 00000000000..3fd1a3cbf94 --- /dev/null +++ b/test/e2e/pkg/grammar/checker.go @@ -0,0 +1,210 @@ +package grammar + +import ( + "errors" + "fmt" + "os" + "strings" + + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/libs/log" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/lexer" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser/symbols" +) + +const Commit = "commit" + +// Checker is a checker that can verify whether a specific set of ABCI calls +// respects the ABCI grammar. +type Checker struct { + logger log.Logger + cfg *Config +} + +// Config allows for setting some parameters, mostly about error logging. +type Config struct { + // The number of errors checker outputs. + NumberOfErrorsToShow int +} + +// DefaultConfig returns a default config for GrammarChecker. +func DefaultConfig() *Config { + return &Config{ + NumberOfErrorsToShow: 1, + } +} + +// Error represents the error type checker returns. +type Error struct { + description string + // height maps 1-to-1 to the consensus height only in case of clean-start. If it is recovery, it corresponds to the height number after recovery: height 0 is + // first consensus height after recovery. + height int +} + +// String returns string representation of an error. +func (e *Error) String() string { + s := fmt.Sprintf("The error: %q has occurred at height %v.", e.description, e.height) + return s +} + +// NewGrammarChecker returns a grammar checker object. +func NewGrammarChecker(cfg *Config) *Checker { + return &Checker{ + cfg: cfg, + logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)), + } +} + +// isSupportedByGrammar returns true for all requests supported by the current grammar ("/pkg/grammar/clean-start/abci_grammar_clean_start.md" and "/pkg/grammar/recovery/abci_grammar_recovery.md"). +// This method needs to be modified if we add another ABCI call. +func (*Checker) isSupportedByGrammar(req *abci.Request) bool { + switch req.Value.(type) { + case *abci.Request_InitChain, *abci.Request_FinalizeBlock, *abci.Request_Commit, + *abci.Request_OfferSnapshot, *abci.Request_ApplySnapshotChunk, *abci.Request_PrepareProposal, + *abci.Request_ProcessProposal, *abci.Request_ExtendVote, *abci.Request_VerifyVoteExtension: + return true + default: + return false + } +} + +// filterRequests returns requests supported by grammar and remove the last height. +func (g *Checker) filterRequests(reqs []*abci.Request) []*abci.Request { + var r []*abci.Request + for _, req := range reqs { + if g.isSupportedByGrammar(req) { + r = append(r, req) + } + } + r, _ = g.filterLastHeight(r) + return r +} + +// filterLastHeight removes ABCI requests from the last height if "commit" has not been called +// and returns the tuple (remaining(non-filtered) requests, # of filtered requests). +func (g *Checker) filterLastHeight(reqs []*abci.Request) ([]*abci.Request, int) { + if len(reqs) == 0 { + return nil, 0 + } + pos := len(reqs) - 1 + cnt := 0 + // Find the last commit. + for pos >= 0 && g.getRequestTerminal(reqs[pos]) != Commit { + pos-- + cnt++ + } + return reqs[:pos+1], cnt +} + +// getRequestTerminal returns a value of a corresponding terminal in the ABCI grammar for a specific request. +func (*Checker) getRequestTerminal(req *abci.Request) string { + // req.String() produces an output like this "init_chain: >" + // we take just the part before the ":" (init_chain, in previous example) for each request + parts := strings.Split(req.String(), ":") + if len(parts) < 2 || len(parts[0]) == 0 { + panic(fmt.Errorf("abci.Request doesn't have the expected string format: %v", req.String())) + } + return parts[0] +} + +// getExecutionString returns a string of terminal symbols in parser readable format. +func (g *Checker) getExecutionString(reqs []*abci.Request) string { + s := "" + for _, r := range reqs { + t := g.getRequestTerminal(r) + // We ensure to have one height per line for readability. + if t == Commit { + s += t + "\n" + } else { + s += t + " " + } + } + return s +} + +// Verify verifies whether a list of request satisfy ABCI grammar. +func (g *Checker) Verify(reqs []*abci.Request, isCleanStart bool) (bool, error) { + if len(reqs) == 0 { + return false, errors.New("execution with no ABCI calls") + } + fullExecution := g.getExecutionString(reqs) + r := g.filterRequests(reqs) + // Check if the execution is incomplete. + if len(r) == 0 { + return true, nil + } + execution := g.getExecutionString(r) + errors := g.verify(execution, isCleanStart) + if errors == nil { + return true, nil + } + return false, fmt.Errorf("%v\nFull execution:\n%v", g.combineErrors(errors, g.cfg.NumberOfErrorsToShow), g.addHeightNumbersToTheExecution(fullExecution)) +} + +// verifyCleanStart verifies if a specific execution is a valid execution. +func (*Checker) verify(execution string, isCleanStart bool) []*Error { + errors := make([]*Error, 0) + lexer := lexer.New([]rune(execution)) + bsrForest, errs := parser.Parse(lexer) + for _, err := range errs { + exp := []string{} + for _, ex := range err.Expected { + exp = append(exp, ex) + } + expectedTokens := strings.Join(exp, ",") + unexpectedToken := err.Token.TypeID() + e := &Error{ + description: fmt.Sprintf("Invalid execution: parser was expecting one of [%v], got [%v] instead.", expectedTokens, unexpectedToken), + height: err.Line - 1, + } + errors = append(errors, e) + } + if len(errors) != 0 { + return errors + } + eType := symbols.NT_Recovery + if isCleanStart { + eType = symbols.NT_CleanStart + } + roots := bsrForest.GetRoots() + for _, r := range roots { + for _, s := range r.Label.Slot().Symbols { + if s == eType { + return nil + } + } + } + e := &Error{ + description: "The execution is not of valid type.", + height: 0, + } + errors = append(errors, e) + return errors +} + +// addHeightNumbersToTheExecution adds height numbers to the execution. This is used just when printing the execution so we can find the height with error more easily. +func (*Checker) addHeightNumbersToTheExecution(execution string) string { + heights := strings.Split(execution, "\n") + s := "" + for i, l := range heights { + if i == len(heights)-1 && l == "" { + break + } + s = fmt.Sprintf("%v%v: %v\n", s, i, l) + } + return s +} + +// combineErrors combines at most n errors in one. +func (*Checker) combineErrors(errors []*Error, n int) error { + s := "" + for i, e := range errors { + if i == n { + break + } + s += e.String() + "\n" + } + return fmt.Errorf("%v", s) +} diff --git a/test/e2e/pkg/grammar/checker_test.go b/test/e2e/pkg/grammar/checker_test.go new file mode 100644 index 00000000000..22b3725f206 --- /dev/null +++ b/test/e2e/pkg/grammar/checker_test.go @@ -0,0 +1,188 @@ +package grammar + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/cometbft/cometbft/abci/types" +) + +var ( + initChain = &abci.Request{Value: &abci.Request_InitChain{InitChain: &abci.InitChainRequest{}}} + finalizeBlock = &abci.Request{Value: &abci.Request_FinalizeBlock{FinalizeBlock: &abci.FinalizeBlockRequest{}}} + commit = &abci.Request{Value: &abci.Request_Commit{Commit: &abci.CommitRequest{}}} + offerSnapshot = &abci.Request{Value: &abci.Request_OfferSnapshot{OfferSnapshot: &abci.OfferSnapshotRequest{}}} + applyChunk = &abci.Request{Value: &abci.Request_ApplySnapshotChunk{ApplySnapshotChunk: &abci.ApplySnapshotChunkRequest{}}} + prepareProposal = &abci.Request{Value: &abci.Request_PrepareProposal{PrepareProposal: &abci.PrepareProposalRequest{}}} + processProposal = &abci.Request{Value: &abci.Request_ProcessProposal{ProcessProposal: &abci.ProcessProposalRequest{}}} + extendVote = &abci.Request{Value: &abci.Request_ExtendVote{ExtendVote: &abci.ExtendVoteRequest{}}} + gotVote = &abci.Request{Value: &abci.Request_VerifyVoteExtension{VerifyVoteExtension: &abci.VerifyVoteExtensionRequest{}}} +) + +const CleanStart = true + +type ABCIExecution struct { + abciCalls []*abci.Request + isValid bool +} + +// consensus-exec part of executions +// consensus-exec = (inf)consensus-height +// it is part of each executions. +var consExecPart = []ABCIExecution{ + // consensus-height = finalizeBlock commit + {[]*abci.Request{finalizeBlock, commit}, true}, + {[]*abci.Request{commit}, false}, + // consensus-height = *consensus-round finalizeBlock commit + // consensus-height = *consensus-round finalizeBlock commit + // consensus-round = proposer + // proposer = *gotVote + {[]*abci.Request{gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, finalizeBlock, commit}, true}, + // proposer = [prepare-proposal [process-proposal]] + {[]*abci.Request{prepareProposal, processProposal, finalizeBlock, commit}, true}, + {[]*abci.Request{prepareProposal, finalizeBlock, commit}, true}, + // proposer = [extend] + {[]*abci.Request{extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{extendVote, gotVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, extendVote, gotVote, gotVote, finalizeBlock, commit}, true}, + // proposer = *gotVote [prepare-proposal [process-proposal]] + {[]*abci.Request{gotVote, prepareProposal, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, prepareProposal, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, prepareProposal, processProposal, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, prepareProposal, processProposal, finalizeBlock, commit}, true}, + // proposer = *gotVote [extend] + // same as just [extend] + // proposer = [prepare-proposal [process-proposal]] [extend] + {[]*abci.Request{prepareProposal, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{prepareProposal, gotVote, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{prepareProposal, extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{prepareProposal, gotVote, extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{prepareProposal, processProposal, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{prepareProposal, processProposal, gotVote, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{prepareProposal, processProposal, extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{prepareProposal, processProposal, gotVote, extendVote, gotVote, finalizeBlock, commit}, true}, + // proposer = *gotVote [prepare-proposal [process-proposal]] [extend] + {[]*abci.Request{gotVote, prepareProposal, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, prepareProposal, gotVote, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, prepareProposal, extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, prepareProposal, gotVote, extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, prepareProposal, processProposal, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, prepareProposal, processProposal, gotVote, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, prepareProposal, processProposal, extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, prepareProposal, processProposal, gotVote, extendVote, gotVote, finalizeBlock, commit}, true}, + + // consensus-round = non-proposer + // non-proposer = *gotVote + // same as for proposer + + // non-proposer = [process-proposal] + {[]*abci.Request{processProposal, finalizeBlock, commit}, true}, + // non-proposer = [extend] + // same as for proposer + + // non-proposer = *gotVote [process-proposal] + {[]*abci.Request{gotVote, processProposal, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, processProposal, finalizeBlock, commit}, true}, + // non-proposer = *gotVote [extend] + // same as just [extend] + + // non-proposer = [process-proposal] [extend] + {[]*abci.Request{processProposal, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{processProposal, gotVote, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{processProposal, extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{processProposal, gotVote, extendVote, gotVote, finalizeBlock, commit}, true}, + + // non-proposer = *gotVote [prepare-proposal [process-proposal]] [extend] + {[]*abci.Request{gotVote, processProposal, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, processProposal, gotVote, extendVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, processProposal, extendVote, gotVote, finalizeBlock, commit}, true}, + {[]*abci.Request{gotVote, gotVote, processProposal, gotVote, extendVote, gotVote, finalizeBlock, commit}, true}, + + {[]*abci.Request{prepareProposal, processProposal, processProposal, prepareProposal, processProposal, processProposal, processProposal, finalizeBlock, commit}, true}, +} + +func TestVerifyCleanStart(t *testing.T) { + // Parts of executions specific for clean-start execution + specificCleanStartPart := []ABCIExecution{ + // start = clean-start + // clean-start = init-chain consensus-exec + {[]*abci.Request{initChain}, true}, + // clean-start = state-sync consensus-exec + // state-sync = success-sync + {[]*abci.Request{offerSnapshot, applyChunk}, true}, + {[]*abci.Request{offerSnapshot, applyChunk, applyChunk}, true}, + {[]*abci.Request{applyChunk}, false}, + {[]*abci.Request{offerSnapshot}, false}, + // state-sync = *state-sync-attempt success-sync + {[]*abci.Request{offerSnapshot, applyChunk, offerSnapshot, applyChunk}, true}, + {[]*abci.Request{offerSnapshot, applyChunk, applyChunk, applyChunk, offerSnapshot, applyChunk}, true}, + {[]*abci.Request{applyChunk, offerSnapshot, applyChunk}, false}, + {[]*abci.Request{offerSnapshot, offerSnapshot, applyChunk}, true}, + // extra invalid executions + {[]*abci.Request{initChain, offerSnapshot, applyChunk}, false}, + {[]*abci.Request{}, false}, + } + for i, part1 := range specificCleanStartPart { + for j, part2 := range consExecPart { + checker := NewGrammarChecker(DefaultConfig()) + execution := append(part1.abciCalls, part2.abciCalls...) + valid := part1.isValid && part2.isValid + result, err := checker.Verify(execution, CleanStart) + if result == valid { + continue + } + if err == nil { + err = fmt.Errorf("grammar parsed an incorrect execution: %v", checker.getExecutionString(execution)) + } + t.Errorf("Test %v:%v returned %v, expected %v\n%v\n", i, j, result, valid, err) + } + } +} + +func TestVerifyRecovery(t *testing.T) { + // Parts of executions specific for recovery execution + specificRecoveryPart := []ABCIExecution{ + // start = recovery + // recovery = init-chain consensus-exec + {[]*abci.Request{initChain}, true}, + // recovery = consensus-exec + {[]*abci.Request{}, true}, + } + for i, part1 := range specificRecoveryPart { + for j, part2 := range consExecPart { + checker := NewGrammarChecker(DefaultConfig()) + execution := append(part1.abciCalls, part2.abciCalls...) + valid := part1.isValid && part2.isValid + result, err := checker.Verify(execution, !CleanStart) + if result == valid { + continue + } + if err == nil { + err = fmt.Errorf("grammar parsed an incorrect execution: %v", checker.getExecutionString(execution)) + } + t.Errorf("Test %v:%v returned %v, expected %v\n%v\n", i, j, result, valid, err) + } + } +} + +func TestFilterLastHeight(t *testing.T) { + reqs := []*abci.Request{initChain, finalizeBlock} + checker := NewGrammarChecker(DefaultConfig()) + r, n := checker.filterLastHeight(reqs) + require.Equal(t, len(r), 0) + require.Equal(t, n, 2) + reqs = append(reqs, commit) + r, n = checker.filterLastHeight(reqs) + require.Equal(t, len(r), len(reqs)) + require.Zero(t, n) + reqs = append(reqs, []*abci.Request{prepareProposal, processProposal}...) + r, n = checker.filterLastHeight(reqs) + require.Equal(t, len(r), 3) + require.Equal(t, n, 2) +} diff --git a/test/e2e/pkg/grammar/grammar-auto/lexer/lexer.go b/test/e2e/pkg/grammar/grammar-auto/lexer/lexer.go new file mode 100644 index 00000000000..8015f118165 --- /dev/null +++ b/test/e2e/pkg/grammar/grammar-auto/lexer/lexer.go @@ -0,0 +1,1428 @@ +// Package lexer is generated by GoGLL. Do not edit. +package lexer + +import ( + // "fmt" + "io/ioutil" + "strings" + "unicode" + + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/token" +) + +type state int + +const nullState state = -1 + +// Unicode categories +var ( + _Cc = unicode.Cc // Cc is the set of Unicode characters in category Cc (Other, control). + _Cf = unicode.Cf // Cf is the set of Unicode characters in category Cf (Other, format). + _Co = unicode.Co // Co is the set of Unicode characters in category Co (Other, private use). + _Cs = unicode.Cs // Cs is the set of Unicode characters in category Cs (Other, surrogate). + _Digit = unicode.Digit // Digit is the set of Unicode characters with the "decimal digit" property. + _Nd = unicode.Nd // Nd is the set of Unicode characters in category Nd (Number, decimal digit). + _Letter = unicode.Letter // Letter/L is the set of Unicode letters, category L. + _L = unicode.L + _Lm = unicode.Lm // Lm is the set of Unicode characters in category Lm (Letter, modifier). + _Lo = unicode.Lo // Lo is the set of Unicode characters in category Lo (Letter, other). + _Lower = unicode.Lower // Lower is the set of Unicode lower case letters. + _Ll = unicode.Ll // Ll is the set of Unicode characters in category Ll (Letter, lowercase). + _Mark = unicode.Mark // Mark/M is the set of Unicode mark characters, category M. + _M = unicode.M + _Mc = unicode.Mc // Mc is the set of Unicode characters in category Mc (Mark, spacing combining). + _Me = unicode.Me // Me is the set of Unicode characters in category Me (Mark, enclosing). + _Mn = unicode.Mn // Mn is the set of Unicode characters in category Mn (Mark, nonspacing). + _Nl = unicode.Nl // Nl is the set of Unicode characters in category Nl (Number, letter). + _No = unicode.No // No is the set of Unicode characters in category No (Number, other). + _Number = unicode.Number // Number/N is the set of Unicode number characters, category N. + _N = unicode.N + _Other = unicode.Other // Other/C is the set of Unicode control and special characters, category C. + _C = unicode.C + _Pc = unicode.Pc // Pc is the set of Unicode characters in category Pc (Punctuation, connector). + _Pd = unicode.Pd // Pd is the set of Unicode characters in category Pd (Punctuation, dash). + _Pe = unicode.Pe // Pe is the set of Unicode characters in category Pe (Punctuation, close). + _Pf = unicode.Pf // Pf is the set of Unicode characters in category Pf (Punctuation, final quote). + _Pi = unicode.Pi // Pi is the set of Unicode characters in category Pi (Punctuation, initial quote). + _Po = unicode.Po // Po is the set of Unicode characters in category Po (Punctuation, other). + _Ps = unicode.Ps // Ps is the set of Unicode characters in category Ps (Punctuation, open). + _Punct = unicode.Punct // Punct/P is the set of Unicode punctuation characters, category P. + _P = unicode.P + _Sc = unicode.Sc // Sc is the set of Unicode characters in category Sc (Symbol, currency). + _Sk = unicode.Sk // Sk is the set of Unicode characters in category Sk (Symbol, modifier). + _Sm = unicode.Sm // Sm is the set of Unicode characters in category Sm (Symbol, math). + _So = unicode.So // So is the set of Unicode characters in category So (Symbol, other). + _Space = unicode.Space // Space/Z is the set of Unicode space characters, category Z. + _Z = unicode.Z + _Symbol = unicode.Symbol // Symbol/S is the set of Unicode symbol characters, category S. + _S = unicode.S + _Title = unicode.Title // Title is the set of Unicode title case letters. + _Lt = unicode.Lt // Lt is the set of Unicode characters in category Lt (Letter, titlecase). + _Upper = unicode.Upper // Upper is the set of Unicode upper case letters. + _Lu = unicode.Lu // Lu is the set of Unicode characters in category Lu (Letter, uppercase). + _Zl = unicode.Zl // Zl is the set of Unicode characters in category Zl (Separator, line). + _Zp = unicode.Zp // Zp is the set of Unicode characters in category Zp (Separator, paragraph). + _Zs = unicode.Zs // Zs is the set of Unicode characters in category Zs (Separator, space). +) + +// Unicode properties +var ( + _ASCII_Hex_Digit = unicode.ASCII_Hex_Digit // ASCII_Hex_Digit is the set of Unicode characters with property ASCII_Hex_Digit. + _Bidi_Control = unicode.Bidi_Control // Bidi_Control is the set of Unicode characters with property Bidi_Control. + _Dash = unicode.Dash // Dash is the set of Unicode characters with property Dash. + _Deprecated = unicode.Deprecated // Deprecated is the set of Unicode characters with property Deprecated. + _Diacritic = unicode.Diacritic // Diacritic is the set of Unicode characters with property Diacritic. + _Extender = unicode.Extender // Extender is the set of Unicode characters with property Extender. + _Hex_Digit = unicode.Hex_Digit // Hex_Digit is the set of Unicode characters with property Hex_Digit. + _Hyphen = unicode.Hyphen // Hyphen is the set of Unicode characters with property Hyphen. + _IDS_Binary_Operator = unicode.IDS_Binary_Operator // IDS_Binary_Operator is the set of Unicode characters with property IDS_Binary_Operator. + _IDS_Trinary_Operator = unicode.IDS_Trinary_Operator // IDS_Trinary_Operator is the set of Unicode characters with property IDS_Trinary_Operator. + _Ideographic = unicode.Ideographic // Ideographic is the set of Unicode characters with property Ideographic. + _Join_Control = unicode.Join_Control // Join_Control is the set of Unicode characters with property Join_Control. + _Logical_Order_Exception = unicode.Logical_Order_Exception // Logical_Order_Exception is the set of Unicode characters with property Logical_Order_Exception. + _Noncharacter_Code_Point = unicode.Noncharacter_Code_Point // Noncharacter_Code_Point is the set of Unicode characters with property Noncharacter_Code_Point. + _Other_Alphabetic = unicode.Other_Alphabetic // Other_Alphabetic is the set of Unicode characters with property Other_Alphabetic. + _Other_Default_Ignorable_Code_Point = unicode.Other_Default_Ignorable_Code_Point // Other_Default_Ignorable_Code_Point is the set of Unicode characters with property Other_Default_Ignorable_Code_Point. + _Other_Grapheme_Extend = unicode.Other_Grapheme_Extend // Other_Grapheme_Extend is the set of Unicode characters with property Other_Grapheme_Extend. + _Other_ID_Continue = unicode.Other_ID_Continue // Other_ID_Continue is the set of Unicode characters with property Other_ID_Continue. + _Other_ID_Start = unicode.Other_ID_Start // Other_ID_Start is the set of Unicode characters with property Other_ID_Start. + _Other_Lowercase = unicode.Other_Lowercase // Other_Lowercase is the set of Unicode characters with property Other_Lowercase. + _Other_Math = unicode.Other_Math // Other_Math is the set of Unicode characters with property Other_Math. + _Other_Uppercase = unicode.Other_Uppercase // Other_Uppercase is the set of Unicode characters with property Other_Uppercase. + _Pattern_Syntax = unicode.Pattern_Syntax // Pattern_Syntax is the set of Unicode characters with property Pattern_Syntax. + _Pattern_White_Space = unicode.Pattern_White_Space // Pattern_White_Space is the set of Unicode characters with property Pattern_White_Space. + _Prepended_Concatenation_Mark = unicode.Prepended_Concatenation_Mark // Prepended_Concatenation_Mark is the set of Unicode characters with property Prepended_Concatenation_Mark. + _Quotation_Mark = unicode.Quotation_Mark // Quotation_Mark is the set of Unicode characters with property Quotation_Mark. + _Radical = unicode.Radical // Radical is the set of Unicode characters with property Radical. + _Regional_Indicator = unicode.Regional_Indicator // Regional_Indicator is the set of Unicode characters with property Regional_Indicator. + _STerm = unicode.STerm // STerm is an alias for Sentence_Terminal. + _Sentence_Terminal = unicode.Sentence_Terminal // Sentence_Terminal is the set of Unicode characters with property Sentence_Terminal. + _Soft_Dotted = unicode.Soft_Dotted // Soft_Dotted is the set of Unicode characters with property Soft_Dotted. + _Terminal_Punctuation = unicode.Terminal_Punctuation // Terminal_Punctuation is the set of Unicode characters with property Terminal_Punctuation. + _Unified_Ideograph = unicode.Unified_Ideograph // Unified_Ideograph is the set of Unicode characters with property Unified_Ideograph. + _Variation_Selector = unicode.Variation_Selector // Variation_Selector is the set of Unicode characters with property Variation_Selector. + _White_Space = unicode.White_Space // White_Space is the set of Unicode characters with property White_Space. +) + +// Lexer contains both the input slice of runes and the slice of tokens +// parsed from the input +type Lexer struct { + // I is the input slice of runes + I []rune + + // Tokens is the slice of tokens constructed by the lexer from I + Tokens []*token.Token +} + +/* +NewFile constructs a Lexer created from the input file, fname. + +If the input file is a markdown file NewFile process treats all text outside +code blocks as whitespace. All text inside code blocks are treated as input text. + +If the input file is a normal text file NewFile treats all text in the inputfile +as input text. +*/ +func NewFile(fname string) *Lexer { + buf, err := ioutil.ReadFile(fname) + if err != nil { + panic(err) + } + input := []rune(string(buf)) + if strings.HasSuffix(fname, ".md") { + loadMd(input) + } + return New(input) +} + +func loadMd(input []rune) { + i := 0 + text := true + for i < len(input) { + if i <= len(input)-3 && input[i] == '`' && input[i+1] == '`' && input[i+2] == '`' { + text = !text + for j := 0; j < 3; j++ { + input[i+j] = ' ' + } + i += 3 + } + if i < len(input) { + if text { + if input[i] == '\n' { + input[i] = '\n' + } else { + input[i] = ' ' + } + } + i += 1 + } + } +} + +/* +New constructs a Lexer from a slice of runes. + +All contents of the input slice are treated as input text. +*/ +func New(input []rune) *Lexer { + lex := &Lexer{ + I: input, + Tokens: make([]*token.Token, 0, 2048), + } + lext := 0 + for lext < len(lex.I) { + for lext < len(lex.I) && unicode.IsSpace(lex.I[lext]) { + lext++ + } + if lext < len(lex.I) { + tok := lex.scan(lext) + lext = tok.Rext() + if !tok.Suppress() { + lex.addToken(tok) + } + } + } + lex.add(token.EOF, len(input), len(input)) + return lex +} + +func (l *Lexer) scan(i int) *token.Token { + // fmt.Printf("lexer.scan(%d)\n", i) + s, typ, rext := nullState, token.Error, i+1 + if i < len(l.I) { + // fmt.Printf(" rext %d, i %d\n", rext, i) + s = nextState[0](l.I[i]) + } + for s != nullState { + if rext >= len(l.I) { + typ = accept[s] + s = nullState + } else { + typ = accept[s] + s = nextState[s](l.I[rext]) + if s != nullState || typ == token.Error { + rext++ + } + } + } + tok := token.New(typ, i, rext, l.I) + // fmt.Printf(" %s\n", tok) + return tok +} + +func escape(r rune) string { + switch r { + case '"': + return "\"" + case '\\': + return "\\\\" + case '\r': + return "\\r" + case '\n': + return "\\n" + case '\t': + return "\\t" + } + return string(r) +} + +// GetLineColumn returns the line and column of rune[i] in the input +func (l *Lexer) GetLineColumn(i int) (line, col int) { + line, col = 1, 1 + for j := 0; j < i; j++ { + switch l.I[j] { + case '\n': + line++ + col = 1 + case '\t': + col += 4 + default: + col++ + } + } + return +} + +// GetLineColumnOfToken returns the line and column of token[i] in the imput +func (l *Lexer) GetLineColumnOfToken(i int) (line, col int) { + return l.GetLineColumn(l.Tokens[i].Lext()) +} + +// GetString returns the input string from the left extent of Token[lext] to +// the right extent of Token[rext] +func (l *Lexer) GetString(lext, rext int) string { + return string(l.I[l.Tokens[lext].Lext():l.Tokens[rext].Rext()]) +} + +func (l *Lexer) add(t token.Type, lext, rext int) { + l.addToken(token.New(t, lext, rext, l.I)) +} + +func (l *Lexer) addToken(tok *token.Token) { + l.Tokens = append(l.Tokens, tok) +} + +func any(r rune, set []rune) bool { + for _, r1 := range set { + if r == r1 { + return true + } + } + return false +} + +func not(r rune, set []rune) bool { + for _, r1 := range set { + if r == r1 { + return false + } + } + return true +} + +var accept = []token.Type{ + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.T_1, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.T_4, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.T_2, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.T_3, + token.T_5, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.T_6, + token.T_7, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.Error, + token.T_0, + token.Error, + token.T_8, +} + +var nextState = []func(r rune) state{ + // Set0 + func(r rune) state { + switch { + case r == 'a': + return 1 + case r == 'c': + return 2 + case r == 'e': + return 3 + case r == 'f': + return 4 + case r == 'i': + return 5 + case r == 'o': + return 6 + case r == 'p': + return 7 + case r == 'v': + return 8 + } + return nullState + }, + // Set1 + func(r rune) state { + switch { + case r == 'p': + return 9 + } + return nullState + }, + // Set2 + func(r rune) state { + switch { + case r == 'o': + return 10 + } + return nullState + }, + // Set3 + func(r rune) state { + switch { + case r == 'x': + return 11 + } + return nullState + }, + // Set4 + func(r rune) state { + switch { + case r == 'i': + return 12 + } + return nullState + }, + // Set5 + func(r rune) state { + switch { + case r == 'n': + return 13 + } + return nullState + }, + // Set6 + func(r rune) state { + switch { + case r == 'f': + return 14 + } + return nullState + }, + // Set7 + func(r rune) state { + switch { + case r == 'r': + return 15 + } + return nullState + }, + // Set8 + func(r rune) state { + switch { + case r == 'e': + return 16 + } + return nullState + }, + // Set9 + func(r rune) state { + switch { + case r == 'p': + return 17 + } + return nullState + }, + // Set10 + func(r rune) state { + switch { + case r == 'm': + return 18 + } + return nullState + }, + // Set11 + func(r rune) state { + switch { + case r == 't': + return 19 + } + return nullState + }, + // Set12 + func(r rune) state { + switch { + case r == 'n': + return 20 + } + return nullState + }, + // Set13 + func(r rune) state { + switch { + case r == 'i': + return 21 + } + return nullState + }, + // Set14 + func(r rune) state { + switch { + case r == 'f': + return 22 + } + return nullState + }, + // Set15 + func(r rune) state { + switch { + case r == 'e': + return 23 + case r == 'o': + return 24 + } + return nullState + }, + // Set16 + func(r rune) state { + switch { + case r == 'r': + return 25 + } + return nullState + }, + // Set17 + func(r rune) state { + switch { + case r == 'l': + return 26 + } + return nullState + }, + // Set18 + func(r rune) state { + switch { + case r == 'm': + return 27 + } + return nullState + }, + // Set19 + func(r rune) state { + switch { + case r == 'e': + return 28 + } + return nullState + }, + // Set20 + func(r rune) state { + switch { + case r == 'a': + return 29 + } + return nullState + }, + // Set21 + func(r rune) state { + switch { + case r == 't': + return 30 + } + return nullState + }, + // Set22 + func(r rune) state { + switch { + case r == 'e': + return 31 + } + return nullState + }, + // Set23 + func(r rune) state { + switch { + case r == 'p': + return 32 + } + return nullState + }, + // Set24 + func(r rune) state { + switch { + case r == 'c': + return 33 + } + return nullState + }, + // Set25 + func(r rune) state { + switch { + case r == 'i': + return 34 + } + return nullState + }, + // Set26 + func(r rune) state { + switch { + case r == 'y': + return 35 + } + return nullState + }, + // Set27 + func(r rune) state { + switch { + case r == 'i': + return 36 + } + return nullState + }, + // Set28 + func(r rune) state { + switch { + case r == 'n': + return 37 + } + return nullState + }, + // Set29 + func(r rune) state { + switch { + case r == 'l': + return 38 + } + return nullState + }, + // Set30 + func(r rune) state { + switch { + case r == '_': + return 39 + } + return nullState + }, + // Set31 + func(r rune) state { + switch { + case r == 'r': + return 40 + } + return nullState + }, + // Set32 + func(r rune) state { + switch { + case r == 'a': + return 41 + } + return nullState + }, + // Set33 + func(r rune) state { + switch { + case r == 'e': + return 42 + } + return nullState + }, + // Set34 + func(r rune) state { + switch { + case r == 'f': + return 43 + } + return nullState + }, + // Set35 + func(r rune) state { + switch { + case r == '_': + return 44 + } + return nullState + }, + // Set36 + func(r rune) state { + switch { + case r == 't': + return 45 + } + return nullState + }, + // Set37 + func(r rune) state { + switch { + case r == 'd': + return 46 + } + return nullState + }, + // Set38 + func(r rune) state { + switch { + case r == 'i': + return 47 + } + return nullState + }, + // Set39 + func(r rune) state { + switch { + case r == 'c': + return 48 + } + return nullState + }, + // Set40 + func(r rune) state { + switch { + case r == '_': + return 49 + } + return nullState + }, + // Set41 + func(r rune) state { + switch { + case r == 'r': + return 50 + } + return nullState + }, + // Set42 + func(r rune) state { + switch { + case r == 's': + return 51 + } + return nullState + }, + // Set43 + func(r rune) state { + switch { + case r == 'y': + return 52 + } + return nullState + }, + // Set44 + func(r rune) state { + switch { + case r == 's': + return 53 + } + return nullState + }, + // Set45 + func(r rune) state { + switch { + } + return nullState + }, + // Set46 + func(r rune) state { + switch { + case r == '_': + return 54 + } + return nullState + }, + // Set47 + func(r rune) state { + switch { + case r == 'z': + return 55 + } + return nullState + }, + // Set48 + func(r rune) state { + switch { + case r == 'h': + return 56 + } + return nullState + }, + // Set49 + func(r rune) state { + switch { + case r == 's': + return 57 + } + return nullState + }, + // Set50 + func(r rune) state { + switch { + case r == 'e': + return 58 + } + return nullState + }, + // Set51 + func(r rune) state { + switch { + case r == 's': + return 59 + } + return nullState + }, + // Set52 + func(r rune) state { + switch { + case r == '_': + return 60 + } + return nullState + }, + // Set53 + func(r rune) state { + switch { + case r == 'n': + return 61 + } + return nullState + }, + // Set54 + func(r rune) state { + switch { + case r == 'v': + return 62 + } + return nullState + }, + // Set55 + func(r rune) state { + switch { + case r == 'e': + return 63 + } + return nullState + }, + // Set56 + func(r rune) state { + switch { + case r == 'a': + return 64 + } + return nullState + }, + // Set57 + func(r rune) state { + switch { + case r == 'n': + return 65 + } + return nullState + }, + // Set58 + func(r rune) state { + switch { + case r == '_': + return 66 + } + return nullState + }, + // Set59 + func(r rune) state { + switch { + case r == '_': + return 67 + } + return nullState + }, + // Set60 + func(r rune) state { + switch { + case r == 'v': + return 68 + } + return nullState + }, + // Set61 + func(r rune) state { + switch { + case r == 'a': + return 69 + } + return nullState + }, + // Set62 + func(r rune) state { + switch { + case r == 'o': + return 70 + } + return nullState + }, + // Set63 + func(r rune) state { + switch { + case r == '_': + return 71 + } + return nullState + }, + // Set64 + func(r rune) state { + switch { + case r == 'i': + return 72 + } + return nullState + }, + // Set65 + func(r rune) state { + switch { + case r == 'a': + return 73 + } + return nullState + }, + // Set66 + func(r rune) state { + switch { + case r == 'p': + return 74 + } + return nullState + }, + // Set67 + func(r rune) state { + switch { + case r == 'p': + return 75 + } + return nullState + }, + // Set68 + func(r rune) state { + switch { + case r == 'o': + return 76 + } + return nullState + }, + // Set69 + func(r rune) state { + switch { + case r == 'p': + return 77 + } + return nullState + }, + // Set70 + func(r rune) state { + switch { + case r == 't': + return 78 + } + return nullState + }, + // Set71 + func(r rune) state { + switch { + case r == 'b': + return 79 + } + return nullState + }, + // Set72 + func(r rune) state { + switch { + case r == 'n': + return 80 + } + return nullState + }, + // Set73 + func(r rune) state { + switch { + case r == 'p': + return 81 + } + return nullState + }, + // Set74 + func(r rune) state { + switch { + case r == 'r': + return 82 + } + return nullState + }, + // Set75 + func(r rune) state { + switch { + case r == 'r': + return 83 + } + return nullState + }, + // Set76 + func(r rune) state { + switch { + case r == 't': + return 84 + } + return nullState + }, + // Set77 + func(r rune) state { + switch { + case r == 's': + return 85 + } + return nullState + }, + // Set78 + func(r rune) state { + switch { + case r == 'e': + return 86 + } + return nullState + }, + // Set79 + func(r rune) state { + switch { + case r == 'l': + return 87 + } + return nullState + }, + // Set80 + func(r rune) state { + switch { + } + return nullState + }, + // Set81 + func(r rune) state { + switch { + case r == 's': + return 88 + } + return nullState + }, + // Set82 + func(r rune) state { + switch { + case r == 'o': + return 89 + } + return nullState + }, + // Set83 + func(r rune) state { + switch { + case r == 'o': + return 90 + } + return nullState + }, + // Set84 + func(r rune) state { + switch { + case r == 'e': + return 91 + } + return nullState + }, + // Set85 + func(r rune) state { + switch { + case r == 'h': + return 92 + } + return nullState + }, + // Set86 + func(r rune) state { + switch { + } + return nullState + }, + // Set87 + func(r rune) state { + switch { + case r == 'o': + return 93 + } + return nullState + }, + // Set88 + func(r rune) state { + switch { + case r == 'h': + return 94 + } + return nullState + }, + // Set89 + func(r rune) state { + switch { + case r == 'p': + return 95 + } + return nullState + }, + // Set90 + func(r rune) state { + switch { + case r == 'p': + return 96 + } + return nullState + }, + // Set91 + func(r rune) state { + switch { + case r == '_': + return 97 + } + return nullState + }, + // Set92 + func(r rune) state { + switch { + case r == 'o': + return 98 + } + return nullState + }, + // Set93 + func(r rune) state { + switch { + case r == 'c': + return 99 + } + return nullState + }, + // Set94 + func(r rune) state { + switch { + case r == 'o': + return 100 + } + return nullState + }, + // Set95 + func(r rune) state { + switch { + case r == 'o': + return 101 + } + return nullState + }, + // Set96 + func(r rune) state { + switch { + case r == 'o': + return 102 + } + return nullState + }, + // Set97 + func(r rune) state { + switch { + case r == 'e': + return 103 + } + return nullState + }, + // Set98 + func(r rune) state { + switch { + case r == 't': + return 104 + } + return nullState + }, + // Set99 + func(r rune) state { + switch { + case r == 'k': + return 105 + } + return nullState + }, + // Set100 + func(r rune) state { + switch { + case r == 't': + return 106 + } + return nullState + }, + // Set101 + func(r rune) state { + switch { + case r == 's': + return 107 + } + return nullState + }, + // Set102 + func(r rune) state { + switch { + case r == 's': + return 108 + } + return nullState + }, + // Set103 + func(r rune) state { + switch { + case r == 'x': + return 109 + } + return nullState + }, + // Set104 + func(r rune) state { + switch { + case r == '_': + return 110 + } + return nullState + }, + // Set105 + func(r rune) state { + switch { + } + return nullState + }, + // Set106 + func(r rune) state { + switch { + } + return nullState + }, + // Set107 + func(r rune) state { + switch { + case r == 'a': + return 111 + } + return nullState + }, + // Set108 + func(r rune) state { + switch { + case r == 'a': + return 112 + } + return nullState + }, + // Set109 + func(r rune) state { + switch { + case r == 't': + return 113 + } + return nullState + }, + // Set110 + func(r rune) state { + switch { + case r == 'c': + return 114 + } + return nullState + }, + // Set111 + func(r rune) state { + switch { + case r == 'l': + return 115 + } + return nullState + }, + // Set112 + func(r rune) state { + switch { + case r == 'l': + return 116 + } + return nullState + }, + // Set113 + func(r rune) state { + switch { + case r == 'e': + return 117 + } + return nullState + }, + // Set114 + func(r rune) state { + switch { + case r == 'h': + return 118 + } + return nullState + }, + // Set115 + func(r rune) state { + switch { + } + return nullState + }, + // Set116 + func(r rune) state { + switch { + } + return nullState + }, + // Set117 + func(r rune) state { + switch { + case r == 'n': + return 119 + } + return nullState + }, + // Set118 + func(r rune) state { + switch { + case r == 'u': + return 120 + } + return nullState + }, + // Set119 + func(r rune) state { + switch { + case r == 's': + return 121 + } + return nullState + }, + // Set120 + func(r rune) state { + switch { + case r == 'n': + return 122 + } + return nullState + }, + // Set121 + func(r rune) state { + switch { + case r == 'i': + return 123 + } + return nullState + }, + // Set122 + func(r rune) state { + switch { + case r == 'k': + return 124 + } + return nullState + }, + // Set123 + func(r rune) state { + switch { + case r == 'o': + return 125 + } + return nullState + }, + // Set124 + func(r rune) state { + switch { + } + return nullState + }, + // Set125 + func(r rune) state { + switch { + case r == 'n': + return 126 + } + return nullState + }, + // Set126 + func(r rune) state { + switch { + } + return nullState + }, +} diff --git a/test/e2e/pkg/grammar/grammar-auto/parser/bsr/bsr.go b/test/e2e/pkg/grammar/grammar-auto/parser/bsr/bsr.go new file mode 100644 index 00000000000..e262b41338c --- /dev/null +++ b/test/e2e/pkg/grammar/grammar-auto/parser/bsr/bsr.go @@ -0,0 +1,685 @@ +// Package bsr is generated by gogll. Do not edit. + +/* +Package bsr implements a Binary Subtree Representation set as defined in + + Scott et al + Derivation representation using binary subtree sets, + Science of Computer Programming 175 (2019) +*/ +package bsr + +import ( + "bytes" + "fmt" + "sort" + "strings" + + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/lexer" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser/slot" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser/symbols" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/sppf" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/token" +) + +type bsr interface { + LeftExtent() int + RightExtent() int + Pivot() int +} + +/* +Set contains the set of Binary Subtree Representations (BSR). +*/ +type Set struct { + slotEntries map[BSR]bool + ntSlotEntries map[ntSlot][]BSR + stringEntries map[stringKey]*stringBSR + rightExtent int + lex *lexer.Lexer + + startSym symbols.NT +} + +type ntSlot struct { + nt symbols.NT + leftExtent int + rightExtent int +} + +// BSR is the binary subtree representation of a parsed nonterminal +type BSR struct { + Label slot.Label + leftExtent int + pivot int + rightExtent int + set *Set +} + +type BSRs []BSR + +type stringBSR struct { + Symbols symbols.Symbols + leftExtent int + pivot int + rightExtent int + set *Set +} + +type stringBSRs []*stringBSR + +type stringKey string + +// New returns a new initialised BSR Set +func New(startSymbol symbols.NT, l *lexer.Lexer) *Set { + return &Set{ + slotEntries: make(map[BSR]bool), + ntSlotEntries: make(map[ntSlot][]BSR), + stringEntries: make(map[stringKey]*stringBSR), + rightExtent: 0, + lex: l, + startSym: startSymbol, + } +} + +/* +Add a bsr to the set. (i,j) is the extent. k is the pivot. +*/ +func (s *Set) Add(l slot.Label, i, k, j int) { + // fmt.Printf("bsr.Add(%s,%d,%d,%d l.Pos %d)\n", l, i, k, j, l.Pos()) + if l.EoR() { + s.insert(BSR{l, i, k, j, s}) + } else { + if l.Pos() > 1 { + s.insert(&stringBSR{l.Symbols()[:l.Pos()], i, k, j, s}) + } + } +} + +// AddEmpty adds a grammar slot: X : ϵ• +func (s *Set) AddEmpty(l slot.Label, i int) { + s.insert(BSR{l, i, i, i, s}) +} + +/* +Contain returns true iff the BSR Set contains the NT symbol with left and +right extent. +*/ +func (s *Set) Contain(nt symbols.NT, left, right int) bool { + // fmt.Printf("bsr.Contain(%s,%d,%d)\n",nt,left,right) + for e := range s.slotEntries { + // fmt.Printf(" (%s,%d,%d)\n",e.Label.Head(),e.leftExtent,e.rightExtent) + if e.Label.Head() == nt && e.leftExtent == left && e.rightExtent == right { + // fmt.Println(" true") + return true + } + } + // fmt.Println(" false") + return false +} + +// Dump prints all the NT and string elements of the BSR set +func (s *Set) Dump() { + fmt.Println("Roots:") + for _, rt := range s.GetRoots() { + fmt.Println(rt) + } + fmt.Println() + + fmt.Println("NT BSRs:") + for _, bsr := range s.getNTBSRs() { + fmt.Println(bsr) + } + fmt.Println() + + fmt.Println("string BSRs:") + for _, bsr := range s.getStringBSRs() { + fmt.Println(bsr) + } + fmt.Println() +} + +// GetAll returns all BSR grammar slot entries +func (s *Set) GetAll() (bsrs []BSR) { + for b := range s.slotEntries { + bsrs = append(bsrs, b) + } + return +} + +// GetRightExtent returns the right extent of the BSR set +func (s *Set) GetRightExtent() int { + return s.rightExtent +} + +// GetRoot returns the root of the parse tree of an unambiguous parse. +// GetRoot fails if the parse was ambiguous. Use GetRoots() for ambiguous parses. +func (s *Set) GetRoot() BSR { + rts := s.GetRoots() + if len(rts) != 1 { + failf("%d parse trees exist for start symbol %s", len(rts), s.startSym) + } + return rts[0] +} + +// GetRoots returns all the roots of parse trees of the start symbol of the grammar. +func (s *Set) GetRoots() (roots []BSR) { + for b := range s.slotEntries { + if b.Label.Head() == s.startSym && b.leftExtent == 0 && s.rightExtent == b.rightExtent { + roots = append(roots, b) + } + } + return +} + +// GetAllStrings returns all string elements with symbols = str, +// left extent = lext and right extent = rext +func (s *Set) GetAllStrings(str symbols.Symbols, lext, rext int) (strs []*stringBSR) { + for _, s := range s.stringEntries { + if s.Symbols.Equal(str) && s.leftExtent == lext && s.rightExtent == rext { + strs = append(strs, s) + } + } + return +} + +func (s *Set) getNTBSRs() BSRs { + bsrs := make(BSRs, 0, len(s.ntSlotEntries)) + for _, bsrl := range s.ntSlotEntries { + for _, bsr := range bsrl { + bsrs = append(bsrs, bsr) + } + } + sort.Sort(bsrs) + return bsrs +} + +func (s *Set) getStringBSRs() stringBSRs { + bsrs := make(stringBSRs, 0, len(s.stringEntries)) + for _, bsr := range s.stringEntries { + bsrs = append(bsrs, bsr) + } + sort.Sort(bsrs) + return bsrs +} + +func (s *Set) getString(symbols symbols.Symbols, leftExtent, rightExtent int) *stringBSR { + // fmt.Printf("Set.getString(%s,%d,%d)\n", symbols, leftExtent, rightExtent) + + strBsr, exist := s.stringEntries[getStringKey(symbols, leftExtent, rightExtent)] + if exist { + return strBsr + } + + panic(fmt.Sprintf("Error: no string %s left extent=%d right extent=%d\n", + symbols, leftExtent, rightExtent)) +} + +func (s *Set) insert(bsr bsr) { + if bsr.RightExtent() > s.rightExtent { + s.rightExtent = bsr.RightExtent() + } + switch b := bsr.(type) { + case BSR: + s.slotEntries[b] = true + nt := ntSlot{b.Label.Head(), b.leftExtent, b.rightExtent} + s.ntSlotEntries[nt] = append(s.ntSlotEntries[nt], b) + case *stringBSR: + s.stringEntries[b.key()] = b + default: + panic(fmt.Sprintf("Invalid type %T", bsr)) + } +} + +func (s *stringBSR) key() stringKey { + return getStringKey(s.Symbols, s.leftExtent, s.rightExtent) +} + +func getStringKey(symbols symbols.Symbols, lext, rext int) stringKey { + return stringKey(fmt.Sprintf("%s,%d,%d", symbols, lext, rext)) +} + +// Alternate returns the index of the grammar rule alternate. +func (b BSR) Alternate() int { + return b.Label.Alternate() +} + +// GetAllNTChildren returns all the NT Children of b. If an NT child of b has +// ambiguous parses then all parses of that child are returned. +func (b BSR) GetAllNTChildren() [][]BSR { + children := [][]BSR{} + for i, s := range b.Label.Symbols() { + if s.IsNonTerminal() { + sChildren := b.GetNTChildrenI(i) + children = append(children, sChildren) + } + } + return children +} + +// GetNTChild returns the BSR of occurrence i of nt in s. +// GetNTChild fails if s has ambiguous subtrees of occurrence i of nt. +func (b BSR) GetNTChild(nt symbols.NT, i int) BSR { + bsrs := b.GetNTChildren(nt, i) + if len(bsrs) != 1 { + ambiguousSlots := []string{} + for _, c := range bsrs { + ambiguousSlots = append(ambiguousSlots, c.String()) + } + b.set.fail(b, "%s is ambiguous in %s\n %s", nt, b, strings.Join(ambiguousSlots, "\n ")) + } + return bsrs[0] +} + +// GetNTChildI returns the BSR of NT symbol[i] in the BSR set. +// GetNTChildI fails if the BSR set has ambiguous subtrees of NT i. +func (b BSR) GetNTChildI(i int) BSR { + bsrs := b.GetNTChildrenI(i) + if len(bsrs) != 1 { + b.set.fail(b, "NT %d is ambiguous in %s", i, b) + } + return bsrs[0] +} + +// GetNTChildren returns all the BSRs of occurrence i of nt in s +func (b BSR) GetNTChildren(nt symbols.NT, i int) []BSR { + // fmt.Printf("GetNTChild(%s,%d) %s\n", nt, i, b) + positions := []int{} + for j, s := range b.Label.Symbols() { + if s == nt { + positions = append(positions, j) + } + } + if len(positions) == 0 { + b.set.fail(b, "Error: %s has no NT %s", b, nt) + } + return b.GetNTChildrenI(positions[i]) +} + +// GetNTChildrenI returns all the BSRs of NT symbol[i] in s +func (b BSR) GetNTChildrenI(i int) []BSR { + // fmt.Printf("bsr.GetNTChildI(%d) %s Pos %d\n", i, b, b.Label.Pos()) + + if i >= len(b.Label.Symbols()) { + b.set.fail(b, "Error: cannot get NT child %d of %s", i, b) + } + if len(b.Label.Symbols()) == 1 { + return b.set.getNTSlot(b.Label.Symbols()[i], b.pivot, b.rightExtent) + } + if len(b.Label.Symbols()) == 2 { + if i == 0 { + return b.set.getNTSlot(b.Label.Symbols()[i], b.leftExtent, b.pivot) + } + return b.set.getNTSlot(b.Label.Symbols()[i], b.pivot, b.rightExtent) + } + if b.Label.Pos() == i+1 { + return b.set.getNTSlot(b.Label.Symbols()[i], b.pivot, b.rightExtent) + } + + // Walk to pos i from the right + symbols := b.Label.Symbols()[:b.Label.Pos()-1] + str := b.set.getString(symbols, b.leftExtent, b.pivot) + for len(symbols) > i+1 && len(symbols) > 2 { + symbols = symbols[:len(symbols)-1] + str = b.set.getString(symbols, str.leftExtent, str.pivot) + } + + bsrs := []BSR{} + if i == 0 { + bsrs = b.set.getNTSlot(b.Label.Symbols()[i], str.leftExtent, str.pivot) + } else { + bsrs = b.set.getNTSlot(b.Label.Symbols()[i], str.pivot, str.rightExtent) + } + + // fmt.Println(bsrs) + + return bsrs +} + +// GetTChildI returns the terminal symbol at position i in b. +// GetTChildI panics if symbol i is not a valid terminal +func (b BSR) GetTChildI(i int) *token.Token { + symbols := b.Label.Symbols() + + if i >= len(symbols) { + panic(fmt.Sprintf("%s has no T child %d", b, i)) + } + if symbols[i].IsNonTerminal() { + panic(fmt.Sprintf("symbol %d in %s is an NT", i, b)) + } + + lext := b.leftExtent + for j := 0; j < i; j++ { + if symbols[j].IsNonTerminal() { + nt := b.GetNTChildI(j) + lext += nt.rightExtent - nt.leftExtent + } else { + lext++ + } + } + return b.set.lex.Tokens[lext] +} + +// LeftExtent returns the left extent of the BSR in the stream of tokens +func (b BSR) LeftExtent() int { + return b.leftExtent +} + +// RightExtent returns the right extent of the BSR in the stream of tokens +func (b BSR) RightExtent() int { + return b.rightExtent +} + +// Pivot returns the pivot of the BSR +func (b BSR) Pivot() int { + return b.pivot +} + +func (b BSR) String() string { + srcStr := "ℇ" + if b.leftExtent < b.rightExtent { + srcStr = b.set.lex.GetString(b.LeftExtent(), b.RightExtent()-1) + } + return fmt.Sprintf("%s,%d,%d,%d - %s", + b.Label, b.leftExtent, b.pivot, b.rightExtent, srcStr) +} + +// BSRs Sort interface +func (bs BSRs) Len() int { + return len(bs) +} + +func (bs BSRs) Less(i, j int) bool { + if bs[i].Label < bs[j].Label { + return true + } + if bs[i].Label > bs[j].Label { + return false + } + if bs[i].leftExtent < bs[j].leftExtent { + return true + } + if bs[i].leftExtent > bs[j].leftExtent { + return false + } + return bs[i].rightExtent < bs[j].rightExtent +} + +func (bs BSRs) Swap(i, j int) { + bs[i], bs[j] = bs[j], bs[i] +} + +// stringBSRs Sort interface +func (sbs stringBSRs) Len() int { + return len(sbs) +} + +func (sbs stringBSRs) Less(i, j int) bool { + if sbs[i].Symbols.String() < sbs[j].Symbols.String() { + return true + } + if sbs[i].Symbols.String() > sbs[j].Symbols.String() { + return false + } + if sbs[i].leftExtent < sbs[j].leftExtent { + return true + } + if sbs[i].leftExtent > sbs[j].leftExtent { + return false + } + return sbs[i].rightExtent < sbs[j].rightExtent +} + +func (sbs stringBSRs) Swap(i, j int) { + sbs[i], sbs[j] = sbs[j], sbs[i] +} + +func (s stringBSR) LeftExtent() int { + return s.leftExtent +} + +func (s stringBSR) RightExtent() int { + return s.rightExtent +} + +func (s stringBSR) Pivot() int { + return s.pivot +} + +func (s stringBSR) Empty() bool { + return s.leftExtent == s.pivot && s.pivot == s.rightExtent +} + +// String returns a string representation of s +func (s stringBSR) String() string { + return fmt.Sprintf("%s,%d,%d,%d - %s", &s.Symbols, s.leftExtent, s.pivot, + s.rightExtent, s.set.lex.GetString(s.LeftExtent(), s.RightExtent())) +} + +func (s *Set) getNTSlot(sym symbols.Symbol, leftExtent, rightExtent int) (bsrs []BSR) { + nt, ok := sym.(symbols.NT) + if !ok { + line, col := s.getLineColumn(leftExtent) + failf("%s is not an NT at line %d col %d", sym, line, col) + } + return s.ntSlotEntries[ntSlot{nt, leftExtent, rightExtent}] +} + +func (s *Set) fail(b BSR, format string, a ...any) { + msg := fmt.Sprintf(format, a...) + line, col := s.getLineColumn(b.LeftExtent()) + panic(fmt.Sprintf("Error in BSR: %s at line %d col %d\n", msg, line, col)) +} + +func failf(format string, args ...any) { + panic(fmt.Sprintf("Error in BSR: %s\n", fmt.Sprintf(format, args...))) +} + +func (s *Set) getLineColumn(cI int) (line, col int) { + return s.lex.GetLineColumnOfToken(cI) +} + +// ReportAmbiguous lists the ambiguous subtrees of the parse forest +func (s *Set) ReportAmbiguous() { + fmt.Println("Ambiguous BSR Subtrees:") + rts := s.GetRoots() + if len(rts) != 1 { + fmt.Printf("BSR has %d ambigous roots\n", len(rts)) + } + for i, b := range s.GetRoots() { + fmt.Println("In root", i) + if !s.report(b) { + fmt.Println("No ambiguous BSRs") + } + } +} + +// report return true iff at least one ambigous BSR was found +func (s *Set) report(b BSR) bool { + ambiguous := false + for i, sym := range b.Label.Symbols() { + ln, col := s.getLineColumn(b.LeftExtent()) + if sym.IsNonTerminal() { + if len(b.GetNTChildrenI(i)) != 1 { + ambiguous = true + fmt.Printf(" Ambigous: in %s: NT %s (%d) at line %d col %d \n", + b, sym, i, ln, col) + fmt.Println(" Children:") + for _, c := range b.GetNTChildrenI(i) { + fmt.Printf(" %s\n", c) + } + } + for _, b1 := range b.GetNTChildrenI(i) { + s.report(b1) + } + } + } + return ambiguous +} + +// IsAmbiguous returns true if the BSR set does not have exactly one root, or +// if any BSR in the set has an NT symbol, which does not have exactly one +// sub-tree. +func (s *Set) IsAmbiguous() bool { + if len(s.GetRoots()) != 1 { + return true + } + return isAmbiguous(s.GetRoot()) +} + +// isAmbiguous returns true if b or any of its NT children is ambiguous. +// A BSR is ambiguous if any of its NT symbols does not have exactly one +// subtrees (children). +func isAmbiguous(b BSR) bool { + for i, s := range b.Label.Symbols() { + if s.IsNonTerminal() { + if len(b.GetNTChildrenI(i)) != 1 { + return true + } + for _, b1 := range b.GetNTChildrenI(i) { + if isAmbiguous(b1) { + return true + } + } + } + } + return false +} + +//---- SPPF ------------ + +type bldSPPF struct { + root *sppf.SymbolNode + extLeafNodes []sppf.Node + pNodes map[string]*sppf.PackedNode + sNodes map[string]*sppf.SymbolNode // Index is Node.Label() +} + +func (pf *Set) ToSPPF() *sppf.SymbolNode { + bld := &bldSPPF{ + pNodes: map[string]*sppf.PackedNode{}, + sNodes: map[string]*sppf.SymbolNode{}, + } + rt := pf.GetRoots()[0] + bld.root = bld.mkSN(rt.Label.Head().String(), rt.leftExtent, rt.rightExtent) + + for len(bld.extLeafNodes) > 0 { + // let w = (μ, i, j) be an extendable leaf node of G + w := bld.extLeafNodes[len(bld.extLeafNodes)-1] + bld.extLeafNodes = bld.extLeafNodes[:len(bld.extLeafNodes)-1] + + // μ is a nonterminal X in Γ + if nt, ok := w.(*sppf.SymbolNode); ok && symbols.IsNT(nt.Symbol) { + bsts := pf.getNTSlot(symbols.ToNT(nt.Symbol), nt.Lext, nt.Rext) + // for each (X ::=γ,i,k, j)∈Υ { mkPN(X ::=γ·,i,k, j,G) } } + for _, bst := range bsts { + slt := bst.Label.Slot() + nt.Children = append(nt.Children, + bld.mkPN(slt.NT, slt.Symbols, slt.Pos, + bst.leftExtent, bst.pivot, bst.rightExtent)) + } + } else { // w is an intermediate node + // suppose μ is X ::=α·δ + in := w.(*sppf.IntermediateNode) + if in.Pos == 1 { + in.Children = append(in.Children, bld.mkPN(in.NT, in.Body, in.Pos, + in.Lext, in.Lext, in.Rext)) + } else { + // for each (α,i,k, j)∈Υ { mkPN(X ::=α·δ,i,k, j,G) } } } } + alpha, delta := in.Body[:in.Pos], in.Body[in.Pos:] + for _, str := range pf.GetAllStrings(alpha, in.Lext, in.Rext) { + body := append(str.Symbols, delta...) + in.Children = append(in.Children, + bld.mkPN(in.NT, body, in.Pos, str.leftExtent, str.pivot, str.rightExtent)) + } + } + } + } + return bld.root +} + +func (bld *bldSPPF) mkIN(nt symbols.NT, body symbols.Symbols, pos int, + lext, rext int, +) *sppf.IntermediateNode { + in := &sppf.IntermediateNode{ + NT: nt, + Body: body, + Pos: pos, + Lext: lext, + Rext: rext, + } + bld.extLeafNodes = append(bld.extLeafNodes, in) + return in +} + +func (bld *bldSPPF) mkPN(nt symbols.NT, body symbols.Symbols, pos int, + lext, pivot, rext int, +) *sppf.PackedNode { + // fmt.Printf("mkPN %s,%d,%d,%d\n", slotString(nt, body, pos), lext, pivot, rext) + + // X ::= ⍺ • β, k + pn := &sppf.PackedNode{ + NT: nt, + Body: body, + Pos: pos, + Lext: lext, + Rext: rext, + Pivot: pivot, + LeftChild: nil, + RightChild: nil, + } + if pn1, exist := bld.pNodes[pn.Label()]; exist { + return pn1 + } + bld.pNodes[pn.Label()] = pn + + if len(body) == 0 { // ⍺ = ϵ + pn.RightChild = bld.mkSN("ϵ", lext, lext) + } else { // if ( α=βx, where |x|=1) { + // mkN(x,k, j, y,G) + pn.RightChild = bld.mkSN(pn.Body[pn.Pos-1].String(), pivot, rext) + + // if (|β|=1) mkN(β,i,k,y,G) + if pos == 2 { + pn.LeftChild = bld.mkSN(pn.Body[pn.Pos-2].String(), lext, pivot) + } + // if (|β|>1) mkN(X ::=β·xδ,i,k,y,G) + if pos > 2 { + pn.LeftChild = bld.mkIN(pn.NT, pn.Body, pn.Pos-1, lext, pivot) + } + } + + return pn +} + +func (bld *bldSPPF) mkSN(symbol string, lext, rext int) *sppf.SymbolNode { + sn := &sppf.SymbolNode{ + Symbol: symbol, + Lext: lext, + Rext: rext, + } + if sn1, exist := bld.sNodes[sn.Label()]; exist { + return sn1 + } + bld.sNodes[sn.Label()] = sn + if symbols.IsNT(symbol) { + bld.extLeafNodes = append(bld.extLeafNodes, sn) + } + return sn +} + +func slotString(nt symbols.NT, body symbols.Symbols, pos int) string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "%s:", nt) + for i, sym := range body { + fmt.Fprint(w, " ") + if i == pos { + fmt.Fprint(w, "•") + } + fmt.Fprint(w, sym) + } + if len(body) == pos { + fmt.Fprint(w, "•") + } + return w.String() +} diff --git a/test/e2e/pkg/grammar/grammar-auto/parser/parser.go b/test/e2e/pkg/grammar/grammar-auto/parser/parser.go new file mode 100644 index 00000000000..8063d2dd061 --- /dev/null +++ b/test/e2e/pkg/grammar/grammar-auto/parser/parser.go @@ -0,0 +1,2107 @@ +// Package parser is generated by gogll. Do not edit. +package parser + +import ( + "bytes" + "fmt" + "sort" + "strings" + + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/lexer" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser/bsr" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser/slot" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser/symbols" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/token" +) + +type parser struct { + cI int + + R *descriptors + U *descriptors + + popped map[poppedNode]bool + crf map[clusterNode][]*crfNode + crfNodes map[crfNode]*crfNode + + lex *lexer.Lexer + parseErrors []*Error + + bsrSet *bsr.Set +} + +func newParser(l *lexer.Lexer) *parser { + return &parser{ + cI: 0, + lex: l, + R: &descriptors{}, + U: &descriptors{}, + popped: make(map[poppedNode]bool), + crf: map[clusterNode][]*crfNode{ + {symbols.NT_Start, 0}: {}, + }, + crfNodes: map[crfNode]*crfNode{}, + bsrSet: bsr.New(symbols.NT_Start, l), + parseErrors: nil, + } +} + +// Parse returns the BSR set containing the parse forest. +// If the parse was successfull []*Error is nil +func Parse(l *lexer.Lexer) (*bsr.Set, []*Error) { + return newParser(l).parse() +} + +func (p *parser) parse() (*bsr.Set, []*Error) { + var L slot.Label + m, cU := len(p.lex.Tokens)-1, 0 + p.ntAdd(symbols.NT_Start, 0) + // p.DumpDescriptors() + for !p.R.empty() { + L, cU, p.cI = p.R.remove() + + // fmt.Println() + // fmt.Printf("L:%s, cI:%d, I[p.cI]:%s, cU:%d\n", L, p.cI, p.lex.Tokens[p.cI], cU) + // p.DumpDescriptors() + + switch L { + case slot.ApplyChunk0R0: // ApplyChunk : ∙apply_snapshot_chunk + + p.bsrSet.Add(slot.ApplyChunk0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_ApplyChunk) { + p.rtn(symbols.NT_ApplyChunk, cU, p.cI) + } else { + p.parseError(slot.ApplyChunk0R0, p.cI, followSets[symbols.NT_ApplyChunk]) + } + case slot.ApplyChunks0R0: // ApplyChunks : ∙ApplyChunk + + p.call(slot.ApplyChunks0R1, cU, p.cI) + case slot.ApplyChunks0R1: // ApplyChunks : ApplyChunk ∙ + + if p.follow(symbols.NT_ApplyChunks) { + p.rtn(symbols.NT_ApplyChunks, cU, p.cI) + } else { + p.parseError(slot.ApplyChunks0R0, p.cI, followSets[symbols.NT_ApplyChunks]) + } + case slot.ApplyChunks1R0: // ApplyChunks : ∙ApplyChunk ApplyChunks + + p.call(slot.ApplyChunks1R1, cU, p.cI) + case slot.ApplyChunks1R1: // ApplyChunks : ApplyChunk ∙ApplyChunks + + if !p.testSelect(slot.ApplyChunks1R1) { + p.parseError(slot.ApplyChunks1R1, p.cI, first[slot.ApplyChunks1R1]) + break + } + + p.call(slot.ApplyChunks1R2, cU, p.cI) + case slot.ApplyChunks1R2: // ApplyChunks : ApplyChunk ApplyChunks ∙ + + if p.follow(symbols.NT_ApplyChunks) { + p.rtn(symbols.NT_ApplyChunks, cU, p.cI) + } else { + p.parseError(slot.ApplyChunks1R0, p.cI, followSets[symbols.NT_ApplyChunks]) + } + case slot.CleanStart0R0: // CleanStart : ∙InitChain ConsensusExec + + p.call(slot.CleanStart0R1, cU, p.cI) + case slot.CleanStart0R1: // CleanStart : InitChain ∙ConsensusExec + + if !p.testSelect(slot.CleanStart0R1) { + p.parseError(slot.CleanStart0R1, p.cI, first[slot.CleanStart0R1]) + break + } + + p.call(slot.CleanStart0R2, cU, p.cI) + case slot.CleanStart0R2: // CleanStart : InitChain ConsensusExec ∙ + + if p.follow(symbols.NT_CleanStart) { + p.rtn(symbols.NT_CleanStart, cU, p.cI) + } else { + p.parseError(slot.CleanStart0R0, p.cI, followSets[symbols.NT_CleanStart]) + } + case slot.CleanStart1R0: // CleanStart : ∙StateSync ConsensusExec + + p.call(slot.CleanStart1R1, cU, p.cI) + case slot.CleanStart1R1: // CleanStart : StateSync ∙ConsensusExec + + if !p.testSelect(slot.CleanStart1R1) { + p.parseError(slot.CleanStart1R1, p.cI, first[slot.CleanStart1R1]) + break + } + + p.call(slot.CleanStart1R2, cU, p.cI) + case slot.CleanStart1R2: // CleanStart : StateSync ConsensusExec ∙ + + if p.follow(symbols.NT_CleanStart) { + p.rtn(symbols.NT_CleanStart, cU, p.cI) + } else { + p.parseError(slot.CleanStart1R0, p.cI, followSets[symbols.NT_CleanStart]) + } + case slot.Commit0R0: // Commit : ∙commit + + p.bsrSet.Add(slot.Commit0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_Commit) { + p.rtn(symbols.NT_Commit, cU, p.cI) + } else { + p.parseError(slot.Commit0R0, p.cI, followSets[symbols.NT_Commit]) + } + case slot.ConsensusExec0R0: // ConsensusExec : ∙ConsensusHeights + + p.call(slot.ConsensusExec0R1, cU, p.cI) + case slot.ConsensusExec0R1: // ConsensusExec : ConsensusHeights ∙ + + if p.follow(symbols.NT_ConsensusExec) { + p.rtn(symbols.NT_ConsensusExec, cU, p.cI) + } else { + p.parseError(slot.ConsensusExec0R0, p.cI, followSets[symbols.NT_ConsensusExec]) + } + case slot.ConsensusHeight0R0: // ConsensusHeight : ∙ConsensusRounds FinalizeBlock Commit + + p.call(slot.ConsensusHeight0R1, cU, p.cI) + case slot.ConsensusHeight0R1: // ConsensusHeight : ConsensusRounds ∙FinalizeBlock Commit + + if !p.testSelect(slot.ConsensusHeight0R1) { + p.parseError(slot.ConsensusHeight0R1, p.cI, first[slot.ConsensusHeight0R1]) + break + } + + p.call(slot.ConsensusHeight0R2, cU, p.cI) + case slot.ConsensusHeight0R2: // ConsensusHeight : ConsensusRounds FinalizeBlock ∙Commit + + if !p.testSelect(slot.ConsensusHeight0R2) { + p.parseError(slot.ConsensusHeight0R2, p.cI, first[slot.ConsensusHeight0R2]) + break + } + + p.call(slot.ConsensusHeight0R3, cU, p.cI) + case slot.ConsensusHeight0R3: // ConsensusHeight : ConsensusRounds FinalizeBlock Commit ∙ + + if p.follow(symbols.NT_ConsensusHeight) { + p.rtn(symbols.NT_ConsensusHeight, cU, p.cI) + } else { + p.parseError(slot.ConsensusHeight0R0, p.cI, followSets[symbols.NT_ConsensusHeight]) + } + case slot.ConsensusHeight1R0: // ConsensusHeight : ∙FinalizeBlock Commit + + p.call(slot.ConsensusHeight1R1, cU, p.cI) + case slot.ConsensusHeight1R1: // ConsensusHeight : FinalizeBlock ∙Commit + + if !p.testSelect(slot.ConsensusHeight1R1) { + p.parseError(slot.ConsensusHeight1R1, p.cI, first[slot.ConsensusHeight1R1]) + break + } + + p.call(slot.ConsensusHeight1R2, cU, p.cI) + case slot.ConsensusHeight1R2: // ConsensusHeight : FinalizeBlock Commit ∙ + + if p.follow(symbols.NT_ConsensusHeight) { + p.rtn(symbols.NT_ConsensusHeight, cU, p.cI) + } else { + p.parseError(slot.ConsensusHeight1R0, p.cI, followSets[symbols.NT_ConsensusHeight]) + } + case slot.ConsensusHeights0R0: // ConsensusHeights : ∙ConsensusHeight + + p.call(slot.ConsensusHeights0R1, cU, p.cI) + case slot.ConsensusHeights0R1: // ConsensusHeights : ConsensusHeight ∙ + + if p.follow(symbols.NT_ConsensusHeights) { + p.rtn(symbols.NT_ConsensusHeights, cU, p.cI) + } else { + p.parseError(slot.ConsensusHeights0R0, p.cI, followSets[symbols.NT_ConsensusHeights]) + } + case slot.ConsensusHeights1R0: // ConsensusHeights : ∙ConsensusHeight ConsensusHeights + + p.call(slot.ConsensusHeights1R1, cU, p.cI) + case slot.ConsensusHeights1R1: // ConsensusHeights : ConsensusHeight ∙ConsensusHeights + + if !p.testSelect(slot.ConsensusHeights1R1) { + p.parseError(slot.ConsensusHeights1R1, p.cI, first[slot.ConsensusHeights1R1]) + break + } + + p.call(slot.ConsensusHeights1R2, cU, p.cI) + case slot.ConsensusHeights1R2: // ConsensusHeights : ConsensusHeight ConsensusHeights ∙ + + if p.follow(symbols.NT_ConsensusHeights) { + p.rtn(symbols.NT_ConsensusHeights, cU, p.cI) + } else { + p.parseError(slot.ConsensusHeights1R0, p.cI, followSets[symbols.NT_ConsensusHeights]) + } + case slot.ConsensusRound0R0: // ConsensusRound : ∙Proposer + + p.call(slot.ConsensusRound0R1, cU, p.cI) + case slot.ConsensusRound0R1: // ConsensusRound : Proposer ∙ + + if p.follow(symbols.NT_ConsensusRound) { + p.rtn(symbols.NT_ConsensusRound, cU, p.cI) + } else { + p.parseError(slot.ConsensusRound0R0, p.cI, followSets[symbols.NT_ConsensusRound]) + } + case slot.ConsensusRound1R0: // ConsensusRound : ∙NonProposer + + p.call(slot.ConsensusRound1R1, cU, p.cI) + case slot.ConsensusRound1R1: // ConsensusRound : NonProposer ∙ + + if p.follow(symbols.NT_ConsensusRound) { + p.rtn(symbols.NT_ConsensusRound, cU, p.cI) + } else { + p.parseError(slot.ConsensusRound1R0, p.cI, followSets[symbols.NT_ConsensusRound]) + } + case slot.ConsensusRounds0R0: // ConsensusRounds : ∙ConsensusRound + + p.call(slot.ConsensusRounds0R1, cU, p.cI) + case slot.ConsensusRounds0R1: // ConsensusRounds : ConsensusRound ∙ + + if p.follow(symbols.NT_ConsensusRounds) { + p.rtn(symbols.NT_ConsensusRounds, cU, p.cI) + } else { + p.parseError(slot.ConsensusRounds0R0, p.cI, followSets[symbols.NT_ConsensusRounds]) + } + case slot.ConsensusRounds1R0: // ConsensusRounds : ∙ConsensusRound ConsensusRounds + + p.call(slot.ConsensusRounds1R1, cU, p.cI) + case slot.ConsensusRounds1R1: // ConsensusRounds : ConsensusRound ∙ConsensusRounds + + if !p.testSelect(slot.ConsensusRounds1R1) { + p.parseError(slot.ConsensusRounds1R1, p.cI, first[slot.ConsensusRounds1R1]) + break + } + + p.call(slot.ConsensusRounds1R2, cU, p.cI) + case slot.ConsensusRounds1R2: // ConsensusRounds : ConsensusRound ConsensusRounds ∙ + + if p.follow(symbols.NT_ConsensusRounds) { + p.rtn(symbols.NT_ConsensusRounds, cU, p.cI) + } else { + p.parseError(slot.ConsensusRounds1R0, p.cI, followSets[symbols.NT_ConsensusRounds]) + } + case slot.Extend0R0: // Extend : ∙ExtendVote + + p.call(slot.Extend0R1, cU, p.cI) + case slot.Extend0R1: // Extend : ExtendVote ∙ + + if p.follow(symbols.NT_Extend) { + p.rtn(symbols.NT_Extend, cU, p.cI) + } else { + p.parseError(slot.Extend0R0, p.cI, followSets[symbols.NT_Extend]) + } + case slot.Extend1R0: // Extend : ∙GotVotes ExtendVote + + p.call(slot.Extend1R1, cU, p.cI) + case slot.Extend1R1: // Extend : GotVotes ∙ExtendVote + + if !p.testSelect(slot.Extend1R1) { + p.parseError(slot.Extend1R1, p.cI, first[slot.Extend1R1]) + break + } + + p.call(slot.Extend1R2, cU, p.cI) + case slot.Extend1R2: // Extend : GotVotes ExtendVote ∙ + + if p.follow(symbols.NT_Extend) { + p.rtn(symbols.NT_Extend, cU, p.cI) + } else { + p.parseError(slot.Extend1R0, p.cI, followSets[symbols.NT_Extend]) + } + case slot.Extend2R0: // Extend : ∙ExtendVote GotVotes + + p.call(slot.Extend2R1, cU, p.cI) + case slot.Extend2R1: // Extend : ExtendVote ∙GotVotes + + if !p.testSelect(slot.Extend2R1) { + p.parseError(slot.Extend2R1, p.cI, first[slot.Extend2R1]) + break + } + + p.call(slot.Extend2R2, cU, p.cI) + case slot.Extend2R2: // Extend : ExtendVote GotVotes ∙ + + if p.follow(symbols.NT_Extend) { + p.rtn(symbols.NT_Extend, cU, p.cI) + } else { + p.parseError(slot.Extend2R0, p.cI, followSets[symbols.NT_Extend]) + } + case slot.Extend3R0: // Extend : ∙GotVotes ExtendVote GotVotes + + p.call(slot.Extend3R1, cU, p.cI) + case slot.Extend3R1: // Extend : GotVotes ∙ExtendVote GotVotes + + if !p.testSelect(slot.Extend3R1) { + p.parseError(slot.Extend3R1, p.cI, first[slot.Extend3R1]) + break + } + + p.call(slot.Extend3R2, cU, p.cI) + case slot.Extend3R2: // Extend : GotVotes ExtendVote ∙GotVotes + + if !p.testSelect(slot.Extend3R2) { + p.parseError(slot.Extend3R2, p.cI, first[slot.Extend3R2]) + break + } + + p.call(slot.Extend3R3, cU, p.cI) + case slot.Extend3R3: // Extend : GotVotes ExtendVote GotVotes ∙ + + if p.follow(symbols.NT_Extend) { + p.rtn(symbols.NT_Extend, cU, p.cI) + } else { + p.parseError(slot.Extend3R0, p.cI, followSets[symbols.NT_Extend]) + } + case slot.ExtendVote0R0: // ExtendVote : ∙extend_vote + + p.bsrSet.Add(slot.ExtendVote0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_ExtendVote) { + p.rtn(symbols.NT_ExtendVote, cU, p.cI) + } else { + p.parseError(slot.ExtendVote0R0, p.cI, followSets[symbols.NT_ExtendVote]) + } + case slot.FinalizeBlock0R0: // FinalizeBlock : ∙finalize_block + + p.bsrSet.Add(slot.FinalizeBlock0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_FinalizeBlock) { + p.rtn(symbols.NT_FinalizeBlock, cU, p.cI) + } else { + p.parseError(slot.FinalizeBlock0R0, p.cI, followSets[symbols.NT_FinalizeBlock]) + } + case slot.GotVote0R0: // GotVote : ∙verify_vote_extension + + p.bsrSet.Add(slot.GotVote0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_GotVote) { + p.rtn(symbols.NT_GotVote, cU, p.cI) + } else { + p.parseError(slot.GotVote0R0, p.cI, followSets[symbols.NT_GotVote]) + } + case slot.GotVotes0R0: // GotVotes : ∙GotVote + + p.call(slot.GotVotes0R1, cU, p.cI) + case slot.GotVotes0R1: // GotVotes : GotVote ∙ + + if p.follow(symbols.NT_GotVotes) { + p.rtn(symbols.NT_GotVotes, cU, p.cI) + } else { + p.parseError(slot.GotVotes0R0, p.cI, followSets[symbols.NT_GotVotes]) + } + case slot.GotVotes1R0: // GotVotes : ∙GotVote GotVotes + + p.call(slot.GotVotes1R1, cU, p.cI) + case slot.GotVotes1R1: // GotVotes : GotVote ∙GotVotes + + if !p.testSelect(slot.GotVotes1R1) { + p.parseError(slot.GotVotes1R1, p.cI, first[slot.GotVotes1R1]) + break + } + + p.call(slot.GotVotes1R2, cU, p.cI) + case slot.GotVotes1R2: // GotVotes : GotVote GotVotes ∙ + + if p.follow(symbols.NT_GotVotes) { + p.rtn(symbols.NT_GotVotes, cU, p.cI) + } else { + p.parseError(slot.GotVotes1R0, p.cI, followSets[symbols.NT_GotVotes]) + } + case slot.InitChain0R0: // InitChain : ∙init_chain + + p.bsrSet.Add(slot.InitChain0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_InitChain) { + p.rtn(symbols.NT_InitChain, cU, p.cI) + } else { + p.parseError(slot.InitChain0R0, p.cI, followSets[symbols.NT_InitChain]) + } + case slot.NonProposer0R0: // NonProposer : ∙GotVotes + + p.call(slot.NonProposer0R1, cU, p.cI) + case slot.NonProposer0R1: // NonProposer : GotVotes ∙ + + if p.follow(symbols.NT_NonProposer) { + p.rtn(symbols.NT_NonProposer, cU, p.cI) + } else { + p.parseError(slot.NonProposer0R0, p.cI, followSets[symbols.NT_NonProposer]) + } + case slot.NonProposer1R0: // NonProposer : ∙ProcessProposal + + p.call(slot.NonProposer1R1, cU, p.cI) + case slot.NonProposer1R1: // NonProposer : ProcessProposal ∙ + + if p.follow(symbols.NT_NonProposer) { + p.rtn(symbols.NT_NonProposer, cU, p.cI) + } else { + p.parseError(slot.NonProposer1R0, p.cI, followSets[symbols.NT_NonProposer]) + } + case slot.NonProposer2R0: // NonProposer : ∙Extend + + p.call(slot.NonProposer2R1, cU, p.cI) + case slot.NonProposer2R1: // NonProposer : Extend ∙ + + if p.follow(symbols.NT_NonProposer) { + p.rtn(symbols.NT_NonProposer, cU, p.cI) + } else { + p.parseError(slot.NonProposer2R0, p.cI, followSets[symbols.NT_NonProposer]) + } + case slot.NonProposer3R0: // NonProposer : ∙GotVotes ProcessProposal + + p.call(slot.NonProposer3R1, cU, p.cI) + case slot.NonProposer3R1: // NonProposer : GotVotes ∙ProcessProposal + + if !p.testSelect(slot.NonProposer3R1) { + p.parseError(slot.NonProposer3R1, p.cI, first[slot.NonProposer3R1]) + break + } + + p.call(slot.NonProposer3R2, cU, p.cI) + case slot.NonProposer3R2: // NonProposer : GotVotes ProcessProposal ∙ + + if p.follow(symbols.NT_NonProposer) { + p.rtn(symbols.NT_NonProposer, cU, p.cI) + } else { + p.parseError(slot.NonProposer3R0, p.cI, followSets[symbols.NT_NonProposer]) + } + case slot.NonProposer4R0: // NonProposer : ∙GotVotes Extend + + p.call(slot.NonProposer4R1, cU, p.cI) + case slot.NonProposer4R1: // NonProposer : GotVotes ∙Extend + + if !p.testSelect(slot.NonProposer4R1) { + p.parseError(slot.NonProposer4R1, p.cI, first[slot.NonProposer4R1]) + break + } + + p.call(slot.NonProposer4R2, cU, p.cI) + case slot.NonProposer4R2: // NonProposer : GotVotes Extend ∙ + + if p.follow(symbols.NT_NonProposer) { + p.rtn(symbols.NT_NonProposer, cU, p.cI) + } else { + p.parseError(slot.NonProposer4R0, p.cI, followSets[symbols.NT_NonProposer]) + } + case slot.NonProposer5R0: // NonProposer : ∙ProcessProposal Extend + + p.call(slot.NonProposer5R1, cU, p.cI) + case slot.NonProposer5R1: // NonProposer : ProcessProposal ∙Extend + + if !p.testSelect(slot.NonProposer5R1) { + p.parseError(slot.NonProposer5R1, p.cI, first[slot.NonProposer5R1]) + break + } + + p.call(slot.NonProposer5R2, cU, p.cI) + case slot.NonProposer5R2: // NonProposer : ProcessProposal Extend ∙ + + if p.follow(symbols.NT_NonProposer) { + p.rtn(symbols.NT_NonProposer, cU, p.cI) + } else { + p.parseError(slot.NonProposer5R0, p.cI, followSets[symbols.NT_NonProposer]) + } + case slot.NonProposer6R0: // NonProposer : ∙GotVotes ProcessProposal Extend + + p.call(slot.NonProposer6R1, cU, p.cI) + case slot.NonProposer6R1: // NonProposer : GotVotes ∙ProcessProposal Extend + + if !p.testSelect(slot.NonProposer6R1) { + p.parseError(slot.NonProposer6R1, p.cI, first[slot.NonProposer6R1]) + break + } + + p.call(slot.NonProposer6R2, cU, p.cI) + case slot.NonProposer6R2: // NonProposer : GotVotes ProcessProposal ∙Extend + + if !p.testSelect(slot.NonProposer6R2) { + p.parseError(slot.NonProposer6R2, p.cI, first[slot.NonProposer6R2]) + break + } + + p.call(slot.NonProposer6R3, cU, p.cI) + case slot.NonProposer6R3: // NonProposer : GotVotes ProcessProposal Extend ∙ + + if p.follow(symbols.NT_NonProposer) { + p.rtn(symbols.NT_NonProposer, cU, p.cI) + } else { + p.parseError(slot.NonProposer6R0, p.cI, followSets[symbols.NT_NonProposer]) + } + case slot.OfferSnapshot0R0: // OfferSnapshot : ∙offer_snapshot + + p.bsrSet.Add(slot.OfferSnapshot0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_OfferSnapshot) { + p.rtn(symbols.NT_OfferSnapshot, cU, p.cI) + } else { + p.parseError(slot.OfferSnapshot0R0, p.cI, followSets[symbols.NT_OfferSnapshot]) + } + case slot.PrepareProposal0R0: // PrepareProposal : ∙prepare_proposal + + p.bsrSet.Add(slot.PrepareProposal0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_PrepareProposal) { + p.rtn(symbols.NT_PrepareProposal, cU, p.cI) + } else { + p.parseError(slot.PrepareProposal0R0, p.cI, followSets[symbols.NT_PrepareProposal]) + } + case slot.ProcessProposal0R0: // ProcessProposal : ∙process_proposal + + p.bsrSet.Add(slot.ProcessProposal0R1, cU, p.cI, p.cI+1) + p.cI++ + if p.follow(symbols.NT_ProcessProposal) { + p.rtn(symbols.NT_ProcessProposal, cU, p.cI) + } else { + p.parseError(slot.ProcessProposal0R0, p.cI, followSets[symbols.NT_ProcessProposal]) + } + case slot.Proposer0R0: // Proposer : ∙GotVotes + + p.call(slot.Proposer0R1, cU, p.cI) + case slot.Proposer0R1: // Proposer : GotVotes ∙ + + if p.follow(symbols.NT_Proposer) { + p.rtn(symbols.NT_Proposer, cU, p.cI) + } else { + p.parseError(slot.Proposer0R0, p.cI, followSets[symbols.NT_Proposer]) + } + case slot.Proposer1R0: // Proposer : ∙ProposerSimple + + p.call(slot.Proposer1R1, cU, p.cI) + case slot.Proposer1R1: // Proposer : ProposerSimple ∙ + + if p.follow(symbols.NT_Proposer) { + p.rtn(symbols.NT_Proposer, cU, p.cI) + } else { + p.parseError(slot.Proposer1R0, p.cI, followSets[symbols.NT_Proposer]) + } + case slot.Proposer2R0: // Proposer : ∙Extend + + p.call(slot.Proposer2R1, cU, p.cI) + case slot.Proposer2R1: // Proposer : Extend ∙ + + if p.follow(symbols.NT_Proposer) { + p.rtn(symbols.NT_Proposer, cU, p.cI) + } else { + p.parseError(slot.Proposer2R0, p.cI, followSets[symbols.NT_Proposer]) + } + case slot.Proposer3R0: // Proposer : ∙GotVotes ProposerSimple + + p.call(slot.Proposer3R1, cU, p.cI) + case slot.Proposer3R1: // Proposer : GotVotes ∙ProposerSimple + + if !p.testSelect(slot.Proposer3R1) { + p.parseError(slot.Proposer3R1, p.cI, first[slot.Proposer3R1]) + break + } + + p.call(slot.Proposer3R2, cU, p.cI) + case slot.Proposer3R2: // Proposer : GotVotes ProposerSimple ∙ + + if p.follow(symbols.NT_Proposer) { + p.rtn(symbols.NT_Proposer, cU, p.cI) + } else { + p.parseError(slot.Proposer3R0, p.cI, followSets[symbols.NT_Proposer]) + } + case slot.Proposer4R0: // Proposer : ∙GotVotes Extend + + p.call(slot.Proposer4R1, cU, p.cI) + case slot.Proposer4R1: // Proposer : GotVotes ∙Extend + + if !p.testSelect(slot.Proposer4R1) { + p.parseError(slot.Proposer4R1, p.cI, first[slot.Proposer4R1]) + break + } + + p.call(slot.Proposer4R2, cU, p.cI) + case slot.Proposer4R2: // Proposer : GotVotes Extend ∙ + + if p.follow(symbols.NT_Proposer) { + p.rtn(symbols.NT_Proposer, cU, p.cI) + } else { + p.parseError(slot.Proposer4R0, p.cI, followSets[symbols.NT_Proposer]) + } + case slot.Proposer5R0: // Proposer : ∙ProposerSimple Extend + + p.call(slot.Proposer5R1, cU, p.cI) + case slot.Proposer5R1: // Proposer : ProposerSimple ∙Extend + + if !p.testSelect(slot.Proposer5R1) { + p.parseError(slot.Proposer5R1, p.cI, first[slot.Proposer5R1]) + break + } + + p.call(slot.Proposer5R2, cU, p.cI) + case slot.Proposer5R2: // Proposer : ProposerSimple Extend ∙ + + if p.follow(symbols.NT_Proposer) { + p.rtn(symbols.NT_Proposer, cU, p.cI) + } else { + p.parseError(slot.Proposer5R0, p.cI, followSets[symbols.NT_Proposer]) + } + case slot.Proposer6R0: // Proposer : ∙GotVotes ProposerSimple Extend + + p.call(slot.Proposer6R1, cU, p.cI) + case slot.Proposer6R1: // Proposer : GotVotes ∙ProposerSimple Extend + + if !p.testSelect(slot.Proposer6R1) { + p.parseError(slot.Proposer6R1, p.cI, first[slot.Proposer6R1]) + break + } + + p.call(slot.Proposer6R2, cU, p.cI) + case slot.Proposer6R2: // Proposer : GotVotes ProposerSimple ∙Extend + + if !p.testSelect(slot.Proposer6R2) { + p.parseError(slot.Proposer6R2, p.cI, first[slot.Proposer6R2]) + break + } + + p.call(slot.Proposer6R3, cU, p.cI) + case slot.Proposer6R3: // Proposer : GotVotes ProposerSimple Extend ∙ + + if p.follow(symbols.NT_Proposer) { + p.rtn(symbols.NT_Proposer, cU, p.cI) + } else { + p.parseError(slot.Proposer6R0, p.cI, followSets[symbols.NT_Proposer]) + } + case slot.ProposerSimple0R0: // ProposerSimple : ∙PrepareProposal + + p.call(slot.ProposerSimple0R1, cU, p.cI) + case slot.ProposerSimple0R1: // ProposerSimple : PrepareProposal ∙ + + if p.follow(symbols.NT_ProposerSimple) { + p.rtn(symbols.NT_ProposerSimple, cU, p.cI) + } else { + p.parseError(slot.ProposerSimple0R0, p.cI, followSets[symbols.NT_ProposerSimple]) + } + case slot.ProposerSimple1R0: // ProposerSimple : ∙PrepareProposal ProcessProposal + + p.call(slot.ProposerSimple1R1, cU, p.cI) + case slot.ProposerSimple1R1: // ProposerSimple : PrepareProposal ∙ProcessProposal + + if !p.testSelect(slot.ProposerSimple1R1) { + p.parseError(slot.ProposerSimple1R1, p.cI, first[slot.ProposerSimple1R1]) + break + } + + p.call(slot.ProposerSimple1R2, cU, p.cI) + case slot.ProposerSimple1R2: // ProposerSimple : PrepareProposal ProcessProposal ∙ + + if p.follow(symbols.NT_ProposerSimple) { + p.rtn(symbols.NT_ProposerSimple, cU, p.cI) + } else { + p.parseError(slot.ProposerSimple1R0, p.cI, followSets[symbols.NT_ProposerSimple]) + } + case slot.Recovery0R0: // Recovery : ∙InitChain ConsensusExec + + p.call(slot.Recovery0R1, cU, p.cI) + case slot.Recovery0R1: // Recovery : InitChain ∙ConsensusExec + + if !p.testSelect(slot.Recovery0R1) { + p.parseError(slot.Recovery0R1, p.cI, first[slot.Recovery0R1]) + break + } + + p.call(slot.Recovery0R2, cU, p.cI) + case slot.Recovery0R2: // Recovery : InitChain ConsensusExec ∙ + + if p.follow(symbols.NT_Recovery) { + p.rtn(symbols.NT_Recovery, cU, p.cI) + } else { + p.parseError(slot.Recovery0R0, p.cI, followSets[symbols.NT_Recovery]) + } + case slot.Recovery1R0: // Recovery : ∙ConsensusExec + + p.call(slot.Recovery1R1, cU, p.cI) + case slot.Recovery1R1: // Recovery : ConsensusExec ∙ + + if p.follow(symbols.NT_Recovery) { + p.rtn(symbols.NT_Recovery, cU, p.cI) + } else { + p.parseError(slot.Recovery1R0, p.cI, followSets[symbols.NT_Recovery]) + } + case slot.Start0R0: // Start : ∙CleanStart + + p.call(slot.Start0R1, cU, p.cI) + case slot.Start0R1: // Start : CleanStart ∙ + + if p.follow(symbols.NT_Start) { + p.rtn(symbols.NT_Start, cU, p.cI) + } else { + p.parseError(slot.Start0R0, p.cI, followSets[symbols.NT_Start]) + } + case slot.Start1R0: // Start : ∙Recovery + + p.call(slot.Start1R1, cU, p.cI) + case slot.Start1R1: // Start : Recovery ∙ + + if p.follow(symbols.NT_Start) { + p.rtn(symbols.NT_Start, cU, p.cI) + } else { + p.parseError(slot.Start1R0, p.cI, followSets[symbols.NT_Start]) + } + case slot.StateSync0R0: // StateSync : ∙StateSyncAttempts SuccessSync + + p.call(slot.StateSync0R1, cU, p.cI) + case slot.StateSync0R1: // StateSync : StateSyncAttempts ∙SuccessSync + + if !p.testSelect(slot.StateSync0R1) { + p.parseError(slot.StateSync0R1, p.cI, first[slot.StateSync0R1]) + break + } + + p.call(slot.StateSync0R2, cU, p.cI) + case slot.StateSync0R2: // StateSync : StateSyncAttempts SuccessSync ∙ + + if p.follow(symbols.NT_StateSync) { + p.rtn(symbols.NT_StateSync, cU, p.cI) + } else { + p.parseError(slot.StateSync0R0, p.cI, followSets[symbols.NT_StateSync]) + } + case slot.StateSync1R0: // StateSync : ∙SuccessSync + + p.call(slot.StateSync1R1, cU, p.cI) + case slot.StateSync1R1: // StateSync : SuccessSync ∙ + + if p.follow(symbols.NT_StateSync) { + p.rtn(symbols.NT_StateSync, cU, p.cI) + } else { + p.parseError(slot.StateSync1R0, p.cI, followSets[symbols.NT_StateSync]) + } + case slot.StateSyncAttempt0R0: // StateSyncAttempt : ∙OfferSnapshot ApplyChunks + + p.call(slot.StateSyncAttempt0R1, cU, p.cI) + case slot.StateSyncAttempt0R1: // StateSyncAttempt : OfferSnapshot ∙ApplyChunks + + if !p.testSelect(slot.StateSyncAttempt0R1) { + p.parseError(slot.StateSyncAttempt0R1, p.cI, first[slot.StateSyncAttempt0R1]) + break + } + + p.call(slot.StateSyncAttempt0R2, cU, p.cI) + case slot.StateSyncAttempt0R2: // StateSyncAttempt : OfferSnapshot ApplyChunks ∙ + + if p.follow(symbols.NT_StateSyncAttempt) { + p.rtn(symbols.NT_StateSyncAttempt, cU, p.cI) + } else { + p.parseError(slot.StateSyncAttempt0R0, p.cI, followSets[symbols.NT_StateSyncAttempt]) + } + case slot.StateSyncAttempt1R0: // StateSyncAttempt : ∙OfferSnapshot + + p.call(slot.StateSyncAttempt1R1, cU, p.cI) + case slot.StateSyncAttempt1R1: // StateSyncAttempt : OfferSnapshot ∙ + + if p.follow(symbols.NT_StateSyncAttempt) { + p.rtn(symbols.NT_StateSyncAttempt, cU, p.cI) + } else { + p.parseError(slot.StateSyncAttempt1R0, p.cI, followSets[symbols.NT_StateSyncAttempt]) + } + case slot.StateSyncAttempts0R0: // StateSyncAttempts : ∙StateSyncAttempt + + p.call(slot.StateSyncAttempts0R1, cU, p.cI) + case slot.StateSyncAttempts0R1: // StateSyncAttempts : StateSyncAttempt ∙ + + if p.follow(symbols.NT_StateSyncAttempts) { + p.rtn(symbols.NT_StateSyncAttempts, cU, p.cI) + } else { + p.parseError(slot.StateSyncAttempts0R0, p.cI, followSets[symbols.NT_StateSyncAttempts]) + } + case slot.StateSyncAttempts1R0: // StateSyncAttempts : ∙StateSyncAttempt StateSyncAttempts + + p.call(slot.StateSyncAttempts1R1, cU, p.cI) + case slot.StateSyncAttempts1R1: // StateSyncAttempts : StateSyncAttempt ∙StateSyncAttempts + + if !p.testSelect(slot.StateSyncAttempts1R1) { + p.parseError(slot.StateSyncAttempts1R1, p.cI, first[slot.StateSyncAttempts1R1]) + break + } + + p.call(slot.StateSyncAttempts1R2, cU, p.cI) + case slot.StateSyncAttempts1R2: // StateSyncAttempts : StateSyncAttempt StateSyncAttempts ∙ + + if p.follow(symbols.NT_StateSyncAttempts) { + p.rtn(symbols.NT_StateSyncAttempts, cU, p.cI) + } else { + p.parseError(slot.StateSyncAttempts1R0, p.cI, followSets[symbols.NT_StateSyncAttempts]) + } + case slot.SuccessSync0R0: // SuccessSync : ∙OfferSnapshot ApplyChunks + + p.call(slot.SuccessSync0R1, cU, p.cI) + case slot.SuccessSync0R1: // SuccessSync : OfferSnapshot ∙ApplyChunks + + if !p.testSelect(slot.SuccessSync0R1) { + p.parseError(slot.SuccessSync0R1, p.cI, first[slot.SuccessSync0R1]) + break + } + + p.call(slot.SuccessSync0R2, cU, p.cI) + case slot.SuccessSync0R2: // SuccessSync : OfferSnapshot ApplyChunks ∙ + + if p.follow(symbols.NT_SuccessSync) { + p.rtn(symbols.NT_SuccessSync, cU, p.cI) + } else { + p.parseError(slot.SuccessSync0R0, p.cI, followSets[symbols.NT_SuccessSync]) + } + + default: + panic("This must not happen") + } + } + if !p.bsrSet.Contain(symbols.NT_Start, 0, m) { + p.sortParseErrors() + return nil, p.parseErrors + } + return p.bsrSet, nil +} + +func (p *parser) ntAdd(nt symbols.NT, j int) { + // fmt.Printf("p.ntAdd(%s, %d)\n", nt, j) + failed := true + expected := map[token.Type]string{} + for _, l := range slot.GetAlternates(nt) { + if p.testSelect(l) { + p.dscAdd(l, j, j) + failed = false + } else { + for k, v := range first[l] { + expected[k] = v + } + } + } + if failed { + for _, l := range slot.GetAlternates(nt) { + p.parseError(l, j, expected) + } + } +} + +/*** Call Return Forest ***/ + +type poppedNode struct { + X symbols.NT + k, j int +} + +type clusterNode struct { + X symbols.NT + k int +} + +type crfNode struct { + L slot.Label + i int +} + +/* +suppose that L is Y ::=αX ·β +if there is no CRF node labelled (L,i) + + create one let u be the CRF node labelled (L,i) + +if there is no CRF node labelled (X, j) { + + create a CRF node v labelled (X, j) + create an edge from v to u + ntAdd(X, j) + } else { + + let v be the CRF node labelled (X, j) + if there is not an edge from v to u { + create an edge from v to u + for all ((X, j,h)∈P) { + dscAdd(L, i, h); + bsrAdd(L, i, j, h) + } + } + } +*/ +func (p *parser) call(L slot.Label, i, j int) { + // fmt.Printf("p.call(%s,%d,%d)\n", L,i,j) + u, exist := p.crfNodes[crfNode{L, i}] + // fmt.Printf(" u exist=%t\n", exist) + if !exist { + u = &crfNode{L, i} + p.crfNodes[*u] = u + } + X := L.Symbols()[L.Pos()-1].(symbols.NT) + ndV := clusterNode{X, j} + v, exist := p.crf[ndV] + if !exist { + // fmt.Println(" v !exist") + p.crf[ndV] = []*crfNode{u} + p.ntAdd(X, j) + } else { + // fmt.Println(" v exist") + if !existEdge(v, u) { + // fmt.Printf(" !existEdge(%v)\n", u) + p.crf[ndV] = append(v, u) + // fmt.Printf("|popped|=%d\n", len(popped)) + for pnd := range p.popped { + if pnd.X == X && pnd.k == j { + p.dscAdd(L, i, pnd.j) + p.bsrSet.Add(L, i, j, pnd.j) + } + } + } + } +} + +func existEdge(nds []*crfNode, nd *crfNode) bool { + for _, nd1 := range nds { + if nd1 == nd { + return true + } + } + return false +} + +func (p *parser) rtn(X symbols.NT, k, j int) { + // fmt.Printf("p.rtn(%s,%d,%d)\n", X,k,j) + pn := poppedNode{X, k, j} + if _, exist := p.popped[pn]; !exist { + p.popped[pn] = true + for _, nd := range p.crf[clusterNode{X, k}] { + p.dscAdd(nd.L, nd.i, j) + p.bsrSet.Add(nd.L, nd.i, k, j) + } + } +} + +// func CRFString() string { +// buf := new(bytes.Buffer) +// buf.WriteString("CRF: {") +// for cn, nds := range crf{ +// for _, nd := range nds { +// fmt.Fprintf(buf, "%s->%s, ", cn, nd) +// } +// } +// buf.WriteString("}") +// return buf.String() +// } + +func (cn clusterNode) String() string { + return fmt.Sprintf("(%s,%d)", cn.X, cn.k) +} + +func (n crfNode) String() string { + return fmt.Sprintf("(%s,%d)", n.L.String(), n.i) +} + +// func PoppedString() string { +// buf := new(bytes.Buffer) +// buf.WriteString("Popped: {") +// for p, _ := range popped { +// fmt.Fprintf(buf, "(%s,%d,%d) ", p.X, p.k, p.j) +// } +// buf.WriteString("}") +// return buf.String() +// } + +/*** descriptors ***/ + +type descriptors struct { + set []*descriptor +} + +func (ds *descriptors) contain(d *descriptor) bool { + for _, d1 := range ds.set { + if d1 == d { + return true + } + } + return false +} + +func (ds *descriptors) empty() bool { + return len(ds.set) == 0 +} + +func (ds *descriptors) String() string { + buf := new(bytes.Buffer) + buf.WriteString("{") + for i, d := range ds.set { + if i > 0 { + buf.WriteString("; ") + } + fmt.Fprintf(buf, "%s", d) + } + buf.WriteString("}") + return buf.String() +} + +type descriptor struct { + L slot.Label + k int + i int +} + +func (d *descriptor) String() string { + return fmt.Sprintf("%s,%d,%d", d.L, d.k, d.i) +} + +func (p *parser) dscAdd(L slot.Label, k, i int) { + // fmt.Printf("p.dscAdd(%s,%d,%d)\n", L, k, i) + d := &descriptor{L, k, i} + if !p.U.contain(d) { + p.R.set = append(p.R.set, d) + p.U.set = append(p.U.set, d) + } +} + +func (ds *descriptors) remove() (L slot.Label, k, i int) { + d := ds.set[len(ds.set)-1] + ds.set = ds.set[:len(ds.set)-1] + // fmt.Printf("remove: %s,%d,%d\n", d.L, d.k, d.i) + return d.L, d.k, d.i +} + +func (p *parser) DumpDescriptors() { + p.DumpR() + p.DumpU() +} + +func (p *parser) DumpR() { + fmt.Println("R:") + for _, d := range p.R.set { + fmt.Printf(" %s\n", d) + } +} + +func (p *parser) DumpU() { + fmt.Println("U:") + for _, d := range p.U.set { + fmt.Printf(" %s\n", d) + } +} + +/*** TestSelect ***/ + +func (p *parser) follow(nt symbols.NT) bool { + _, exist := followSets[nt][p.lex.Tokens[p.cI].Type()] + return exist +} + +func (p *parser) testSelect(l slot.Label) bool { + _, exist := first[l][p.lex.Tokens[p.cI].Type()] + // fmt.Printf("testSelect(%s) = %t\n", l, exist) + return exist +} + +var first = []map[token.Type]string{ + // ApplyChunk : ∙apply_snapshot_chunk + { + token.T_0: "apply_snapshot_chunk", + }, + // ApplyChunk : apply_snapshot_chunk ∙ + { + token.T_0: "apply_snapshot_chunk", + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_5: "offer_snapshot", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ApplyChunks : ∙ApplyChunk + { + token.T_0: "apply_snapshot_chunk", + }, + // ApplyChunks : ApplyChunk ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_5: "offer_snapshot", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ApplyChunks : ∙ApplyChunk ApplyChunks + { + token.T_0: "apply_snapshot_chunk", + }, + // ApplyChunks : ApplyChunk ∙ApplyChunks + { + token.T_0: "apply_snapshot_chunk", + }, + // ApplyChunks : ApplyChunk ApplyChunks ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_5: "offer_snapshot", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // CleanStart : ∙InitChain ConsensusExec + { + token.T_4: "init_chain", + }, + // CleanStart : InitChain ∙ConsensusExec + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // CleanStart : InitChain ConsensusExec ∙ + { + token.EOF: "$", + }, + // CleanStart : ∙StateSync ConsensusExec + { + token.T_5: "offer_snapshot", + }, + // CleanStart : StateSync ∙ConsensusExec + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // CleanStart : StateSync ConsensusExec ∙ + { + token.EOF: "$", + }, + // Commit : ∙commit + { + token.T_1: "commit", + }, + // Commit : commit ∙ + { + token.EOF: "$", + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusExec : ∙ConsensusHeights + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusExec : ConsensusHeights ∙ + { + token.EOF: "$", + }, + // ConsensusHeight : ∙ConsensusRounds FinalizeBlock Commit + { + token.T_2: "extend_vote", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusHeight : ConsensusRounds ∙FinalizeBlock Commit + { + token.T_3: "finalize_block", + }, + // ConsensusHeight : ConsensusRounds FinalizeBlock ∙Commit + { + token.T_1: "commit", + }, + // ConsensusHeight : ConsensusRounds FinalizeBlock Commit ∙ + { + token.EOF: "$", + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusHeight : ∙FinalizeBlock Commit + { + token.T_3: "finalize_block", + }, + // ConsensusHeight : FinalizeBlock ∙Commit + { + token.T_1: "commit", + }, + // ConsensusHeight : FinalizeBlock Commit ∙ + { + token.EOF: "$", + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusHeights : ∙ConsensusHeight + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusHeights : ConsensusHeight ∙ + { + token.EOF: "$", + }, + // ConsensusHeights : ∙ConsensusHeight ConsensusHeights + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusHeights : ConsensusHeight ∙ConsensusHeights + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusHeights : ConsensusHeight ConsensusHeights ∙ + { + token.EOF: "$", + }, + // ConsensusRound : ∙Proposer + { + token.T_2: "extend_vote", + token.T_6: "prepare_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusRound : Proposer ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusRound : ∙NonProposer + { + token.T_2: "extend_vote", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusRound : NonProposer ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusRounds : ∙ConsensusRound + { + token.T_2: "extend_vote", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusRounds : ConsensusRound ∙ + { + token.T_3: "finalize_block", + }, + // ConsensusRounds : ∙ConsensusRound ConsensusRounds + { + token.T_2: "extend_vote", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusRounds : ConsensusRound ∙ConsensusRounds + { + token.T_2: "extend_vote", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusRounds : ConsensusRound ConsensusRounds ∙ + { + token.T_3: "finalize_block", + }, + // Extend : ∙ExtendVote + { + token.T_2: "extend_vote", + }, + // Extend : ExtendVote ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Extend : ∙GotVotes ExtendVote + { + token.T_8: "verify_vote_extension", + }, + // Extend : GotVotes ∙ExtendVote + { + token.T_2: "extend_vote", + }, + // Extend : GotVotes ExtendVote ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Extend : ∙ExtendVote GotVotes + { + token.T_2: "extend_vote", + }, + // Extend : ExtendVote ∙GotVotes + { + token.T_8: "verify_vote_extension", + }, + // Extend : ExtendVote GotVotes ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Extend : ∙GotVotes ExtendVote GotVotes + { + token.T_8: "verify_vote_extension", + }, + // Extend : GotVotes ∙ExtendVote GotVotes + { + token.T_2: "extend_vote", + }, + // Extend : GotVotes ExtendVote ∙GotVotes + { + token.T_8: "verify_vote_extension", + }, + // Extend : GotVotes ExtendVote GotVotes ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ExtendVote : ∙extend_vote + { + token.T_2: "extend_vote", + }, + // ExtendVote : extend_vote ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // FinalizeBlock : ∙finalize_block + { + token.T_3: "finalize_block", + }, + // FinalizeBlock : finalize_block ∙ + { + token.T_1: "commit", + }, + // GotVote : ∙verify_vote_extension + { + token.T_8: "verify_vote_extension", + }, + // GotVote : verify_vote_extension ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // GotVotes : ∙GotVote + { + token.T_8: "verify_vote_extension", + }, + // GotVotes : GotVote ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // GotVotes : ∙GotVote GotVotes + { + token.T_8: "verify_vote_extension", + }, + // GotVotes : GotVote ∙GotVotes + { + token.T_8: "verify_vote_extension", + }, + // GotVotes : GotVote GotVotes ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // InitChain : ∙init_chain + { + token.T_4: "init_chain", + }, + // InitChain : init_chain ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // NonProposer : ∙GotVotes + { + token.T_8: "verify_vote_extension", + }, + // NonProposer : GotVotes ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // NonProposer : ∙ProcessProposal + { + token.T_7: "process_proposal", + }, + // NonProposer : ProcessProposal ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // NonProposer : ∙Extend + { + token.T_2: "extend_vote", + token.T_8: "verify_vote_extension", + }, + // NonProposer : Extend ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // NonProposer : ∙GotVotes ProcessProposal + { + token.T_8: "verify_vote_extension", + }, + // NonProposer : GotVotes ∙ProcessProposal + { + token.T_7: "process_proposal", + }, + // NonProposer : GotVotes ProcessProposal ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // NonProposer : ∙GotVotes Extend + { + token.T_8: "verify_vote_extension", + }, + // NonProposer : GotVotes ∙Extend + { + token.T_2: "extend_vote", + token.T_8: "verify_vote_extension", + }, + // NonProposer : GotVotes Extend ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // NonProposer : ∙ProcessProposal Extend + { + token.T_7: "process_proposal", + }, + // NonProposer : ProcessProposal ∙Extend + { + token.T_2: "extend_vote", + token.T_8: "verify_vote_extension", + }, + // NonProposer : ProcessProposal Extend ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // NonProposer : ∙GotVotes ProcessProposal Extend + { + token.T_8: "verify_vote_extension", + }, + // NonProposer : GotVotes ∙ProcessProposal Extend + { + token.T_7: "process_proposal", + }, + // NonProposer : GotVotes ProcessProposal ∙Extend + { + token.T_2: "extend_vote", + token.T_8: "verify_vote_extension", + }, + // NonProposer : GotVotes ProcessProposal Extend ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // OfferSnapshot : ∙offer_snapshot + { + token.T_5: "offer_snapshot", + }, + // OfferSnapshot : offer_snapshot ∙ + { + token.T_0: "apply_snapshot_chunk", + token.T_5: "offer_snapshot", + }, + // PrepareProposal : ∙prepare_proposal + { + token.T_6: "prepare_proposal", + }, + // PrepareProposal : prepare_proposal ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ProcessProposal : ∙process_proposal + { + token.T_7: "process_proposal", + }, + // ProcessProposal : process_proposal ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Proposer : ∙GotVotes + { + token.T_8: "verify_vote_extension", + }, + // Proposer : GotVotes ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Proposer : ∙ProposerSimple + { + token.T_6: "prepare_proposal", + }, + // Proposer : ProposerSimple ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Proposer : ∙Extend + { + token.T_2: "extend_vote", + token.T_8: "verify_vote_extension", + }, + // Proposer : Extend ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Proposer : ∙GotVotes ProposerSimple + { + token.T_8: "verify_vote_extension", + }, + // Proposer : GotVotes ∙ProposerSimple + { + token.T_6: "prepare_proposal", + }, + // Proposer : GotVotes ProposerSimple ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Proposer : ∙GotVotes Extend + { + token.T_8: "verify_vote_extension", + }, + // Proposer : GotVotes ∙Extend + { + token.T_2: "extend_vote", + token.T_8: "verify_vote_extension", + }, + // Proposer : GotVotes Extend ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Proposer : ∙ProposerSimple Extend + { + token.T_6: "prepare_proposal", + }, + // Proposer : ProposerSimple ∙Extend + { + token.T_2: "extend_vote", + token.T_8: "verify_vote_extension", + }, + // Proposer : ProposerSimple Extend ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Proposer : ∙GotVotes ProposerSimple Extend + { + token.T_8: "verify_vote_extension", + }, + // Proposer : GotVotes ∙ProposerSimple Extend + { + token.T_6: "prepare_proposal", + }, + // Proposer : GotVotes ProposerSimple ∙Extend + { + token.T_2: "extend_vote", + token.T_8: "verify_vote_extension", + }, + // Proposer : GotVotes ProposerSimple Extend ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ProposerSimple : ∙PrepareProposal + { + token.T_6: "prepare_proposal", + }, + // ProposerSimple : PrepareProposal ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ProposerSimple : ∙PrepareProposal ProcessProposal + { + token.T_6: "prepare_proposal", + }, + // ProposerSimple : PrepareProposal ∙ProcessProposal + { + token.T_7: "process_proposal", + }, + // ProposerSimple : PrepareProposal ProcessProposal ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Recovery : ∙InitChain ConsensusExec + { + token.T_4: "init_chain", + }, + // Recovery : InitChain ∙ConsensusExec + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Recovery : InitChain ConsensusExec ∙ + { + token.EOF: "$", + }, + // Recovery : ∙ConsensusExec + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Recovery : ConsensusExec ∙ + { + token.EOF: "$", + }, + // Start : ∙CleanStart + { + token.T_4: "init_chain", + token.T_5: "offer_snapshot", + }, + // Start : CleanStart ∙ + { + token.EOF: "$", + }, + // Start : ∙Recovery + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_4: "init_chain", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Start : Recovery ∙ + { + token.EOF: "$", + }, + // StateSync : ∙StateSyncAttempts SuccessSync + { + token.T_5: "offer_snapshot", + }, + // StateSync : StateSyncAttempts ∙SuccessSync + { + token.T_5: "offer_snapshot", + }, + // StateSync : StateSyncAttempts SuccessSync ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // StateSync : ∙SuccessSync + { + token.T_5: "offer_snapshot", + }, + // StateSync : SuccessSync ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // StateSyncAttempt : ∙OfferSnapshot ApplyChunks + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempt : OfferSnapshot ∙ApplyChunks + { + token.T_0: "apply_snapshot_chunk", + }, + // StateSyncAttempt : OfferSnapshot ApplyChunks ∙ + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempt : ∙OfferSnapshot + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempt : OfferSnapshot ∙ + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempts : ∙StateSyncAttempt + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempts : StateSyncAttempt ∙ + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempts : ∙StateSyncAttempt StateSyncAttempts + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempts : StateSyncAttempt ∙StateSyncAttempts + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempts : StateSyncAttempt StateSyncAttempts ∙ + { + token.T_5: "offer_snapshot", + }, + // SuccessSync : ∙OfferSnapshot ApplyChunks + { + token.T_5: "offer_snapshot", + }, + // SuccessSync : OfferSnapshot ∙ApplyChunks + { + token.T_0: "apply_snapshot_chunk", + }, + // SuccessSync : OfferSnapshot ApplyChunks ∙ + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, +} + +var followSets = []map[token.Type]string{ + // ApplyChunk + { + token.T_0: "apply_snapshot_chunk", + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_5: "offer_snapshot", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ApplyChunks + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_5: "offer_snapshot", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // CleanStart + { + token.EOF: "$", + }, + // Commit + { + token.EOF: "$", + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusExec + { + token.EOF: "$", + }, + // ConsensusHeight + { + token.EOF: "$", + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusHeights + { + token.EOF: "$", + }, + // ConsensusRound + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ConsensusRounds + { + token.T_3: "finalize_block", + }, + // Extend + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ExtendVote + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // FinalizeBlock + { + token.T_1: "commit", + }, + // GotVote + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // GotVotes + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // InitChain + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // NonProposer + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // OfferSnapshot + { + token.T_0: "apply_snapshot_chunk", + token.T_5: "offer_snapshot", + }, + // PrepareProposal + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ProcessProposal + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Proposer + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // ProposerSimple + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // Recovery + { + token.EOF: "$", + }, + // Start + { + token.EOF: "$", + }, + // StateSync + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, + // StateSyncAttempt + { + token.T_5: "offer_snapshot", + }, + // StateSyncAttempts + { + token.T_5: "offer_snapshot", + }, + // SuccessSync + { + token.T_2: "extend_vote", + token.T_3: "finalize_block", + token.T_6: "prepare_proposal", + token.T_7: "process_proposal", + token.T_8: "verify_vote_extension", + }, +} + +/*** Errors ***/ + +/* +Error is returned by Parse at every point at which the parser fails to parse +a grammar production. For non-LL-1 grammars there will be an error for each +alternate attempted by the parser. + +The errors are sorted in descending order of input position (index of token in +the stream of tokens). + +Normally the error of interest is the one that has parsed the largest number of +tokens. +*/ +type Error struct { + // Index of token that caused the error. + cI int + + // Grammar slot at which the error occured. + Slot slot.Label + + // The token at which the error occurred. + Token *token.Token + + // The line and column in the input text at which the error occurred + Line, Column int + + // The tokens expected at the point where the error occurred + Expected map[token.Type]string +} + +func (pe *Error) String() string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "Parse Error: %s I[%d]=%s at line %d col %d\n", + pe.Slot, pe.cI, pe.Token, pe.Line, pe.Column) + exp := []string{} + for _, e := range pe.Expected { + exp = append(exp, e) + } + fmt.Fprintf(w, "Expected one of: [%s]", strings.Join(exp, ",")) + return w.String() +} + +func (p *parser) parseError(slot slot.Label, i int, expected map[token.Type]string) { + pe := &Error{cI: i, Slot: slot, Token: p.lex.Tokens[i], Expected: expected} + p.parseErrors = append(p.parseErrors, pe) +} + +func (p *parser) sortParseErrors() { + sort.Slice(p.parseErrors, + func(i, j int) bool { + return p.parseErrors[j].Token.Lext() < p.parseErrors[i].Token.Lext() + }) + for _, pe := range p.parseErrors { + pe.Line, pe.Column = p.lex.GetLineColumn(pe.Token.Lext()) + } +} diff --git a/test/e2e/pkg/grammar/grammar-auto/parser/slot/slot.go b/test/e2e/pkg/grammar/grammar-auto/parser/slot/slot.go new file mode 100644 index 00000000000..e5f69183944 --- /dev/null +++ b/test/e2e/pkg/grammar/grammar-auto/parser/slot/slot.go @@ -0,0 +1,1482 @@ +// Package slot is generated by gogll. Do not edit. +package slot + +import ( + "bytes" + "fmt" + + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser/symbols" +) + +type Label int + +const ( + ApplyChunk0R0 Label = iota + ApplyChunk0R1 + ApplyChunks0R0 + ApplyChunks0R1 + ApplyChunks1R0 + ApplyChunks1R1 + ApplyChunks1R2 + CleanStart0R0 + CleanStart0R1 + CleanStart0R2 + CleanStart1R0 + CleanStart1R1 + CleanStart1R2 + Commit0R0 + Commit0R1 + ConsensusExec0R0 + ConsensusExec0R1 + ConsensusHeight0R0 + ConsensusHeight0R1 + ConsensusHeight0R2 + ConsensusHeight0R3 + ConsensusHeight1R0 + ConsensusHeight1R1 + ConsensusHeight1R2 + ConsensusHeights0R0 + ConsensusHeights0R1 + ConsensusHeights1R0 + ConsensusHeights1R1 + ConsensusHeights1R2 + ConsensusRound0R0 + ConsensusRound0R1 + ConsensusRound1R0 + ConsensusRound1R1 + ConsensusRounds0R0 + ConsensusRounds0R1 + ConsensusRounds1R0 + ConsensusRounds1R1 + ConsensusRounds1R2 + Extend0R0 + Extend0R1 + Extend1R0 + Extend1R1 + Extend1R2 + Extend2R0 + Extend2R1 + Extend2R2 + Extend3R0 + Extend3R1 + Extend3R2 + Extend3R3 + ExtendVote0R0 + ExtendVote0R1 + FinalizeBlock0R0 + FinalizeBlock0R1 + GotVote0R0 + GotVote0R1 + GotVotes0R0 + GotVotes0R1 + GotVotes1R0 + GotVotes1R1 + GotVotes1R2 + InitChain0R0 + InitChain0R1 + NonProposer0R0 + NonProposer0R1 + NonProposer1R0 + NonProposer1R1 + NonProposer2R0 + NonProposer2R1 + NonProposer3R0 + NonProposer3R1 + NonProposer3R2 + NonProposer4R0 + NonProposer4R1 + NonProposer4R2 + NonProposer5R0 + NonProposer5R1 + NonProposer5R2 + NonProposer6R0 + NonProposer6R1 + NonProposer6R2 + NonProposer6R3 + OfferSnapshot0R0 + OfferSnapshot0R1 + PrepareProposal0R0 + PrepareProposal0R1 + ProcessProposal0R0 + ProcessProposal0R1 + Proposer0R0 + Proposer0R1 + Proposer1R0 + Proposer1R1 + Proposer2R0 + Proposer2R1 + Proposer3R0 + Proposer3R1 + Proposer3R2 + Proposer4R0 + Proposer4R1 + Proposer4R2 + Proposer5R0 + Proposer5R1 + Proposer5R2 + Proposer6R0 + Proposer6R1 + Proposer6R2 + Proposer6R3 + ProposerSimple0R0 + ProposerSimple0R1 + ProposerSimple1R0 + ProposerSimple1R1 + ProposerSimple1R2 + Recovery0R0 + Recovery0R1 + Recovery0R2 + Recovery1R0 + Recovery1R1 + Start0R0 + Start0R1 + Start1R0 + Start1R1 + StateSync0R0 + StateSync0R1 + StateSync0R2 + StateSync1R0 + StateSync1R1 + StateSyncAttempt0R0 + StateSyncAttempt0R1 + StateSyncAttempt0R2 + StateSyncAttempt1R0 + StateSyncAttempt1R1 + StateSyncAttempts0R0 + StateSyncAttempts0R1 + StateSyncAttempts1R0 + StateSyncAttempts1R1 + StateSyncAttempts1R2 + SuccessSync0R0 + SuccessSync0R1 + SuccessSync0R2 +) + +type Slot struct { + NT symbols.NT + Alt int + Pos int + Symbols symbols.Symbols + Label Label +} + +type Index struct { + NT symbols.NT + Alt int + Pos int +} + +func GetAlternates(nt symbols.NT) []Label { + alts, exist := alternates[nt] + if !exist { + panic(fmt.Sprintf("Invalid NT %s", nt)) + } + return alts +} + +func GetLabel(nt symbols.NT, alt, pos int) Label { + l, exist := slotIndex[Index{nt, alt, pos}] + if exist { + return l + } + panic(fmt.Sprintf("Error: no slot label for NT=%s, alt=%d, pos=%d", nt, alt, pos)) +} + +func (l Label) EoR() bool { + return l.Slot().EoR() +} + +func (l Label) Head() symbols.NT { + return l.Slot().NT +} + +func (l Label) Index() Index { + s := l.Slot() + return Index{s.NT, s.Alt, s.Pos} +} + +func (l Label) Alternate() int { + return l.Slot().Alt +} + +func (l Label) Pos() int { + return l.Slot().Pos +} + +func (l Label) Slot() *Slot { + s, exist := slots[l] + if !exist { + panic(fmt.Sprintf("Invalid slot label %d", l)) + } + return s +} + +func (l Label) String() string { + return l.Slot().String() +} + +func (l Label) Symbols() symbols.Symbols { + return l.Slot().Symbols +} + +func (s *Slot) EoR() bool { + return s.Pos >= len(s.Symbols) +} + +func (s *Slot) String() string { + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "%s : ", s.NT) + for i, sym := range s.Symbols { + if i == s.Pos { + fmt.Fprintf(buf, "∙") + } + fmt.Fprintf(buf, "%s ", sym) + } + if s.Pos >= len(s.Symbols) { + fmt.Fprintf(buf, "∙") + } + return buf.String() +} + +var slots = map[Label]*Slot{ + ApplyChunk0R0: { + symbols.NT_ApplyChunk, 0, 0, + symbols.Symbols{ + symbols.T_0, + }, + ApplyChunk0R0, + }, + ApplyChunk0R1: { + symbols.NT_ApplyChunk, 0, 1, + symbols.Symbols{ + symbols.T_0, + }, + ApplyChunk0R1, + }, + ApplyChunks0R0: { + symbols.NT_ApplyChunks, 0, 0, + symbols.Symbols{ + symbols.NT_ApplyChunk, + }, + ApplyChunks0R0, + }, + ApplyChunks0R1: { + symbols.NT_ApplyChunks, 0, 1, + symbols.Symbols{ + symbols.NT_ApplyChunk, + }, + ApplyChunks0R1, + }, + ApplyChunks1R0: { + symbols.NT_ApplyChunks, 1, 0, + symbols.Symbols{ + symbols.NT_ApplyChunk, + symbols.NT_ApplyChunks, + }, + ApplyChunks1R0, + }, + ApplyChunks1R1: { + symbols.NT_ApplyChunks, 1, 1, + symbols.Symbols{ + symbols.NT_ApplyChunk, + symbols.NT_ApplyChunks, + }, + ApplyChunks1R1, + }, + ApplyChunks1R2: { + symbols.NT_ApplyChunks, 1, 2, + symbols.Symbols{ + symbols.NT_ApplyChunk, + symbols.NT_ApplyChunks, + }, + ApplyChunks1R2, + }, + CleanStart0R0: { + symbols.NT_CleanStart, 0, 0, + symbols.Symbols{ + symbols.NT_InitChain, + symbols.NT_ConsensusExec, + }, + CleanStart0R0, + }, + CleanStart0R1: { + symbols.NT_CleanStart, 0, 1, + symbols.Symbols{ + symbols.NT_InitChain, + symbols.NT_ConsensusExec, + }, + CleanStart0R1, + }, + CleanStart0R2: { + symbols.NT_CleanStart, 0, 2, + symbols.Symbols{ + symbols.NT_InitChain, + symbols.NT_ConsensusExec, + }, + CleanStart0R2, + }, + CleanStart1R0: { + symbols.NT_CleanStart, 1, 0, + symbols.Symbols{ + symbols.NT_StateSync, + symbols.NT_ConsensusExec, + }, + CleanStart1R0, + }, + CleanStart1R1: { + symbols.NT_CleanStart, 1, 1, + symbols.Symbols{ + symbols.NT_StateSync, + symbols.NT_ConsensusExec, + }, + CleanStart1R1, + }, + CleanStart1R2: { + symbols.NT_CleanStart, 1, 2, + symbols.Symbols{ + symbols.NT_StateSync, + symbols.NT_ConsensusExec, + }, + CleanStart1R2, + }, + Commit0R0: { + symbols.NT_Commit, 0, 0, + symbols.Symbols{ + symbols.T_1, + }, + Commit0R0, + }, + Commit0R1: { + symbols.NT_Commit, 0, 1, + symbols.Symbols{ + symbols.T_1, + }, + Commit0R1, + }, + ConsensusExec0R0: { + symbols.NT_ConsensusExec, 0, 0, + symbols.Symbols{ + symbols.NT_ConsensusHeights, + }, + ConsensusExec0R0, + }, + ConsensusExec0R1: { + symbols.NT_ConsensusExec, 0, 1, + symbols.Symbols{ + symbols.NT_ConsensusHeights, + }, + ConsensusExec0R1, + }, + ConsensusHeight0R0: { + symbols.NT_ConsensusHeight, 0, 0, + symbols.Symbols{ + symbols.NT_ConsensusRounds, + symbols.NT_FinalizeBlock, + symbols.NT_Commit, + }, + ConsensusHeight0R0, + }, + ConsensusHeight0R1: { + symbols.NT_ConsensusHeight, 0, 1, + symbols.Symbols{ + symbols.NT_ConsensusRounds, + symbols.NT_FinalizeBlock, + symbols.NT_Commit, + }, + ConsensusHeight0R1, + }, + ConsensusHeight0R2: { + symbols.NT_ConsensusHeight, 0, 2, + symbols.Symbols{ + symbols.NT_ConsensusRounds, + symbols.NT_FinalizeBlock, + symbols.NT_Commit, + }, + ConsensusHeight0R2, + }, + ConsensusHeight0R3: { + symbols.NT_ConsensusHeight, 0, 3, + symbols.Symbols{ + symbols.NT_ConsensusRounds, + symbols.NT_FinalizeBlock, + symbols.NT_Commit, + }, + ConsensusHeight0R3, + }, + ConsensusHeight1R0: { + symbols.NT_ConsensusHeight, 1, 0, + symbols.Symbols{ + symbols.NT_FinalizeBlock, + symbols.NT_Commit, + }, + ConsensusHeight1R0, + }, + ConsensusHeight1R1: { + symbols.NT_ConsensusHeight, 1, 1, + symbols.Symbols{ + symbols.NT_FinalizeBlock, + symbols.NT_Commit, + }, + ConsensusHeight1R1, + }, + ConsensusHeight1R2: { + symbols.NT_ConsensusHeight, 1, 2, + symbols.Symbols{ + symbols.NT_FinalizeBlock, + symbols.NT_Commit, + }, + ConsensusHeight1R2, + }, + ConsensusHeights0R0: { + symbols.NT_ConsensusHeights, 0, 0, + symbols.Symbols{ + symbols.NT_ConsensusHeight, + }, + ConsensusHeights0R0, + }, + ConsensusHeights0R1: { + symbols.NT_ConsensusHeights, 0, 1, + symbols.Symbols{ + symbols.NT_ConsensusHeight, + }, + ConsensusHeights0R1, + }, + ConsensusHeights1R0: { + symbols.NT_ConsensusHeights, 1, 0, + symbols.Symbols{ + symbols.NT_ConsensusHeight, + symbols.NT_ConsensusHeights, + }, + ConsensusHeights1R0, + }, + ConsensusHeights1R1: { + symbols.NT_ConsensusHeights, 1, 1, + symbols.Symbols{ + symbols.NT_ConsensusHeight, + symbols.NT_ConsensusHeights, + }, + ConsensusHeights1R1, + }, + ConsensusHeights1R2: { + symbols.NT_ConsensusHeights, 1, 2, + symbols.Symbols{ + symbols.NT_ConsensusHeight, + symbols.NT_ConsensusHeights, + }, + ConsensusHeights1R2, + }, + ConsensusRound0R0: { + symbols.NT_ConsensusRound, 0, 0, + symbols.Symbols{ + symbols.NT_Proposer, + }, + ConsensusRound0R0, + }, + ConsensusRound0R1: { + symbols.NT_ConsensusRound, 0, 1, + symbols.Symbols{ + symbols.NT_Proposer, + }, + ConsensusRound0R1, + }, + ConsensusRound1R0: { + symbols.NT_ConsensusRound, 1, 0, + symbols.Symbols{ + symbols.NT_NonProposer, + }, + ConsensusRound1R0, + }, + ConsensusRound1R1: { + symbols.NT_ConsensusRound, 1, 1, + symbols.Symbols{ + symbols.NT_NonProposer, + }, + ConsensusRound1R1, + }, + ConsensusRounds0R0: { + symbols.NT_ConsensusRounds, 0, 0, + symbols.Symbols{ + symbols.NT_ConsensusRound, + }, + ConsensusRounds0R0, + }, + ConsensusRounds0R1: { + symbols.NT_ConsensusRounds, 0, 1, + symbols.Symbols{ + symbols.NT_ConsensusRound, + }, + ConsensusRounds0R1, + }, + ConsensusRounds1R0: { + symbols.NT_ConsensusRounds, 1, 0, + symbols.Symbols{ + symbols.NT_ConsensusRound, + symbols.NT_ConsensusRounds, + }, + ConsensusRounds1R0, + }, + ConsensusRounds1R1: { + symbols.NT_ConsensusRounds, 1, 1, + symbols.Symbols{ + symbols.NT_ConsensusRound, + symbols.NT_ConsensusRounds, + }, + ConsensusRounds1R1, + }, + ConsensusRounds1R2: { + symbols.NT_ConsensusRounds, 1, 2, + symbols.Symbols{ + symbols.NT_ConsensusRound, + symbols.NT_ConsensusRounds, + }, + ConsensusRounds1R2, + }, + Extend0R0: { + symbols.NT_Extend, 0, 0, + symbols.Symbols{ + symbols.NT_ExtendVote, + }, + Extend0R0, + }, + Extend0R1: { + symbols.NT_Extend, 0, 1, + symbols.Symbols{ + symbols.NT_ExtendVote, + }, + Extend0R1, + }, + Extend1R0: { + symbols.NT_Extend, 1, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ExtendVote, + }, + Extend1R0, + }, + Extend1R1: { + symbols.NT_Extend, 1, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ExtendVote, + }, + Extend1R1, + }, + Extend1R2: { + symbols.NT_Extend, 1, 2, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ExtendVote, + }, + Extend1R2, + }, + Extend2R0: { + symbols.NT_Extend, 2, 0, + symbols.Symbols{ + symbols.NT_ExtendVote, + symbols.NT_GotVotes, + }, + Extend2R0, + }, + Extend2R1: { + symbols.NT_Extend, 2, 1, + symbols.Symbols{ + symbols.NT_ExtendVote, + symbols.NT_GotVotes, + }, + Extend2R1, + }, + Extend2R2: { + symbols.NT_Extend, 2, 2, + symbols.Symbols{ + symbols.NT_ExtendVote, + symbols.NT_GotVotes, + }, + Extend2R2, + }, + Extend3R0: { + symbols.NT_Extend, 3, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ExtendVote, + symbols.NT_GotVotes, + }, + Extend3R0, + }, + Extend3R1: { + symbols.NT_Extend, 3, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ExtendVote, + symbols.NT_GotVotes, + }, + Extend3R1, + }, + Extend3R2: { + symbols.NT_Extend, 3, 2, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ExtendVote, + symbols.NT_GotVotes, + }, + Extend3R2, + }, + Extend3R3: { + symbols.NT_Extend, 3, 3, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ExtendVote, + symbols.NT_GotVotes, + }, + Extend3R3, + }, + ExtendVote0R0: { + symbols.NT_ExtendVote, 0, 0, + symbols.Symbols{ + symbols.T_2, + }, + ExtendVote0R0, + }, + ExtendVote0R1: { + symbols.NT_ExtendVote, 0, 1, + symbols.Symbols{ + symbols.T_2, + }, + ExtendVote0R1, + }, + FinalizeBlock0R0: { + symbols.NT_FinalizeBlock, 0, 0, + symbols.Symbols{ + symbols.T_3, + }, + FinalizeBlock0R0, + }, + FinalizeBlock0R1: { + symbols.NT_FinalizeBlock, 0, 1, + symbols.Symbols{ + symbols.T_3, + }, + FinalizeBlock0R1, + }, + GotVote0R0: { + symbols.NT_GotVote, 0, 0, + symbols.Symbols{ + symbols.T_8, + }, + GotVote0R0, + }, + GotVote0R1: { + symbols.NT_GotVote, 0, 1, + symbols.Symbols{ + symbols.T_8, + }, + GotVote0R1, + }, + GotVotes0R0: { + symbols.NT_GotVotes, 0, 0, + symbols.Symbols{ + symbols.NT_GotVote, + }, + GotVotes0R0, + }, + GotVotes0R1: { + symbols.NT_GotVotes, 0, 1, + symbols.Symbols{ + symbols.NT_GotVote, + }, + GotVotes0R1, + }, + GotVotes1R0: { + symbols.NT_GotVotes, 1, 0, + symbols.Symbols{ + symbols.NT_GotVote, + symbols.NT_GotVotes, + }, + GotVotes1R0, + }, + GotVotes1R1: { + symbols.NT_GotVotes, 1, 1, + symbols.Symbols{ + symbols.NT_GotVote, + symbols.NT_GotVotes, + }, + GotVotes1R1, + }, + GotVotes1R2: { + symbols.NT_GotVotes, 1, 2, + symbols.Symbols{ + symbols.NT_GotVote, + symbols.NT_GotVotes, + }, + GotVotes1R2, + }, + InitChain0R0: { + symbols.NT_InitChain, 0, 0, + symbols.Symbols{ + symbols.T_4, + }, + InitChain0R0, + }, + InitChain0R1: { + symbols.NT_InitChain, 0, 1, + symbols.Symbols{ + symbols.T_4, + }, + InitChain0R1, + }, + NonProposer0R0: { + symbols.NT_NonProposer, 0, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + }, + NonProposer0R0, + }, + NonProposer0R1: { + symbols.NT_NonProposer, 0, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + }, + NonProposer0R1, + }, + NonProposer1R0: { + symbols.NT_NonProposer, 1, 0, + symbols.Symbols{ + symbols.NT_ProcessProposal, + }, + NonProposer1R0, + }, + NonProposer1R1: { + symbols.NT_NonProposer, 1, 1, + symbols.Symbols{ + symbols.NT_ProcessProposal, + }, + NonProposer1R1, + }, + NonProposer2R0: { + symbols.NT_NonProposer, 2, 0, + symbols.Symbols{ + symbols.NT_Extend, + }, + NonProposer2R0, + }, + NonProposer2R1: { + symbols.NT_NonProposer, 2, 1, + symbols.Symbols{ + symbols.NT_Extend, + }, + NonProposer2R1, + }, + NonProposer3R0: { + symbols.NT_NonProposer, 3, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProcessProposal, + }, + NonProposer3R0, + }, + NonProposer3R1: { + symbols.NT_NonProposer, 3, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProcessProposal, + }, + NonProposer3R1, + }, + NonProposer3R2: { + symbols.NT_NonProposer, 3, 2, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProcessProposal, + }, + NonProposer3R2, + }, + NonProposer4R0: { + symbols.NT_NonProposer, 4, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_Extend, + }, + NonProposer4R0, + }, + NonProposer4R1: { + symbols.NT_NonProposer, 4, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_Extend, + }, + NonProposer4R1, + }, + NonProposer4R2: { + symbols.NT_NonProposer, 4, 2, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_Extend, + }, + NonProposer4R2, + }, + NonProposer5R0: { + symbols.NT_NonProposer, 5, 0, + symbols.Symbols{ + symbols.NT_ProcessProposal, + symbols.NT_Extend, + }, + NonProposer5R0, + }, + NonProposer5R1: { + symbols.NT_NonProposer, 5, 1, + symbols.Symbols{ + symbols.NT_ProcessProposal, + symbols.NT_Extend, + }, + NonProposer5R1, + }, + NonProposer5R2: { + symbols.NT_NonProposer, 5, 2, + symbols.Symbols{ + symbols.NT_ProcessProposal, + symbols.NT_Extend, + }, + NonProposer5R2, + }, + NonProposer6R0: { + symbols.NT_NonProposer, 6, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProcessProposal, + symbols.NT_Extend, + }, + NonProposer6R0, + }, + NonProposer6R1: { + symbols.NT_NonProposer, 6, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProcessProposal, + symbols.NT_Extend, + }, + NonProposer6R1, + }, + NonProposer6R2: { + symbols.NT_NonProposer, 6, 2, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProcessProposal, + symbols.NT_Extend, + }, + NonProposer6R2, + }, + NonProposer6R3: { + symbols.NT_NonProposer, 6, 3, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProcessProposal, + symbols.NT_Extend, + }, + NonProposer6R3, + }, + OfferSnapshot0R0: { + symbols.NT_OfferSnapshot, 0, 0, + symbols.Symbols{ + symbols.T_5, + }, + OfferSnapshot0R0, + }, + OfferSnapshot0R1: { + symbols.NT_OfferSnapshot, 0, 1, + symbols.Symbols{ + symbols.T_5, + }, + OfferSnapshot0R1, + }, + PrepareProposal0R0: { + symbols.NT_PrepareProposal, 0, 0, + symbols.Symbols{ + symbols.T_6, + }, + PrepareProposal0R0, + }, + PrepareProposal0R1: { + symbols.NT_PrepareProposal, 0, 1, + symbols.Symbols{ + symbols.T_6, + }, + PrepareProposal0R1, + }, + ProcessProposal0R0: { + symbols.NT_ProcessProposal, 0, 0, + symbols.Symbols{ + symbols.T_7, + }, + ProcessProposal0R0, + }, + ProcessProposal0R1: { + symbols.NT_ProcessProposal, 0, 1, + symbols.Symbols{ + symbols.T_7, + }, + ProcessProposal0R1, + }, + Proposer0R0: { + symbols.NT_Proposer, 0, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + }, + Proposer0R0, + }, + Proposer0R1: { + symbols.NT_Proposer, 0, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + }, + Proposer0R1, + }, + Proposer1R0: { + symbols.NT_Proposer, 1, 0, + symbols.Symbols{ + symbols.NT_ProposerSimple, + }, + Proposer1R0, + }, + Proposer1R1: { + symbols.NT_Proposer, 1, 1, + symbols.Symbols{ + symbols.NT_ProposerSimple, + }, + Proposer1R1, + }, + Proposer2R0: { + symbols.NT_Proposer, 2, 0, + symbols.Symbols{ + symbols.NT_Extend, + }, + Proposer2R0, + }, + Proposer2R1: { + symbols.NT_Proposer, 2, 1, + symbols.Symbols{ + symbols.NT_Extend, + }, + Proposer2R1, + }, + Proposer3R0: { + symbols.NT_Proposer, 3, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProposerSimple, + }, + Proposer3R0, + }, + Proposer3R1: { + symbols.NT_Proposer, 3, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProposerSimple, + }, + Proposer3R1, + }, + Proposer3R2: { + symbols.NT_Proposer, 3, 2, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProposerSimple, + }, + Proposer3R2, + }, + Proposer4R0: { + symbols.NT_Proposer, 4, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_Extend, + }, + Proposer4R0, + }, + Proposer4R1: { + symbols.NT_Proposer, 4, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_Extend, + }, + Proposer4R1, + }, + Proposer4R2: { + symbols.NT_Proposer, 4, 2, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_Extend, + }, + Proposer4R2, + }, + Proposer5R0: { + symbols.NT_Proposer, 5, 0, + symbols.Symbols{ + symbols.NT_ProposerSimple, + symbols.NT_Extend, + }, + Proposer5R0, + }, + Proposer5R1: { + symbols.NT_Proposer, 5, 1, + symbols.Symbols{ + symbols.NT_ProposerSimple, + symbols.NT_Extend, + }, + Proposer5R1, + }, + Proposer5R2: { + symbols.NT_Proposer, 5, 2, + symbols.Symbols{ + symbols.NT_ProposerSimple, + symbols.NT_Extend, + }, + Proposer5R2, + }, + Proposer6R0: { + symbols.NT_Proposer, 6, 0, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProposerSimple, + symbols.NT_Extend, + }, + Proposer6R0, + }, + Proposer6R1: { + symbols.NT_Proposer, 6, 1, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProposerSimple, + symbols.NT_Extend, + }, + Proposer6R1, + }, + Proposer6R2: { + symbols.NT_Proposer, 6, 2, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProposerSimple, + symbols.NT_Extend, + }, + Proposer6R2, + }, + Proposer6R3: { + symbols.NT_Proposer, 6, 3, + symbols.Symbols{ + symbols.NT_GotVotes, + symbols.NT_ProposerSimple, + symbols.NT_Extend, + }, + Proposer6R3, + }, + ProposerSimple0R0: { + symbols.NT_ProposerSimple, 0, 0, + symbols.Symbols{ + symbols.NT_PrepareProposal, + }, + ProposerSimple0R0, + }, + ProposerSimple0R1: { + symbols.NT_ProposerSimple, 0, 1, + symbols.Symbols{ + symbols.NT_PrepareProposal, + }, + ProposerSimple0R1, + }, + ProposerSimple1R0: { + symbols.NT_ProposerSimple, 1, 0, + symbols.Symbols{ + symbols.NT_PrepareProposal, + symbols.NT_ProcessProposal, + }, + ProposerSimple1R0, + }, + ProposerSimple1R1: { + symbols.NT_ProposerSimple, 1, 1, + symbols.Symbols{ + symbols.NT_PrepareProposal, + symbols.NT_ProcessProposal, + }, + ProposerSimple1R1, + }, + ProposerSimple1R2: { + symbols.NT_ProposerSimple, 1, 2, + symbols.Symbols{ + symbols.NT_PrepareProposal, + symbols.NT_ProcessProposal, + }, + ProposerSimple1R2, + }, + Recovery0R0: { + symbols.NT_Recovery, 0, 0, + symbols.Symbols{ + symbols.NT_InitChain, + symbols.NT_ConsensusExec, + }, + Recovery0R0, + }, + Recovery0R1: { + symbols.NT_Recovery, 0, 1, + symbols.Symbols{ + symbols.NT_InitChain, + symbols.NT_ConsensusExec, + }, + Recovery0R1, + }, + Recovery0R2: { + symbols.NT_Recovery, 0, 2, + symbols.Symbols{ + symbols.NT_InitChain, + symbols.NT_ConsensusExec, + }, + Recovery0R2, + }, + Recovery1R0: { + symbols.NT_Recovery, 1, 0, + symbols.Symbols{ + symbols.NT_ConsensusExec, + }, + Recovery1R0, + }, + Recovery1R1: { + symbols.NT_Recovery, 1, 1, + symbols.Symbols{ + symbols.NT_ConsensusExec, + }, + Recovery1R1, + }, + Start0R0: { + symbols.NT_Start, 0, 0, + symbols.Symbols{ + symbols.NT_CleanStart, + }, + Start0R0, + }, + Start0R1: { + symbols.NT_Start, 0, 1, + symbols.Symbols{ + symbols.NT_CleanStart, + }, + Start0R1, + }, + Start1R0: { + symbols.NT_Start, 1, 0, + symbols.Symbols{ + symbols.NT_Recovery, + }, + Start1R0, + }, + Start1R1: { + symbols.NT_Start, 1, 1, + symbols.Symbols{ + symbols.NT_Recovery, + }, + Start1R1, + }, + StateSync0R0: { + symbols.NT_StateSync, 0, 0, + symbols.Symbols{ + symbols.NT_StateSyncAttempts, + symbols.NT_SuccessSync, + }, + StateSync0R0, + }, + StateSync0R1: { + symbols.NT_StateSync, 0, 1, + symbols.Symbols{ + symbols.NT_StateSyncAttempts, + symbols.NT_SuccessSync, + }, + StateSync0R1, + }, + StateSync0R2: { + symbols.NT_StateSync, 0, 2, + symbols.Symbols{ + symbols.NT_StateSyncAttempts, + symbols.NT_SuccessSync, + }, + StateSync0R2, + }, + StateSync1R0: { + symbols.NT_StateSync, 1, 0, + symbols.Symbols{ + symbols.NT_SuccessSync, + }, + StateSync1R0, + }, + StateSync1R1: { + symbols.NT_StateSync, 1, 1, + symbols.Symbols{ + symbols.NT_SuccessSync, + }, + StateSync1R1, + }, + StateSyncAttempt0R0: { + symbols.NT_StateSyncAttempt, 0, 0, + symbols.Symbols{ + symbols.NT_OfferSnapshot, + symbols.NT_ApplyChunks, + }, + StateSyncAttempt0R0, + }, + StateSyncAttempt0R1: { + symbols.NT_StateSyncAttempt, 0, 1, + symbols.Symbols{ + symbols.NT_OfferSnapshot, + symbols.NT_ApplyChunks, + }, + StateSyncAttempt0R1, + }, + StateSyncAttempt0R2: { + symbols.NT_StateSyncAttempt, 0, 2, + symbols.Symbols{ + symbols.NT_OfferSnapshot, + symbols.NT_ApplyChunks, + }, + StateSyncAttempt0R2, + }, + StateSyncAttempt1R0: { + symbols.NT_StateSyncAttempt, 1, 0, + symbols.Symbols{ + symbols.NT_OfferSnapshot, + }, + StateSyncAttempt1R0, + }, + StateSyncAttempt1R1: { + symbols.NT_StateSyncAttempt, 1, 1, + symbols.Symbols{ + symbols.NT_OfferSnapshot, + }, + StateSyncAttempt1R1, + }, + StateSyncAttempts0R0: { + symbols.NT_StateSyncAttempts, 0, 0, + symbols.Symbols{ + symbols.NT_StateSyncAttempt, + }, + StateSyncAttempts0R0, + }, + StateSyncAttempts0R1: { + symbols.NT_StateSyncAttempts, 0, 1, + symbols.Symbols{ + symbols.NT_StateSyncAttempt, + }, + StateSyncAttempts0R1, + }, + StateSyncAttempts1R0: { + symbols.NT_StateSyncAttempts, 1, 0, + symbols.Symbols{ + symbols.NT_StateSyncAttempt, + symbols.NT_StateSyncAttempts, + }, + StateSyncAttempts1R0, + }, + StateSyncAttempts1R1: { + symbols.NT_StateSyncAttempts, 1, 1, + symbols.Symbols{ + symbols.NT_StateSyncAttempt, + symbols.NT_StateSyncAttempts, + }, + StateSyncAttempts1R1, + }, + StateSyncAttempts1R2: { + symbols.NT_StateSyncAttempts, 1, 2, + symbols.Symbols{ + symbols.NT_StateSyncAttempt, + symbols.NT_StateSyncAttempts, + }, + StateSyncAttempts1R2, + }, + SuccessSync0R0: { + symbols.NT_SuccessSync, 0, 0, + symbols.Symbols{ + symbols.NT_OfferSnapshot, + symbols.NT_ApplyChunks, + }, + SuccessSync0R0, + }, + SuccessSync0R1: { + symbols.NT_SuccessSync, 0, 1, + symbols.Symbols{ + symbols.NT_OfferSnapshot, + symbols.NT_ApplyChunks, + }, + SuccessSync0R1, + }, + SuccessSync0R2: { + symbols.NT_SuccessSync, 0, 2, + symbols.Symbols{ + symbols.NT_OfferSnapshot, + symbols.NT_ApplyChunks, + }, + SuccessSync0R2, + }, +} + +var slotIndex = map[Index]Label{ + {symbols.NT_ApplyChunk, 0, 0}: ApplyChunk0R0, + {symbols.NT_ApplyChunk, 0, 1}: ApplyChunk0R1, + {symbols.NT_ApplyChunks, 0, 0}: ApplyChunks0R0, + {symbols.NT_ApplyChunks, 0, 1}: ApplyChunks0R1, + {symbols.NT_ApplyChunks, 1, 0}: ApplyChunks1R0, + {symbols.NT_ApplyChunks, 1, 1}: ApplyChunks1R1, + {symbols.NT_ApplyChunks, 1, 2}: ApplyChunks1R2, + {symbols.NT_CleanStart, 0, 0}: CleanStart0R0, + {symbols.NT_CleanStart, 0, 1}: CleanStart0R1, + {symbols.NT_CleanStart, 0, 2}: CleanStart0R2, + {symbols.NT_CleanStart, 1, 0}: CleanStart1R0, + {symbols.NT_CleanStart, 1, 1}: CleanStart1R1, + {symbols.NT_CleanStart, 1, 2}: CleanStart1R2, + {symbols.NT_Commit, 0, 0}: Commit0R0, + {symbols.NT_Commit, 0, 1}: Commit0R1, + {symbols.NT_ConsensusExec, 0, 0}: ConsensusExec0R0, + {symbols.NT_ConsensusExec, 0, 1}: ConsensusExec0R1, + {symbols.NT_ConsensusHeight, 0, 0}: ConsensusHeight0R0, + {symbols.NT_ConsensusHeight, 0, 1}: ConsensusHeight0R1, + {symbols.NT_ConsensusHeight, 0, 2}: ConsensusHeight0R2, + {symbols.NT_ConsensusHeight, 0, 3}: ConsensusHeight0R3, + {symbols.NT_ConsensusHeight, 1, 0}: ConsensusHeight1R0, + {symbols.NT_ConsensusHeight, 1, 1}: ConsensusHeight1R1, + {symbols.NT_ConsensusHeight, 1, 2}: ConsensusHeight1R2, + {symbols.NT_ConsensusHeights, 0, 0}: ConsensusHeights0R0, + {symbols.NT_ConsensusHeights, 0, 1}: ConsensusHeights0R1, + {symbols.NT_ConsensusHeights, 1, 0}: ConsensusHeights1R0, + {symbols.NT_ConsensusHeights, 1, 1}: ConsensusHeights1R1, + {symbols.NT_ConsensusHeights, 1, 2}: ConsensusHeights1R2, + {symbols.NT_ConsensusRound, 0, 0}: ConsensusRound0R0, + {symbols.NT_ConsensusRound, 0, 1}: ConsensusRound0R1, + {symbols.NT_ConsensusRound, 1, 0}: ConsensusRound1R0, + {symbols.NT_ConsensusRound, 1, 1}: ConsensusRound1R1, + {symbols.NT_ConsensusRounds, 0, 0}: ConsensusRounds0R0, + {symbols.NT_ConsensusRounds, 0, 1}: ConsensusRounds0R1, + {symbols.NT_ConsensusRounds, 1, 0}: ConsensusRounds1R0, + {symbols.NT_ConsensusRounds, 1, 1}: ConsensusRounds1R1, + {symbols.NT_ConsensusRounds, 1, 2}: ConsensusRounds1R2, + {symbols.NT_Extend, 0, 0}: Extend0R0, + {symbols.NT_Extend, 0, 1}: Extend0R1, + {symbols.NT_Extend, 1, 0}: Extend1R0, + {symbols.NT_Extend, 1, 1}: Extend1R1, + {symbols.NT_Extend, 1, 2}: Extend1R2, + {symbols.NT_Extend, 2, 0}: Extend2R0, + {symbols.NT_Extend, 2, 1}: Extend2R1, + {symbols.NT_Extend, 2, 2}: Extend2R2, + {symbols.NT_Extend, 3, 0}: Extend3R0, + {symbols.NT_Extend, 3, 1}: Extend3R1, + {symbols.NT_Extend, 3, 2}: Extend3R2, + {symbols.NT_Extend, 3, 3}: Extend3R3, + {symbols.NT_ExtendVote, 0, 0}: ExtendVote0R0, + {symbols.NT_ExtendVote, 0, 1}: ExtendVote0R1, + {symbols.NT_FinalizeBlock, 0, 0}: FinalizeBlock0R0, + {symbols.NT_FinalizeBlock, 0, 1}: FinalizeBlock0R1, + {symbols.NT_GotVote, 0, 0}: GotVote0R0, + {symbols.NT_GotVote, 0, 1}: GotVote0R1, + {symbols.NT_GotVotes, 0, 0}: GotVotes0R0, + {symbols.NT_GotVotes, 0, 1}: GotVotes0R1, + {symbols.NT_GotVotes, 1, 0}: GotVotes1R0, + {symbols.NT_GotVotes, 1, 1}: GotVotes1R1, + {symbols.NT_GotVotes, 1, 2}: GotVotes1R2, + {symbols.NT_InitChain, 0, 0}: InitChain0R0, + {symbols.NT_InitChain, 0, 1}: InitChain0R1, + {symbols.NT_NonProposer, 0, 0}: NonProposer0R0, + {symbols.NT_NonProposer, 0, 1}: NonProposer0R1, + {symbols.NT_NonProposer, 1, 0}: NonProposer1R0, + {symbols.NT_NonProposer, 1, 1}: NonProposer1R1, + {symbols.NT_NonProposer, 2, 0}: NonProposer2R0, + {symbols.NT_NonProposer, 2, 1}: NonProposer2R1, + {symbols.NT_NonProposer, 3, 0}: NonProposer3R0, + {symbols.NT_NonProposer, 3, 1}: NonProposer3R1, + {symbols.NT_NonProposer, 3, 2}: NonProposer3R2, + {symbols.NT_NonProposer, 4, 0}: NonProposer4R0, + {symbols.NT_NonProposer, 4, 1}: NonProposer4R1, + {symbols.NT_NonProposer, 4, 2}: NonProposer4R2, + {symbols.NT_NonProposer, 5, 0}: NonProposer5R0, + {symbols.NT_NonProposer, 5, 1}: NonProposer5R1, + {symbols.NT_NonProposer, 5, 2}: NonProposer5R2, + {symbols.NT_NonProposer, 6, 0}: NonProposer6R0, + {symbols.NT_NonProposer, 6, 1}: NonProposer6R1, + {symbols.NT_NonProposer, 6, 2}: NonProposer6R2, + {symbols.NT_NonProposer, 6, 3}: NonProposer6R3, + {symbols.NT_OfferSnapshot, 0, 0}: OfferSnapshot0R0, + {symbols.NT_OfferSnapshot, 0, 1}: OfferSnapshot0R1, + {symbols.NT_PrepareProposal, 0, 0}: PrepareProposal0R0, + {symbols.NT_PrepareProposal, 0, 1}: PrepareProposal0R1, + {symbols.NT_ProcessProposal, 0, 0}: ProcessProposal0R0, + {symbols.NT_ProcessProposal, 0, 1}: ProcessProposal0R1, + {symbols.NT_Proposer, 0, 0}: Proposer0R0, + {symbols.NT_Proposer, 0, 1}: Proposer0R1, + {symbols.NT_Proposer, 1, 0}: Proposer1R0, + {symbols.NT_Proposer, 1, 1}: Proposer1R1, + {symbols.NT_Proposer, 2, 0}: Proposer2R0, + {symbols.NT_Proposer, 2, 1}: Proposer2R1, + {symbols.NT_Proposer, 3, 0}: Proposer3R0, + {symbols.NT_Proposer, 3, 1}: Proposer3R1, + {symbols.NT_Proposer, 3, 2}: Proposer3R2, + {symbols.NT_Proposer, 4, 0}: Proposer4R0, + {symbols.NT_Proposer, 4, 1}: Proposer4R1, + {symbols.NT_Proposer, 4, 2}: Proposer4R2, + {symbols.NT_Proposer, 5, 0}: Proposer5R0, + {symbols.NT_Proposer, 5, 1}: Proposer5R1, + {symbols.NT_Proposer, 5, 2}: Proposer5R2, + {symbols.NT_Proposer, 6, 0}: Proposer6R0, + {symbols.NT_Proposer, 6, 1}: Proposer6R1, + {symbols.NT_Proposer, 6, 2}: Proposer6R2, + {symbols.NT_Proposer, 6, 3}: Proposer6R3, + {symbols.NT_ProposerSimple, 0, 0}: ProposerSimple0R0, + {symbols.NT_ProposerSimple, 0, 1}: ProposerSimple0R1, + {symbols.NT_ProposerSimple, 1, 0}: ProposerSimple1R0, + {symbols.NT_ProposerSimple, 1, 1}: ProposerSimple1R1, + {symbols.NT_ProposerSimple, 1, 2}: ProposerSimple1R2, + {symbols.NT_Recovery, 0, 0}: Recovery0R0, + {symbols.NT_Recovery, 0, 1}: Recovery0R1, + {symbols.NT_Recovery, 0, 2}: Recovery0R2, + {symbols.NT_Recovery, 1, 0}: Recovery1R0, + {symbols.NT_Recovery, 1, 1}: Recovery1R1, + {symbols.NT_Start, 0, 0}: Start0R0, + {symbols.NT_Start, 0, 1}: Start0R1, + {symbols.NT_Start, 1, 0}: Start1R0, + {symbols.NT_Start, 1, 1}: Start1R1, + {symbols.NT_StateSync, 0, 0}: StateSync0R0, + {symbols.NT_StateSync, 0, 1}: StateSync0R1, + {symbols.NT_StateSync, 0, 2}: StateSync0R2, + {symbols.NT_StateSync, 1, 0}: StateSync1R0, + {symbols.NT_StateSync, 1, 1}: StateSync1R1, + {symbols.NT_StateSyncAttempt, 0, 0}: StateSyncAttempt0R0, + {symbols.NT_StateSyncAttempt, 0, 1}: StateSyncAttempt0R1, + {symbols.NT_StateSyncAttempt, 0, 2}: StateSyncAttempt0R2, + {symbols.NT_StateSyncAttempt, 1, 0}: StateSyncAttempt1R0, + {symbols.NT_StateSyncAttempt, 1, 1}: StateSyncAttempt1R1, + {symbols.NT_StateSyncAttempts, 0, 0}: StateSyncAttempts0R0, + {symbols.NT_StateSyncAttempts, 0, 1}: StateSyncAttempts0R1, + {symbols.NT_StateSyncAttempts, 1, 0}: StateSyncAttempts1R0, + {symbols.NT_StateSyncAttempts, 1, 1}: StateSyncAttempts1R1, + {symbols.NT_StateSyncAttempts, 1, 2}: StateSyncAttempts1R2, + {symbols.NT_SuccessSync, 0, 0}: SuccessSync0R0, + {symbols.NT_SuccessSync, 0, 1}: SuccessSync0R1, + {symbols.NT_SuccessSync, 0, 2}: SuccessSync0R2, +} + +var alternates = map[symbols.NT][]Label{ + symbols.NT_Start: {Start0R0, Start1R0}, + symbols.NT_CleanStart: {CleanStart0R0, CleanStart1R0}, + symbols.NT_StateSync: {StateSync0R0, StateSync1R0}, + symbols.NT_StateSyncAttempts: {StateSyncAttempts0R0, StateSyncAttempts1R0}, + symbols.NT_StateSyncAttempt: {StateSyncAttempt0R0, StateSyncAttempt1R0}, + symbols.NT_SuccessSync: {SuccessSync0R0}, + symbols.NT_ApplyChunks: {ApplyChunks0R0, ApplyChunks1R0}, + symbols.NT_Recovery: {Recovery0R0, Recovery1R0}, + symbols.NT_ConsensusExec: {ConsensusExec0R0}, + symbols.NT_ConsensusHeights: {ConsensusHeights0R0, ConsensusHeights1R0}, + symbols.NT_ConsensusHeight: {ConsensusHeight0R0, ConsensusHeight1R0}, + symbols.NT_ConsensusRounds: {ConsensusRounds0R0, ConsensusRounds1R0}, + symbols.NT_ConsensusRound: {ConsensusRound0R0, ConsensusRound1R0}, + symbols.NT_Proposer: {Proposer0R0, Proposer1R0, Proposer2R0, Proposer3R0, Proposer4R0, Proposer5R0, Proposer6R0}, + symbols.NT_ProposerSimple: {ProposerSimple0R0, ProposerSimple1R0}, + symbols.NT_NonProposer: {NonProposer0R0, NonProposer1R0, NonProposer2R0, NonProposer3R0, NonProposer4R0, NonProposer5R0, NonProposer6R0}, + symbols.NT_Extend: {Extend0R0, Extend1R0, Extend2R0, Extend3R0}, + symbols.NT_GotVotes: {GotVotes0R0, GotVotes1R0}, + symbols.NT_InitChain: {InitChain0R0}, + symbols.NT_FinalizeBlock: {FinalizeBlock0R0}, + symbols.NT_Commit: {Commit0R0}, + symbols.NT_OfferSnapshot: {OfferSnapshot0R0}, + symbols.NT_ApplyChunk: {ApplyChunk0R0}, + symbols.NT_PrepareProposal: {PrepareProposal0R0}, + symbols.NT_ProcessProposal: {ProcessProposal0R0}, + symbols.NT_ExtendVote: {ExtendVote0R0}, + symbols.NT_GotVote: {GotVote0R0}, +} diff --git a/test/e2e/pkg/grammar/grammar-auto/parser/symbols/symbols.go b/test/e2e/pkg/grammar/grammar-auto/parser/symbols/symbols.go new file mode 100644 index 00000000000..f889b46e453 --- /dev/null +++ b/test/e2e/pkg/grammar/grammar-auto/parser/symbols/symbols.go @@ -0,0 +1,200 @@ +// Package symbols is generated by gogll. Do not edit. +package symbols + +import ( + "bytes" + "fmt" +) + +type Symbol interface { + isSymbol() + IsNonTerminal() bool + String() string +} + +func (NT) isSymbol() {} +func (T) isSymbol() {} + +// NT is the type of non-terminals symbols +type NT int + +const ( + NT_ApplyChunk NT = iota + NT_ApplyChunks + NT_CleanStart + NT_Commit + NT_ConsensusExec + NT_ConsensusHeight + NT_ConsensusHeights + NT_ConsensusRound + NT_ConsensusRounds + NT_Extend + NT_ExtendVote + NT_FinalizeBlock + NT_GotVote + NT_GotVotes + NT_InitChain + NT_NonProposer + NT_OfferSnapshot + NT_PrepareProposal + NT_ProcessProposal + NT_Proposer + NT_ProposerSimple + NT_Recovery + NT_Start + NT_StateSync + NT_StateSyncAttempt + NT_StateSyncAttempts + NT_SuccessSync +) + +// T is the type of terminals symbols +type T int + +const ( + T_0 T = iota // apply_snapshot_chunk + T_1 // commit + T_2 // extend_vote + T_3 // finalize_block + T_4 // init_chain + T_5 // offer_snapshot + T_6 // prepare_proposal + T_7 // process_proposal + T_8 // verify_vote_extension +) + +type Symbols []Symbol + +func (ss Symbols) Equal(ss1 Symbols) bool { + if len(ss) != len(ss1) { + return false + } + for i, s := range ss { + if s.String() != ss1[i].String() { + return false + } + } + return true +} + +func (ss Symbols) String() string { + w := new(bytes.Buffer) + for i, s := range ss { + if i > 0 { + fmt.Fprint(w, " ") + } + fmt.Fprintf(w, "%s", s) + } + return w.String() +} + +func (ss Symbols) Strings() []string { + strs := make([]string, len(ss)) + for i, s := range ss { + strs[i] = s.String() + } + return strs +} + +func (NT) IsNonTerminal() bool { + return true +} + +func (T) IsNonTerminal() bool { + return false +} + +func (nt NT) String() string { + return ntToString[nt] +} + +func (t T) String() string { + return tToString[t] +} + +// IsNT returns true iff sym is a non-terminal symbol of the grammar +func IsNT(sym string) bool { + _, exist := stringNT[sym] + return exist +} + +// ToNT returns the NT value of sym or panics if sym is not a non-terminal of the grammar +func ToNT(sym string) NT { + nt, exist := stringNT[sym] + if !exist { + panic(fmt.Sprintf("No NT: %s", sym)) + } + return nt +} + +var ntToString = []string{ + "ApplyChunk", /* NT_ApplyChunk */ + "ApplyChunks", /* NT_ApplyChunks */ + "CleanStart", /* NT_CleanStart */ + "Commit", /* NT_Commit */ + "ConsensusExec", /* NT_ConsensusExec */ + "ConsensusHeight", /* NT_ConsensusHeight */ + "ConsensusHeights", /* NT_ConsensusHeights */ + "ConsensusRound", /* NT_ConsensusRound */ + "ConsensusRounds", /* NT_ConsensusRounds */ + "Extend", /* NT_Extend */ + "ExtendVote", /* NT_ExtendVote */ + "FinalizeBlock", /* NT_FinalizeBlock */ + "GotVote", /* NT_GotVote */ + "GotVotes", /* NT_GotVotes */ + "InitChain", /* NT_InitChain */ + "NonProposer", /* NT_NonProposer */ + "OfferSnapshot", /* NT_OfferSnapshot */ + "PrepareProposal", /* NT_PrepareProposal */ + "ProcessProposal", /* NT_ProcessProposal */ + "Proposer", /* NT_Proposer */ + "ProposerSimple", /* NT_ProposerSimple */ + "Recovery", /* NT_Recovery */ + "Start", /* NT_Start */ + "StateSync", /* NT_StateSync */ + "StateSyncAttempt", /* NT_StateSyncAttempt */ + "StateSyncAttempts", /* NT_StateSyncAttempts */ + "SuccessSync", /* NT_SuccessSync */ +} + +var tToString = []string{ + "apply_snapshot_chunk", /* T_0 */ + "commit", /* T_1 */ + "extend_vote", /* T_2 */ + "finalize_block", /* T_3 */ + "init_chain", /* T_4 */ + "offer_snapshot", /* T_5 */ + "prepare_proposal", /* T_6 */ + "process_proposal", /* T_7 */ + "verify_vote_extension", /* T_8 */ +} + +var stringNT = map[string]NT{ + "ApplyChunk": NT_ApplyChunk, + "ApplyChunks": NT_ApplyChunks, + "CleanStart": NT_CleanStart, + "Commit": NT_Commit, + "ConsensusExec": NT_ConsensusExec, + "ConsensusHeight": NT_ConsensusHeight, + "ConsensusHeights": NT_ConsensusHeights, + "ConsensusRound": NT_ConsensusRound, + "ConsensusRounds": NT_ConsensusRounds, + "Extend": NT_Extend, + "ExtendVote": NT_ExtendVote, + "FinalizeBlock": NT_FinalizeBlock, + "GotVote": NT_GotVote, + "GotVotes": NT_GotVotes, + "InitChain": NT_InitChain, + "NonProposer": NT_NonProposer, + "OfferSnapshot": NT_OfferSnapshot, + "PrepareProposal": NT_PrepareProposal, + "ProcessProposal": NT_ProcessProposal, + "Proposer": NT_Proposer, + "ProposerSimple": NT_ProposerSimple, + "Recovery": NT_Recovery, + "Start": NT_Start, + "StateSync": NT_StateSync, + "StateSyncAttempt": NT_StateSyncAttempt, + "StateSyncAttempts": NT_StateSyncAttempts, + "SuccessSync": NT_SuccessSync, +} diff --git a/test/e2e/pkg/grammar/grammar-auto/sppf/sppf.go b/test/e2e/pkg/grammar/grammar-auto/sppf/sppf.go new file mode 100644 index 00000000000..d6f7ef00cd6 --- /dev/null +++ b/test/e2e/pkg/grammar/grammar-auto/sppf/sppf.go @@ -0,0 +1,207 @@ +// Package sppf is generated by gogll. Do not edit. + +/* +Package sppf implements a Shared Packed Parse Forest as defined in: + + Elizabeth Scott, Adrian Johnstone + GLL parse-tree generation + Science of Computer Programming (2012), doi:10.1016/j.scico.2012.03.005 +*/ +package sppf + +import ( + "bytes" + "fmt" + + "github.com/goccmack/goutil/ioutil" + + "github.com/cometbft/cometbft/test/e2e/pkg/grammar/grammar-auto/parser/symbols" +) + +type Node interface { + isNode() + dot(*dotBuilder) + Label() string + String() string +} + +type IntermediateNode struct { + NT symbols.NT + Body symbols.Symbols + Pos int + Lext, Rext int + Children []*PackedNode +} + +type SymbolNode struct { + Symbol string + Lext, Rext int + Children []*PackedNode +} + +type PackedNode struct { + NT symbols.NT + Body symbols.Symbols + Pos int + Lext, Pivot, Rext int + + LeftChild Node // Either an intermediate or Symbol node + RightChild *SymbolNode +} + +func (*IntermediateNode) isNode() {} +func (*SymbolNode) isNode() {} +func (*PackedNode) isNode() {} + +func slotString(nt symbols.NT, body symbols.Symbols, pos int) string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "%s:", nt) + for i, sym := range body { + fmt.Fprint(w, " ") + if i == pos { + fmt.Fprint(w, "•") + } + fmt.Fprint(w, sym) + } + if len(body) == pos { + fmt.Fprint(w, "•") + } + return w.String() +} + +func (n *IntermediateNode) Label() string { + return fmt.Sprintf("\"%s:,%d,%d\"", slotString(n.NT, n.Body, n.Pos), n.Lext, n.Rext) +} + +func (n *SymbolNode) Label() string { + return fmt.Sprintf("\"%s,%d,%d\"", n.Symbol, n.Lext, n.Rext) +} + +func (n *PackedNode) Label() string { + return fmt.Sprintf("\"%s,%d,%d,%d\"", slotString(n.NT, n.Body, n.Pos), n.Lext, n.Pivot, n.Rext) +} + +func (n *IntermediateNode) String() string { + return "IN: " + n.Label() +} + +func (n *SymbolNode) String() string { + return "SN: " + n.Label() +} + +func (n *PackedNode) String() string { + return "PN: " + n.Label() +} + +// ---- Dot ---- + +type dotBuilder struct { + nodes map[string]bool // index = node.Label() + w *bytes.Buffer +} + +func (bld *dotBuilder) add(n Node) { + // fmt.Printf("dotBuilder.add: %s\n", n.Label()) + if bld.done(n) { + panic(fmt.Sprintf("duplicate %s", n.Label())) + } + // fmt.Println(" Before:") + // bld.dumpNodes() + + bld.nodes[n.Label()] = true + + // fmt.Println(" After:") + // bld.dumpNodes() + // fmt.Println() +} + +func (bld *dotBuilder) done(n Node) bool { + return bld.nodes[n.Label()] +} + +func (bld *dotBuilder) dumpNodes() { + for n, t := range bld.nodes { + fmt.Printf(" %s = %t\n", n, t) + } +} + +// DotFile writes a graph representation of the SPPF in dot notation to file +func (root *SymbolNode) DotFile(file string) { + bld := &dotBuilder{ + nodes: make(map[string]bool), + w: new(bytes.Buffer), + } + fmt.Fprintln(bld.w, "digraph SPPF {") + root.dot(bld) + fmt.Fprintln(bld.w, "}") + ioutil.WriteFile(file, bld.w.Bytes()) +} + +func (n *IntermediateNode) dot(bld *dotBuilder) { + // fmt.Println("in.dot", n.Label()) + + if bld.done(n) { + return + } + bld.add(n) + + fmt.Fprintf(bld.w, "%s [shape=box]\n", n.Label()) + + for _, c := range n.Children { + fmt.Fprintf(bld.w, "%s -> %s\n", n.Label(), c.Label()) + if !bld.done(c) { + c.dot(bld) + } + } +} + +func (n *PackedNode) dot(bld *dotBuilder) { + // fmt.Println("pn.dot", n.Label(), "exist", bld.nodes[n.Label()]) + + if bld.done(n) { + return + } + bld.add(n) + + fmt.Fprintf(bld.w, "%s [shape=box,style=rounded,penwidth=3]\n", n.Label()) + if n.LeftChild != nil { + if !bld.done(n.LeftChild) { + n.LeftChild.dot(bld) + } + fmt.Fprintf(bld.w, "%s -> %s\n", n.Label(), n.LeftChild.Label()) + } + if n.RightChild != nil { + if !bld.done(n.RightChild) { + n.RightChild.dot(bld) + } + fmt.Fprintf(bld.w, "%s -> %s\n", n.Label(), n.RightChild.Label()) + } + if n.LeftChild != nil && n.RightChild != nil { + fmt.Fprintf(bld.w, "%s,%s\n", n.LeftChild.Label(), n.RightChild.Label()) + } +} + +func (n *SymbolNode) dot(bld *dotBuilder) { + // fmt.Println("sn.dot", n.Label(), "done=", bld.done(n)) + + if bld.done(n) { + return + } + bld.add(n) + + fmt.Fprintln(bld.w, n.Label()) + for _, pn := range n.Children { + // fmt.Printf(" child: %s\n", pn.Label()) + fmt.Fprintf(bld.w, "%s -> %s\n", n.Label(), pn.Label()) + if !bld.done(pn) { + pn.dot(bld) + } + } + for i, pn := range n.Children { + if i > 0 { + fmt.Fprint(bld.w, ";") + } + fmt.Fprintf(bld.w, "%s", pn.Label()) + } + fmt.Fprintln(bld.w) +} diff --git a/test/e2e/pkg/grammar/grammar-auto/token/token.go b/test/e2e/pkg/grammar/grammar-auto/token/token.go new file mode 100644 index 00000000000..01dcf380590 --- /dev/null +++ b/test/e2e/pkg/grammar/grammar-auto/token/token.go @@ -0,0 +1,215 @@ +// Package token is generated by GoGLL. Do not edit +package token + +import ( + "fmt" +) + +// Token is returned by the lexer for every scanned lexical token +type Token struct { + typ Type + lext, rext int + input []rune +} + +/* +New returns a new token. +lext is the left extent and rext the right extent of the token in the input. +input is the input slice scanned by the lexer. +*/ +func New(t Type, lext, rext int, input []rune) *Token { + return &Token{ + typ: t, + lext: lext, + rext: rext, + input: input, + } +} + +// GetLineColumn returns the line and column of the left extent of t +func (t *Token) GetLineColumn() (line, col int) { + line, col = 1, 1 + for j := 0; j < t.lext; j++ { + switch t.input[j] { + case '\n': + line++ + col = 1 + case '\t': + col += 4 + default: + col++ + } + } + return +} + +// GetInput returns the input from which t was parsed. +func (t *Token) GetInput() []rune { + return t.input +} + +// Lext returns the left extent of t in the input stream of runes +func (t *Token) Lext() int { + return t.lext +} + +// Literal returns the literal runes of t scanned by the lexer +func (t *Token) Literal() []rune { + return t.input[t.lext:t.rext] +} + +// LiteralString returns string(t.Literal()) +func (t *Token) LiteralString() string { + return string(t.Literal()) +} + +// LiteralStripEscape returns the literal runes of t scanned by the lexer +func (t *Token) LiteralStripEscape() []rune { + lit := t.Literal() + strip := make([]rune, 0, len(lit)) + for i := 0; i < len(lit); i++ { + if lit[i] == '\\' { + i++ + switch lit[i] { + case 't': + strip = append(strip, '\t') + case 'r': + strip = append(strip, '\r') + case 'n': + strip = append(strip, '\r') + default: + strip = append(strip, lit[i]) + } + } else { + strip = append(strip, lit[i]) + } + } + return strip +} + +// LiteralStringStripEscape returns string(t.LiteralStripEscape()) +func (t *Token) LiteralStringStripEscape() string { + return string(t.LiteralStripEscape()) +} + +// Rext returns the right extent of t in the input stream of runes +func (t *Token) Rext() int { + return t.rext +} + +func (t *Token) String() string { + return fmt.Sprintf("%s (%d,%d) %s", + t.TypeID(), t.lext, t.rext, t.LiteralString()) +} + +// Suppress returns true iff t is suppressed by the lexer +func (t *Token) Suppress() bool { + return Suppress[t.typ] +} + +// Type returns the token Type of t +func (t *Token) Type() Type { + return t.typ +} + +// TypeID returns the token Type ID of t. +// This may be different from the literal of token t. +func (t *Token) TypeID() string { + return t.Type().ID() +} + +// Type is the token type +type Type int + +func (t Type) String() string { + return TypeToString[t] +} + +// ID returns the token type ID of token Type t +func (t Type) ID() string { + return TypeToID[t] +} + +const ( + Error Type = iota // Error + EOF // $ + T_0 // apply_snapshot_chunk + T_1 // commit + T_2 // extend_vote + T_3 // finalize_block + T_4 // init_chain + T_5 // offer_snapshot + T_6 // prepare_proposal + T_7 // process_proposal + T_8 // verify_vote_extension +) + +var TypeToString = []string{ + "Error", + "EOF", + "T_0", + "T_1", + "T_2", + "T_3", + "T_4", + "T_5", + "T_6", + "T_7", + "T_8", +} + +var StringToType = map[string]Type{ + "Error": Error, + "EOF": EOF, + "T_0": T_0, + "T_1": T_1, + "T_2": T_2, + "T_3": T_3, + "T_4": T_4, + "T_5": T_5, + "T_6": T_6, + "T_7": T_7, + "T_8": T_8, +} + +var TypeToID = []string{ + "Error", + "$", + "apply_snapshot_chunk", + "commit", + "extend_vote", + "finalize_block", + "init_chain", + "offer_snapshot", + "prepare_proposal", + "process_proposal", + "verify_vote_extension", +} + +var IDToType = map[string]Type{ + "Error": 0, + "$": 1, + "apply_snapshot_chunk": 2, + "commit": 3, + "extend_vote": 4, + "finalize_block": 5, + "init_chain": 6, + "offer_snapshot": 7, + "prepare_proposal": 8, + "process_proposal": 9, + "verify_vote_extension": 10, +} + +var Suppress = []bool{ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, +} diff --git a/test/e2e/pkg/infra/digitalocean/digitalocean.go b/test/e2e/pkg/infra/digitalocean/digitalocean.go new file mode 100644 index 00000000000..75690d82a06 --- /dev/null +++ b/test/e2e/pkg/infra/digitalocean/digitalocean.go @@ -0,0 +1,206 @@ +package digitalocean + +import ( + "context" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + + e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/test/e2e/pkg/exec" + "github.com/cometbft/cometbft/test/e2e/pkg/infra" +) + +var _ infra.Provider = (*Provider)(nil) + +// Provider implements a DigitalOcean-backed infrastructure provider. +type Provider struct { + infra.ProviderData +} + +// Setup generates the file mapping IPs to zones, used for emulating latencies. +func (p *Provider) Setup() error { + err := infra.GenerateIPZonesTable(p.Testnet.Nodes, p.IPZonesFilePath(), false) + if err != nil { + return err + } + + for _, n := range p.Testnet.Nodes { + if n.ClockSkew != 0 { + return fmt.Errorf("node %q contains clock skew configuration (not supported on DO)", n.Name) + } + } + + return nil +} + +var ymlPlaybookSeq int + +func getNextPlaybookFilename() string { + const ymlPlaybookAction = "playbook-action" + ymlPlaybookSeq++ + return ymlPlaybookAction + strconv.Itoa(ymlPlaybookSeq) + ".yml" +} + +func (p Provider) StartNodes(ctx context.Context, nodes ...*e2e.Node) error { + nodeIPs := make([]string, len(nodes)) + for i, n := range nodes { + nodeIPs[i] = n.ExternalIP.String() + } + playbook := ansibleSystemdBytes(true) + playbookFile := getNextPlaybookFilename() + if err := p.writePlaybook(playbookFile, playbook); err != nil { + return err + } + + return execAnsible(ctx, p.Testnet.Dir, playbookFile, nodeIPs) +} + +// SetLatency prepares and executes the latency-setter script in the given node. +func (p Provider) SetLatency(ctx context.Context, node *e2e.Node) error { + // Directory in the DigitalOcean node that contains all latency files. + remoteDir := "/root/cometbft/test/e2e/pkg/latency/" + + playbook := "- name: e2e custom playbook\n" + + " hosts: all\n" + + " tasks:\n" + + // Add task to copy the necessary files to the node. + playbook = ansibleAddCopyTask(playbook, "copy zones file to node", filepath.Base(p.IPZonesFilePath()), remoteDir) + + // Add task to execute latency-setter script in the node. + cmd := fmt.Sprintf("%s set %s %s eth0", + filepath.Join(remoteDir, "latency-setter.py"), + filepath.Join(remoteDir, filepath.Base(p.IPZonesFilePath())), + filepath.Join(remoteDir, "aws-latencies.csv"), + ) + playbook = ansibleAddShellTasks(playbook, "execute latency setter script", cmd) + + // Execute playbook + playbookFile := getNextPlaybookFilename() + if err := p.writePlaybook(playbookFile, playbook); err != nil { + return err + } + return execAnsible(ctx, p.Testnet.Dir, playbookFile, []string{node.ExternalIP.String()}) +} + +func (p Provider) StopTestnet(ctx context.Context) error { + nodeIPs := make([]string, len(p.Testnet.Nodes)) + for i, n := range p.Testnet.Nodes { + nodeIPs[i] = n.ExternalIP.String() + } + + playbook := ansibleSystemdBytes(false) + playbookFile := getNextPlaybookFilename() + if err := p.writePlaybook(playbookFile, playbook); err != nil { + return err + } + return execAnsible(ctx, p.Testnet.Dir, playbookFile, nodeIPs) +} + +func (p Provider) Disconnect(ctx context.Context, _ string, ip string) error { + playbook := ansiblePerturbConnectionBytes(true) + playbookFile := getNextPlaybookFilename() + if err := p.writePlaybook(playbookFile, playbook); err != nil { + return err + } + return execAnsible(ctx, p.Testnet.Dir, playbookFile, []string{ip}) +} + +func (p Provider) Reconnect(ctx context.Context, _ string, ip string) error { + playbook := ansiblePerturbConnectionBytes(false) + playbookFile := getNextPlaybookFilename() + if err := p.writePlaybook(playbookFile, playbook); err != nil { + return err + } + return execAnsible(ctx, p.Testnet.Dir, playbookFile, []string{ip}) +} + +func (Provider) CheckUpgraded(_ context.Context, node *e2e.Node) (string, bool, error) { + // Upgrade not supported yet by DO provider + return node.Name, false, nil +} + +func (p Provider) writePlaybook(yaml, playbook string) error { + //nolint: gosec + // G306: Expect WriteFile permissions to be 0600 or less + err := os.WriteFile(filepath.Join(p.Testnet.Dir, yaml), []byte(playbook), 0o644) + if err != nil { + return err + } + return nil +} + +const basePlaybook = `- name: e2e custom playbook + hosts: all + gather_facts: yes + vars: + ansible_host_key_checking: false + + tasks: +` + +func ansibleAddTask(playbook, name, contents string) string { + return playbook + " - name: " + name + "\n" + contents + "\n" +} + +func ansibleAddCopyTask(playbook, name, src, dest string) string { + copyTask := fmt.Sprintf(" ansible.builtin.copy:\n"+ + " src: %s\n"+ + " dest: %s\n", + src, dest) + return ansibleAddTask(playbook, name, copyTask) +} + +func ansibleAddSystemdTask(playbook string, starting bool) string { + startStop := "stopped" + if starting { + startStop = "started" + } + // testappd is the name of the daemon running the node in the ansible scripts in the qa-infra repo. + contents := fmt.Sprintf(` ansible.builtin.systemd: + name: testappd + state: %s + enabled: yes`, startStop) + + return ansibleAddTask(playbook, "operate on the systemd-unit", contents) +} + +func ansibleAddShellTasks(playbook, name string, shells ...string) string { + for _, shell := range shells { + contents := fmt.Sprintf(" shell: \"%s\"\n", shell) + playbook = ansibleAddTask(playbook, name, contents) + } + return playbook +} + +// file as bytes to be written out to disk. +// ansibleStartBytes generates an Ansible playbook to start the network. +func ansibleSystemdBytes(starting bool) string { + return ansibleAddSystemdTask(basePlaybook, starting) +} + +func ansiblePerturbConnectionBytes(disconnect bool) string { + disconnecting := "reconnect" + op := "-D" + if disconnect { + disconnecting = "disconnect" + op = "-A" + } + playbook := basePlaybook + for _, dir := range []string{"INPUT", "OUTPUT"} { + playbook = ansibleAddShellTasks(playbook, disconnecting+" node", + fmt.Sprintf("iptables %s %s -p tcp --dport 26656 -j DROP", op, dir)) + } + return playbook +} + +// ExecCompose runs a Docker Compose command for a testnet. +func execAnsible(ctx context.Context, dir, playbook string, nodeIPs []string, args ...string) error { //nolint:unparam + playbook = filepath.Join(dir, playbook) + return exec.CommandVerbose(ctx, append( + []string{"ansible-playbook", playbook, "-f", "50", "-u", "root", "--inventory", strings.Join(nodeIPs, ",") + ","}, + args...)...) +} diff --git a/test/e2e/pkg/infra/docker/docker.go b/test/e2e/pkg/infra/docker/docker.go index f1f6161ed02..f7a2ab9ec74 100644 --- a/test/e2e/pkg/infra/docker/docker.go +++ b/test/e2e/pkg/infra/docker/docker.go @@ -2,19 +2,21 @@ package docker import ( "bytes" + "context" "os" "path/filepath" "text/template" e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/test/e2e/pkg/exec" "github.com/cometbft/cometbft/test/e2e/pkg/infra" ) -var _ infra.Provider = &Provider{} +var _ infra.Provider = (*Provider)(nil) // Provider implements a docker-compose backed infrastructure provider. type Provider struct { - Testnet *e2e.Testnet + infra.ProviderData } // Setup generates the docker-compose file and write it to disk, erroring if @@ -24,15 +26,70 @@ func (p *Provider) Setup() error { if err != nil { return err } - //nolint: gosec - // G306: Expect WriteFile permissions to be 0600 or less + //nolint: gosec // G306: Expect WriteFile permissions to be 0600 or less err = os.WriteFile(filepath.Join(p.Testnet.Dir, "docker-compose.yml"), compose, 0o644) if err != nil { return err } + + err = infra.GenerateIPZonesTable(p.Testnet.Nodes, p.IPZonesFilePath(), true) + if err != nil { + return err + } + return nil } +func (p Provider) StartNodes(ctx context.Context, nodes ...*e2e.Node) error { + nodeNames := make([]string, len(nodes)) + for i, n := range nodes { + nodeNames[i] = n.Name + } + return ExecCompose(ctx, p.Testnet.Dir, append([]string{"up", "-d"}, nodeNames...)...) +} + +func (p Provider) StopTestnet(ctx context.Context) error { + return ExecCompose(ctx, p.Testnet.Dir, "down") +} + +func (p Provider) Disconnect(ctx context.Context, name string, _ string) error { + return Exec(ctx, "network", "disconnect", p.Testnet.Name+"_"+p.Testnet.Name, name) +} + +func (p Provider) Reconnect(ctx context.Context, name string, _ string) error { + return Exec(ctx, "network", "connect", p.Testnet.Name+"_"+p.Testnet.Name, name) +} + +func (Provider) CheckUpgraded(ctx context.Context, node *e2e.Node) (string, bool, error) { + testnet := node.Testnet + out, err := ExecComposeOutput(ctx, testnet.Dir, "ps", "-q", node.Name) + if err != nil { + return "", false, err + } + name := node.Name + upgraded := false + if len(out) == 0 { + name += "_u" + upgraded = true + } + return name, upgraded, nil +} + +func (p Provider) SetLatency(ctx context.Context, node *e2e.Node) error { + containerDir := "/scripts/" + + // Copy zone file used by the script that sets latency. + if err := Exec(ctx, "cp", p.IPZonesFilePath(), node.Name+":"+containerDir); err != nil { + return err + } + + // Execute the latency setter script in the container. + return ExecVerbose(ctx, "exec", "--privileged", node.Name, + filepath.Join(containerDir, "latency-setter.py"), "set", + filepath.Join(containerDir, filepath.Base(p.IPZonesFilePath())), + filepath.Join(containerDir, "aws-latencies.csv"), "eth0") +} + // dockerComposeBytes generates a Docker Compose config file for a testnet and returns the // file as bytes to be written out to disk. func dockerComposeBytes(testnet *e2e.Testnet) ([]byte, error) { @@ -58,23 +115,31 @@ services: e2e: true container_name: {{ .Name }} image: {{ .Version }} -{{- if or (eq .ABCIProtocol "builtin") (eq .ABCIProtocol "builtin_unsync") }} +{{- if or (eq .ABCIProtocol "builtin") (eq .ABCIProtocol "builtin_connsync") }} entrypoint: /usr/bin/entrypoint-builtin +{{- end }} +{{- if .ClockSkew }} + environment: + - COMETBFT_CLOCK_SKEW={{ .ClockSkew }} {{- end }} init: true ports: - 26656 - - {{ if .ProxyPort }}{{ .ProxyPort }}:{{ end }}26657 + - {{ if .RPCProxyPort }}{{ .RPCProxyPort }}:{{ end }}26657 + - {{ if .GRPCProxyPort }}{{ .GRPCProxyPort }}:{{ end }}26670 + - {{ if .GRPCPrivilegedProxyPort }}{{ .GRPCPrivilegedProxyPort }}:{{ end }}26671 {{- if .PrometheusProxyPort }} - {{ .PrometheusProxyPort }}:26660 {{- end }} - 6060 + - 2345 + - 2346 volumes: - ./{{ .Name }}:/cometbft - ./{{ .Name }}:/tendermint networks: {{ $.Name }}: - ipv{{ if $.IPv6 }}6{{ else }}4{{ end}}_address: {{ .IP }} + ipv{{ if $.IPv6 }}6{{ else }}4{{ end}}_address: {{ .InternalIP }} {{- if ne .Version $.UpgradeVersion}} {{ .Name }}_u: @@ -82,23 +147,31 @@ services: e2e: true container_name: {{ .Name }}_u image: {{ $.UpgradeVersion }} -{{- if or (eq .ABCIProtocol "builtin") (eq .ABCIProtocol "builtin_unsync") }} +{{- if or (eq .ABCIProtocol "builtin") (eq .ABCIProtocol "builtin_connsync") }} entrypoint: /usr/bin/entrypoint-builtin +{{- end }} +{{- if .ClockSkew }} + environment: + - COMETBFT_CLOCK_SKEW={{ .ClockSkew }} {{- end }} init: true ports: - 26656 - - {{ if .ProxyPort }}{{ .ProxyPort }}:{{ end }}26657 + - {{ if .RPCProxyPort }}{{ .RPCProxyPort }}:{{ end }}26657 + - {{ if .GRPCProxyPort }}{{ .GRPCProxyPort }}:{{ end }}26670 + - {{ if .GRPCPrivilegedProxyPort }}{{ .GRPCPrivilegedProxyPort }}:{{ end }}26671 {{- if .PrometheusProxyPort }} - {{ .PrometheusProxyPort }}:26660 {{- end }} - 6060 + - 2345 + - 2346 volumes: - ./{{ .Name }}:/cometbft - ./{{ .Name }}:/tendermint networks: {{ $.Name }}: - ipv{{ if $.IPv6 }}6{{ else }}4{{ end}}_address: {{ .IP }} + ipv{{ if $.IPv6 }}6{{ else }}4{{ end}}_address: {{ .InternalIP }} {{- end }} {{end}}`) @@ -112,3 +185,34 @@ services: } return buf.Bytes(), nil } + +// ExecCompose runs a Docker Compose command for a testnet. +func ExecCompose(ctx context.Context, dir string, args ...string) error { + return exec.Command(ctx, append( + []string{"docker-compose", "-f", filepath.Join(dir, "docker-compose.yml")}, + args...)...) +} + +// ExecCompose runs a Docker Compose command for a testnet and returns the command's output. +func ExecComposeOutput(ctx context.Context, dir string, args ...string) ([]byte, error) { + return exec.CommandOutput(ctx, append( + []string{"docker-compose", "-f", filepath.Join(dir, "docker-compose.yml")}, + args...)...) +} + +// ExecComposeVerbose runs a Docker Compose command for a testnet and displays its output. +func ExecComposeVerbose(ctx context.Context, dir string, args ...string) error { + return exec.CommandVerbose(ctx, append( + []string{"docker-compose", "-f", filepath.Join(dir, "docker-compose.yml")}, + args...)...) +} + +// Exec runs a Docker command. +func Exec(ctx context.Context, args ...string) error { + return exec.Command(ctx, append([]string{"docker"}, args...)...) +} + +// Exec runs a Docker command while displaying its output. +func ExecVerbose(ctx context.Context, args ...string) error { + return exec.CommandVerbose(ctx, append([]string{"docker"}, args...)...) +} diff --git a/test/e2e/pkg/infra/latencies.go b/test/e2e/pkg/infra/latencies.go new file mode 100644 index 00000000000..0d2223b5ee8 --- /dev/null +++ b/test/e2e/pkg/infra/latencies.go @@ -0,0 +1,48 @@ +package infra + +import ( + "bytes" + "os" + "text/template" + + e2e "github.com/cometbft/cometbft/test/e2e/pkg" +) + +// GenerateIPZonesTable generates a file with a table mapping IP addresses to geographical zone for latencies. +func GenerateIPZonesTable(nodes []*e2e.Node, zonesPath string, useInternalIP bool) error { + // Generate file with table mapping IP addresses to geographical zone for latencies. + zonesTable, err := zonesTableBytes(nodes, useInternalIP) + if err != nil { + return err + } + //nolint: gosec // G306: Expect WriteFile permissions to be 0600 or less + err = os.WriteFile(zonesPath, zonesTable, 0o644) + if err != nil { + return err + } + return nil +} + +func zonesTableBytes(nodes []*e2e.Node, useInternalIP bool) ([]byte, error) { + tmpl, err := template.New("zones").Parse(`Node,IP,Zone +{{- range .Nodes }} +{{- if .Zone }} +{{ .Name }},{{ if $.UseInternalIP }}{{ .InternalIP }}{{ else }}{{ .ExternalIP }}{{ end }},{{ .Zone }} +{{- end }} +{{- end }}`) + if err != nil { + return nil, err + } + var buf bytes.Buffer + err = tmpl.Execute(&buf, struct { + Nodes []*e2e.Node + UseInternalIP bool + }{ + Nodes: nodes, + UseInternalIP: useInternalIP, + }) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} diff --git a/test/e2e/pkg/infra/provider.go b/test/e2e/pkg/infra/provider.go index 03b821de384..1c01bcdef29 100644 --- a/test/e2e/pkg/infra/provider.go +++ b/test/e2e/pkg/infra/provider.go @@ -1,20 +1,55 @@ package infra +import ( + "context" + "path/filepath" + + e2e "github.com/cometbft/cometbft/test/e2e/pkg" +) + // Provider defines an API for manipulating the infrastructure of a // specific set of testnet infrastructure. type Provider interface { - // Setup generates any necessary configuration for the infrastructure // provider during testnet setup. Setup() error + + // Starts the nodes passed as parameter. A nodes MUST NOT + // be started twice before calling StopTestnet + // If no nodes are passed, start the whole network + StartNodes(ctx context.Context, nodes ...*e2e.Node) error + + // Set emulated latencies from a node to other nodes. + SetLatency(ctx context.Context, node *e2e.Node) error + + // Stops the whole network + StopTestnet(ctx context.Context) error + + // Disconnects the node from the network + Disconnect(ctx context.Context, name string, ip string) error + + // Reconnects the node to the network. + // This should only be called after Disconnect + Reconnect(ctx context.Context, name string, ip string) error + + // Returns the provider's infrastructure data + GetInfrastructureData() *e2e.InfrastructureData + + // Checks whether the node has been upgraded in this run + CheckUpgraded(ctx context.Context, node *e2e.Node) (string, bool, error) } -// NoopProvider implements the provider interface by performing noops for every -// interface method. This may be useful if the infrastructure is managed by a -// separate process. -type NoopProvider struct { +type ProviderData struct { + Testnet *e2e.Testnet + InfrastructureData e2e.InfrastructureData } -func (NoopProvider) Setup() error { return nil } +// GetInfrastructureData returns the provider's infrastructure data. +func (pd ProviderData) GetInfrastructureData() *e2e.InfrastructureData { + return &pd.InfrastructureData +} -var _ Provider = NoopProvider{} +// IPZonesFilePath returns the path to the file with the mapping from IP addresses to zones. +func (pd ProviderData) IPZonesFilePath() string { + return filepath.Join(pd.Testnet.Dir, "zones.csv") +} diff --git a/test/e2e/pkg/infrastructure.go b/test/e2e/pkg/infrastructure.go index 2fc0e4bac6e..0328fbea760 100644 --- a/test/e2e/pkg/infrastructure.go +++ b/test/e2e/pkg/infrastructure.go @@ -5,6 +5,7 @@ import ( "fmt" "net" "os" + "sort" ) const ( @@ -17,6 +18,7 @@ const ( // InfrastructureData contains the relevant information for a set of existing // infrastructure that is to be used for running a testnet. type InfrastructureData struct { + Path string `json:"path"` // Provider is the name of infrastructure provider backing the testnet. // For example, 'docker' if it is running locally in a docker network or @@ -37,7 +39,21 @@ type InfrastructureData struct { // InstanceData contains the relevant information for a machine instance backing // one of the nodes in the testnet. type InstanceData struct { - IPAddress net.IP `json:"ip_address"` + IPAddress net.IP `json:"ip_address"` + ExtIPAddress net.IP `json:"ext_ip_address"` + RPCPort uint32 `json:"rpc_port"` + GRPCPort uint32 `json:"grpc_port"` + PrivilegedGRPCPort uint32 `json:"privileged_grpc_port"` +} + +func sortNodeNames(m Manifest) []string { + // Set up nodes, in alphabetical order (IPs and ports get same order). + nodeNames := []string{} + for name := range m.Nodes { + nodeNames = append(nodeNames, name) + } + sort.Strings(nodeNames) + return nodeNames } func NewDockerInfrastructureData(m Manifest) (InfrastructureData, error) { @@ -49,15 +65,22 @@ func NewDockerInfrastructureData(m Manifest) (InfrastructureData, error) { if err != nil { return InfrastructureData{}, fmt.Errorf("invalid IP network address %q: %w", netAddress, err) } + + portGen := newPortGenerator(proxyPortFirst) ipGen := newIPGenerator(ipNet) ifd := InfrastructureData{ Provider: "docker", Instances: make(map[string]InstanceData), Network: netAddress, } - for name := range m.Nodes { + localHostIP := net.ParseIP("127.0.0.1") + for _, name := range sortNodeNames(m) { ifd.Instances[name] = InstanceData{ - IPAddress: ipGen.Next(), + IPAddress: ipGen.Next(), + ExtIPAddress: localHostIP, + RPCPort: portGen.Next(), + GRPCPort: portGen.Next(), + PrivilegedGRPCPort: portGen.Next(), } } return ifd, nil @@ -76,5 +99,6 @@ func InfrastructureDataFromFile(p string) (InfrastructureData, error) { if ifd.Network == "" { ifd.Network = globalIPv4CIDR } + ifd.Path = p return ifd, nil } diff --git a/test/e2e/pkg/latency/aws-latencies.csv b/test/e2e/pkg/latency/aws-latencies.csv new file mode 100644 index 00000000000..9e77dac2145 --- /dev/null +++ b/test/e2e/pkg/latency/aws-latencies.csv @@ -0,0 +1,14 @@ +From/to,N_Virginia,Canada,N_California,London,Oregon,Ireland,Frankfurt,S_Paulo,Tokyo,Mumbai,Sydney,Seoul,Singapore +N_Virginia,0,7,30,38,39,33,44,58,73,93,98,87,105 +Canada,7,0,38,39,29,35,46,63,70,94,97,85,103 +N_California,30,39,0,68,10,68,75,88,54,116,69,67,86 +London,38,39,68,0,63,5,8,94,104,56,131,118,82 +Oregon,39,29,10,63,0,59,68,88,49,109,69,63,84 +Ireland,33,35,68,5,59,0,13,88,100,61,127,114,90 +Frankfurt,44,46,75,8,68,13,0,101,111,60,143,109,77 +S_Paulo,58,63,88,94,88,89,101,0,128,151,155,142,161 +Tokyo,73,70,54,104,49,100,111,128,0,60,57,16,39 +Mumbai,93,94,116,56,109,61,60,151,60,0,76,57,27 +Sydney,98,97,69,131,69,127,143,155,57,76,0,69,45 +Seoul,87,84,67,118,63,114,109,142,17,57,69,0,36 +Singapore,105,103,86,82,81,90,77,161,39,27,45,36,0 diff --git a/test/e2e/pkg/latency/latency-setter.py b/test/e2e/pkg/latency/latency-setter.py new file mode 100755 index 00000000000..4b0baaef222 --- /dev/null +++ b/test/e2e/pkg/latency/latency-setter.py @@ -0,0 +1,106 @@ +#!/usr/bin/python3 +# +# Modified version of latsetter.py script from +# https://github.com/paulo-coelho/latency-setter + +import csv +import os +import sys +import netifaces as nif + + +def usage(): + print("Usage:") + print(f"\t{sys.argv[0]} set ip-zones-csv latency-matrix-csv interface-name") + print("or") + print(f"\t{sys.argv[0]} unset interface-name") + exit(1) + + +def unset_latency(iface): + os.system(f"tc qdisc del dev {iface} root") + + +def read_ip_zones_file(path): + """ The first line of the file should contain the column names, corresponding to: node-name, ip, + and zone. """ + with open(path, "r") as ips: + return list(csv.DictReader(ips)) + + +def read_latency_matrix_file(path): + with open(path, "r") as f: + lines = list(list(rec) for rec in csv.reader(f, delimiter=",")) + all_zones = lines[0][1:] # discard first element of the first line (value "from/to") + zone_latencies = lines[1:] # each line is a zone name, followed by the latencies to other nodes + + # Convert lines of comma-separated values to dictionary from pairs of zones to latencies. + latencies = {} + for ls in zone_latencies: + source_zone = ls[0] + for i, dest_zone in enumerate(all_zones): + value = float(ls[i+1]) + if value != 0: + latencies[(source_zone,dest_zone)] = value + + return all_zones, latencies + + +def set_latency(ips_path, latencies_path, iface): + ip_zones = read_ip_zones_file(ips_path) + all_zones, latencies = read_latency_matrix_file(latencies_path) + + # Get my IP address + try: + myip = nif.ifaddresses(iface)[nif.AF_INET][0]["addr"] + except ValueError: + print(f"IP address not found for {iface}") + exit(1) + + # Get my zone and node name + myzone, mynode = next(((e["Zone"], e["Node"]) for e in ip_zones if e["IP"] == myip), (None, None)) + if not myzone: + print(f"No zone configured for node {myip}") + exit(1) + + # print(f"# Setting rules for interface {iface} in zone {myzone} with IP {myip}") + + # TODO: explain the following commands + os.system(f"tc qdisc del dev {iface} root 2> /dev/null") + os.system(f"tc qdisc add dev {iface} root handle 1: htb default 10") + os.system(f"tc class add dev {iface} parent 1: classid 1:1 htb rate 1gbit 2> /dev/null") + os.system(f"tc class add dev {iface} parent 1:1 classid 1:10 htb rate 1gbit 2> /dev/null") + os.system(f"tc qdisc add dev {iface} parent 1:10 handle 10: sfq perturb 10") + + handle = 11 # why this initial number? + for zone in all_zones: + lat = latencies.get((myzone,zone)) + if not lat or lat <= 0: + continue + + delta = .05 * lat + + # TODO: explain the following commands + os.system(f"tc class add dev {iface} parent 1:1 classid 1:{handle} htb rate 1gbit 2> /dev/null") + os.system(f"tc qdisc add dev {iface} parent 1:{handle} handle {handle}: netem delay {lat:.2f}ms {delta:.2f}ms distribution normal") + + for item in ip_zones: + if item["Zone"] == zone: + ip = item["IP"] + node = item["Node"] + print(f"# Setting latency from {mynode}/{myip} ({myzone}) to {node}/{ip} ({zone}): {lat:.2f}ms +/- {delta:.2f}ms") + os.system(f"tc filter add dev {iface} protocol ip parent 1: prio 1 u32 match ip dst {ip}/32 flowid 1:{handle}") + + handle += 1 + + +if __name__ == "__main__": + if len(sys.argv) < 3: + usage() + + if sys.argv[1] == "unset" and sys.argv[2]: + unset_latency(sys.argv[2]) + elif sys.argv[1] == "set" and sys.argv[2] and sys.argv[3] and sys.argv[4]: + set_latency(sys.argv[2], sys.argv[3], sys.argv[4]) + else: + usage() diff --git a/test/e2e/pkg/manifest.go b/test/e2e/pkg/manifest.go index eb841b78bf6..2f12f52dde2 100644 --- a/test/e2e/pkg/manifest.go +++ b/test/e2e/pkg/manifest.go @@ -48,6 +48,9 @@ type Manifest struct { // Nodes specifies the network nodes. At least one node must be given. Nodes map[string]*ManifestNode `toml:"node"` + // Disable the peer-exchange reactor on all nodes. + DisablePexReactor bool `toml:"disable_pex"` + // KeyType sets the curve that will be used by validators. // Options are ed25519 & secp256k1 KeyType string `toml:"key_type"` @@ -56,21 +59,16 @@ type Manifest struct { // testnet via the RPC endpoint of a random node. Default is 0 Evidence int `toml:"evidence"` - // VoteExtensionsEnableHeight configures the first height during which - // the chain will use and require vote extension data to be present - // in precommit messages. - VoteExtensionsEnableHeight int64 `toml:"vote_extensions_enable_height"` - // ABCIProtocol specifies the protocol used to communicate with the ABCI - // application: "unix", "tcp", "grpc", "builtin" or "builtin_unsync". + // application: "unix", "tcp", "grpc", "builtin" or "builtin_connsync". // // Defaults to "builtin". "builtin" will build a complete CometBFT node // into the application and launch it instead of launching a separate // CometBFT process. // - // "builtin_unsync" is basically the same as "builtin", except that it uses - // an "unsynchronized" local client creator, which attempts to replicate the - // same concurrency model locally as the socket client. + // "builtin_connsync" is basically the same as "builtin", except that it + // uses a "connection-synchronized" local client creator, which attempts to + // replicate the same concurrency model locally as the socket client. ABCIProtocol string `toml:"abci_protocol"` // Add artificial delays to each of the main ABCI calls to mimic computation time @@ -88,10 +86,55 @@ type Manifest struct { LoadTxSizeBytes int `toml:"load_tx_size_bytes"` LoadTxBatchSize int `toml:"load_tx_batch_size"` LoadTxConnections int `toml:"load_tx_connections"` + LoadMaxTxs int `toml:"load_max_txs"` // Enable or disable Prometheus metrics on all nodes. // Defaults to false (disabled). Prometheus bool `toml:"prometheus"` + + // BlockMaxBytes specifies the maximum size in bytes of a block. This + // value will be written to the genesis file of all nodes. + BlockMaxBytes int64 `toml:"block_max_bytes"` + + // Defines a minimum size for the vote extensions. + VoteExtensionSize uint `toml:"vote_extension_size"` + + // VoteExtensionsEnableHeight configures the first height during which + // the chain will use and require vote extension data to be present + // in precommit messages. + VoteExtensionsEnableHeight int64 `toml:"vote_extensions_enable_height"` + + // VoteExtensionsUpdateHeight configures the height at which consensus + // param VoteExtensionsEnableHeight will be set. + // -1 denotes it is set at genesis. + // 0 denotes it is set at InitChain. + VoteExtensionsUpdateHeight int64 `toml:"vote_extensions_update_height"` + + // Upper bound of sleep duration then gossipping votes and block parts + PeerGossipIntraloopSleepDuration time.Duration `toml:"peer_gossip_intraloop_sleep_duration"` + + // Maximum number of peers to which the node gossips transactions + ExperimentalMaxGossipConnectionsToPersistentPeers uint `toml:"experimental_max_gossip_connections_to_persistent_peers"` + ExperimentalMaxGossipConnectionsToNonPersistentPeers uint `toml:"experimental_max_gossip_connections_to_non_persistent_peers"` + + // Enable or disable e2e tests for CometBFT's expected behavior with respect + // to ABCI. + ABCITestsEnabled bool `toml:"abci_tests_enabled"` + + // Default geographical zone ID for simulating latencies, assigned to nodes that don't have a + // specific zone assigned. + DefaultZone string `toml:"default_zone"` + + // PbtsEnableHeight configures the first height during which + // the chain will start using Proposer-Based Timestamps (PBTS) + // to create and validate new blocks. + PbtsEnableHeight int64 `toml:"pbts_enable_height"` + + // PbtsUpdateHeight configures the height at which consensus + // param PbtsEnableHeight will be set. + // -1 denotes it is set at genesis. + // 0 denotes it is set at InitChain. + PbtsUpdateHeight int64 `toml:"pbts_update_height"` } // ManifestNode represents a node in a testnet manifest. @@ -117,8 +160,8 @@ type ManifestNode struct { // this relates to the providers the light client is connected to. PersistentPeers []string `toml:"persistent_peers"` - // Database specifies the database backend: "goleveldb", "cleveldb", - // "rocksdb", "boltdb", or "badgerdb". Defaults to goleveldb. + // Database specifies the database backend: "goleveldb", "rocksdb", + // "pebbledb" or "badgerdb". Defaults to "goleveldb". Database string `toml:"database"` // PrivvalProtocol specifies the protocol used to sign consensus messages: @@ -155,6 +198,10 @@ type ManifestNode struct { // SnapshotInterval and EvidenceAgeHeight. RetainBlocks uint64 `toml:"retain_blocks"` + // EnableCompanionPruning specifies whether or not storage pruning on the + // node should take a data companion into account. + EnableCompanionPruning bool `toml:"enable_companion_pruning"` + // Perturb lists perturbations to apply to the node after it has been // started and synced with the network: // @@ -168,6 +215,27 @@ type ManifestNode struct { // It defaults to false so unless the configured, the node will // receive load. SendNoLoad bool `toml:"send_no_load"` + + // Geographical zone ID for simulating latencies. + Zone string `toml:"zone"` + + // ExperimentalKeyLayout sets the key representation in the DB + ExperimentalKeyLayout string `toml:"experimental_db_key_layout"` + + // Compact triggers compaction on the DB after pruning + Compact bool `toml:"compact"` + + // CompactionInterval sets the number of blocks at which we trigger compaction + CompactionInterval int64 `toml:"compaction_interval"` + + // DiscardABCIResponses disables abci rsponses + DiscardABCIResponses bool `toml:"discard_abci_responses"` + + // Indexer sets the indexer, default kv + Indexer string `toml:"indexer"` + + // Simulated clock skew for this node + ClockSkew time.Duration `toml:"clock_skew"` } // Save saves the testnet manifest to a file. diff --git a/test/e2e/pkg/templates/prometheus-yaml.tmpl b/test/e2e/pkg/templates/prometheus-yaml.tmpl new file mode 100644 index 00000000000..3c7636e0ddc --- /dev/null +++ b/test/e2e/pkg/templates/prometheus-yaml.tmpl @@ -0,0 +1,9 @@ +global: + scrape_interval: 1s + +scrape_configs: +{{- range .Nodes }} + - job_name: '{{ .Name }}' + static_configs: + - targets: ['localhost:{{ .PrometheusProxyPort }}'] +{{end}} \ No newline at end of file diff --git a/test/e2e/pkg/testnet.go b/test/e2e/pkg/testnet.go index d0d5ae67295..6066ad3ef22 100644 --- a/test/e2e/pkg/testnet.go +++ b/test/e2e/pkg/testnet.go @@ -1,21 +1,31 @@ package e2e import ( + "bytes" + "context" + "encoding/csv" "errors" "fmt" "io" "math/rand" "net" + "os" "path/filepath" - "sort" + "slices" "strconv" "strings" + "text/template" "time" + _ "embed" + "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/crypto/secp256k1" rpchttp "github.com/cometbft/cometbft/rpc/client/http" + grpcclient "github.com/cometbft/cometbft/rpc/grpc/client" + grpcprivileged "github.com/cometbft/cometbft/rpc/grpc/client/privileged" + "github.com/cometbft/cometbft/types" ) const ( @@ -34,6 +44,7 @@ type ( Mode string Protocol string Perturbation string + ZoneID string ) const ( @@ -42,12 +53,12 @@ const ( ModeLight Mode = "light" ModeSeed Mode = "seed" - ProtocolBuiltin Protocol = "builtin" - ProtocolBuiltinUnsync Protocol = "builtin_unsync" - ProtocolFile Protocol = "file" - ProtocolGRPC Protocol = "grpc" - ProtocolTCP Protocol = "tcp" - ProtocolUNIX Protocol = "unix" + ProtocolBuiltin Protocol = "builtin" + ProtocolBuiltinConnSync Protocol = "builtin_connsync" + ProtocolFile Protocol = "file" + ProtocolGRPC Protocol = "grpc" + ProtocolTCP Protocol = "tcp" + ProtocolUNIX Protocol = "unix" PerturbationDisconnect Perturbation = "disconnect" PerturbationKill Perturbation = "kill" @@ -61,77 +72,103 @@ const ( // Testnet represents a single testnet. type Testnet struct { - Name string - File string - Dir string - IP *net.IPNet - InitialHeight int64 - InitialState map[string]string - Validators map[*Node]int64 - ValidatorUpdates map[int64]map[*Node]int64 - Nodes []*Node - KeyType string - Evidence int - LoadTxSizeBytes int - LoadTxBatchSize int - LoadTxConnections int - ABCIProtocol string - PrepareProposalDelay time.Duration - ProcessProposalDelay time.Duration - CheckTxDelay time.Duration - VoteExtensionDelay time.Duration - FinalizeBlockDelay time.Duration - UpgradeVersion string - Prometheus bool - VoteExtensionsEnableHeight int64 + Name string + File string + Dir string + IP *net.IPNet + InitialHeight int64 + InitialState map[string]string + Validators map[*Node]int64 + ValidatorUpdates map[int64]map[*Node]int64 + Nodes []*Node + DisablePexReactor bool + KeyType string + Evidence int + LoadTxSizeBytes int + LoadTxBatchSize int + LoadTxConnections int + LoadMaxTxs int + ABCIProtocol string + PrepareProposalDelay time.Duration + ProcessProposalDelay time.Duration + CheckTxDelay time.Duration + VoteExtensionDelay time.Duration + FinalizeBlockDelay time.Duration + UpgradeVersion string + Prometheus bool + BlockMaxBytes int64 + VoteExtensionsEnableHeight int64 + VoteExtensionsUpdateHeight int64 + VoteExtensionSize uint + PeerGossipIntraloopSleepDuration time.Duration + ExperimentalMaxGossipConnectionsToPersistentPeers uint + ExperimentalMaxGossipConnectionsToNonPersistentPeers uint + ABCITestsEnabled bool + DefaultZone string + PbtsEnableHeight int64 + PbtsUpdateHeight int64 } // Node represents a CometBFT node in a testnet. type Node struct { - Name string - Version string - Testnet *Testnet - Mode Mode - PrivvalKey crypto.PrivKey - NodeKey crypto.PrivKey - IP net.IP - ProxyPort uint32 - StartAt int64 - BlockSyncVersion string - StateSync bool - Database string - ABCIProtocol Protocol - PrivvalProtocol Protocol - PersistInterval uint64 - SnapshotInterval uint64 - RetainBlocks uint64 - Seeds []*Node - PersistentPeers []*Node - Perturbations []Perturbation - SendNoLoad bool - Prometheus bool - PrometheusProxyPort uint32 -} - -// LoadTestnet loads a testnet from a manifest file, using the filename to -// determine the testnet name and directory (from the basename of the file). + Name string + Version string + Testnet *Testnet + Mode Mode + PrivvalKey crypto.PrivKey + NodeKey crypto.PrivKey + InternalIP net.IP + ExternalIP net.IP + RPCProxyPort uint32 + GRPCProxyPort uint32 + GRPCPrivilegedProxyPort uint32 + StartAt int64 + BlockSyncVersion string + StateSync bool + Database string + ABCIProtocol Protocol + PrivvalProtocol Protocol + PersistInterval uint64 + SnapshotInterval uint64 + RetainBlocks uint64 + EnableCompanionPruning bool + Seeds []*Node + PersistentPeers []*Node + Perturbations []Perturbation + SendNoLoad bool + Prometheus bool + PrometheusProxyPort uint32 + Zone ZoneID + ExperimentalKeyLayout string + Compact bool + CompactionInterval int64 + DiscardABCIResponses bool + Indexer string + ClockSkew time.Duration +} + +// LoadTestnet loads a testnet from a manifest file. The testnet files are +// generated in the given directory, which is also use to determine the testnet +// name (the directory's basename). // The testnet generation must be deterministic, since it is generated // separately by the runner and the test cases. For this reason, testnets use a // random seed to generate e.g. keys. -func LoadTestnet(file string, ifd InfrastructureData) (*Testnet, error) { +func LoadTestnet(file string, ifd InfrastructureData, dir string) (*Testnet, error) { manifest, err := LoadManifest(file) if err != nil { return nil, err } - return NewTestnetFromManifest(manifest, file, ifd) + return NewTestnetFromManifest(manifest, file, ifd, dir) } -// NewTestnetFromManifest creates and validates a testnet from a manifest -func NewTestnetFromManifest(manifest Manifest, file string, ifd InfrastructureData) (*Testnet, error) { - dir := strings.TrimSuffix(file, filepath.Ext(file)) +// NewTestnetFromManifest creates and validates a testnet from a manifest. +func NewTestnetFromManifest(manifest Manifest, file string, ifd InfrastructureData, dir string) (*Testnet, error) { + if dir == "" { + // Set default testnet directory. + dir = strings.TrimSuffix(file, filepath.Ext(file)) + } keyGen := newKeyGenerator(randomSeed) - proxyPortGen := newPortGenerator(proxyPortFirst) prometheusProxyPortGen := newPortGenerator(prometheusProxyPortFirst) _, ipNet, err := net.ParseCIDR(ifd.Network) if err != nil { @@ -139,28 +176,40 @@ func NewTestnetFromManifest(manifest Manifest, file string, ifd InfrastructureDa } testnet := &Testnet{ - Name: filepath.Base(dir), - File: file, - Dir: dir, - IP: ipNet, - InitialHeight: 1, - InitialState: manifest.InitialState, - Validators: map[*Node]int64{}, - ValidatorUpdates: map[int64]map[*Node]int64{}, - Nodes: []*Node{}, - Evidence: manifest.Evidence, - LoadTxSizeBytes: manifest.LoadTxSizeBytes, - LoadTxBatchSize: manifest.LoadTxBatchSize, - LoadTxConnections: manifest.LoadTxConnections, - ABCIProtocol: manifest.ABCIProtocol, - PrepareProposalDelay: manifest.PrepareProposalDelay, - ProcessProposalDelay: manifest.ProcessProposalDelay, - CheckTxDelay: manifest.CheckTxDelay, - VoteExtensionDelay: manifest.VoteExtensionDelay, - FinalizeBlockDelay: manifest.FinalizeBlockDelay, - UpgradeVersion: manifest.UpgradeVersion, - Prometheus: manifest.Prometheus, - VoteExtensionsEnableHeight: manifest.VoteExtensionsEnableHeight, + Name: filepath.Base(dir), + File: file, + Dir: dir, + IP: ipNet, + InitialHeight: 1, + InitialState: manifest.InitialState, + Validators: map[*Node]int64{}, + ValidatorUpdates: map[int64]map[*Node]int64{}, + Nodes: []*Node{}, + DisablePexReactor: manifest.DisablePexReactor, + Evidence: manifest.Evidence, + LoadTxSizeBytes: manifest.LoadTxSizeBytes, + LoadTxBatchSize: manifest.LoadTxBatchSize, + LoadTxConnections: manifest.LoadTxConnections, + LoadMaxTxs: manifest.LoadMaxTxs, + ABCIProtocol: manifest.ABCIProtocol, + PrepareProposalDelay: manifest.PrepareProposalDelay, + ProcessProposalDelay: manifest.ProcessProposalDelay, + CheckTxDelay: manifest.CheckTxDelay, + VoteExtensionDelay: manifest.VoteExtensionDelay, + FinalizeBlockDelay: manifest.FinalizeBlockDelay, + UpgradeVersion: manifest.UpgradeVersion, + Prometheus: manifest.Prometheus, + BlockMaxBytes: manifest.BlockMaxBytes, + VoteExtensionsEnableHeight: manifest.VoteExtensionsEnableHeight, + VoteExtensionsUpdateHeight: manifest.VoteExtensionsUpdateHeight, + VoteExtensionSize: manifest.VoteExtensionSize, + PeerGossipIntraloopSleepDuration: manifest.PeerGossipIntraloopSleepDuration, + ExperimentalMaxGossipConnectionsToPersistentPeers: manifest.ExperimentalMaxGossipConnectionsToPersistentPeers, + ExperimentalMaxGossipConnectionsToNonPersistentPeers: manifest.ExperimentalMaxGossipConnectionsToNonPersistentPeers, + ABCITestsEnabled: manifest.ABCITestsEnabled, + DefaultZone: manifest.DefaultZone, + PbtsEnableHeight: manifest.PbtsEnableHeight, + PbtsUpdateHeight: manifest.PbtsUpdateHeight, } if len(manifest.KeyType) != 0 { testnet.KeyType = manifest.KeyType @@ -184,45 +233,53 @@ func NewTestnetFromManifest(manifest Manifest, file string, ifd InfrastructureDa testnet.LoadTxSizeBytes = defaultTxSizeBytes } - // Set up nodes, in alphabetical order (IPs and ports get same order). - nodeNames := []string{} - for name := range manifest.Nodes { - nodeNames = append(nodeNames, name) - } - sort.Strings(nodeNames) - - for _, name := range nodeNames { + for _, name := range sortNodeNames(manifest) { nodeManifest := manifest.Nodes[name] ind, ok := ifd.Instances[name] if !ok { return nil, fmt.Errorf("information for node '%s' missing from infrastructure data", name) } + extIP := ind.ExtIPAddress + if len(extIP) == 0 { + extIP = ind.IPAddress + } v := nodeManifest.Version if v == "" { v = localVersion } node := &Node{ - Name: name, - Version: v, - Testnet: testnet, - PrivvalKey: keyGen.Generate(manifest.KeyType), - NodeKey: keyGen.Generate("ed25519"), - IP: ind.IPAddress, - ProxyPort: proxyPortGen.Next(), - Mode: ModeValidator, - Database: "goleveldb", - ABCIProtocol: Protocol(testnet.ABCIProtocol), - PrivvalProtocol: ProtocolFile, - StartAt: nodeManifest.StartAt, - BlockSyncVersion: nodeManifest.BlockSyncVersion, - StateSync: nodeManifest.StateSync, - PersistInterval: 1, - SnapshotInterval: nodeManifest.SnapshotInterval, - RetainBlocks: nodeManifest.RetainBlocks, - Perturbations: []Perturbation{}, - SendNoLoad: nodeManifest.SendNoLoad, - Prometheus: testnet.Prometheus, + Name: name, + Version: v, + Testnet: testnet, + PrivvalKey: keyGen.Generate(manifest.KeyType), + NodeKey: keyGen.Generate("ed25519"), + InternalIP: ind.IPAddress, + ExternalIP: extIP, + RPCProxyPort: ind.RPCPort, + GRPCProxyPort: ind.GRPCPort, + GRPCPrivilegedProxyPort: ind.PrivilegedGRPCPort, + Mode: ModeValidator, + Database: "goleveldb", + ABCIProtocol: Protocol(testnet.ABCIProtocol), + PrivvalProtocol: ProtocolFile, + StartAt: nodeManifest.StartAt, + BlockSyncVersion: nodeManifest.BlockSyncVersion, + StateSync: nodeManifest.StateSync, + PersistInterval: 1, + SnapshotInterval: nodeManifest.SnapshotInterval, + RetainBlocks: nodeManifest.RetainBlocks, + EnableCompanionPruning: nodeManifest.EnableCompanionPruning, + Perturbations: []Perturbation{}, + SendNoLoad: nodeManifest.SendNoLoad, + Prometheus: testnet.Prometheus, + Zone: ZoneID(nodeManifest.Zone), + ExperimentalKeyLayout: nodeManifest.ExperimentalKeyLayout, + Compact: nodeManifest.Compact, + CompactionInterval: nodeManifest.CompactionInterval, + DiscardABCIResponses: nodeManifest.DiscardABCIResponses, + Indexer: nodeManifest.Indexer, + ClockSkew: nodeManifest.ClockSkew, } if node.StartAt == testnet.InitialHeight { node.StartAt = 0 // normalize to 0 for initial nodes, since code expects this @@ -251,6 +308,12 @@ func NewTestnetFromManifest(manifest Manifest, file string, ifd InfrastructureDa for _, p := range nodeManifest.Perturb { node.Perturbations = append(node.Perturbations, Perturbation(p)) } + if nodeManifest.Zone != "" { + node.Zone = ZoneID(nodeManifest.Zone) + } else if testnet.DefaultZone != "" { + node.Zone = ZoneID(testnet.DefaultZone) + } + testnet.Nodes = append(testnet.Nodes, node) } @@ -335,6 +398,70 @@ func (t Testnet) Validate() error { if len(t.Nodes) == 0 { return errors.New("network has no nodes") } + if err := t.validateZones(t.Nodes); err != nil { + return err + } + if t.BlockMaxBytes > types.MaxBlockSizeBytes { + return fmt.Errorf("value of BlockMaxBytes cannot be higher than %d", types.MaxBlockSizeBytes) + } + if t.VoteExtensionsUpdateHeight < -1 { + return fmt.Errorf("value of VoteExtensionsUpdateHeight must be positive, 0 (InitChain), "+ + "or -1 (Genesis); update height %d", t.VoteExtensionsUpdateHeight) + } + if t.VoteExtensionsEnableHeight < 0 { + return fmt.Errorf("value of VoteExtensionsEnableHeight must be positive, or 0 (disable); "+ + "enable height %d", t.VoteExtensionsEnableHeight) + } + if t.VoteExtensionsUpdateHeight > 0 && t.VoteExtensionsUpdateHeight < t.InitialHeight { + return fmt.Errorf("a value of VoteExtensionsUpdateHeight greater than 0 "+ + "must not be less than InitialHeight; "+ //nolint: goconst + "update height %d, initial height %d", + t.VoteExtensionsUpdateHeight, t.InitialHeight, + ) + } + if t.VoteExtensionsEnableHeight > 0 { + if t.VoteExtensionsEnableHeight < t.InitialHeight { + return fmt.Errorf("a value of VoteExtensionsEnableHeight greater than 0 "+ + "must not be less than InitialHeight; "+ + "enable height %d, initial height %d", + t.VoteExtensionsEnableHeight, t.InitialHeight, + ) + } + if t.VoteExtensionsEnableHeight <= t.VoteExtensionsUpdateHeight { + return fmt.Errorf("a value of VoteExtensionsEnableHeight greater than 0 "+ + "must be greater than VoteExtensionsUpdateHeight; "+ + "update height %d, enable height %d", + t.VoteExtensionsUpdateHeight, t.VoteExtensionsEnableHeight, + ) + } + } + if t.PbtsEnableHeight < 0 { + return fmt.Errorf("value of PbtsEnableHeight must be positive, or 0 (disable); "+ + "enable height %d", t.PbtsEnableHeight) + } + if t.PbtsUpdateHeight > 0 && t.PbtsUpdateHeight < t.InitialHeight { + return fmt.Errorf("a value of PbtsUpdateHeight greater than 0 "+ + "must not be less than InitialHeight; "+ + "update height %d, initial height %d", + t.PbtsUpdateHeight, t.InitialHeight, + ) + } + if t.PbtsEnableHeight > 0 { + if t.PbtsEnableHeight < t.InitialHeight { + return fmt.Errorf("a value of PbtsEnableHeight greater than 0 "+ + "must not be less than InitialHeight; "+ + "enable height %d, initial height %d", + t.PbtsEnableHeight, t.InitialHeight, + ) + } + if t.PbtsEnableHeight <= t.PbtsUpdateHeight { + return fmt.Errorf("a value of PbtsEnableHeight greater than 0 "+ + "must be greater than PbtsUpdateHeight; "+ + "update height %d, enable height %d", + t.PbtsUpdateHeight, t.PbtsEnableHeight, + ) + } + } for _, node := range t.Nodes { if err := node.Validate(t); err != nil { return fmt.Errorf("invalid node %q: %w", node.Name, err) @@ -343,29 +470,62 @@ func (t Testnet) Validate() error { return nil } +func (Testnet) validateZones(nodes []*Node) error { + zoneMatrix, err := loadZoneLatenciesMatrix() + if err != nil { + return err + } + + // Get list of zone ids in matrix. + zones := make([]ZoneID, 0, len(zoneMatrix)) + for zone := range zoneMatrix { + zones = append(zones, zone) + } + + // Check that the zone ids of all nodes are valid when the matrix file exists. + nodesWithoutZone := make([]string, 0, len(nodes)) + for _, node := range nodes { + if !node.ZoneIsSet() { + nodesWithoutZone = append(nodesWithoutZone, node.Name) + continue + } + if !slices.Contains(zones, node.Zone) { + return fmt.Errorf("invalid zone %s for node %s, not present in zone-latencies matrix", + string(node.Zone), node.Name) + } + } + + // Either all nodes have a zone or none have. + if len(nodesWithoutZone) > 0 && len(nodesWithoutZone) != len(nodes) { + return fmt.Errorf("the following nodes do not have a zone assigned (while other nodes have): %v", strings.Join(nodesWithoutZone, ", ")) + } + + return nil +} + // Validate validates a node. func (n Node) Validate(testnet Testnet) error { if n.Name == "" { return errors.New("node has no name") } - if n.IP == nil { + if n.InternalIP == nil { return errors.New("node has no IP address") } - if !testnet.IP.Contains(n.IP) { - return fmt.Errorf("node IP %v is not in testnet network %v", n.IP, testnet.IP) + if !testnet.IP.Contains(n.InternalIP) { + return fmt.Errorf("node IP %v is not in testnet network %v", n.InternalIP, testnet.IP) } - if n.ProxyPort == n.PrometheusProxyPort { - return fmt.Errorf("node local port %v used also for Prometheus local port", n.ProxyPort) + if n.RPCProxyPort == n.PrometheusProxyPort { + return fmt.Errorf("node local port %v used also for Prometheus local port", n.RPCProxyPort) } - if n.ProxyPort > 0 && n.ProxyPort <= 1024 { - return fmt.Errorf("local port %v must be >1024", n.ProxyPort) + if n.RPCProxyPort > 0 && n.RPCProxyPort <= 1024 { + return fmt.Errorf("local port %v must be >1024", n.RPCProxyPort) } if n.PrometheusProxyPort > 0 && n.PrometheusProxyPort <= 1024 { return fmt.Errorf("local port %v must be >1024", n.PrometheusProxyPort) } for _, peer := range testnet.Nodes { - if peer.Name != n.Name && peer.ProxyPort == n.ProxyPort { - return fmt.Errorf("peer %q also has local port %v", peer.Name, n.ProxyPort) + if peer.Name != n.Name && peer.RPCProxyPort == n.RPCProxyPort && peer.ExternalIP.Equal(n.ExternalIP) { + return fmt.Errorf("peer %q also has local port %v", peer.Name, n.RPCProxyPort) } if n.PrometheusProxyPort > 0 { if peer.Name != n.Name && peer.PrometheusProxyPort == n.PrometheusProxyPort { @@ -379,18 +539,21 @@ func (n Node) Validate(testnet Testnet) error { return fmt.Errorf("invalid block sync setting %q", n.BlockSyncVersion) } switch n.Database { - case "goleveldb", "cleveldb", "boltdb", "rocksdb", "badgerdb": + case "goleveldb", "rocksdb", "badgerdb", "pebbledb": default: return fmt.Errorf("invalid database setting %q", n.Database) } switch n.ABCIProtocol { - case ProtocolBuiltin, ProtocolBuiltinUnsync, ProtocolUNIX, ProtocolTCP, ProtocolGRPC: + case ProtocolBuiltin, ProtocolBuiltinConnSync, ProtocolUNIX, ProtocolTCP, ProtocolGRPC: default: return fmt.Errorf("invalid ABCI protocol setting %q", n.ABCIProtocol) } - if n.Mode == ModeLight && n.ABCIProtocol != ProtocolBuiltin && n.ABCIProtocol != ProtocolBuiltinUnsync { + if n.Mode == ModeLight && n.ABCIProtocol != ProtocolBuiltin && n.ABCIProtocol != ProtocolBuiltinConnSync { return errors.New("light client must use builtin protocol") } + if n.Mode != ModeFull && n.Mode != ModeValidator && n.ClockSkew != 0 { + return errors.New("clock skew configuration only supported on full nodes") + } switch n.PrivvalProtocol { case ProtocolFile, ProtocolUNIX, ProtocolTCP: default: @@ -423,7 +586,7 @@ func (n Node) Validate(testnet Testnet) error { switch perturbation { case PerturbationUpgrade: if upgradeFound { - return fmt.Errorf("'upgrade' perturbation can appear at most once per node") + return errors.New("'upgrade' perturbation can appear at most once per node") } upgradeFound = true case PerturbationDisconnect, PerturbationKill, PerturbationPause, PerturbationRestart: @@ -483,10 +646,38 @@ func (t Testnet) HasPerturbations() bool { return false } +//go:embed templates/prometheus-yaml.tmpl +var prometheusYamlTemplate string + +func (t Testnet) prometheusConfigBytes() ([]byte, error) { + tmpl, err := template.New("prometheus-yaml").Parse(prometheusYamlTemplate) + if err != nil { + return nil, err + } + var buf bytes.Buffer + err = tmpl.Execute(&buf, t) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (t Testnet) WritePrometheusConfig() error { + bytes, err := t.prometheusConfigBytes() + if err != nil { + return err + } + err = os.WriteFile(filepath.Join(t.Dir, "prometheus.yaml"), bytes, 0o644) //nolint:gosec + if err != nil { + return err + } + return nil +} + // Address returns a P2P endpoint address for the node. func (n Node) AddressP2P(withID bool) string { - ip := n.IP.String() - if n.IP.To4() == nil { + ip := n.InternalIP.String() + if n.InternalIP.To4() == nil { // IPv6 addresses must be wrapped in [] to avoid conflict with : port separator ip = fmt.Sprintf("[%v]", ip) } @@ -499,24 +690,48 @@ func (n Node) AddressP2P(withID bool) string { // Address returns an RPC endpoint address for the node. func (n Node) AddressRPC() string { - ip := n.IP.String() - if n.IP.To4() == nil { + ip := n.InternalIP.String() + if n.InternalIP.To4() == nil { // IPv6 addresses must be wrapped in [] to avoid conflict with : port separator ip = fmt.Sprintf("[%v]", ip) } return fmt.Sprintf("%v:26657", ip) } -// Client returns an RPC client for a node. +// Client returns an RPC client for the node. func (n Node) Client() (*rpchttp.HTTP, error) { - return rpchttp.New(fmt.Sprintf("http://127.0.0.1:%v", n.ProxyPort), "/websocket") + //nolint:nosprintfhostport + return rpchttp.New(fmt.Sprintf("http://%s:%v/v1", n.ExternalIP, n.RPCProxyPort)) +} + +// GRPCClient creates a gRPC client for the node. +func (n Node) GRPCClient(ctx context.Context) (grpcclient.Client, error) { + return grpcclient.New( + ctx, + fmt.Sprintf("127.0.0.1:%v", n.GRPCProxyPort), + grpcclient.WithInsecure(), + ) +} + +// GRPCClient creates a gRPC client for the node. +func (n Node) GRPCPrivilegedClient(ctx context.Context) (grpcprivileged.Client, error) { + return grpcprivileged.New( + ctx, + fmt.Sprintf("127.0.0.1:%v", n.GRPCPrivilegedProxyPort), + grpcprivileged.WithInsecure(), + ) } -// Stateless returns true if the node is either a seed node or a light node +// Stateless returns true if the node is either a seed node or a light node. func (n Node) Stateless() bool { return n.Mode == ModeLight || n.Mode == ModeSeed } +// ZoneIsSet returns if the node has a zone set for latency emulation. +func (n Node) ZoneIsSet() bool { + return len(n.Zone) > 0 +} + // keyGenerator generates pseudorandom Ed25519 keys based on a seed. type keyGenerator struct { random *rand.Rand @@ -601,3 +816,47 @@ func (g *ipGenerator) Next() net.IP { } return ip } + +//go:embed latency/aws-latencies.csv +var awsLatenciesMatrixCsvContent string + +func loadZoneLatenciesMatrix() (map[ZoneID][]uint32, error) { + records, err := parseCsv(awsLatenciesMatrixCsvContent) + if err != nil { + return nil, err + } + records = records[1:] // Ignore first headers line + matrix := make(map[ZoneID][]uint32, len(records)) + for _, r := range records { + zoneID := ZoneID(r[0]) + matrix[zoneID] = make([]uint32, len(r)-1) + for i, l := range r[1:] { + lat, err := strconv.ParseUint(l, 10, 32) + if err != nil { + return nil, ErrInvalidZoneID{l, err} + } + matrix[zoneID][i] = uint32(lat) + } + } + return matrix, nil +} + +type ErrInvalidZoneID struct { + ZoneID string + Err error +} + +func (e ErrInvalidZoneID) Error() string { + return fmt.Sprintf("invalid zone id (%s): %v", e.ZoneID, e.Err) +} + +func parseCsv(csvString string) ([][]string, error) { + csvReader := csv.NewReader(strings.NewReader(csvString)) + csvReader.Comment = '#' + records, err := csvReader.ReadAll() + if err != nil { + return nil, err + } + + return records, nil +} diff --git a/test/e2e/runner/benchmark.go b/test/e2e/runner/benchmark.go index bd671fc4f58..2f3bfea7be1 100644 --- a/test/e2e/runner/benchmark.go +++ b/test/e2e/runner/benchmark.go @@ -20,7 +20,7 @@ import ( // 4. Min block interval (fastest block) // // Metrics are based of the `benchmarkLength`, the amount of consecutive blocks -// sampled from in the testnet +// sampled from in the testnet. func Benchmark(ctx context.Context, testnet *e2e.Testnet, benchmarkLength int64) error { block, _, err := waitForHeight(ctx, testnet, 0) if err != nil { @@ -84,7 +84,7 @@ type testnetStats struct { } func (t *testnetStats) OutputJSON(net *e2e.Testnet) string { - jsn, err := json.Marshal(map[string]interface{}{ + jsn, err := json.Marshal(map[string]any{ "case": filepath.Base(net.File), "start_height": t.startHeight, "end_height": t.endHeight, @@ -97,7 +97,6 @@ func (t *testnetStats) OutputJSON(net *e2e.Testnet) string { "txns": t.numtxns, "dur": t.totalTime.Seconds(), }) - if err != nil { return "" } diff --git a/test/e2e/runner/cleanup.go b/test/e2e/runner/cleanup.go index 735a451fb87..b1899d77101 100644 --- a/test/e2e/runner/cleanup.go +++ b/test/e2e/runner/cleanup.go @@ -1,6 +1,7 @@ package main import ( + "context" "errors" "fmt" "os" @@ -8,6 +9,8 @@ import ( "github.com/cometbft/cometbft/libs/log" e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/test/e2e/pkg/exec" + "github.com/cometbft/cometbft/test/e2e/pkg/infra/docker" ) // Cleanup removes the Docker Compose containers and testnet directory. @@ -32,13 +35,13 @@ func cleanupDocker() error { // does this by default. Ugly, but works. xargsR := `$(if [[ $OSTYPE == "linux-gnu"* ]]; then echo -n "-r"; fi)` - err := exec("bash", "-c", fmt.Sprintf( + err := exec.Command(context.Background(), "bash", "-c", fmt.Sprintf( "docker container ls -qa --filter label=e2e | xargs %v docker container rm -f", xargsR)) if err != nil { return err } - err = exec("bash", "-c", fmt.Sprintf( + err = exec.Command(context.Background(), "bash", "-c", fmt.Sprintf( "docker network ls -q --filter label=e2e | xargs %v docker network rm", xargsR)) if err != nil { return err @@ -47,7 +50,7 @@ func cleanupDocker() error { return nil } -// cleanupDir cleans up a testnet directory +// cleanupDir cleans up a testnet directory. func cleanupDir(dir string) error { if dir == "" { return errors.New("no directory set") @@ -60,7 +63,7 @@ func cleanupDir(dir string) error { return err } - logger.Info("cleanup dir", "msg", log.NewLazySprintf("Removing testnet directory %q", dir)) + logger.Info("cleanup dir", "msg", log.NewLazySprintf("Removing testnet directory %#q", dir)) // On Linux, some local files in the volume will be owned by root since CometBFT // runs as root inside the container, so we need to clean them up from within a @@ -69,7 +72,7 @@ func cleanupDir(dir string) error { if err != nil { return err } - err = execDocker("run", "--rm", "--entrypoint", "", "-v", fmt.Sprintf("%v:/network", absDir), + err = docker.Exec(context.Background(), "run", "--rm", "--entrypoint", "", "-v", fmt.Sprintf("%v:/network", absDir), "cometbft/e2e-node", "sh", "-c", "rm -rf /network/*/") if err != nil { return err diff --git a/test/e2e/runner/evidence.go b/test/e2e/runner/evidence.go index 42646adfb14..322442e1725 100644 --- a/test/e2e/runner/evidence.go +++ b/test/e2e/runner/evidence.go @@ -10,22 +10,21 @@ import ( "path/filepath" "time" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/tmhash" "github.com/cometbft/cometbft/internal/test" cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/privval" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" e2e "github.com/cometbft/cometbft/test/e2e/pkg" "github.com/cometbft/cometbft/types" "github.com/cometbft/cometbft/version" ) -// 1 in 4 evidence is light client evidence, the rest is duplicate vote evidence +// 1 in 4 evidence is light client evidence, the rest is duplicate vote evidence. const lightClientEvidenceRatio = 4 -// InjectEvidence takes a running testnet and generates an amount of valid +// InjectEvidence takes a running testnet and generates an amount of valid/invalid // evidence and broadcasts it to a random node through the rpc endpoint `/broadcast_evidence`. // Evidence is random and can be a mixture of LightClientAttackEvidence and // DuplicateVoteEvidence. @@ -88,15 +87,17 @@ func InjectEvidence(ctx context.Context, r *rand.Rand, testnet *e2e.Testnet, amo } var ev types.Evidence - for i := 1; i <= amount; i++ { + for i := 0; i < amount; i++ { + validEv := true if i%lightClientEvidenceRatio == 0 { + validEv = i%(lightClientEvidenceRatio*2) != 0 // Alternate valid and invalid evidence ev, err = generateLightClientAttackEvidence( - ctx, privVals, evidenceHeight, valSet, testnet.Name, blockRes.Block.Time, + ctx, privVals, evidenceHeight, valSet, testnet.Name, blockRes.Block.Time, validEv, ) } else { var dve *types.DuplicateVoteEvidence dve, err = generateDuplicateVoteEvidence( - ctx, privVals, evidenceHeight, valSet, testnet.Name, blockRes.Block.Time, + privVals, evidenceHeight, valSet, testnet.Name, blockRes.Block.Time, ) if dve.VoteA.Height < testnet.VoteExtensionsEnableHeight { dve.VoteA.Extension = nil @@ -111,7 +112,15 @@ func InjectEvidence(ctx context.Context, r *rand.Rand, testnet *e2e.Testnet, amo } _, err := client.BroadcastEvidence(ctx, ev) - if err != nil { + if !validEv { + // The tests will count committed evidences later on, + // and only valid evidences will make it + amount++ + } + if validEv != (err == nil) { + if err == nil { + return errors.New("submitting invalid evidence didn't return an error") + } return err } } @@ -156,6 +165,7 @@ func generateLightClientAttackEvidence( vals *types.ValidatorSet, chainID string, evTime time.Time, + validEvidence bool, ) (*types.LightClientAttackEvidence, error) { // forge a random header forgedHeight := height + 2 @@ -165,7 +175,7 @@ func generateLightClientAttackEvidence( // add a new bogus validator and remove an existing one to // vary the validator set slightly - pv, conflictingVals, err := mutateValidatorSet(ctx, privVals, vals) + pv, conflictingVals, err := mutateValidatorSet(ctx, privVals, vals, !validEvidence) if err != nil { return nil, err } @@ -174,12 +184,17 @@ func generateLightClientAttackEvidence( // create a commit for the forged header blockID := makeBlockID(header.Hash(), 1000, []byte("partshash")) - voteSet := types.NewVoteSet(chainID, forgedHeight, 0, cmtproto.SignedMsgType(2), conflictingVals) + voteSet := types.NewVoteSet(chainID, forgedHeight, 0, types.SignedMsgType(2), conflictingVals) commit, err := test.MakeCommitFromVoteSet(blockID, voteSet, pv, forgedTime) if err != nil { return nil, err } + // malleate the last signature of the commit by adding one to its first byte + if !validEvidence { + commit.Signatures[len(commit.Signatures)-1].Signature[0]++ + } + ev := &types.LightClientAttackEvidence{ ConflictingBlock: &types.LightBlock{ SignedHeader: &types.SignedHeader{ @@ -199,9 +214,8 @@ func generateLightClientAttackEvidence( } // generateDuplicateVoteEvidence picks a random validator from the val set and -// returns duplicate vote evidence against the validator +// returns duplicate vote evidence against the validator. func generateDuplicateVoteEvidence( - ctx context.Context, privVals []types.MockPV, height int64, vals *types.ValidatorSet, @@ -229,7 +243,7 @@ func generateDuplicateVoteEvidence( } // getRandomValidatorIndex picks a random validator from a slice of mock PrivVals that's -// also part of the validator set, returning the PrivVal and its index in the validator set +// also part of the validator set, returning the PrivVal and its index in the validator set. func getRandomValidatorIndex(privVals []types.MockPV, vals *types.ValidatorSet) (types.MockPV, int32, error) { for _, idx := range rand.Perm(len(privVals)) { pv := privVals[idx] @@ -294,7 +308,11 @@ func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.Bloc } } -func mutateValidatorSet(ctx context.Context, privVals []types.MockPV, vals *types.ValidatorSet, +func mutateValidatorSet( + ctx context.Context, + privVals []types.MockPV, + vals *types.ValidatorSet, + nop bool, ) ([]types.PrivValidator, *types.ValidatorSet, error) { newVal, newPrivVal, err := test.Validator(ctx, 10) if err != nil { @@ -302,10 +320,14 @@ func mutateValidatorSet(ctx context.Context, privVals []types.MockPV, vals *type } var newVals *types.ValidatorSet - if vals.Size() > 2 { - newVals = types.NewValidatorSet(append(vals.Copy().Validators[:vals.Size()-1], newVal)) + if nop { + newVals = types.NewValidatorSet(vals.Copy().Validators) } else { - newVals = types.NewValidatorSet(append(vals.Copy().Validators, newVal)) + if vals.Size() > 2 { + newVals = types.NewValidatorSet(append(vals.Copy().Validators[:vals.Size()-1], newVal)) + } else { + newVals = types.NewValidatorSet(append(vals.Copy().Validators, newVal)) + } } // we need to sort the priv validators with the same index as the validator set diff --git a/test/e2e/runner/exec.go b/test/e2e/runner/exec.go deleted file mode 100644 index 38b758360a8..00000000000 --- a/test/e2e/runner/exec.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "fmt" - "os" - osexec "os/exec" - "path/filepath" -) - -// execute executes a shell command. -func exec(args ...string) error { - _, err := execOutput(args...) - return err -} - -func execOutput(args ...string) ([]byte, error) { - cmd := osexec.Command(args[0], args[1:]...) //nolint:gosec - out, err := cmd.CombinedOutput() - switch err := err.(type) { - case nil: - return out, nil - case *osexec.ExitError: - return nil, fmt.Errorf("failed to run %q:\n%v", args, string(out)) - default: - return nil, err - } -} - -// execVerbose executes a shell command while displaying its output. -func execVerbose(args ...string) error { - cmd := osexec.Command(args[0], args[1:]...) //nolint:gosec - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - return cmd.Run() -} - -// execCompose runs a Docker Compose command for a testnet. -func execCompose(dir string, args ...string) error { - return exec(append( - []string{"docker-compose", "-f", filepath.Join(dir, "docker-compose.yml")}, - args...)...) -} - -func execComposeOutput(dir string, args ...string) ([]byte, error) { - return execOutput(append( - []string{"docker-compose", "-f", filepath.Join(dir, "docker-compose.yml")}, - args...)...) -} - -// execComposeVerbose runs a Docker Compose command for a testnet and displays its output. -func execComposeVerbose(dir string, args ...string) error { - return execVerbose(append( - []string{"docker-compose", "-f", filepath.Join(dir, "docker-compose.yml")}, - args...)...) -} - -// execDocker runs a Docker command. -func execDocker(args ...string) error { - return exec(append([]string{"docker"}, args...)...) -} diff --git a/test/e2e/runner/load.go b/test/e2e/runner/load.go index 3bb211c5547..f0930e95194 100644 --- a/test/e2e/runner/load.go +++ b/test/e2e/runner/load.go @@ -7,12 +7,13 @@ import ( "sync" "time" + "github.com/google/uuid" + "github.com/cometbft/cometbft/libs/log" rpchttp "github.com/cometbft/cometbft/rpc/client/http" e2e "github.com/cometbft/cometbft/test/e2e/pkg" "github.com/cometbft/cometbft/test/loadtime/payload" "github.com/cometbft/cometbft/types" - "github.com/google/uuid" ) const workerPoolSize = 16 @@ -23,6 +24,7 @@ func Load(ctx context.Context, testnet *e2e.Testnet) error { initialTimeout := 1 * time.Minute stallTimeout := 30 * time.Second chSuccess := make(chan struct{}) + chFailed := make(chan struct{}) ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -39,32 +41,48 @@ func Load(ctx context.Context, testnet *e2e.Testnet) error { } for w := 0; w < testnet.LoadTxConnections; w++ { - go loadProcess(ctx, txCh, chSuccess, n) + go loadProcess(ctx, txCh, chSuccess, chFailed, n) } } - // Monitor successful transactions, and abort on stalls. - success := 0 + // Monitor successful and failed transactions, and abort on stalls. + success, failed := 0, 0 timeout := initialTimeout for { + rate := log.NewLazySprintf("%.1f", float64(success)/time.Since(started).Seconds()) + select { case <-chSuccess: success++ timeout = stallTimeout + case <-chFailed: + failed++ case <-time.After(timeout): return fmt.Errorf("unable to submit transactions for %v", timeout) case <-ctx.Done(): if success == 0 { return errors.New("failed to submit any transactions") } - logger.Info("load", "msg", log.NewLazySprintf("Ending transaction load after %v txs (%.1f tx/s)...", - success, float64(success)/time.Since(started).Seconds())) + logger.Info("load", "msg", log.NewLazySprintf("Ending transaction load after %v txs (%v tx/s)...", success, rate)) + return nil + } + + // Log every ~1 second the number of sent transactions. + total := success + failed + if total%testnet.LoadTxBatchSize == 0 { + successRate := float64(success) / float64(total) + logger.Debug("load", "success", success, "failed", failed, "success/total", log.NewLazySprintf("%.2f", successRate), "tx/s", rate) + } + + // Check if reached max number of allowed transactions to send. + if testnet.LoadMaxTxs > 0 && success >= testnet.LoadMaxTxs { + logger.Info("load", "msg", log.NewLazySprintf("Ending transaction load after reaching %v txs (%v tx/s)...", success, rate)) return nil } } } -// loadGenerate generates jobs until the context is canceled +// loadGenerate generates jobs until the context is canceled. func loadGenerate(ctx context.Context, txCh chan<- types.Tx, testnet *e2e.Testnet, id []byte) { t := time.NewTimer(0) defer t.Stop() @@ -120,7 +138,6 @@ func createTxBatch(ctx context.Context, txCh chan<- types.Tx, testnet *e2e.Testn select { case genCh <- struct{}{}: case <-ctx.Done(): - break } } close(genCh) @@ -129,7 +146,7 @@ func createTxBatch(ctx context.Context, txCh chan<- types.Tx, testnet *e2e.Testn // loadProcess processes transactions by sending transactions received on the txCh // to the client. -func loadProcess(ctx context.Context, txCh <-chan types.Tx, chSuccess chan<- struct{}, n *e2e.Node) { +func loadProcess(ctx context.Context, txCh <-chan types.Tx, chSuccess chan<- struct{}, chFailed chan<- struct{}, n *e2e.Node) { var client *rpchttp.HTTP var err error s := struct{}{} @@ -142,6 +159,8 @@ func loadProcess(ctx context.Context, txCh <-chan types.Tx, chSuccess chan<- str } } if _, err = client.BroadcastTxSync(ctx, tx); err != nil { + logger.Error("failed to send transaction", "err", err) + chFailed <- s continue } chSuccess <- s diff --git a/test/e2e/runner/main.go b/test/e2e/runner/main.go index 901b6d850e7..a68bf6e5c4c 100644 --- a/test/e2e/runner/main.go +++ b/test/e2e/runner/main.go @@ -13,6 +13,7 @@ import ( "github.com/cometbft/cometbft/libs/log" e2e "github.com/cometbft/cometbft/test/e2e/pkg" "github.com/cometbft/cometbft/test/e2e/pkg/infra" + "github.com/cometbft/cometbft/test/e2e/pkg/infra/digitalocean" "github.com/cometbft/cometbft/test/e2e/pkg/infra/docker" ) @@ -40,7 +41,7 @@ func NewCLI() *CLI { Short: "End-to-end test runner", SilenceUsage: true, SilenceErrors: true, // we'll output them ourselves in Run() - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { file, err := cmd.Flags().GetString("file") if err != nil { return err @@ -79,19 +80,38 @@ func NewCLI() *CLI { return fmt.Errorf("unknown infrastructure type '%s'", inft) } - testnet, err := e2e.LoadTestnet(file, ifd) + testnetDir, err := cmd.Flags().GetString("testnet-dir") + if err != nil { + return err + } + + testnet, err := e2e.LoadTestnet(file, ifd, testnetDir) if err != nil { return fmt.Errorf("loading testnet: %s", err) } cli.testnet = testnet - cli.infp = &infra.NoopProvider{} - if inft == "docker" { - cli.infp = &docker.Provider{Testnet: testnet} + switch inft { + case "docker": + cli.infp = &docker.Provider{ + ProviderData: infra.ProviderData{ + Testnet: testnet, + InfrastructureData: ifd, + }, + } + case "digital-ocean": + cli.infp = &digitalocean.Provider{ + ProviderData: infra.ProviderData{ + Testnet: testnet, + InfrastructureData: ifd, + }, + } + default: + return fmt.Errorf("bad infrastructure type: %s", inft) } return nil }, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { if err := Cleanup(cli.testnet); err != nil { return err } @@ -112,7 +132,7 @@ func NewCLI() *CLI { chLoadResult <- err }() - if err := Start(cmd.Context(), cli.testnet); err != nil { + if err := Start(cmd.Context(), cli.testnet, cli.infp); err != nil { return err } @@ -121,7 +141,7 @@ func NewCLI() *CLI { } if cli.testnet.HasPerturbations() { - if err := Perturb(cmd.Context(), cli.testnet); err != nil { + if err := Perturb(cmd.Context(), cli.testnet, cli.infp); err != nil { return err } if err := Wait(cmd.Context(), cli.testnet, 5); err != nil { // allow some txs to go through @@ -145,7 +165,7 @@ func NewCLI() *CLI { if err := Wait(cmd.Context(), cli.testnet, 5); err != nil { // wait for network to settle before tests return err } - if err := Test(cli.testnet); err != nil { + if err := Test(cli.testnet, cli.infp.GetInfrastructureData()); err != nil { return err } if !cli.preserve { @@ -160,6 +180,8 @@ func NewCLI() *CLI { cli.root.PersistentFlags().StringP("file", "f", "", "Testnet TOML manifest") _ = cli.root.MarkPersistentFlagRequired("file") + cli.root.PersistentFlags().StringP("testnet-dir", "d", "", "Set the directory for the testnet files generated during setup") + cli.root.PersistentFlags().StringP("infrastructure-type", "", "docker", "Backing infrastructure used to run the testnet. Either 'digital-ocean' or 'docker'") cli.root.PersistentFlags().StringP("infrastructure-data", "", "", "path to the json file containing the infrastructure data. Only used if the 'infrastructure-type' is set to a value other than 'docker'") @@ -170,15 +192,15 @@ func NewCLI() *CLI { cli.root.AddCommand(&cobra.Command{ Use: "setup", Short: "Generates the testnet directory and configuration", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return Setup(cli.testnet, cli.infp) }, }) cli.root.AddCommand(&cobra.Command{ Use: "start", - Short: "Starts the Docker testnet, waiting for nodes to become available", - RunE: func(cmd *cobra.Command, args []string) error { + Short: "Starts the testnet, waiting for nodes to become available", + RunE: func(cmd *cobra.Command, _ []string) error { _, err := os.Stat(cli.testnet.Dir) if os.IsNotExist(err) { err = Setup(cli.testnet, cli.infp) @@ -186,39 +208,39 @@ func NewCLI() *CLI { if err != nil { return err } - return Start(cmd.Context(), cli.testnet) + return Start(cmd.Context(), cli.testnet, cli.infp) }, }) cli.root.AddCommand(&cobra.Command{ Use: "perturb", - Short: "Perturbs the Docker testnet, e.g. by restarting or disconnecting nodes", - RunE: func(cmd *cobra.Command, args []string) error { - return Perturb(cmd.Context(), cli.testnet) + Short: "Perturbs the testnet, e.g. by restarting or disconnecting nodes", + RunE: func(cmd *cobra.Command, _ []string) error { + return Perturb(cmd.Context(), cli.testnet, cli.infp) }, }) cli.root.AddCommand(&cobra.Command{ Use: "wait", Short: "Waits for a few blocks to be produced and all nodes to catch up", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { return Wait(cmd.Context(), cli.testnet, 5) }, }) cli.root.AddCommand(&cobra.Command{ Use: "stop", - Short: "Stops the Docker testnet", - RunE: func(cmd *cobra.Command, args []string) error { + Short: "Stops the testnet", + RunE: func(_ *cobra.Command, _ []string) error { logger.Info("Stopping testnet") - return execCompose(cli.testnet.Dir, "down") + return cli.infp.StopTestnet(context.Background()) }, }) cli.root.AddCommand(&cobra.Command{ Use: "load", Short: "Generates transaction load until the command is canceled", - RunE: func(cmd *cobra.Command, args []string) (err error) { + RunE: func(_ *cobra.Command, _ []string) (err error) { return Load(context.Background(), cli.testnet) }, }) @@ -249,15 +271,15 @@ func NewCLI() *CLI { cli.root.AddCommand(&cobra.Command{ Use: "test", Short: "Runs test cases against a running testnet", - RunE: func(cmd *cobra.Command, args []string) error { - return Test(cli.testnet) + RunE: func(_ *cobra.Command, _ []string) error { + return Test(cli.testnet, cli.infp.GetInfrastructureData()) }, }) cli.root.AddCommand(&cobra.Command{ Use: "cleanup", Short: "Removes the testnet directory", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return Cleanup(cli.testnet) }, }) @@ -265,16 +287,16 @@ func NewCLI() *CLI { cli.root.AddCommand(&cobra.Command{ Use: "logs", Short: "Shows the testnet logs", - RunE: func(cmd *cobra.Command, args []string) error { - return execComposeVerbose(cli.testnet.Dir, "logs") + RunE: func(_ *cobra.Command, _ []string) error { + return docker.ExecComposeVerbose(context.Background(), cli.testnet.Dir, "logs") }, }) cli.root.AddCommand(&cobra.Command{ Use: "tail", Short: "Tails the testnet logs", - RunE: func(cmd *cobra.Command, args []string) error { - return execComposeVerbose(cli.testnet.Dir, "logs", "--follow") + RunE: func(_ *cobra.Command, _ []string) error { + return docker.ExecComposeVerbose(context.Background(), cli.testnet.Dir, "logs", "--follow") }, }) @@ -290,7 +312,7 @@ over a 100 block sampling period. Does not run any perturbations. `, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { if err := Cleanup(cli.testnet); err != nil { return err } @@ -309,7 +331,7 @@ Does not run any perturbations. chLoadResult <- err }() - if err := Start(cmd.Context(), cli.testnet); err != nil { + if err := Start(cmd.Context(), cli.testnet, cli.infp); err != nil { return err } @@ -327,11 +349,7 @@ Does not run any perturbations. return err } - if err := Cleanup(cli.testnet); err != nil { - return err - } - - return nil + return Cleanup(cli.testnet) }, }) diff --git a/test/e2e/runner/perturb.go b/test/e2e/runner/perturb.go index f407854997c..d9fefae048d 100644 --- a/test/e2e/runner/perturb.go +++ b/test/e2e/runner/perturb.go @@ -8,13 +8,15 @@ import ( "github.com/cometbft/cometbft/libs/log" rpctypes "github.com/cometbft/cometbft/rpc/core/types" e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/test/e2e/pkg/infra" + "github.com/cometbft/cometbft/test/e2e/pkg/infra/docker" ) // Perturbs a running testnet. -func Perturb(ctx context.Context, testnet *e2e.Testnet) error { +func Perturb(ctx context.Context, testnet *e2e.Testnet, ifp infra.Provider) error { for _, node := range testnet.Nodes { for _, perturbation := range node.Perturbations { - _, err := PerturbNode(ctx, node, perturbation) + _, err := PerturbNode(ctx, node, perturbation, ifp) if err != nil { return err } @@ -26,57 +28,62 @@ func Perturb(ctx context.Context, testnet *e2e.Testnet) error { // PerturbNode perturbs a node with a given perturbation, returning its status // after recovering. -func PerturbNode(ctx context.Context, node *e2e.Node, perturbation e2e.Perturbation) (*rpctypes.ResultStatus, error) { +func PerturbNode(ctx context.Context, node *e2e.Node, perturbation e2e.Perturbation, ifp infra.Provider) (*rpctypes.ResultStatus, error) { testnet := node.Testnet - out, err := execComposeOutput(testnet.Dir, "ps", "-q", node.Name) + + name, upgraded, err := ifp.CheckUpgraded(ctx, node) if err != nil { return nil, err } - name := node.Name - upgraded := false - if len(out) == 0 { - name = name + "_u" - upgraded = true + if upgraded { logger.Info("perturb node", "msg", log.NewLazySprintf("Node %v already upgraded, operating on alternate container %v", node.Name, name)) } + timeout := 20 * time.Second + switch perturbation { case e2e.PerturbationDisconnect: logger.Info("perturb node", "msg", log.NewLazySprintf("Disconnecting node %v...", node.Name)) - if err := execDocker("network", "disconnect", testnet.Name+"_"+testnet.Name, name); err != nil { + if err := ifp.Disconnect(context.Background(), name, node.ExternalIP.String()); err != nil { return nil, err } time.Sleep(10 * time.Second) - if err := execDocker("network", "connect", testnet.Name+"_"+testnet.Name, name); err != nil { + if err := ifp.Reconnect(context.Background(), name, node.ExternalIP.String()); err != nil { return nil, err } case e2e.PerturbationKill: logger.Info("perturb node", "msg", log.NewLazySprintf("Killing node %v...", node.Name)) - if err := execCompose(testnet.Dir, "kill", "-s", "SIGKILL", name); err != nil { + if err := docker.ExecCompose(context.Background(), testnet.Dir, "kill", "-s", "SIGKILL", name); err != nil { return nil, err } - if err := execCompose(testnet.Dir, "start", name); err != nil { + if err := docker.ExecCompose(context.Background(), testnet.Dir, "start", name); err != nil { return nil, err } + if node.PersistInterval == 0 { + timeout *= 5 + } case e2e.PerturbationPause: logger.Info("perturb node", "msg", log.NewLazySprintf("Pausing node %v...", node.Name)) - if err := execCompose(testnet.Dir, "pause", name); err != nil { + if err := docker.ExecCompose(context.Background(), testnet.Dir, "pause", name); err != nil { return nil, err } time.Sleep(10 * time.Second) - if err := execCompose(testnet.Dir, "unpause", name); err != nil { + if err := docker.ExecCompose(context.Background(), testnet.Dir, "unpause", name); err != nil { return nil, err } case e2e.PerturbationRestart: logger.Info("perturb node", "msg", log.NewLazySprintf("Restarting node %v...", node.Name)) - if err := execCompose(testnet.Dir, "restart", name); err != nil { + if err := docker.ExecCompose(context.Background(), testnet.Dir, "restart", name); err != nil { return nil, err } + if node.PersistInterval == 0 { + timeout *= 5 + } case e2e.PerturbationUpgrade: oldV := node.Version @@ -95,19 +102,22 @@ func PerturbNode(ctx context.Context, node *e2e.Node, perturbation e2e.Perturbat log.NewLazySprintf("Upgrading node %v from version '%v' to version '%v'...", node.Name, oldV, newV)) - if err := execCompose(testnet.Dir, "stop", name); err != nil { + if err := docker.ExecCompose(context.Background(), testnet.Dir, "stop", name); err != nil { return nil, err } time.Sleep(10 * time.Second) - if err := execCompose(testnet.Dir, "up", "-d", name+"_u"); err != nil { + if err := docker.ExecCompose(context.Background(), testnet.Dir, "up", "-d", name+"_u"); err != nil { return nil, err } + if node.PersistInterval == 0 { + timeout *= 5 + } default: return nil, fmt.Errorf("unexpected perturbation %q", perturbation) } - status, err := waitForNode(ctx, node, 0, 20*time.Second) + status, err := waitForNode(ctx, node, 0, timeout) if err != nil { return nil, err } diff --git a/test/e2e/runner/rpc.go b/test/e2e/runner/rpc.go index f6f17384230..b1adce51329 100644 --- a/test/e2e/runner/rpc.go +++ b/test/e2e/runner/rpc.go @@ -72,7 +72,6 @@ func waitForHeight(ctx context.Context, testnet *e2e.Testnet, height int64) (*ty } timer.Reset(1 * time.Second) } - } } diff --git a/test/e2e/runner/setup.go b/test/e2e/runner/setup.go index 4fc57252aa5..bd62663433d 100644 --- a/test/e2e/runner/setup.go +++ b/test/e2e/runner/setup.go @@ -10,6 +10,7 @@ import ( "path/filepath" "regexp" "sort" + "strconv" "strings" "time" @@ -39,7 +40,7 @@ const ( // Setup sets up the testnet configuration. func Setup(testnet *e2e.Testnet, infp infra.Provider) error { - logger.Info("setup", "msg", log.NewLazySprintf("Generating testnet files in %q", testnet.Dir)) + logger.Info("setup", "msg", log.NewLazySprintf("Generating testnet files in %#q", testnet.Dir)) if err := os.MkdirAll(testnet.Dir, os.ModePerm); err != nil { return err @@ -116,6 +117,12 @@ func Setup(testnet *e2e.Testnet, infp infra.Provider) error { )).Save() } + if testnet.Prometheus { + if err := testnet.WritePrometheusConfig(); err != nil { + return err + } + } + return nil } @@ -131,7 +138,15 @@ func MakeGenesis(testnet *e2e.Testnet) (types.GenesisDoc, error) { genesis.ConsensusParams.Version.App = 1 genesis.ConsensusParams.Evidence.MaxAgeNumBlocks = e2e.EvidenceAgeHeight genesis.ConsensusParams.Evidence.MaxAgeDuration = e2e.EvidenceAgeTime - genesis.ConsensusParams.ABCI.VoteExtensionsEnableHeight = testnet.VoteExtensionsEnableHeight + if testnet.BlockMaxBytes != 0 { + genesis.ConsensusParams.Block.MaxBytes = testnet.BlockMaxBytes + } + if testnet.VoteExtensionsUpdateHeight == -1 { + genesis.ConsensusParams.Feature.VoteExtensionsEnableHeight = testnet.VoteExtensionsEnableHeight + } + if testnet.PbtsUpdateHeight == -1 { + genesis.ConsensusParams.Feature.PbtsEnableHeight = testnet.PbtsEnableHeight + } for validator, power := range testnet.Validators { genesis.Validators = append(genesis.Validators, types.GenesisValidator{ Name: validator.Name, @@ -160,13 +175,34 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { cfg := config.DefaultConfig() cfg.Moniker = node.Name cfg.ProxyApp = AppAddressTCP + cfg.RPC.ListenAddress = "tcp://0.0.0.0:26657" cfg.RPC.PprofListenAddress = ":6060" + + cfg.GRPC.ListenAddress = "tcp://0.0.0.0:26670" + cfg.GRPC.VersionService.Enabled = true + cfg.GRPC.BlockService.Enabled = true + cfg.GRPC.BlockResultsService.Enabled = true + cfg.P2P.ExternalAddress = fmt.Sprintf("tcp://%v", node.AddressP2P(false)) cfg.P2P.AddrBookStrict = false + cfg.DBBackend = node.Database cfg.StateSync.DiscoveryTime = 5 * time.Second cfg.BlockSync.Version = node.BlockSyncVersion + cfg.Consensus.PeerGossipIntraloopSleepDuration = node.Testnet.PeerGossipIntraloopSleepDuration + cfg.Mempool.ExperimentalMaxGossipConnectionsToNonPersistentPeers = int(node.Testnet.ExperimentalMaxGossipConnectionsToNonPersistentPeers) + cfg.Mempool.ExperimentalMaxGossipConnectionsToPersistentPeers = int(node.Testnet.ExperimentalMaxGossipConnectionsToPersistentPeers) + + // Assume that full nodes and validators will have a data companion + // attached, which will need access to the privileged gRPC endpoint. + if (node.Mode == e2e.ModeValidator || node.Mode == e2e.ModeFull) && node.EnableCompanionPruning { + cfg.Storage.Pruning.DataCompanion.Enabled = true + cfg.Storage.Pruning.DataCompanion.InitialBlockRetainHeight = 0 + cfg.Storage.Pruning.DataCompanion.InitialBlockResultsRetainHeight = 0 + cfg.GRPC.Privileged.ListenAddress = "tcp://0.0.0.0:26671" + cfg.GRPC.Privileged.PruningService.Enabled = true + } switch node.ABCIProtocol { case e2e.ProtocolUNIX: @@ -176,7 +212,7 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { case e2e.ProtocolGRPC: cfg.ProxyApp = AppAddressTCP cfg.ABCI = "grpc" - case e2e.ProtocolBuiltin, e2e.ProtocolBuiltinUnsync: + case e2e.ProtocolBuiltin, e2e.ProtocolBuiltinConnSync: cfg.ProxyApp = "" cfg.ABCI = "" default: @@ -241,32 +277,59 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { } cfg.P2P.PersistentPeers += peer.AddressP2P(true) } + if node.Testnet.DisablePexReactor { + cfg.P2P.PexReactor = false + } if node.Prometheus { cfg.Instrumentation.Prometheus = true } + if node.ExperimentalKeyLayout != "" { + cfg.Storage.ExperimentalKeyLayout = node.ExperimentalKeyLayout + } + + if node.Compact { + cfg.Storage.Compact = node.Compact + } + + if node.DiscardABCIResponses { + cfg.Storage.DiscardABCIResponses = node.DiscardABCIResponses + } + + if node.Indexer != "" { + cfg.TxIndex.Indexer = node.Indexer + } + + if node.CompactionInterval != 0 && node.Compact { + cfg.Storage.CompactionInterval = node.CompactionInterval + } return cfg, nil } // MakeAppConfig generates an ABCI application config for a node. func MakeAppConfig(node *e2e.Node) ([]byte, error) { - cfg := map[string]interface{}{ - "chain_id": node.Testnet.Name, - "dir": "data/app", - "listen": AppAddressUNIX, - "mode": node.Mode, - "proxy_port": node.ProxyPort, - "protocol": "socket", - "persist_interval": node.PersistInterval, - "snapshot_interval": node.SnapshotInterval, - "retain_blocks": node.RetainBlocks, - "key_type": node.PrivvalKey.Type(), - "prepare_proposal_delay": node.Testnet.PrepareProposalDelay, - "process_proposal_delay": node.Testnet.ProcessProposalDelay, - "check_tx_delay": node.Testnet.CheckTxDelay, - "vote_extension_delay": node.Testnet.VoteExtensionDelay, - "finalize_block_delay": node.Testnet.FinalizeBlockDelay, + cfg := map[string]any{ + "chain_id": node.Testnet.Name, + "dir": "data/app", + "listen": AppAddressUNIX, + "mode": node.Mode, + "protocol": "socket", + "persist_interval": node.PersistInterval, + "snapshot_interval": node.SnapshotInterval, + "retain_blocks": node.RetainBlocks, + "key_type": node.PrivvalKey.Type(), + "prepare_proposal_delay": node.Testnet.PrepareProposalDelay, + "process_proposal_delay": node.Testnet.ProcessProposalDelay, + "check_tx_delay": node.Testnet.CheckTxDelay, + "vote_extension_delay": node.Testnet.VoteExtensionDelay, + "finalize_block_delay": node.Testnet.FinalizeBlockDelay, + "vote_extension_size": node.Testnet.VoteExtensionSize, + "vote_extensions_enable_height": node.Testnet.VoteExtensionsEnableHeight, + "vote_extensions_update_height": node.Testnet.VoteExtensionsUpdateHeight, + "abci_requests_logging_enabled": node.Testnet.ABCITestsEnabled, + "pbts_enable_height": node.Testnet.PbtsEnableHeight, + "pbts_update_height": node.Testnet.PbtsUpdateHeight, } switch node.ABCIProtocol { case e2e.ProtocolUNIX: @@ -276,7 +339,7 @@ func MakeAppConfig(node *e2e.Node) ([]byte, error) { case e2e.ProtocolGRPC: cfg["listen"] = AppAddressTCP cfg["protocol"] = "grpc" - case e2e.ProtocolBuiltin, e2e.ProtocolBuiltinUnsync: + case e2e.ProtocolBuiltin, e2e.ProtocolBuiltinConnSync: delete(cfg, "listen") cfg["protocol"] = string(node.ABCIProtocol) default: @@ -305,7 +368,7 @@ func MakeAppConfig(node *e2e.Node) ([]byte, error) { for node, power := range validators { updateVals[base64.StdEncoding.EncodeToString(node.PrivvalKey.PubKey().Bytes())] = power } - validatorUpdates[fmt.Sprintf("%v", height)] = updateVals + validatorUpdates[strconv.FormatInt(height, 10)] = updateVals } cfg["validator_update"] = validatorUpdates } diff --git a/test/e2e/runner/start.go b/test/e2e/runner/start.go index 491088da691..6c72b7fbfe5 100644 --- a/test/e2e/runner/start.go +++ b/test/e2e/runner/start.go @@ -2,17 +2,18 @@ package main import ( "context" - "fmt" + "errors" "sort" "time" "github.com/cometbft/cometbft/libs/log" e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/test/e2e/pkg/infra" ) -func Start(ctx context.Context, testnet *e2e.Testnet) error { +func Start(ctx context.Context, testnet *e2e.Testnet, p infra.Provider) error { if len(testnet.Nodes) == 0 { - return fmt.Errorf("no nodes in testnet") + return errors.New("no nodes in testnet") } // Nodes are already sorted by name. Sort them by name then startAt, @@ -36,24 +37,38 @@ func Start(ctx context.Context, testnet *e2e.Testnet) error { }) if nodeQueue[0].StartAt > 0 { - return fmt.Errorf("no initial nodes in testnet") + return errors.New("no initial nodes in testnet") } // Start initial nodes (StartAt: 0) logger.Info("Starting initial network nodes...") + nodesAtZero := make([]*e2e.Node, 0) for len(nodeQueue) > 0 && nodeQueue[0].StartAt == 0 { - node := nodeQueue[0] + nodesAtZero = append(nodesAtZero, nodeQueue[0]) nodeQueue = nodeQueue[1:] - if err := execCompose(testnet.Dir, "up", "-d", node.Name); err != nil { - return err - } + } + err := p.StartNodes(context.Background(), nodesAtZero...) + if err != nil { + return err + } + for _, node := range nodesAtZero { if _, err := waitForNode(ctx, node, 0, 15*time.Second); err != nil { return err } if node.PrometheusProxyPort > 0 { - logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://127.0.0.1:%v; with Prometheus on http://127.0.0.1:%v/metrics", node.Name, node.ProxyPort, node.PrometheusProxyPort)) + logger.Info("start", "msg", + log.NewLazySprintf("Node %v up on http://%s:%v; with Prometheus on http://%s:%v/metrics", + node.Name, node.ExternalIP, node.RPCProxyPort, node.ExternalIP, node.PrometheusProxyPort), + ) } else { - logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://127.0.0.1:%v", node.Name, node.ProxyPort)) + logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://%s:%v", + node.Name, node.ExternalIP, node.RPCProxyPort)) + } + if node.ZoneIsSet() { + logger.Info("setting latency", "zone", node.Zone) + if err := p.SetLatency(ctx, node); err != nil { + return err + } } } @@ -102,15 +117,27 @@ func Start(ctx context.Context, testnet *e2e.Testnet) error { logger.Info("Starting catch up node", "node", node.Name, "height", node.StartAt) - if err := execCompose(testnet.Dir, "up", "-d", node.Name); err != nil { + err := p.StartNodes(context.Background(), node) + if err != nil { return err } status, err := waitForNode(ctx, node, node.StartAt, 3*time.Minute) if err != nil { return err } - logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://127.0.0.1:%v at height %v", - node.Name, node.ProxyPort, status.SyncInfo.LatestBlockHeight)) + if node.PrometheusProxyPort > 0 { + logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://%s:%v at height %v; with Prometheus on http://%s:%v/metrics", + node.Name, node.ExternalIP, node.RPCProxyPort, status.SyncInfo.LatestBlockHeight, node.ExternalIP, node.PrometheusProxyPort)) + } else { + logger.Info("start", "msg", log.NewLazySprintf("Node %v up on http://%s:%v at height %v", + node.Name, node.ExternalIP, node.RPCProxyPort, status.SyncInfo.LatestBlockHeight)) + } + if node.ZoneIsSet() { + logger.Info("setting latency", "zone", node.Zone) + if err := p.SetLatency(ctx, node); err != nil { + return err + } + } } return nil diff --git a/test/e2e/runner/test.go b/test/e2e/runner/test.go index f39e2a0da55..de3d0a06793 100644 --- a/test/e2e/runner/test.go +++ b/test/e2e/runner/test.go @@ -1,19 +1,42 @@ package main import ( + "context" "os" e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/test/e2e/pkg/exec" ) -// Test runs test cases under tests/ -func Test(testnet *e2e.Testnet) error { +// Test runs test cases under tests. +func Test(testnet *e2e.Testnet, ifd *e2e.InfrastructureData) error { logger.Info("Running tests in ./tests/...") err := os.Setenv("E2E_MANIFEST", testnet.File) if err != nil { return err } + err = os.Setenv("E2E_TESTNET_DIR", testnet.Dir) + if err != nil { + return err + } + if p := ifd.Path; p != "" { + err = os.Setenv("INFRASTRUCTURE_FILE", p) + if err != nil { + return err + } + } + err = os.Setenv("INFRASTRUCTURE_TYPE", ifd.Provider) + if err != nil { + return err + } + + cmd := []string{"go", "test", "-count", "1"} + verbose := os.Getenv("VERBOSE") + if verbose == "1" { + cmd = append(cmd, "-v") + } + cmd = append(cmd, "./tests/...") - return execVerbose("go", "test", "-count", "1", "./tests/...") + return exec.CommandVerbose(context.Background(), cmd...) } diff --git a/test/e2e/tests/abci_test.go b/test/e2e/tests/abci_test.go new file mode 100644 index 00000000000..82d7fdb8cc2 --- /dev/null +++ b/test/e2e/tests/abci_test.go @@ -0,0 +1,39 @@ +package e2e_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/test/e2e/pkg/grammar" +) + +func TestCheckABCIGrammar(t *testing.T) { + checker := grammar.NewGrammarChecker(grammar.DefaultConfig()) + testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() + if !node.Testnet.ABCITestsEnabled { + return + } + executions, err := fetchABCIRequests(t, node.Name) + require.NoError(t, err) + for i, e := range executions { + isCleanStart := i == 0 + _, err := checker.Verify(e, isCleanStart) + require.NoError(t, err) + } + }) +} + +func TestNodeNameExtracting(t *testing.T) { + testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() + if !node.Testnet.ABCITestsEnabled { + return + } + reqs, err := fetchABCIRequests(t, node.Name) + require.NoError(t, err) + require.NotZero(t, len(reqs)) + }) +} diff --git a/test/e2e/tests/app_test.go b/test/e2e/tests/app_test.go index d4f0f91561e..31ae1ee2b65 100644 --- a/test/e2e/tests/app_test.go +++ b/test/e2e/tests/app_test.go @@ -2,6 +2,7 @@ package e2e_test import ( "bytes" + "encoding/hex" "fmt" "math/rand" "strconv" @@ -18,6 +19,7 @@ import ( // Tests that any initial state given in genesis has made it into the app. func TestApp_InitialState(t *testing.T) { testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() if len(node.Testnet.InitialState) == 0 { return } @@ -36,7 +38,9 @@ func TestApp_InitialState(t *testing.T) { // Tests that the app hash (as reported by the app) matches the last // block and the node sync status. func TestApp_Hash(t *testing.T) { + t.Helper() testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() client, err := node.Client() require.NoError(t, err) @@ -52,20 +56,22 @@ func TestApp_Hash(t *testing.T) { require.NoError(t, err) require.NotZero(t, status.SyncInfo.LatestBlockHeight) return status.SyncInfo.LatestBlockHeight >= requestedHeight - }, 5*time.Second, 500*time.Millisecond) + }, 30*time.Second, 500*time.Millisecond) block, err := client.Block(ctx, &requestedHeight) require.NoError(t, err) require.Equal(t, - fmt.Sprintf("%x", info.Response.LastBlockAppHash), - fmt.Sprintf("%x", block.Block.AppHash.Bytes()), + hex.EncodeToString(info.Response.LastBlockAppHash), + hex.EncodeToString(block.Block.AppHash.Bytes()), "app hash does not match last block's app hash") }) } // Tests that we can set a value and retrieve it. func TestApp_Tx(t *testing.T) { + t.Helper() testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() client, err := node.Client() require.NoError(t, err) @@ -77,7 +83,7 @@ func TestApp_Tx(t *testing.T) { require.NoError(t, err) key := fmt.Sprintf("testapp-tx-%v", node.Name) - value := fmt.Sprintf("%x", bz) + value := hex.EncodeToString(bz) tx := types.Tx(fmt.Sprintf("%v=%v", key, value)) _, err = client.BroadcastTxSync(ctx, tx) @@ -101,12 +107,13 @@ func TestApp_Tx(t *testing.T) { require.NoError(t, err) assert.Equal(t, key, string(abciResp.Response.Key)) assert.Equal(t, value, string(abciResp.Response.Value)) - }) } func TestApp_VoteExtensions(t *testing.T) { + t.Helper() testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() client, err := node.Client() require.NoError(t, err) info, err := client.ABCIInfo(ctx) @@ -120,7 +127,6 @@ func TestApp_VoteExtensions(t *testing.T) { // the app to have any extension value set (via a normal tx). if node.Testnet.VoteExtensionsEnableHeight != 0 && info.Response.LastBlockHeight > node.Testnet.VoteExtensionsEnableHeight { - parts := bytes.Split(resp.Response.Value, []byte("|")) require.Len(t, parts, 2) extSum, err := strconv.Atoi(string(parts[0])) diff --git a/test/e2e/tests/block_test.go b/test/e2e/tests/block_test.go index e76e622eb11..136c094dbca 100644 --- a/test/e2e/tests/block_test.go +++ b/test/e2e/tests/block_test.go @@ -11,9 +11,11 @@ import ( // Tests that block headers are identical across nodes where present. func TestBlock_Header(t *testing.T) { + t.Helper() blocks := fetchBlockChain(t) testNode(t, func(t *testing.T, node e2e.Node) { - if node.Mode == e2e.ModeSeed { + t.Helper() + if node.Mode == e2e.ModeSeed || node.EnableCompanionPruning { return } @@ -25,7 +27,13 @@ func TestBlock_Header(t *testing.T) { first := status.SyncInfo.EarliestBlockHeight last := status.SyncInfo.LatestBlockHeight if node.RetainBlocks > 0 { - first++ // avoid race conditions with block pruning + // This was done in case pruning is activated. + // As it happens in the background this lowers the chances + // that the block at height=first will be pruned by the time we test + // this. If this test starts to fail often, it is worth revisiting this logic. + // To reproduce this failure locally, it is advised to set the storage.pruning.interval + // to 1s instead of 10s. + first += int64(node.RetainBlocks) // avoid race conditions with block pruning } for _, block := range blocks { @@ -49,8 +57,12 @@ func TestBlock_Header(t *testing.T) { // Tests that the node contains the expected block range. func TestBlock_Range(t *testing.T) { + t.Helper() testNode(t, func(t *testing.T, node e2e.Node) { - if node.Mode == e2e.ModeSeed { + t.Helper() + // We do not run this test on seed nodes or nodes with data + // companion-related pruning enabled. + if node.Mode == e2e.ModeSeed || node.EnableCompanionPruning { return } @@ -69,8 +81,13 @@ func TestBlock_Range(t *testing.T) { case node.RetainBlocks > 0 && int64(node.RetainBlocks) < (last-node.Testnet.InitialHeight+1): // Delta handles race conditions in reading first/last heights. - assert.InDelta(t, node.RetainBlocks, last-first+1, 1, + // The pruning mechanism is now asynchronous and might have been woken up yet to complete the pruning + // So we have no guarantees that all the blocks will have been pruned by the time we check + // Thus we allow for some flexibility in the difference between the expected retain blocks number + // and the actual retain blocks (which should be greater) + assert.InDelta(t, node.RetainBlocks, last-first+1, 10, "node not pruning expected blocks") + assert.GreaterOrEqual(t, uint64(last-first+1), node.RetainBlocks, "node pruned more blocks than it should") default: assert.Equal(t, node.Testnet.InitialHeight, first, @@ -93,3 +110,24 @@ func TestBlock_Range(t *testing.T) { } }) } + +// Tests that time is monotonically increasing, +// and that blocks produced according to BFT Time follow MedianTime calculation. +func TestBlock_Time(t *testing.T) { + t.Helper() + blocks := fetchBlockChain(t) + testnet := loadTestnet(t) + + lastBlock := blocks[0] + valSchedule := newValidatorSchedule(testnet) + for _, block := range blocks[1:] { + require.Less(t, lastBlock.Time, block.Time) + lastBlock = block + + valSchedule.Increment(1) + if testnet.PbtsEnableHeight == 0 || block.Height < testnet.PbtsEnableHeight { + expTime := block.LastCommit.MedianTime(valSchedule.Set) + require.Equal(t, expTime, block.Time, "height=%d", block.Height) + } + } +} diff --git a/test/e2e/tests/e2e_test.go b/test/e2e/tests/e2e_test.go index f1669e747c3..b0df27b68ee 100644 --- a/test/e2e/tests/e2e_test.go +++ b/test/e2e/tests/e2e_test.go @@ -4,14 +4,18 @@ import ( "context" "os" "path/filepath" + "strings" "sync" "testing" "github.com/stretchr/testify/require" + abci "github.com/cometbft/cometbft/abci/types" rpchttp "github.com/cometbft/cometbft/rpc/client/http" rpctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cometbft/cometbft/test/e2e/app" e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/test/e2e/pkg/infra/docker" "github.com/cometbft/cometbft/types" ) @@ -19,6 +23,7 @@ func init() { // This can be used to manually specify a testnet manifest and/or node to // run tests against. The testnet must have been started by the runner first. // os.Setenv("E2E_MANIFEST", "networks/ci.toml") + // os.Setenv("E2E_TESTNET_DIR", "networks/ci") // os.Setenv("E2E_NODE", "validator01") } @@ -56,12 +61,47 @@ func testNode(t *testing.T, testFunc func(*testing.T, e2e.Node)) { node := *node t.Run(node.Name, func(t *testing.T) { - t.Parallel() testFunc(t, node) }) } } +// Similar to testNode, except only runs the given test on full nodes or +// validators. Also only runs the test on the given maximum number of nodes. +// +// If maxNodes is set to 0 or below, all full nodes and validators will be +// tested. +func testFullNodesOrValidators(t *testing.T, maxNodes int, testFunc func(*testing.T, e2e.Node)) { //nolint:unparam // maxNodes always receives 0 but that could change so we should keep the parameter. + t.Helper() + + testnet := loadTestnet(t) + nodes := testnet.Nodes + + if name := os.Getenv("E2E_NODE"); name != "" { + node := testnet.LookupNode(name) + require.NotNil(t, node, "node %q not found in testnet %q", name, testnet.Name) + nodes = []*e2e.Node{node} + } + + nodeCount := 0 + for _, node := range nodes { + if node.Stateless() { + continue + } + + if node.Mode == e2e.ModeFull || node.Mode == e2e.ModeValidator { + node := *node + t.Run(node.Name, func(t *testing.T) { + testFunc(t, node) + }) + nodeCount++ + if maxNodes > 0 && nodeCount >= maxNodes { + break + } + } + } +} + // loadTestnet loads the testnet based on the E2E_MANIFEST envvar. func loadTestnet(t *testing.T) e2e.Testnet { t.Helper() @@ -73,7 +113,11 @@ func loadTestnet(t *testing.T) e2e.Testnet { if !filepath.IsAbs(manifestFile) { manifestFile = filepath.Join("..", manifestFile) } - + ifdType := os.Getenv("INFRASTRUCTURE_TYPE") + ifdFile := os.Getenv("INFRASTRUCTURE_FILE") + if ifdType != "docker" && ifdFile == "" { + t.Fatalf("INFRASTRUCTURE_FILE not set and INFRASTRUCTURE_TYPE is not 'docker'") + } testnetCacheMtx.Lock() defer testnetCacheMtx.Unlock() if testnet, ok := testnetCache[manifestFile]; ok { @@ -81,10 +125,25 @@ func loadTestnet(t *testing.T) e2e.Testnet { } m, err := e2e.LoadManifest(manifestFile) require.NoError(t, err) - ifd, err := e2e.NewDockerInfrastructureData(m) + + var ifd e2e.InfrastructureData + switch ifdType { + case "docker": + ifd, err = e2e.NewDockerInfrastructureData(m) + require.NoError(t, err) + case "digital-ocean": + ifd, err = e2e.InfrastructureDataFromFile(ifdFile) + require.NoError(t, err) + default: + } require.NoError(t, err) - testnet, err := e2e.LoadTestnet(manifestFile, ifd) + testnetDir := os.Getenv("E2E_TESTNET_DIR") + if !filepath.IsAbs(testnetDir) { + testnetDir = filepath.Join("..", testnetDir) + } + + testnet, err := e2e.LoadTestnet(manifestFile, ifd, testnetDir) require.NoError(t, err) testnetCache[manifestFile] = *testnet return *testnet @@ -141,3 +200,38 @@ func fetchBlockChain(t *testing.T) []*types.Block { return blocks } + +// fetchABCIRequests go through the logs of a specific node and collect all ABCI requests (each slice represents requests from beginning until the first crash, +// and then between two crashes) for a specific node. +func fetchABCIRequests(t *testing.T, nodeName string) ([][]*abci.Request, error) { + t.Helper() + testnet := loadTestnet(t) + logs, err := fetchNodeLogs(testnet) + if err != nil { + return nil, err + } + reqs := make([][]*abci.Request, 0) + // Parse output line by line. + lines := strings.Split(string(logs), "\n") + for _, line := range lines { + if !strings.Contains(line, nodeName) { + continue + } + if strings.Contains(line, "Application started") { + reqs = append(reqs, make([]*abci.Request, 0)) + continue + } + r, err := app.GetABCIRequestFromString(line) + require.NoError(t, err) + // Ship the lines that does not contain abci request. + if r == nil { + continue + } + reqs[len(reqs)-1] = append(reqs[len(reqs)-1], r) + } + return reqs, nil +} + +func fetchNodeLogs(testnet e2e.Testnet) ([]byte, error) { + return docker.ExecComposeOutput(context.Background(), testnet.Dir, "logs") +} diff --git a/test/e2e/tests/evidence_test.go b/test/e2e/tests/evidence_test.go index f7f2ede7902..34a7e24e150 100644 --- a/test/e2e/tests/evidence_test.go +++ b/test/e2e/tests/evidence_test.go @@ -7,7 +7,7 @@ import ( ) // assert that all nodes that have blocks at the height of a misbehavior has evidence -// for that misbehavior +// for that misbehavior. func TestEvidence_Misbehavior(t *testing.T) { blocks := fetchBlockChain(t) testnet := loadTestnet(t) diff --git a/test/e2e/tests/grpc_test.go b/test/e2e/tests/grpc_test.go new file mode 100644 index 00000000000..5be0b1c7620 --- /dev/null +++ b/test/e2e/tests/grpc_test.go @@ -0,0 +1,261 @@ +package e2e_test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + coretypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cometbft/cometbft/rpc/grpc/client/privileged" + e2e "github.com/cometbft/cometbft/test/e2e/pkg" + "github.com/cometbft/cometbft/version" +) + +func TestGRPC_Version(t *testing.T) { + t.Helper() + testFullNodesOrValidators(t, 0, func(t *testing.T, node e2e.Node) { + t.Helper() + ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute) + defer ctxCancel() + client, err := node.GRPCClient(ctx) + require.NoError(t, err) + defer client.Close() + + res, err := client.GetVersion(ctx) + require.NoError(t, err) + + require.Equal(t, version.CMTSemVer, res.Node) + require.Equal(t, version.ABCIVersion, res.ABCI) + require.Equal(t, version.P2PProtocol, res.P2P) + require.Equal(t, version.BlockProtocol, res.Block) + }) +} + +func TestGRPC_Block_GetByHeight(t *testing.T) { + testFullNodesOrValidators(t, 0, func(t *testing.T, node e2e.Node) { + t.Helper() + client, err := node.Client() + require.NoError(t, err) + status, err := client.Status(ctx) + require.NoError(t, err) + + // We are not testing getting the first block in these + // tests to prevent race conditions with the pruning mechanism + // that might make the tests fail. Just testing the last block + // is enough to validate the fact that we can fetch a block using + // the gRPC endpoint + last := status.SyncInfo.LatestBlockHeight + + ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute) + defer ctxCancel() + gRPCClient, err := node.GRPCClient(ctx) + require.NoError(t, err) + defer gRPCClient.Close() + + // Get last block and fetch it using the gRPC endpoint + lastBlock, err := gRPCClient.GetBlockByHeight(ctx, last) + + // Last block tests + require.NoError(t, err) + require.NotNil(t, lastBlock.BlockID) + require.Equal(t, lastBlock.Block.Height, last) + }) +} + +func TestGRPC_Block_GetLatestHeight(t *testing.T) { + t.Helper() + testFullNodesOrValidators(t, 0, func(t *testing.T, node e2e.Node) { + t.Helper() + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + client, err := node.Client() + require.NoError(t, err) + status, err := client.Status(ctx) + require.NoError(t, err) + + gclient, err := node.GRPCClient(ctx) + require.NoError(t, err) + defer gclient.Close() + + resultCh, err := gclient.GetLatestHeight(ctx) + require.NoError(t, err) + + select { + case <-ctx.Done(): + require.Fail(t, "did not expect context to be canceled") + case result := <-resultCh: + require.NoError(t, result.Error) + require.True(t, result.Height == status.SyncInfo.LatestBlockHeight || result.Height == status.SyncInfo.LatestBlockHeight+1) + } + }) +} + +func TestGRPC_GetBlockResults(t *testing.T) { + t.Helper() + testFullNodesOrValidators(t, 0, func(t *testing.T, node e2e.Node) { + t.Helper() + client, err := node.Client() + require.NoError(t, err) + status, err := client.Status(ctx) + require.NoError(t, err) + + first := status.SyncInfo.EarliestBlockHeight + last := status.SyncInfo.LatestBlockHeight + if node.RetainBlocks > 0 { + // This was done in case pruning is activated. + // As it happens in the background this lowers the chances + // that the block at height=first will be pruned by the time we test + // this. If this test starts to fail often, it is worth revisiting this logic. + // To reproduce this failure locally, it is advised to set the storage.pruning.interval + // to 1s instead of 10s. + first += int64(node.RetainBlocks) + } + + ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute) + defer ctxCancel() + gRPCClient, err := node.GRPCClient(ctx) + require.NoError(t, err) + defer gRPCClient.Close() + + latestHeightCh, err := gRPCClient.GetLatestHeight(ctx) + require.NoError(t, err) + + latestBlockHeight := int64(0) + select { + case <-ctx.Done(): + require.Fail(t, "did not expect context to be canceled") + case result := <-latestHeightCh: + require.NoError(t, result.Error) + latestBlockHeight = result.Height + } + + successCases := []struct { + expectedHeight int64 + }{ + {first}, + {latestBlockHeight}, + } + errorCases := []struct { + requestHeight int64 + }{ + {first - int64(node.RetainBlocks) - 2}, + {last + 100000}, + } + + for _, tc := range successCases { + res, err := gRPCClient.GetBlockResults(ctx, tc.expectedHeight) + + require.NoError(t, err, fmt.Sprintf("Unexpected error for GetBlockResults at expected height: %d", tc.expectedHeight)) + require.NotNil(t, res) + require.Equal(t, tc.expectedHeight, res.Height) + } + for _, tc := range errorCases { + _, err = gRPCClient.GetBlockResults(ctx, tc.requestHeight) + require.Error(t, err) + } + }) +} + +func TestGRPC_BlockRetainHeight(t *testing.T) { + t.Helper() + testFullNodesOrValidators(t, 0, func(t *testing.T, node e2e.Node) { + t.Helper() + if !node.EnableCompanionPruning { + return + } + + grpcClient, status, cleanup := getGRPCPrivilegedClientForTesting(t, node) + defer cleanup() + + err := grpcClient.SetBlockRetainHeight(ctx, uint64(status.SyncInfo.LatestBlockHeight-1)) + require.NoError(t, err) + + res, err := grpcClient.GetBlockRetainHeight(ctx) + require.NoError(t, err) + require.NotNil(t, res) + require.Equal(t, res.PruningService, uint64(status.SyncInfo.LatestBlockHeight-1)) + }) +} + +func TestGRPC_BlockResultsRetainHeight(t *testing.T) { + t.Helper() + testFullNodesOrValidators(t, 0, func(t *testing.T, node e2e.Node) { + t.Helper() + if !node.EnableCompanionPruning { + return + } + + grpcClient, status, cleanup := getGRPCPrivilegedClientForTesting(t, node) + defer cleanup() + + err := grpcClient.SetBlockResultsRetainHeight(ctx, uint64(status.SyncInfo.LatestBlockHeight)-1) + require.NoError(t, err, "Unexpected error for SetBlockResultsRetainHeight") + + height, err := grpcClient.GetBlockResultsRetainHeight(ctx) + require.NoError(t, err, "Unexpected error for GetBlockRetainHeight") + require.Equal(t, height, uint64(status.SyncInfo.LatestBlockHeight)-1) + }) +} + +func TestGRPC_TxIndexerRetainHeight(t *testing.T) { + testFullNodesOrValidators(t, 0, func(t *testing.T, node e2e.Node) { + t.Helper() + if !node.EnableCompanionPruning { + return + } + + grpcClient, status, cleanup := getGRPCPrivilegedClientForTesting(t, node) + defer cleanup() + + err := grpcClient.SetTxIndexerRetainHeight(ctx, uint64(status.SyncInfo.LatestBlockHeight)-1) + require.NoError(t, err, "Unexpected error for SetTxIndexerRetainHeight") + + height, err := grpcClient.GetTxIndexerRetainHeight(ctx) + require.NoError(t, err, "Unexpected error for GetTxIndexerRetainHeight") + require.Equal(t, height, uint64(status.SyncInfo.LatestBlockHeight)-1) + }) +} + +func TestGRPC_BlockIndexerRetainHeight(t *testing.T) { + t.Helper() + testFullNodesOrValidators(t, 0, func(t *testing.T, node e2e.Node) { + t.Helper() + if !node.EnableCompanionPruning { + return + } + + grpcClient, status, cleanup := getGRPCPrivilegedClientForTesting(t, node) + defer cleanup() + + err := grpcClient.SetBlockIndexerRetainHeight(ctx, uint64(status.SyncInfo.LatestBlockHeight)-1) + require.NoError(t, err, "Unexpected error for SetTxIndexerRetainHeight") + + height, err := grpcClient.GetBlockIndexerRetainHeight(ctx) + require.NoError(t, err, "Unexpected error for GetTxIndexerRetainHeight") + require.Equal(t, height, uint64(status.SyncInfo.LatestBlockHeight)-1) + }) +} + +func getGRPCPrivilegedClientForTesting(t *testing.T, node e2e.Node) (privileged.Client, *coretypes.ResultStatus, func()) { + t.Helper() + ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute) + + grpcClient, err := node.GRPCPrivilegedClient(ctx) + require.NoError(t, err) + + client, err := node.Client() + require.NoError(t, err) + + status, err := client.Status(ctx) + require.NoError(t, err) + + return grpcClient, status, func() { + ctxCancel() + err := grpcClient.Close() + require.NoError(t, err) + } +} diff --git a/test/e2e/tests/net_test.go b/test/e2e/tests/net_test.go index bdb71d83dee..84fbe3290f2 100644 --- a/test/e2e/tests/net_test.go +++ b/test/e2e/tests/net_test.go @@ -14,6 +14,7 @@ func TestNet_Peers(t *testing.T) { t.SkipNow() testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() // Seed nodes shouldn't necessarily mesh with the entire network. if node.Mode == e2e.ModeSeed { return @@ -34,7 +35,7 @@ func TestNet_Peers(t *testing.T) { for _, peerInfo := range netInfo.Peers { peer := node.Testnet.LookupNode(peerInfo.NodeInfo.Moniker) require.NotNil(t, peer, "unknown node %v", peerInfo.NodeInfo.Moniker) - require.Equal(t, peer.IP.String(), peerInfo.RemoteIP, + require.Equal(t, peer.InternalIP.String(), peerInfo.RemoteIP, "unexpected IP address for peer %v", peer.Name) seen[peerInfo.NodeInfo.Moniker] = true } diff --git a/test/e2e/tests/validator_test.go b/test/e2e/tests/validator_test.go index c13c775846f..acb4eb9a265 100644 --- a/test/e2e/tests/validator_test.go +++ b/test/e2e/tests/validator_test.go @@ -13,8 +13,10 @@ import ( // Tests that validator sets are available and correct according to // scheduled validator updates. func TestValidator_Sets(t *testing.T) { + t.Helper() testNode(t, func(t *testing.T, node e2e.Node) { - if node.Mode == e2e.ModeSeed { + t.Helper() + if node.Mode == e2e.ModeSeed || node.EnableCompanionPruning { return } @@ -28,7 +30,13 @@ func TestValidator_Sets(t *testing.T) { // skip first block if node is pruning blocks, to avoid race conditions if node.RetainBlocks > 0 { - first++ + // This was done in case pruning is activated. + // As it happens in the background this lowers the chances + // that the block at height=first will be pruned by the time we test + // this. If this test starts to fail often, it is worth revisiting this logic. + // To reproduce this failure locally, it is advised to set the storage.pruning.interval + // to 1s instead of 10s. + first += int64(node.RetainBlocks) } valSchedule := newValidatorSchedule(*node.Testnet) @@ -55,8 +63,10 @@ func TestValidator_Sets(t *testing.T) { // Tests that a validator proposes blocks when it's supposed to. It tolerates some // missed blocks, e.g. due to testnet perturbations. func TestValidator_Propose(t *testing.T) { + t.Helper() blocks := fetchBlockChain(t) testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() if node.Mode != e2e.ModeValidator { return } @@ -75,19 +85,28 @@ func TestValidator_Propose(t *testing.T) { valSchedule.Increment(1) } - require.False(t, proposeCount == 0 && expectCount > 0, - "node did not propose any blocks (expected %v)", expectCount) - if expectCount > 5 { - require.GreaterOrEqual(t, proposeCount, 3, "validator didn't propose even 3 blocks") + if expectCount == 0 { + return + } + + if node.ClockSkew != 0 && node.Testnet.PbtsEnableHeight != 0 { + t.Logf("node with skewed clock (by %v), proposed %v, expected %v", + node.ClockSkew, proposeCount, expectCount) + return } + require.Greater(t, proposeCount, 0, + "node did not propose any blocks (expected %v)", expectCount) + require.False(t, expectCount > 5 && proposeCount < 3, "node only proposed %v blocks, expected %v", proposeCount, expectCount) }) } // Tests that a validator signs blocks when it's supposed to. It tolerates some // missed blocks, e.g. due to testnet perturbations. func TestValidator_Sign(t *testing.T) { + t.Helper() blocks := fetchBlockChain(t) testNode(t, func(t *testing.T, node e2e.Node) { + t.Helper() if node.Mode != e2e.ModeValidator { return } diff --git a/test/fuzz/mempool/checktx.go b/test/fuzz/mempool/checktx.go index 79865f8fcc3..50d634fedb3 100644 --- a/test/fuzz/mempool/checktx.go +++ b/test/fuzz/mempool/checktx.go @@ -12,7 +12,7 @@ var mempool mempl.Mempool func init() { app := kvstore.NewInMemoryApplication() cc := proxy.NewLocalClientCreator(app) - appConnMem, _ := cc.NewABCIClient() + appConnMem, _ := cc.NewABCIMempoolClient() err := appConnMem.Start() if err != nil { panic(err) @@ -24,7 +24,7 @@ func init() { } func Fuzz(data []byte) int { - err := mempool.CheckTx(data, nil, mempl.TxInfo{}) + _, err := mempool.CheckTx(data) if err != nil { return 0 } diff --git a/test/fuzz/tests/mempool_test.go b/test/fuzz/tests/mempool_test.go index 65dff8fbcd9..9dd16fdef68 100644 --- a/test/fuzz/tests/mempool_test.go +++ b/test/fuzz/tests/mempool_test.go @@ -8,8 +8,8 @@ import ( abciclient "github.com/cometbft/cometbft/abci/client" "github.com/cometbft/cometbft/abci/example/kvstore" "github.com/cometbft/cometbft/config" - cmtsync "github.com/cometbft/cometbft/libs/sync" - mempool "github.com/cometbft/cometbft/mempool" + cmtsync "github.com/cometbft/cometbft/internal/sync" + "github.com/cometbft/cometbft/mempool" ) func FuzzMempool(f *testing.F) { @@ -26,7 +26,7 @@ func FuzzMempool(f *testing.F) { mp := mempool.NewCListMempool(cfg, conn, 0) - f.Fuzz(func(t *testing.T, data []byte) { - _ = mp.CheckTx(data, nil, mempool.TxInfo{}) + f.Fuzz(func(_ *testing.T, data []byte) { + _, _ = mp.CheckTx(data) }) } diff --git a/test/fuzz/tests/p2p_secretconnection_test.go b/test/fuzz/tests/p2p_secretconnection_test.go index f61fa14d9c8..6b3f4bcd65c 100644 --- a/test/fuzz/tests/p2p_secretconnection_test.go +++ b/test/fuzz/tests/p2p_secretconnection_test.go @@ -10,12 +10,12 @@ import ( "testing" "github.com/cometbft/cometbft/crypto/ed25519" - "github.com/cometbft/cometbft/libs/async" + "github.com/cometbft/cometbft/internal/async" sc "github.com/cometbft/cometbft/p2p/conn" ) func FuzzP2PSecretConnection(f *testing.F) { - f.Fuzz(func(t *testing.T, data []byte) { + f.Fuzz(func(_ *testing.T, data []byte) { fuzz(data) }) } @@ -69,12 +69,12 @@ func (drw kvstoreConn) Close() (err error) { err2 := drw.PipeWriter.CloseWithError(io.EOF) err1 := drw.PipeReader.Close() if err2 != nil { - return err + return err //nolint:nilerr // this is a false positive } return err1 } -// Each returned ReadWriteCloser is akin to a net.Connection +// Each returned ReadWriteCloser is akin to a net.Connection. func makeKVStoreConnPair() (fooConn, barConn kvstoreConn) { barReader, fooWriter := io.Pipe() fooReader, barWriter := io.Pipe() @@ -92,7 +92,7 @@ func makeSecretConnPair() (fooSecConn, barSecConn *sc.SecretConnection) { // Make connections from both sides in parallel. trs, ok := async.Parallel( - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { fooSecConn, err = sc.MakeSecretConnection(fooConn, fooPrvKey) if err != nil { log.Printf("failed to establish SecretConnection for foo: %v", err) @@ -107,7 +107,7 @@ func makeSecretConnPair() (fooSecConn, barSecConn *sc.SecretConnection) { } return nil, false, nil }, - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { barSecConn, err = sc.MakeSecretConnection(barConn, barPrvKey) if barSecConn == nil { log.Printf("failed to establish SecretConnection for bar: %v", err) diff --git a/test/fuzz/tests/rpc_jsonrpc_server_test.go b/test/fuzz/tests/rpc_jsonrpc_server_test.go index db6c0a2090e..de7ee7fd0f7 100644 --- a/test/fuzz/tests/rpc_jsonrpc_server_test.go +++ b/test/fuzz/tests/rpc_jsonrpc_server_test.go @@ -21,19 +21,19 @@ func FuzzRPCJSONRPCServer(f *testing.F) { I int `json:"i"` } rpcFuncMap := map[string]*rpcserver.RPCFunc{ - "c": rpcserver.NewRPCFunc(func(ctx *rpctypes.Context, args *args, options ...rpcserver.Option) (string, error) { + "c": rpcserver.NewRPCFunc(func(_ *rpctypes.Context, _ *args, _ ...rpcserver.Option) (string, error) { return "foo", nil }, "args"), } mux := http.NewServeMux() rpcserver.RegisterRPCFuncs(mux, rpcFuncMap, log.NewNopLogger()) - f.Fuzz(func(t *testing.T, data []byte) { + f.Fuzz(func(_ *testing.T, data []byte) { if len(data) == 0 { return } - req, err := http.NewRequest("POST", "http://localhost/", bytes.NewReader(data)) + req, err := http.NewRequest(http.MethodPost, "http://localhost/", bytes.NewReader(data)) if err != nil { panic(err) } diff --git a/test/loadtime/README.md b/test/loadtime/README.md index c19880c4917..6deddced691 100644 --- a/test/loadtime/README.md +++ b/test/loadtime/README.md @@ -22,12 +22,12 @@ make build The `load` binary is built when `make build` is invoked. The `load` tool generates transactions and broadcasts them to CometBFT. -`load` leverages the [tm-load-test](https://github.com/informalsystems/tm-load-test) -framework. As a result, all flags and options specified on the `tm-load-test` apply to +`load` leverages the [cometbft-load-test](https://github.com/cometbft/cometbft-load-test) +framework. As a result, all flags and options specified on the `cometbft-load-test` apply to `load`. -Below is a basic invocation for generating load against a CometBFT websocket running -on `localhost:25567` +Below is a basic invocation for generating load against a CometBFT websocket v1 running +on `localhost:26657` ```bash ./build/load \ diff --git a/test/loadtime/basic.sh b/test/loadtime/basic.sh index b135232b8db..68d68092133 100755 --- a/test/loadtime/basic.sh +++ b/test/loadtime/basic.sh @@ -5,7 +5,7 @@ set -euo pipefail # A basic invocation of the loadtime tool. ./build/load \ - -c 1 -T 10 -r 1000 -s 1024 \ + -c 1 -T 100 -r 1000 -s 1024 \ --broadcast-tx-method sync \ - --endpoints ws://localhost:26657/websocket + --endpoints ws://localhost:26657/v1/websocket diff --git a/test/loadtime/cmd/load/main.go b/test/loadtime/cmd/load/main.go index d6bb798bc1d..03746af3c63 100644 --- a/test/loadtime/cmd/load/main.go +++ b/test/loadtime/cmd/load/main.go @@ -1,11 +1,11 @@ package main import ( - "fmt" + "errors" "github.com/google/uuid" - "github.com/informalsystems/tm-load-test/pkg/loadtest" + "github.com/cometbft/cometbft-load-test/pkg/loadtest" "github.com/cometbft/cometbft/test/loadtime/payload" ) @@ -43,13 +43,13 @@ func main() { }) } -func (f *ClientFactory) ValidateConfig(cfg loadtest.Config) error { +func (*ClientFactory) ValidateConfig(cfg loadtest.Config) error { psb, err := payload.MaxUnpaddedSize() if err != nil { return err } if psb > cfg.Size { - return fmt.Errorf("payload size exceeds configured size") + return errors.New("payload size exceeds configured size") } return nil } diff --git a/test/loadtime/cmd/report/main.go b/test/loadtime/cmd/report/main.go index 4b00f6adb72..429ba5da2f0 100644 --- a/test/loadtime/cmd/report/main.go +++ b/test/loadtime/cmd/report/main.go @@ -10,15 +10,15 @@ import ( "strings" dbm "github.com/cometbft/cometbft-db" - - "github.com/cometbft/cometbft/store" + "github.com/cometbft/cometbft/internal/store" "github.com/cometbft/cometbft/test/loadtime/report" ) var ( - db = flag.String("database-type", "goleveldb", "the type of database holding the blockstore") - dir = flag.String("data-dir", "", "path to the directory containing the CometBFT databases") - csvOut = flag.String("csv", "", "dump the extracted latencies as raw csv for use in additional tooling") + db = flag.String("database-type", "goleveldb", "the type of database holding the blockstore") + dir = flag.String("data-dir", "", "path to the directory containing the CometBFT databases") + csvOut = flag.String("csv", "", "dump the extracted latencies as raw csv for use in additional tooling") + oneline = flag.Bool("oneline", false, "display the results in one line of comma-separated values") ) func main() { @@ -65,19 +65,26 @@ func main() { return } for _, r := range rs.List() { - fmt.Printf(""+ - "Experiment ID: %s\n\n"+ - "\tConnections: %d\n"+ - "\tRate: %d\n"+ - "\tSize: %d\n\n"+ - "\tTotal Valid Tx: %d\n"+ - "\tTotal Negative Latencies: %d\n"+ - "\tMinimum Latency: %s\n"+ - "\tMaximum Latency: %s\n"+ - "\tAverage Latency: %s\n"+ - "\tStandard Deviation: %s\n\n", r.ID, r.Connections, r.Rate, r.Size, len(r.All), r.NegativeCount, r.Min, r.Max, r.Avg, r.StdDev) + if *oneline { + fmt.Printf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + r.ID, r.Connections, r.Rate, r.Size, len(r.All), r.NegativeCount, r.Min.Nanoseconds(), r.Max.Nanoseconds(), r.Avg.Nanoseconds(), r.StdDev.Nanoseconds(), rs.ErrorCount()) + } else { + fmt.Printf(""+ + "Experiment ID: %s\n\n"+ + "\tConnections: %d\n"+ + "\tRate: %d\n"+ + "\tSize: %d\n\n"+ + "\tTotal Valid Tx: %d\n"+ + "\tTotal Negative Latencies: %d\n"+ + "\tMinimum Latency: %s\n"+ + "\tMaximum Latency: %s\n"+ + "\tAverage Latency: %s\n"+ + "\tStandard Deviation: %s\n\n", r.ID, r.Connections, r.Rate, r.Size, len(r.All), r.NegativeCount, r.Min, r.Max, r.Avg, r.StdDev) + } + } + if !*oneline { + fmt.Printf("Total Invalid Tx: %d\n", rs.ErrorCount()) } - fmt.Printf("Total Invalid Tx: %d\n", rs.ErrorCount()) } func toCSVRecords(rs []report.Report) [][]string { diff --git a/test/loadtime/payload/payload.go b/test/loadtime/payload/payload.go index 778729f8b9d..c845e2ccc22 100644 --- a/test/loadtime/payload/payload.go +++ b/test/loadtime/payload/payload.go @@ -8,35 +8,37 @@ import ( "math" "google.golang.org/protobuf/proto" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/timestamppb" ) -const keyPrefix = "a=" -const maxPayloadSize = 4 * 1024 * 1024 +const ( + keyPrefix = "a=" + maxPayloadSize = 4 * 1024 * 1024 +) // NewBytes generates a new payload and returns the encoded representation of // the payload as a slice of bytes. NewBytes uses the fields on the Options // to create the payload. func NewBytes(p *Payload) ([]byte, error) { p.Padding = make([]byte, 1) - if p.Time == nil { + if p.GetTime() == nil { p.Time = timestamppb.Now() } us, err := CalculateUnpaddedSize(p) if err != nil { return nil, err } - if p.Size > maxPayloadSize { - return nil, fmt.Errorf("configured size %d is too large (>%d)", p.Size, maxPayloadSize) + if p.GetSize() > maxPayloadSize { + return nil, fmt.Errorf("configured size %d is too large (>%d)", p.GetSize(), maxPayloadSize) } - pSize := int(p.Size) // #nosec -- The "if" above makes this cast safe + pSize := int(p.GetSize()) // #nosec -- The "if" above makes this cast safe if pSize < us { return nil, fmt.Errorf("configured size %d not large enough to fit unpadded transaction of size %d", pSize, us) } // We halve the padding size because we transform the TX to hex p.Padding = make([]byte, (pSize-us)/2) - _, err = rand.Read(p.Padding) + _, err = rand.Read(p.GetPadding()) if err != nil { return nil, err } @@ -89,8 +91,8 @@ func MaxUnpaddedSize() (int, error) { // purpose of determining how much padding to add to add to reach the target size. // CalculateUnpaddedSize returns an error if the payload Padding field is longer than 1. func CalculateUnpaddedSize(p *Payload) (int, error) { - if len(p.Padding) != 1 { - return 0, fmt.Errorf("expected length of padding to be 1, received %d", len(p.Padding)) + if len(p.GetPadding()) != 1 { + return 0, fmt.Errorf("expected length of padding to be 1, received %d", len(p.GetPadding())) } b, err := proto.Marshal(p) if err != nil { diff --git a/test/loadtime/payload/payload_test.go b/test/loadtime/payload/payload_test.go index 62ea3919f79..b095a6781af 100644 --- a/test/loadtime/payload/payload_test.go +++ b/test/loadtime/payload/payload_test.go @@ -43,16 +43,16 @@ func TestRoundTrip(t *testing.T) { if err != nil { t.Fatalf("reading payload %s", err) } - if p.Size != payloadSizeTarget { - t.Fatalf("payload size value %d does not match expected %d", p.Size, payloadSizeTarget) + if p.GetSize() != payloadSizeTarget { + t.Fatalf("payload size value %d does not match expected %d", p.GetSize(), payloadSizeTarget) } - if p.Connections != testConns { - t.Fatalf("payload connections value %d does not match expected %d", p.Connections, testConns) + if p.GetConnections() != testConns { + t.Fatalf("payload connections value %d does not match expected %d", p.GetConnections(), testConns) } - if p.Rate != testRate { - t.Fatalf("payload rate value %d does not match expected %d", p.Rate, testRate) + if p.GetRate() != testRate { + t.Fatalf("payload rate value %d does not match expected %d", p.GetRate(), testRate) } - if !bytes.Equal(p.Id, testID[:]) { - t.Fatalf("payload ID value %d does not match expected %d", p.Id, testID) + if !bytes.Equal(p.GetId(), testID[:]) { + t.Fatalf("payload ID value %d does not match expected %d", p.GetId(), testID) } } diff --git a/test/loadtime/report/report.go b/test/loadtime/report/report.go index bd533be00fe..83b994b0e0e 100644 --- a/test/loadtime/report/report.go +++ b/test/loadtime/report/report.go @@ -2,6 +2,7 @@ package report import ( "math" + "sort" "sync" "time" @@ -19,7 +20,7 @@ import ( type BlockStore interface { Height() int64 Base() int64 - LoadBlock(int64) *types.Block + LoadBlock(height int64) (*types.Block, *types.BlockMeta) } // DataPoint contains the set of data collected for each transaction. @@ -112,6 +113,12 @@ func (rs *Reports) calculateAll() { r.StdDev = time.Duration(int64(stat.StdDev(toFloat(r.All), nil))) rs.l = append(rs.l, r) } + sort.Slice(rs.l, func(i, j int) bool { + if rs.l[i].Connections == rs.l[j].Connections { + return rs.l[i].Rate < rs.l[j].Rate + } + return rs.l[i].Connections < rs.l[j].Connections + }) } func (rs *Reports) addError() { @@ -159,16 +166,16 @@ func GenerateFromBlockStore(s BlockStore) (*Reports, error) { continue } - l := b.bt.Sub(p.Time.AsTime()) - idb := (*[16]byte)(p.Id) + l := b.bt.Sub(p.GetTime().AsTime()) + idb := (*[16]byte)(p.GetId()) pdc <- payloadData{ l: l, bt: b.bt, hash: b.tx.Hash(), id: uuid.UUID(*idb), - connections: p.Connections, - rate: p.Rate, - size: p.Size, + connections: p.GetConnections(), + rate: p.GetRate(), + size: p.GetSize(), } } }() @@ -180,7 +187,7 @@ func GenerateFromBlockStore(s BlockStore) (*Reports, error) { go func() { base, height := s.Base(), s.Height() - prev := s.LoadBlock(base) + prev, _ := s.LoadBlock(base) for i := base + 1; i < height; i++ { // Data from two adjacent block are used here simultaneously, // blocks of height H and H+1. The transactions of the block of @@ -193,7 +200,7 @@ func GenerateFromBlockStore(s BlockStore) (*Reports, error) { // chain contains payload transactions, those transactions will not // be used in the latency calculations because the last block whose // transactions are used is the block one before the last. - cur := s.LoadBlock(i) + cur, _ := s.LoadBlock(i) for _, tx := range prev.Data.Txs { txc <- txData{tx: tx, bt: cur.Time} } diff --git a/test/loadtime/report/report_test.go b/test/loadtime/report/report_test.go index a8525b42723..1d9cdecba8b 100644 --- a/test/loadtime/report/report_test.go +++ b/test/loadtime/report/report_test.go @@ -12,6 +12,10 @@ import ( "github.com/cometbft/cometbft/types" ) +const ( + testPartSize = 65536 +) + type mockBlockStore struct { base int64 blocks []*types.Block @@ -25,8 +29,14 @@ func (m *mockBlockStore) Base() int64 { return m.base } -func (m *mockBlockStore) LoadBlock(i int64) *types.Block { - return m.blocks[i-m.base] +func (m *mockBlockStore) LoadBlock(i int64) (*types.Block, *types.BlockMeta) { + block := m.blocks[i-m.base] + partSet, err := block.MakePartSet(testPartSize) + if err != nil { + panic("could not create a part set") + } + blockMeta := types.NewBlockMeta(block, partSet) + return block, blockMeta } func TestGenerateReport(t *testing.T) { diff --git a/test/monitoring/.gitignore b/test/monitoring/.gitignore new file mode 100644 index 00000000000..5f5d6b1c584 --- /dev/null +++ b/test/monitoring/.gitignore @@ -0,0 +1,3 @@ +data-grafana +data-prometheus + diff --git a/test/monitoring/README.md b/test/monitoring/README.md new file mode 100644 index 00000000000..82e1d724880 --- /dev/null +++ b/test/monitoring/README.md @@ -0,0 +1,26 @@ +# localnet monitoring +Prometheus and Grafana server for localnet. + +# How to run +```bash +docker-compose up -d +``` +This will start both Prometheus and Grafana. + +# Details +This docker compose (`compose.yml`) creates a local Granafa and Prometheus server. +It is useful for local debugging and monitoring, especially for `localnet` setups. + +Prometheus will connect to the host machine's ports for data. By default it will connect to 26670,26671,26672,26673 +which are the prometheus ports defined for `node0`, `node1`, `node2`, `node3` in `make localnet-start`. + +Ports and other settings can be changed in the `config-prometheus/prometheus.yml` file before startup. + +You can access the Grafana web interface at `http://localhost:3000` and the Prometheus web interface at `http://localhost:9090`. + +The default Grafana username and password is `admin`/`admin`. You will only need it if you want to change something. The +pre-loaded dashboards can be viewed without a password. + +Data from Grafana and Prometheus end up in the `data-grafana` and `data-prometheus` folders on your host machine. +This allows you to stop and restart the servers without data loss. The folders are excluded from Git. + diff --git a/test/monitoring/compose.yml b/test/monitoring/compose.yml new file mode 100644 index 00000000000..e10bcce3c9d --- /dev/null +++ b/test/monitoring/compose.yml @@ -0,0 +1,56 @@ +services: + prometheus: + image: prom/prometheus + container_name: prometheus + ports: + - 127.0.0.1:9090:9090 + volumes: + - ./config-prometheus/prometheus.yml:/etc/prometheus/prometheus.yml + - ./data-prometheus:/prometheus + extra_hosts: + - "host.docker.internal:host-gateway" + node-exporter: + image: prom/node-exporter + container_name: node-exporter + volumes: + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /:/rootfs:ro + command: + - '--path.procfs=/host/proc' + - '--path.rootfs=/rootfs' + - '--path.sysfs=/host/sys' + - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)' + grafana: + image: grafana/grafana-oss + container_name: grafana + # if you are running as root then set it to 0 + # else find the right id with the id -u command + user: '501' + ports: + - 127.0.0.1:3000:3000 + volumes: + - ./data-grafana:/var/lib/grafana + - ./config-grafana/provisioning:/etc/grafana/provisioning + environment: + GF_LOG_LEVEL: error + GF_ANALYTICS_ENABLED: false + GF_ANALYTICS_REPORTING_ENABLED: false + GF_ANALYTICS_CHECK_FOR_PLUGIN_UPDATES: false + GF_ANALYTICS_CHECK_FOR_UPDATES: false + GF_ANALYTICS_FEEDBACK_LINKS_ENABLED: false + GF_SECURITY_DISABLE_GRAVATAR: true + GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH: /etc/grafana/provisioning/dashboards-data/main.json + GF_USERS_DEFAULT_THEME: system + GF_USERS_EDITORS_CAN_ADMIN: true + GF_AUTH_ANONYMOUS_ENABLED: true + GF_AUTH_ANONYMOUS_ORG_ROLE: Editor + GF_AUTH_BASIC_ENABLED: false + GF_NEWS_NEWS_FEED_ENABLED: false + GF_RENDERING_RENDERER_TOKEN: "-" + GF_RENDERING_SERVER_URL: http://grafana-image-renderer:8081/render + GF_RENDERING_CALLBACK_URL: http://grafana:3000/ + GF_LOG_FILTERS: rendering:debug + grafana-image-renderer: + image: grafana/grafana-image-renderer + container_name: grafana-image-renderer diff --git a/test/monitoring/config-grafana/provisioning/alerting/.placeholder b/test/monitoring/config-grafana/provisioning/alerting/.placeholder new file mode 100644 index 00000000000..bf4aeaf198d --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/alerting/.placeholder @@ -0,0 +1 @@ +Placeholder so the Grafana log does not complain about missing folders. diff --git a/test/monitoring/config-grafana/provisioning/dashboards-data/main.json b/test/monitoring/config-grafana/provisioning/dashboards-data/main.json new file mode 100644 index 00000000000..c1c2713023d --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/dashboards-data/main.json @@ -0,0 +1,1613 @@ +{ + "title": "Main", + "id": null, + "uid": null, + "version": 1, + "editable": true, + "liveNow": false, + "timezone": "browser", + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "title": "Consensus", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisPlacement": "auto", + "axisWidth": 80, + "drawStyle": "line", + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "mean" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 18, + "x": 0, + "y": 1 + }, + "options": { + "legend": { + "calcs": [ + "last" + ], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "cometbft_consensus_height", + "format": "time_series", + "hide": false, + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(cometbft_consensus_height)/ count(count by (job) (cometbft_consensus_height))", + "hide": false, + "interval": "500ms", + "legendFormat": "mean", + "range": true, + "refId": "B" + } + ], + "title": "Chain height", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 18, + "x": 0, + "y": 8 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "cometbft_consensus_total_txs", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Chain size (#txs)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 18, + "x": 0, + "y": 14 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "builder", + "expr": "cometbft_consensus_block_size_bytes/1024", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Block size (kb)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 18, + "x": 0, + "y": 19 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "builder", + "expr": "cometbft_consensus_rounds", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Round number", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "mempool_Txs" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "super-light-yellow", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "consensus_BlockPart" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 2 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "(sum(rate(cometbft_p2p_message_send_bytes_total[1m])) by (message_type))/1024", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Sent kb per message type", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "mempool_Txs" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "super-light-yellow", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "consensus_BlockPart" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 10 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "(sum(rate(cometbft_p2p_message_receive_bytes_total[1m])) by (message_type))/1024", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Received kb per message type", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 18 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "builder", + "expr": "cometbft_p2p_peers", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Number of peers", + "type": "timeseries" + } + ], + "title": "P2P", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 3 + }, + "options": { + "legend": { + "calcs": [ + "mean" + ], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "cometbft_mempool_size", + "format": "time_series", + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Mempool size (#txs)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 10 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "builder", + "expr": "rate(cometbft_mempool_tx_size_bytes_sum[$__rate_interval])/2014", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Size of txs (kb) added to the mempool", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 17 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "rate(cometbft_p2p_message_receive_bytes_total{message_type=~\"mempool_Txs|mempool_Message|mempool_WantTx|mempool_SeenTx\"}[$__rate_interval])/1024", + "hide": false, + "legendFormat": "{{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Received kb (only mempool messages)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 24 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "rate(cometbft_p2p_message_send_bytes_total{message_type=~\"mempool_Txs|mempool_Message|mempool_SeenTx|mempool_WantTx\"}[$__rate_interval])/1024", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Sent kb (only mempool messages)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 31 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum(rate(cometbft_mempool_recheck_times[1m])) by (job)", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Recheck rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 38 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "builder", + "expr": "rate(cometbft_mempool_already_received_txs[$__rate_interval])", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Already received txs (rate)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 73 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "cometbft_mempool_failed_txs / (cometbft_mempool_failed_txs + cometbft_consensus_total_txs) * 100", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Txs rejected by the app (%)", + "type": "timeseries" + } + ], + "title": "Mempool", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 4 + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "width": 200, + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "builder", + "expr": "cometbft_blocksync_syncing", + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Block syncing", + "type": "timeseries" + } + ], + "title": "BlockSync", + "type": "row" + } + ], + "refresh": "1s", + "schemaVersion": 38, + "style": "dark", + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "prometheus", + "value": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "1s", + "3s", + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + } +} diff --git a/test/monitoring/config-grafana/provisioning/dashboards-data/mempool_compact.json b/test/monitoring/config-grafana/provisioning/dashboards-data/mempool_compact.json new file mode 100644 index 00000000000..7071b60c6a6 --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/dashboards-data/mempool_compact.json @@ -0,0 +1,1711 @@ +{ + "title": "Mempool [compact]", + "id": null, + "uid": null, + "version": 1, + "editable": true, + "liveNow": false, + "timezone": "browser", + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "panels": [], + "title": "Consensus", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisGridShow": true, + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "last" + ], + "displayMode": "list", + "placement": "right", + "showLegend": false, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "min(cometbft_consensus_height)", + "format": "time_series", + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Chain height", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 11, + "y": 1 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": false, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "min(cometbft_consensus_total_txs)", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Chain size (#txs)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 50, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 11, + "x": 0, + "y": 8 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": false, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "avg(cometbft_consensus_block_size_bytes)", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Block size (bytes)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 50, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 11, + "x": 11, + "y": 8 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": false, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "exemplar": false, + "expr": "avg(cometbft_consensus_num_txs)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "legendFormat": "{{job}}", + "range": true, + "refId": "B" + } + ], + "title": "Block size (#txs)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 6, + "panels": [], + "title": "P2P", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 19, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 3, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "consensus_BlockPart" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + }, + { + "id": "custom.lineWidth", + "value": 1 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "mempool_*" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-yellow", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 30 + }, + { + "id": "custom.lineWidth", + "value": 2 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 11, + "x": 0, + "y": 15 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum(rate(cometbft_p2p_message_send_bytes_total{message_type=~\"consensus_BlockPart\"}[$__rate_interval])) by (message_type)/1024", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "sum(rate(cometbft_p2p_message_send_bytes_total{message_type=~\"mempool_Txs|mempool_SeenTx|mempool_WantTx\"}[$__rate_interval]))/1024", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "mempool_*", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "Sent kb per message type", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "consensus_BlockPart" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "mempool_*" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-yellow", + "mode": "fixed" + } + }, + { + "id": "custom.lineWidth", + "value": 2 + }, + { + "id": "custom.fillOpacity", + "value": 30 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 11, + "x": 11, + "y": 15 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum(rate(cometbft_p2p_message_receive_bytes_total{message_type=~\"consensus_BlockPart\"}[$__rate_interval])) by (message_type)/1024", + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "(sum(sum(rate(cometbft_p2p_message_receive_bytes_total{message_type=~\"mempool_Txs|mempool_SeenTx|mempool_WantTx\"}[$__rate_interval])) by (message_type)))/1024", + "hide": false, + "legendFormat": "mempool_*", + "range": true, + "refId": "B" + } + ], + "title": "Received kb per message type", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 10, + "panels": [], + "title": "Mempool", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 50, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 24 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "avg(rate(cometbft_mempool_tx_size_bytes_sum[$__interval])/1024)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Avg. size of txs added to mempools (kb)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 50, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 11, + "y": 24 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": false, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "exemplar": false, + "expr": "avg(cometbft_mempool_size)", + "format": "heatmap", + "hide": false, + "instant": false, + "interval": "10s", + "legendFormat": "__auto", + "range": true, + "refId": "B" + } + ], + "title": "Avg. mempool size (#txs)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "validator receiving all load" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "avg. of other validators" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#808080", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 31 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "(sum(rate(cometbft_p2p_message_send_bytes_total{message_type=~\"mempool_Txs|mempool_Message|mempool_SeenTx|mempool_WantTx\", job=\"validator001\"}[$__rate_interval])))/1024", + "legendFormat": "validator receiving all load", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "(avg(rate(cometbft_p2p_message_send_bytes_total{message_type=~\"mempool_Txs|mempool_Message|mempool_SeenTx|mempool_WantTx\", job!=\"validator001\"}[$__rate_interval])))/1024", + "hide": false, + "legendFormat": "avg. of other validators", + "range": true, + "refId": "B" + } + ], + "title": "Sent kb (only mempool messages)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "validator receiving all load" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "avg. of other validators" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7f7f7f", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 11, + "y": 31 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "(sum(rate(cometbft_p2p_message_receive_bytes_total{message_type=~\"mempool_Txs|mempool_Message|mempool_WantTx|mempool_SeenTx\", job=\"validator001\"}[$__rate_interval])))/1024", + "hide": false, + "legendFormat": "validator receiving all load", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "(avg(rate(cometbft_p2p_message_receive_bytes_total{message_type=~\"mempool_Txs|mempool_Message|mempool_WantTx|mempool_SeenTx\", job!=\"validator001\"}[$__rate_interval])))/1024", + "hide": false, + "legendFormat": "avg. of other validators", + "range": true, + "refId": "A" + } + ], + "title": "Received kb (only mempool messages)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 50, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "validator receiving all load" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "avg. of other validators" + }, + "properties": [ + { + "id": "color", + "value": { + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 11, + "x": 0, + "y": 38 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum(rate(cometbft_mempool_recheck_times{job=\"validator001\"}[$__rate_interval]))", + "legendFormat": "validator receiving all load", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "avg(rate(cometbft_mempool_recheck_times{job!=\"validator001\"}[$__rate_interval]))", + "hide": false, + "legendFormat": "avg. of other validators", + "range": true, + "refId": "B" + } + ], + "title": "Recheck rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Number of received txs that hit the cache.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 70, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "validator receiving all load" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "avg. of other validators" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#808080", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 11, + "x": 11, + "y": 38 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum(rate(cometbft_mempool_already_received_txs{job=\"validator001\"}[$__rate_interval]))", + "legendFormat": "validator receiving all load", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "avg(rate(cometbft_mempool_already_received_txs{job!=\"validator001\"}[$__rate_interval]))", + "hide": false, + "legendFormat": "avg. of other validators", + "range": true, + "refId": "B" + } + ], + "title": "Already received txs", + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "prometheus", + "value": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "1s", + "3s", + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + } +} diff --git a/test/monitoring/config-grafana/provisioning/dashboards-data/node-exporter-full.json b/test/monitoring/config-grafana/provisioning/dashboards-data/node-exporter-full.json new file mode 100644 index 00000000000..a8b02dab295 --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/dashboards-data/node-exporter-full.json @@ -0,0 +1,23825 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.4.3" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:1058", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 1860, + "graphTooltip": 1, + "id": null, + "links": [ + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "GitHub", + "type": "link", + "url": "https://github.com/rfmoz/grafana-dashboards" + }, + { + "icon": "external link", + "tags": [], + "targetBlank": true, + "title": "Grafana", + "type": "link", + "url": "https://grafana.com/grafana/dashboards/1860" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 261, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Quick CPU / Mem / Disk", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Busy state of all CPU cores together", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 20, + "links": [], + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "(sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode!=\"idle\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))) * 100", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "", + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "CPU Busy", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Busy state of all CPU cores together (5 min average)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 155, + "links": [], + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "avg_over_time(node_load5{instance=\"$node\",job=\"$job\"}[$__rate_interval]) * 100 / on(instance) group_left sum by (instance)(irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "Sys Load (5m avg)", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Busy state of all CPU cores together (15 min average)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 19, + "links": [], + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "avg_over_time(node_load15{instance=\"$node\",job=\"$job\"}[$__rate_interval]) * 100 / on(instance) group_left sum by (instance)(irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval]))", + "hide": false, + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "Sys Load (15m avg)", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Non available RAM memory", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 1 + }, + "hideTimeOverride": false, + "id": 16, + "links": [], + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "((avg_over_time(node_memory_MemTotal_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval]) - avg_over_time(node_memory_MemFree_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval])) / (avg_over_time(node_memory_MemTotal_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval]) )) * 100", + "format": "time_series", + "hide": true, + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "100 - ((avg_over_time(node_memory_MemAvailable_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval]) * 100) / avg_over_time(node_memory_MemTotal_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval]))", + "format": "time_series", + "hide": false, + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "B", + "step": 240 + } + ], + "title": "RAM Used", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Used Swap", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 10 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 25 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 21, + "links": [], + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "((avg_over_time(node_memory_SwapTotal_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval]) - avg_over_time(node_memory_SwapFree_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval])) / (avg_over_time(node_memory_SwapTotal_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval]) )) * 100", + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "SWAP Used", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Used Root FS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 154, + "links": [], + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "100 - ((avg_over_time(node_filesystem_avail_bytes{instance=\"$node\",job=\"$job\",mountpoint=\"/\",fstype!=\"rootfs\"}[$__rate_interval]) * 100) / avg_over_time(node_filesystem_size_bytes{instance=\"$node\",job=\"$job\",mountpoint=\"/\",fstype!=\"rootfs\"}[$__rate_interval]))", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "Root FS Used", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Total number of CPU cores", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 18, + "y": 1 + }, + "id": 14, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "count(count(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}) by (cpu))", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "CPU Cores", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "System uptime", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 20, + "y": 1 + }, + "hideTimeOverride": true, + "id": 15, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "node_time_seconds{instance=\"$node\",job=\"$job\"} - node_boot_time_seconds{instance=\"$node\",job=\"$job\"}", + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "Uptime", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Total RootFS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 70 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 18, + "y": 3 + }, + "id": 23, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "node_filesystem_size_bytes{instance=\"$node\",job=\"$job\",mountpoint=\"/\",fstype!=\"rootfs\"}", + "format": "time_series", + "hide": false, + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "RootFS Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Total RAM", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 20, + "y": 3 + }, + "id": 75, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "node_memory_MemTotal_bytes{instance=\"$node\",job=\"$job\"}", + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "RAM Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Total SWAP", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 2, + "x": 22, + "y": 3 + }, + "id": 18, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.4.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "node_memory_SwapTotal_bytes{instance=\"$node\",job=\"$job\"}", + "instant": true, + "intervalFactor": 1, + "range": false, + "refId": "A", + "step": 240 + } + ], + "title": "SWAP Total", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 263, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Basic CPU / Mem / Net / Disk", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Basic CPU info", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "percent" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Busy Iowait" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Idle" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Busy Iowait" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Idle" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Busy System" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Busy User" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Busy Other" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 77, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "width": 250 + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"system\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Busy System", + "range": true, + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"user\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Busy User", + "range": true, + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"iowait\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Busy Iowait", + "range": true, + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=~\".*irq\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Busy IRQs", + "range": true, + "refId": "D", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode!='idle',mode!='user',mode!='system',mode!='iowait',mode!='irq',mode!='softirq'}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Busy Other", + "range": true, + "refId": "E", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"idle\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Idle", + "range": true, + "refId": "F", + "step": 240 + } + ], + "title": "CPU Basic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Basic memory usage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "SWAP Used" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap Used" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM Cache + Buffer" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Available" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#DEDAF7", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 78, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_MemTotal_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "RAM Total", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_MemTotal_bytes{instance=\"$node\",job=\"$job\"} - node_memory_MemFree_bytes{instance=\"$node\",job=\"$job\"} - (node_memory_Cached_bytes{instance=\"$node\",job=\"$job\"} + node_memory_Buffers_bytes{instance=\"$node\",job=\"$job\"} + node_memory_SReclaimable_bytes{instance=\"$node\",job=\"$job\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "RAM Used", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Cached_bytes{instance=\"$node\",job=\"$job\"} + node_memory_Buffers_bytes{instance=\"$node\",job=\"$job\"} + node_memory_SReclaimable_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RAM Cache + Buffer", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_MemFree_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "RAM Free", + "refId": "D", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "(node_memory_SwapTotal_bytes{instance=\"$node\",job=\"$job\"} - node_memory_SwapFree_bytes{instance=\"$node\",job=\"$job\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SWAP Used", + "refId": "E", + "step": 240 + } + ], + "title": "Memory Basic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Basic network info per interface", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Recv_bytes_eth2" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Recv_bytes_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Recv_drop_eth2" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Recv_drop_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Recv_errs_eth2" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Recv_errs_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CCA300", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Trans_bytes_eth2" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Trans_bytes_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Trans_drop_eth2" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Trans_drop_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Trans_errs_eth2" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Trans_errs_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CCA300", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "recv_bytes_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "recv_drop_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "recv_drop_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#967302", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "recv_errs_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "recv_errs_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "trans_bytes_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "trans_bytes_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "trans_drop_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "trans_drop_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#967302", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "trans_errs_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "trans_errs_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 74, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_bytes_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])*8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "recv {{device}}", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_bytes_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])*8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "trans {{device}} ", + "refId": "B", + "step": 240 + } + ], + "title": "Network Traffic Basic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Disk space used of all filesystems mounted", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 152, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "100 - ((node_filesystem_avail_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'} * 100) / node_filesystem_size_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{mountpoint}}", + "refId": "A", + "step": 240 + } + ], + "title": "Disk Space Used Basic", + "type": "timeseries" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 265, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "percentage", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 70, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "percent" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Idle - Waiting for something to happen" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Iowait - Waiting for I/O to complete" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Irq - Servicing interrupts" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Nice - Niced processes executing in user mode" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Softirq - Servicing softirqs" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Steal - Time spent in other operating systems when running in a virtualized environment" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCE2DE", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "System - Processes executing in kernel mode" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "User - Normal processes executing in user mode" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#5195CE", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 3, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 250 + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"system\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "System - Processes executing in kernel mode", + "range": true, + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"user\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "User - Normal processes executing in user mode", + "range": true, + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"nice\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Nice - Niced processes executing in user mode", + "range": true, + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"iowait\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Iowait - Waiting for I/O to complete", + "range": true, + "refId": "E", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"irq\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Irq - Servicing interrupts", + "range": true, + "refId": "F", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"softirq\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Softirq - Servicing softirqs", + "range": true, + "refId": "G", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"steal\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Steal - Time spent in other operating systems when running in a virtualized environment", + "range": true, + "refId": "H", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"idle\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Idle - Waiting for something to happen", + "range": true, + "refId": "J", + "step": 240 + } + ], + "title": "CPU", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap - Swap memory usage" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused - Free memory unassigned" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*Hardware Corrupted - *./" + }, + "properties": [ + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 24, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_MemTotal_bytes{instance=\"$node\",job=\"$job\"} - node_memory_MemFree_bytes{instance=\"$node\",job=\"$job\"} - node_memory_Buffers_bytes{instance=\"$node\",job=\"$job\"} - node_memory_Cached_bytes{instance=\"$node\",job=\"$job\"} - node_memory_Slab_bytes{instance=\"$node\",job=\"$job\"} - node_memory_PageTables_bytes{instance=\"$node\",job=\"$job\"} - node_memory_SwapCached_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Apps - Memory used by user-space applications", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_PageTables_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "PageTables - Memory used to map between virtual and physical memory addresses", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_SwapCached_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SwapCache - Memory that keeps track of pages that have been fetched from swap but not yet been modified", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Slab_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Slab - Memory used by the kernel to cache data structures for its own use (caches like inode, dentry, etc)", + "refId": "D", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Cached_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Cache - Parked file data (file content) cache", + "refId": "E", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Buffers_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Buffers - Block device (e.g. harddisk) cache", + "refId": "F", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_MemFree_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Unused - Free memory unassigned", + "refId": "G", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "(node_memory_SwapTotal_bytes{instance=\"$node\",job=\"$job\"} - node_memory_SwapFree_bytes{instance=\"$node\",job=\"$job\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Swap - Swap space used", + "refId": "H", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_HardwareCorrupted_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working", + "refId": "I", + "step": 240 + } + ], + "title": "Memory Stack", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bits out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "receive_packets_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "receive_packets_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "transmit_packets_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "transmit_packets_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 84, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_bytes_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])*8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_bytes_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])*8", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit", + "refId": "B", + "step": 240 + } + ], + "title": "Network Traffic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 156, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filesystem_size_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'} - node_filesystem_avail_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{mountpoint}}", + "refId": "A", + "step": 240 + } + ], + "title": "Disk Space Used", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "IO read (-) / write (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "iops" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Read.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 229, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_reads_completed_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"}[$__rate_interval])", + "intervalFactor": 4, + "legendFormat": "{{device}} - Reads completed", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_writes_completed_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Writes completed", + "refId": "B", + "step": 240 + } + ], + "title": "Disk IOps", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes read (-) / write (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "io time" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*read*./" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byType", + "options": "time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 42, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_read_bytes_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}} - Successfully read bytes", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_written_bytes_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}} - Successfully written bytes", + "refId": "B", + "step": 240 + } + ], + "title": "I/O Usage Read / Write", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "%util", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 40, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "io time" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byType", + "options": "time" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "hidden" + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 127, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_io_time_seconds_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"} [$__rate_interval])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{device}}", + "refId": "A", + "step": 240 + } + ], + "title": "I/O Utilization", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "percentage", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 70, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 3, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "max": 1, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^Guest - /" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#5195ce", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^GuestNice - /" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#c15c17", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 319, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_guest_seconds_total{instance=\"$node\",job=\"$job\", mode=\"user\"}[1m])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[1m])))", + "hide": false, + "legendFormat": "Guest - Time spent running a virtual CPU for a guest operating system", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum by(instance) (irate(node_cpu_guest_seconds_total{instance=\"$node\",job=\"$job\", mode=\"nice\"}[1m])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[1m])))", + "hide": false, + "legendFormat": "GuestNice - Time spent running a niced guest (virtual CPU for guest operating system)", + "range": true, + "refId": "B" + } + ], + "title": "CPU spent seconds in guests (VMs)", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "CPU / Memory / Net / Disk", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 266, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 54 + }, + "id": 136, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Inactive_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Inactive - Memory which has been less recently used. It is more eligible to be reclaimed for other purposes", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Active_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Active - Memory that has been used more recently and usually not reclaimed unless absolutely necessary", + "refId": "B", + "step": 240 + } + ], + "title": "Memory Active / Inactive", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*CommitLimit - *./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 54 + }, + "id": 135, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Committed_AS_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Committed_AS - Amount of memory presently allocated on the system", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_CommitLimit_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "CommitLimit - Amount of memory currently available to be allocated on the system", + "refId": "B", + "step": 240 + } + ], + "title": "Memory Committed", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 64 + }, + "id": 191, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Inactive_file_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Inactive_file - File-backed memory on inactive LRU list", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Inactive_anon_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Inactive_anon - Anonymous and swap cache on inactive LRU list, including tmpfs (shmem)", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Active_file_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Active_file - File-backed memory on active LRU list", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Active_anon_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Active_anon - Anonymous and swap cache on active least-recently-used (LRU) list, including tmpfs", + "refId": "D", + "step": 240 + } + ], + "title": "Memory Active / Inactive Detail", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 64 + }, + "id": 130, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Writeback_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Writeback - Memory which is actively being written back to disk", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_WritebackTmp_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "WritebackTmp - Memory used by FUSE for temporary writeback buffers", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Dirty_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Dirty - Memory which is waiting to get written back to the disk", + "refId": "C", + "step": 240 + } + ], + "title": "Memory Writeback and Dirty", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "ShmemHugePages - Memory used by shared memory (shmem) and tmpfs allocated with huge pages" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "ShmemHugePages - Memory used by shared memory (shmem) and tmpfs allocated with huge pages" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 74 + }, + "id": 138, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Mapped_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Mapped - Used memory in mapped pages files which have been mapped, such as libraries", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Shmem_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Shmem - Used shared memory (shared between several processes, thus including RAM disks)", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_ShmemHugePages_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "ShmemHugePages - Memory used by shared memory (shmem) and tmpfs allocated with huge pages", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_ShmemPmdMapped_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "ShmemPmdMapped - Amount of shared (shmem/tmpfs) memory backed by huge pages", + "refId": "D", + "step": 240 + } + ], + "title": "Memory Shared and Mapped", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 74 + }, + "id": 131, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_SUnreclaim_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SUnreclaim - Part of Slab, that cannot be reclaimed on memory pressure", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_SReclaimable_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "SReclaimable - Part of Slab, that might be reclaimed, such as caches", + "refId": "B", + "step": 240 + } + ], + "title": "Memory Slab", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 84 + }, + "id": 70, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_VmallocChunk_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "VmallocChunk - Largest contiguous block of vmalloc area which is free", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_VmallocTotal_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "VmallocTotal - Total size of vmalloc memory area", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_VmallocUsed_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "VmallocUsed - Amount of vmalloc area which is used", + "refId": "C", + "step": 240 + } + ], + "title": "Memory Vmalloc", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 84 + }, + "id": 159, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Bounce_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Bounce - Memory used for block device bounce buffers", + "refId": "A", + "step": 240 + } + ], + "title": "Memory Bounce", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*Inactive *./" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 94 + }, + "id": 129, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_AnonHugePages_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "AnonHugePages - Memory in anonymous huge pages", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_AnonPages_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "AnonPages - Memory in user pages not backed by files", + "refId": "B", + "step": 240 + } + ], + "title": "Memory Anonymous", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 94 + }, + "id": 160, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_KernelStack_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "KernelStack - Kernel memory stack. This is not reclaimable", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Percpu_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "PerCPU - Per CPU memory allocated dynamically by loadable modules", + "refId": "B", + "step": 240 + } + ], + "title": "Memory Kernel / CPU", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "pages", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 104 + }, + "id": 140, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_HugePages_Free{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "HugePages_Free - Huge pages in the pool that are not yet allocated", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_HugePages_Rsvd{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "HugePages_Rsvd - Huge pages for which a commitment to allocate from the pool has been made, but no allocation has yet been made", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_HugePages_Surp{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "HugePages_Surp - Huge pages in the pool above the value in /proc/sys/vm/nr_hugepages", + "refId": "C", + "step": 240 + } + ], + "title": "Memory HugePages Counter", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 104 + }, + "id": 71, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_HugePages_Total{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "HugePages - Total size of the pool of huge pages", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Hugepagesize_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Hugepagesize - Huge Page size", + "refId": "B", + "step": 240 + } + ], + "title": "Memory HugePages Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 114 + }, + "id": 128, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_DirectMap1G_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "DirectMap1G - Amount of pages mapped as this size", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_DirectMap2M_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "DirectMap2M - Amount of pages mapped as this size", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_DirectMap4k_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "DirectMap4K - Amount of pages mapped as this size", + "refId": "C", + "step": 240 + } + ], + "title": "Memory DirectMap", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 114 + }, + "id": 137, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Unevictable_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Unevictable - Amount of unevictable memory that can't be swapped out for a variety of reasons", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_Mlocked_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "MLocked - Size of pages locked to memory using the mlock() system call", + "refId": "B", + "step": 240 + } + ], + "title": "Memory Unevictable and MLocked", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 124 + }, + "id": 132, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_memory_NFS_Unstable_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "NFS Unstable - Memory in NFS pages sent to the server, but not yet committed to the storage", + "refId": "A", + "step": 240 + } + ], + "title": "Memory NFS", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Memory Meminfo", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 267, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "pages out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*out/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 176, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_vmstat_pgpgin{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pagesin - Page in operations", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_vmstat_pgpgout{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pagesout - Page out operations", + "refId": "B", + "step": 240 + } + ], + "title": "Memory Pages In / Out", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "pages out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*out/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 22, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_vmstat_pswpin{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pswpin - Pages swapped in", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_vmstat_pswpout{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pswpout - Pages swapped out", + "refId": "B", + "step": 240 + } + ], + "title": "Memory Pages Swap In / Out", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "faults", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Apps" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#629E51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A437C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CFFAFF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "RAM_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#806EB7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#2F575E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Unused" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Pgfault - Page major and minor fault operations" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 51 + }, + "id": 175, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 350 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_vmstat_pgfault{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pgfault - Page major and minor fault operations", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_vmstat_pgmajfault{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pgmajfault - Major page fault operations", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_vmstat_pgfault{instance=\"$node\",job=\"$job\"}[$__rate_interval]) - irate(node_vmstat_pgmajfault{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pgminfault - Minor page fault operations", + "refId": "C", + "step": 240 + } + ], + "title": "Memory Page Faults", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#99440A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Buffers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#58140C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6D1F62", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Cached" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Committed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#508642", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Dirty" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Free" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#B7DBAB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Mapped" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "PageTables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Page_Tables" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Slab_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Swap_Cache" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C15C17", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#511749", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total RAM + Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#052B51", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Total Swap" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "VmallocUsed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 51 + }, + "id": 307, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_vmstat_oom_kill{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "oom killer invocations ", + "refId": "A", + "step": 240 + } + ], + "title": "OOM Killer", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Memory Vmstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 293, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "seconds", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Variation*./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 56 + }, + "id": 260, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_timex_estimated_error_seconds{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Estimated error in seconds", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_timex_offset_seconds{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Time offset in between local system and reference clock", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_timex_maxerror_seconds{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Maximum error in seconds", + "refId": "C", + "step": 240 + } + ], + "title": "Time Synchronized Drift", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 56 + }, + "id": 291, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_timex_loop_time_constant{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Phase-locked loop time adjust", + "refId": "A", + "step": 240 + } + ], + "title": "Time PLL Adjust", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Variation*./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 66 + }, + "id": 168, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_timex_sync_status{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Is clock synchronized to a reliable server (1 = yes, 0 = no)", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_timex_frequency_adjustment_ratio{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Local clock frequency adjustment", + "refId": "B", + "step": 240 + } + ], + "title": "Time Synchronized Status", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "seconds", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 66 + }, + "id": 294, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_timex_tick_seconds{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Seconds between clock ticks", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_timex_tai_offset_seconds{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "International Atomic Time (TAI) offset", + "refId": "B", + "step": 240 + } + ], + "title": "Time Misc", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "System Timesync", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 312, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 62, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_procs_blocked{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Processes blocked waiting for I/O to complete", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_procs_running{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Processes in runnable state", + "refId": "B", + "step": 240 + } + ], + "title": "Processes Status", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Enable with --collector.processes argument on node-exporter", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 315, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_processes_state{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ state }}", + "refId": "A", + "step": 240 + } + ], + "title": "Processes State", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "forks / sec", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 53 + }, + "id": 148, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_forks_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Processes forks second", + "refId": "A", + "step": 240 + } + ], + "title": "Processes Forks", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Max.*/" + }, + "properties": [ + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 53 + }, + "id": 149, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(process_virtual_memory_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Processes virtual memory size in bytes", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "process_resident_memory_max_bytes{instance=\"$node\",job=\"$job\"}", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Maximum amount of virtual memory available in bytes", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(process_virtual_memory_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Processes virtual memory size in bytes", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(process_virtual_memory_max_bytes{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Maximum amount of virtual memory available in bytes", + "refId": "D", + "step": 240 + } + ], + "title": "Processes Memory", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Enable with --collector.processes argument on node-exporter", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "PIDs limit" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2495C", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 63 + }, + "id": 313, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_processes_pids{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Number of PIDs", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_processes_max_processes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "PIDs limit", + "refId": "B", + "step": 240 + } + ], + "title": "PIDs Number and Limit", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "seconds", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*waiting.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 63 + }, + "id": 305, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_schedstat_running_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU {{ cpu }} - seconds spent running a process", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_schedstat_waiting_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU {{ cpu }} - seconds spent by processing waiting for this CPU", + "refId": "B", + "step": 240 + } + ], + "title": "Process schedule stats Running / Waiting", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Enable with --collector.processes argument on node-exporter", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Threads limit" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2495C", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 73 + }, + "id": 314, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_processes_threads{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Allocated threads", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_processes_max_threads{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Threads limit", + "refId": "B", + "step": 240 + } + ], + "title": "Threads Number and Limit", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "System Processes", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 269, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 8, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_context_switches_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Context switches", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_intr_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Interrupts", + "refId": "B", + "step": 240 + } + ], + "title": "Context Switches / Interrupts", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 7, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_load1{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "Load 1m", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_load5{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "Load 5m", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_load15{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "Load 15m", + "refId": "C", + "step": 240 + } + ], + "title": "System Load", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "hertz" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Max" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "dash": [ + 10, + 10 + ], + "fill": "dash" + } + }, + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 10 + }, + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": false, + "viz": false + } + }, + { + "id": "custom.fillBelowTo", + "value": "Min" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Min" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "dash": [ + 10, + 10 + ], + "fill": "dash" + } + }, + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + }, + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": false, + "viz": false + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 321, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "node_cpu_scaling_frequency_hertz{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU {{ cpu }}", + "range": true, + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg(node_cpu_scaling_frequency_max_hertz{instance=\"$node\",job=\"$job\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Max", + "range": true, + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg(node_cpu_scaling_frequency_min_hertz{instance=\"$node\",job=\"$job\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Min", + "range": true, + "refId": "C", + "step": 240 + } + ], + "title": "CPU Frequency Scaling", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "https://docs.kernel.org/accounting/psi.html", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Memory some" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-red", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Memory full" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-red", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "I/O some" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "I/O full" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-blue", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 36 + }, + "id": 322, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(node_pressure_cpu_waiting_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "CPU some", + "range": true, + "refId": "CPU some", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(node_pressure_memory_waiting_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Memory some", + "range": true, + "refId": "Memory some", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(node_pressure_memory_stalled_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Memory full", + "range": true, + "refId": "Memory full", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(node_pressure_io_waiting_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "I/O some", + "range": true, + "refId": "I/O some", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(node_pressure_io_stalled_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "I/O full", + "range": true, + "refId": "I/O full", + "step": 240 + } + ], + "title": "Pressure Stall Information", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Enable with --collector.interrupts argument on node-exporter", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Critical*./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*Max*./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 259, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_interrupts_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ type }} - {{ info }}", + "refId": "A", + "step": 240 + } + ], + "title": "Interrupts Detail", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 46 + }, + "id": 306, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_schedstat_timeslices_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU {{ cpu }}", + "refId": "A", + "step": 240 + } + ], + "title": "Schedule timeslices executed by each cpu", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 56 + }, + "id": 151, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_entropy_available_bits{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Entropy available to random number generators", + "refId": "A", + "step": 240 + } + ], + "title": "Entropy", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "seconds", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 56 + }, + "id": 308, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(process_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Time spent", + "refId": "A", + "step": 240 + } + ], + "title": "CPU time spent in user and system contexts", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Max*./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 66 + }, + "id": 64, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "process_max_fds{instance=\"$node\",job=\"$job\"}", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Maximum open file descriptors", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "process_open_fds{instance=\"$node\",job=\"$job\"}", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Open file descriptors", + "refId": "B", + "step": 240 + } + ], + "title": "File Descriptors", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "System Misc", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 304, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "temperature", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Critical*./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*Max*./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 158, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_hwmon_temp_celsius{instance=\"$node\",job=\"$job\"} * on(chip) group_left(chip_name) node_hwmon_chip_names{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ chip_name }} {{ sensor }} temp", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_hwmon_temp_crit_alarm_celsius{instance=\"$node\",job=\"$job\"} * on(chip) group_left(chip_name) node_hwmon_chip_names{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ chip_name }} {{ sensor }} Critical Alarm", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_hwmon_temp_crit_celsius{instance=\"$node\",job=\"$job\"} * on(chip) group_left(chip_name) node_hwmon_chip_names{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ chip_name }} {{ sensor }} Critical", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_hwmon_temp_crit_hyst_celsius{instance=\"$node\",job=\"$job\"} * on(chip) group_left(chip_name) node_hwmon_chip_names{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ chip_name }} {{ sensor }} Critical Historical", + "refId": "D", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_hwmon_temp_max_celsius{instance=\"$node\",job=\"$job\"} * on(chip) group_left(chip_name) node_hwmon_chip_names{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ chip_name }} {{ sensor }} Max", + "refId": "E", + "step": 240 + } + ], + "title": "Hardware temperature monitor", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Max*./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 300, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_cooling_device_cur_state{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Current {{ name }} in {{ type }}", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_cooling_device_max_state{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Max {{ name }} in {{ type }}", + "refId": "B", + "step": 240 + } + ], + "title": "Throttle cooling device", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 69 + }, + "id": 302, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_power_supply_online{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ power_supply }} online", + "refId": "A", + "step": 240 + } + ], + "title": "Power supply", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Hardware Misc", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 27 + }, + "id": 296, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 297, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_systemd_socket_accepted_connections_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{ name }} Connections", + "refId": "A", + "step": 240 + } + ], + "title": "Systemd Sockets", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Failed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2495C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inactive" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF9830", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Active" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#73BF69", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Deactivating" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFCB7D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Activating" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C8F2C2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 46 + }, + "id": 298, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_systemd_units{instance=\"$node\",job=\"$job\",state=\"activating\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Activating", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_systemd_units{instance=\"$node\",job=\"$job\",state=\"active\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Active", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_systemd_units{instance=\"$node\",job=\"$job\",state=\"deactivating\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Deactivating", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_systemd_units{instance=\"$node\",job=\"$job\",state=\"failed\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Failed", + "refId": "D", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_systemd_units{instance=\"$node\",job=\"$job\",state=\"inactive\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Inactive", + "refId": "E", + "step": 240 + } + ], + "title": "Systemd Units State", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Systemd", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 28 + }, + "id": 270, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "The number (after merges) of I/O requests completed per second for the device", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "IO read (-) / write (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "iops" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Read.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 9, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_reads_completed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "intervalFactor": 4, + "legendFormat": "{{device}} - Reads completed", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_writes_completed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Writes completed", + "refId": "B", + "step": 240 + } + ], + "title": "Disk IOps Completed", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "The number of bytes read from or written to the device per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes read (-) / write (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Read.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 33, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_read_bytes_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "{{device}} - Read bytes", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_written_bytes_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Written bytes", + "refId": "B", + "step": 240 + } + ], + "title": "Disk R/W Data", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "The average time for requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "time. read (-) / write (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 30, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Read.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 57 + }, + "id": 37, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_read_time_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval]) / irate(node_disk_reads_completed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "hide": false, + "interval": "", + "intervalFactor": 4, + "legendFormat": "{{device}} - Read wait time avg", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_write_time_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval]) / irate(node_disk_writes_completed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{device}} - Write wait time avg", + "refId": "B", + "step": 240 + } + ], + "title": "Disk Average Wait Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "The average queue length of the requests that were issued to the device", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "aqu-sz", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 57 + }, + "id": 35, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_io_time_weighted_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "intervalFactor": 4, + "legendFormat": "{{device}}", + "refId": "A", + "step": 240 + } + ], + "title": "Average Queue Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "The number of read and write requests merged per second that were queued to the device", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "I/Os", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "iops" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Read.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 133, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_reads_merged_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Read merged", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_writes_merged_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "intervalFactor": 1, + "legendFormat": "{{device}} - Write merged", + "refId": "B", + "step": 240 + } + ], + "title": "Disk R/W Merged", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Percentage of elapsed time during which I/O requests were issued to the device (bandwidth utilization for the device). Device saturation occurs when this value is close to 100% for devices serving requests serially. But for devices serving requests in parallel, such as RAID arrays and modern SSDs, this number does not reflect their performance limits.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "%util", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 30, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 36, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_io_time_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "intervalFactor": 4, + "legendFormat": "{{device}} - IO", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_discard_time_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "intervalFactor": 4, + "legendFormat": "{{device}} - discard", + "refId": "B", + "step": 240 + } + ], + "title": "Time Spent Doing I/Os", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "The number of outstanding requests at the instant the sample was taken. Incremented as requests are given to appropriate struct request_queue and decremented as they finish.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Outstanding req.", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 77 + }, + "id": 34, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_disk_io_now{instance=\"$node\",job=\"$job\"}", + "interval": "", + "intervalFactor": 4, + "legendFormat": "{{device}} - IO now", + "refId": "A", + "step": 240 + } + ], + "title": "Instantaneous Queue Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "IOs", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "iops" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EAB839", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#6ED0E0", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EF843C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#584477", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda2_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BA43A9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sda3_.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F4D598", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#0A50A1", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#BF1B00", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdb3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0752D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#962D82", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#614D93", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdc3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#9AC48A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#65C5DB", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9934E", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#EA6460", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde1.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0F9D7", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sdd2.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FCEACA", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*sde3.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F9E2D2", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 77 + }, + "id": 301, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_discards_completed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "intervalFactor": 4, + "legendFormat": "{{device}} - Discards completed", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_disk_discards_merged_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{device}} - Discards merged", + "refId": "B", + "step": 240 + } + ], + "title": "Disk IOps Discards completed / merged", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Storage Disk", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 29 + }, + "id": 271, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 62 + }, + "id": 43, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filesystem_avail_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Available", + "metric": "", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filesystem_free_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Free", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filesystem_size_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": true, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Size", + "refId": "C", + "step": 240 + } + ], + "title": "Filesystem space available", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "file nodes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 62 + }, + "id": 41, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filesystem_files_free{instance=\"$node\",job=\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Free file nodes", + "refId": "A", + "step": 240 + } + ], + "title": "File Nodes Free", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "files", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 72 + }, + "id": 28, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filefd_maximum{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 4, + "legendFormat": "Max open files", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filefd_allocated{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Open files", + "refId": "B", + "step": 240 + } + ], + "title": "File Descriptor", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "file Nodes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 72 + }, + "id": 219, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filesystem_files{instance=\"$node\",job=\"$job\",device!~'rootfs'}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - File nodes total", + "refId": "A", + "step": 240 + } + ], + "title": "File Nodes Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "max": 1, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "/ ReadOnly" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 82 + }, + "id": 44, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filesystem_readonly{instance=\"$node\",job=\"$job\",device!~'rootfs'}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - ReadOnly", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_filesystem_device_error{instance=\"$node\",job=\"$job\",device!~'rootfs',fstype!~'tmpfs'}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mountpoint}} - Device error", + "refId": "B", + "step": 240 + } + ], + "title": "Filesystem in ReadOnly / Error", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Storage Filesystem", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 272, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packets out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "receive_packets_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "receive_packets_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "transmit_packets_eth0" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#7EB26D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "transmit_packets_lo" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E24D42", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 60, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_packets_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_packets_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit", + "refId": "B", + "step": 240 + } + ], + "title": "Network Traffic by Packets", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packets out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 142, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_errs_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive errors", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_errs_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit errors", + "refId": "B", + "step": 240 + } + ], + "title": "Network Traffic Errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packets out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 57 + }, + "id": 143, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_drop_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive drop", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_drop_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit drop", + "refId": "B", + "step": 240 + } + ], + "title": "Network Traffic Drop", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packets out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 57 + }, + "id": 141, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_compressed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive compressed", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_compressed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit compressed", + "refId": "B", + "step": 240 + } + ], + "title": "Network Traffic Compressed", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packets out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 146, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_multicast_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive multicast", + "refId": "A", + "step": 240 + } + ], + "title": "Network Traffic Multicast", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packets out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 144, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_fifo_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive fifo", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_fifo_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit fifo", + "refId": "B", + "step": 240 + } + ], + "title": "Network Traffic Fifo", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packets out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 77 + }, + "id": 145, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_receive_frame_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{device}} - Receive frame", + "refId": "A", + "step": 240 + } + ], + "title": "Network Traffic Frame", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 77 + }, + "id": 231, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_carrier_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Statistic transmit_carrier", + "refId": "A", + "step": 240 + } + ], + "title": "Network Traffic Carrier", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Trans.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 87 + }, + "id": 232, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_network_transmit_colls_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{device}} - Transmit colls", + "refId": "A", + "step": 240 + } + ], + "title": "Network Traffic Colls", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "entries", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "NF conntrack limit" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 87 + }, + "id": 61, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_nf_conntrack_entries{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "NF conntrack entries", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_nf_conntrack_entries_limit{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "NF conntrack limit", + "refId": "B", + "step": 240 + } + ], + "title": "NF Conntrack", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Entries", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 97 + }, + "id": 230, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_arp_entries{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ device }} - ARP entries", + "refId": "A", + "step": 240 + } + ], + "title": "ARP Entries", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 97 + }, + "id": 288, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_network_mtu_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ device }} - Bytes", + "refId": "A", + "step": 240 + } + ], + "title": "MTU", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 107 + }, + "id": 280, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_network_speed_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ device }} - Speed", + "refId": "A", + "step": 240 + } + ], + "title": "Speed", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packets", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 107 + }, + "id": 289, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_network_transmit_queue_length{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{ device }} - Interface transmit queue length", + "refId": "A", + "step": 240 + } + ], + "title": "Queue Length", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "packetes drop (-) / process (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Dropped.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 117 + }, + "id": 290, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_softnet_processed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU {{cpu}} - Processed", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_softnet_dropped_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU {{cpu}} - Dropped", + "refId": "B", + "step": 240 + } + ], + "title": "Softnet Packets", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 117 + }, + "id": 310, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_softnet_times_squeezed_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU {{cpu}} - Squeezed", + "refId": "A", + "step": 240 + } + ], + "title": "Softnet Out of Quota", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 127 + }, + "id": 309, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_network_up{operstate=\"up\",instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{interface}} - Operational state UP", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_network_carrier{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "instant": false, + "legendFormat": "{{device}} - Physical link state", + "refId": "B" + } + ], + "title": "Network Operational Status", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Network Traffic", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 273, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 63, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_TCP_alloc{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "TCP_alloc - Allocated sockets", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_TCP_inuse{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "TCP_inuse - Tcp sockets currently in use", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_TCP_mem{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "TCP_mem - Used memory for tcp", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_TCP_orphan{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "TCP_orphan - Orphan sockets", + "refId": "D", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_TCP_tw{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "TCP_tw - Sockets waiting close", + "refId": "E", + "step": 240 + } + ], + "title": "Sockstat TCP", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 124, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_UDPLITE_inuse{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "UDPLITE_inuse - Udplite sockets currently in use", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_UDP_inuse{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "UDP_inuse - Udp sockets currently in use", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_UDP_mem{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "UDP_mem - Used memory for udp", + "refId": "C", + "step": 240 + } + ], + "title": "Sockstat UDP", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 125, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_FRAG_inuse{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "FRAG_inuse - Frag sockets currently in use", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_RAW_inuse{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "RAW_inuse - Raw sockets currently in use", + "refId": "C", + "step": 240 + } + ], + "title": "Sockstat FRAG / RAW", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "bytes", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 220, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_TCP_mem_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "mem_bytes - TCP sockets in that state", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_UDP_mem_bytes{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "mem_bytes - UDP sockets in that state", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_FRAG_memory{instance=\"$node\",job=\"$job\"}", + "interval": "", + "intervalFactor": 1, + "legendFormat": "FRAG_memory - Used memory for frag", + "refId": "C" + } + ], + "title": "Sockstat Memory Size", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "sockets", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 68 + }, + "id": 126, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_sockstat_sockets_used{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Sockets_used - Sockets currently in use", + "refId": "A", + "step": 240 + } + ], + "title": "Sockstat Used", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Network Sockstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 274, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "octets out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Out.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 221, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_IpExt_InOctets{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "InOctets - Received octets", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_IpExt_OutOctets{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "OutOctets - Sent octets", + "refId": "B", + "step": 240 + } + ], + "title": "Netstat IP In / Out Octets", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "datagrams", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 81, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "width": 300 + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Ip_Forwarding{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Forwarding - IP forwarding", + "refId": "A", + "step": 240 + } + ], + "title": "Netstat IP Forwarding", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "messages out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Out.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 115, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Icmp_InMsgs{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "InMsgs - Messages which the entity received. Note that this counter includes all those counted by icmpInErrors", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Icmp_OutMsgs{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "OutMsgs - Messages which this entity attempted to send. Note that this counter includes all those counted by icmpOutErrors", + "refId": "B", + "step": 240 + } + ], + "title": "ICMP In / Out", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "messages out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Out.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 50, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Icmp_InErrors{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "InErrors - Messages which the entity received but determined as having ICMP-specific errors (bad ICMP checksums, bad length, etc.)", + "refId": "A", + "step": 240 + } + ], + "title": "ICMP Errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "datagrams out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Out.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*Snd.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 69 + }, + "id": 55, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Udp_InDatagrams{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "InDatagrams - Datagrams received", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Udp_OutDatagrams{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "OutDatagrams - Datagrams sent", + "refId": "B", + "step": 240 + } + ], + "title": "UDP In / Out", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "datagrams", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 69 + }, + "id": 109, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Udp_InErrors{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "InErrors - UDP Datagrams that could not be delivered to an application", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Udp_NoPorts{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "NoPorts - UDP Datagrams received on a port with no listener", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_UdpLite_InErrors{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "legendFormat": "InErrors Lite - UDPLite Datagrams that could not be delivered to an application", + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Udp_RcvbufErrors{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "RcvbufErrors - UDP buffer errors received", + "refId": "D", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Udp_SndbufErrors{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "SndbufErrors - UDP buffer errors send", + "refId": "E", + "step": 240 + } + ], + "title": "UDP Errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "datagrams out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Out.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/.*Snd.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 79 + }, + "id": 299, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Tcp_InSegs{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "InSegs - Segments received, including those received in error. This count includes segments received on currently established connections", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Tcp_OutSegs{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "OutSegs - Segments sent, including those on current connections but excluding those containing only retransmitted octets", + "refId": "B", + "step": 240 + } + ], + "title": "TCP In / Out", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 79 + }, + "id": 104, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_TcpExt_ListenOverflows{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "ListenOverflows - Times the listen queue of a socket overflowed", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_TcpExt_ListenDrops{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "ListenDrops - SYNs to LISTEN sockets ignored", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_TcpExt_TCPSynRetrans{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "TCPSynRetrans - SYN-SYN/ACK retransmits to break down retransmissions in SYN, fast/timeout retransmits", + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Tcp_RetransSegs{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "legendFormat": "RetransSegs - Segments retransmitted - that is, the number of TCP segments transmitted containing one or more previously transmitted octets", + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Tcp_InErrs{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "legendFormat": "InErrs - Segments received in error (e.g., bad TCP checksums)", + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Tcp_OutRsts{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "interval": "", + "legendFormat": "OutRsts - Segments sent with RST flag", + "refId": "F" + } + ], + "title": "TCP Errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "connections", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*MaxConn *./" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#890F02", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 89 + }, + "id": 85, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_netstat_Tcp_CurrEstab{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "CurrEstab - TCP connections for which the current state is either ESTABLISHED or CLOSE- WAIT", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_netstat_Tcp_MaxConn{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "MaxConn - Limit on the total number of TCP connections the entity can support (Dynamic is \"-1\")", + "refId": "B", + "step": 240 + } + ], + "title": "TCP Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter out (-) / in (+)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*Sent.*/" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 89 + }, + "id": 91, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_TcpExt_SyncookiesFailed{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "SyncookiesFailed - Invalid SYN cookies received", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_TcpExt_SyncookiesRecv{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "SyncookiesRecv - SYN cookies received", + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_TcpExt_SyncookiesSent{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "SyncookiesSent - SYN cookies sent", + "refId": "C", + "step": 240 + } + ], + "title": "TCP SynCookie", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "connections", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 99 + }, + "id": 82, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Tcp_ActiveOpens{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "ActiveOpens - TCP connections that have made a direct transition to the SYN-SENT state from the CLOSED state", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "irate(node_netstat_Tcp_PassiveOpens{instance=\"$node\",job=\"$job\"}[$__rate_interval])", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "PassiveOpens - TCP connections that have made a direct transition to the SYN-RCVD state from the LISTEN state", + "refId": "B", + "step": 240 + } + ], + "title": "TCP Direct Transition", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Enable with --collector.tcpstat argument on node-exporter", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "connections", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 99 + }, + "id": 320, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "node_tcp_connection_states{state=\"established\",instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "established - TCP sockets in established state", + "range": true, + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "node_tcp_connection_states{state=\"fin_wait2\",instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "fin_wait2 - TCP sockets in fin_wait2 state", + "range": true, + "refId": "B", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "node_tcp_connection_states{state=\"listen\",instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "listen - TCP sockets in listen state", + "range": true, + "refId": "C", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "node_tcp_connection_states{state=\"time_wait\",instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "time_wait - TCP sockets in time_wait state", + "range": true, + "refId": "D", + "step": 240 + } + ], + "title": "TCP Stat", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Network Netstat", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 33 + }, + "id": 279, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "seconds", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 66 + }, + "id": 40, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_scrape_collector_duration_seconds{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{collector}} - Scrape duration", + "refId": "A", + "step": 240 + } + ], + "title": "Node Exporter Scrape Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "counter", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/.*error.*/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2495C", + "mode": "fixed" + } + }, + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 66 + }, + "id": 157, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_scrape_collector_success{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{collector}} - Scrape success", + "refId": "A", + "step": 240 + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "expr": "node_textfile_scrape_error{instance=\"$node\",job=\"$job\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{collector}} - Scrape textfile error (1 = true)", + "refId": "B", + "step": 240 + } + ], + "title": "Node Exporter Scrape", + "type": "timeseries" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "000000001" + }, + "refId": "A" + } + ], + "title": "Node Exporter", + "type": "row" + } + ], + "refresh": "", + "revision": 1, + "schemaVersion": 38, + "style": "dark", + "tags": [ + "linux" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "Datasource", + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "", + "hide": 0, + "includeAll": false, + "label": "Job", + "multi": false, + "name": "job", + "options": [], + "query": { + "query": "label_values(node_uname_info, job)", + "refId": "Prometheus-job-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(node_uname_info{job=\"$job\"}, instance)", + "hide": 0, + "includeAll": false, + "label": "Host", + "multi": false, + "name": "node", + "options": [], + "query": { + "query": "label_values(node_uname_info{job=\"$job\"}, instance)", + "refId": "Prometheus-node-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+", + "value": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+" + }, + "hide": 2, + "includeAll": false, + "multi": false, + "name": "diskdevices", + "options": [ + { + "selected": true, + "text": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+", + "value": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+" + } + ], + "query": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Node Exporter Full", + "uid": "rYdddlPWk", + "version": 87, + "weekStart": "" +} diff --git a/test/monitoring/config-grafana/provisioning/dashboards-data/storage.json b/test/monitoring/config-grafana/provisioning/dashboards-data/storage.json new file mode 100644 index 00000000000..618e2cb19ba --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/dashboards-data/storage.json @@ -0,0 +1,1122 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 4, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "panels": [], + "title": "RAM", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "go_memstats_sys_bytes - measures how many bytes of memory in total is taken from system by Go", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "host" + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "go_memstats_sys_bytes / 1024 / 1024", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Memory used by Go [MB]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "go_memstats_gc_sys_bytes – shows how many in garbage collection metadata", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "host" + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": true, + "tooltip": true, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "go_memstats_gc_sys_bytes / 1024 / 1024", + "instant": false, + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Go Garbage Collector Size [MB]", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 12, + "panels": [], + "title": "Other", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "cometbft_mempool_size", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "cometbft_mempool_size", + "instant": false, + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Mempool size (#txs)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum by (job) (cometbft_state_block_processing_time_sum / cometbft_state_block_processing_time_count)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Block processing time average [ms]", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 4, + "panels": [], + "title": "Consensus", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "last" + ], + "displayMode": "list", + "placement": "right", + "showLegend": true, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "cometbft_consensus_height", + "format": "time_series", + "hide": false, + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Chain height", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum by (job, step) (cometbft_consensus_step_duration_seconds_sum / cometbft_consensus_step_duration_seconds_count) * 1000", + "instant": false, + "interval": "500ms", + "legendFormat": "{{step}}-{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Consensus step duration average [ms]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "cometbft_consensus_total_txs", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisWidth": 80, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 13, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "right", + "showLegend": true, + "width": 200 + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "cometbft_consensus_total_txs", + "format": "time_series", + "hide": false, + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Total transactions committed", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 9, + "panels": [], + "title": "Storage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum by (job, method) (cometbft_store_block_store_access_duration_seconds_sum / cometbft_store_block_store_access_duration_seconds_count) * 1000", + "instant": false, + "interval": "500ms", + "legendFormat": "{{method}}-{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Block store access duration average [ms]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 36 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum by (job, method) (cometbft_state_store_access_duration_seconds_sum / cometbft_state_store_access_duration_seconds_count) * 1000", + "instant": false, + "interval": "500ms", + "legendFormat": "{{method}}-{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "State store access duration average [ms]", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 44 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum by (job) (cometbft_consensus_block_interval_seconds_sum / cometbft_consensus_block_interval_seconds_count) * 1000", + "instant": false, + "interval": "500ms", + "legendFormat": "{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Block interval average [ms]", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "prometheus", + "value": "prometheus" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Storage", + "uid": "f39669c6-a6bc-46b8-9272-c5216d0855fb", + "version": 8, + "weekStart": "" +} diff --git a/test/monitoring/config-grafana/provisioning/dashboards/comet.yml b/test/monitoring/config-grafana/provisioning/dashboards/comet.yml new file mode 100644 index 00000000000..8a1e028a1f6 --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/dashboards/comet.yml @@ -0,0 +1,13 @@ +apiVersion: 1 + +providers: + - name: 'default' + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + allowUiUpdates: true + options: + path: '/etc/grafana/provisioning/dashboards-data' + foldersFromFilesStructure: true diff --git a/test/monitoring/config-grafana/provisioning/datasources/prometheus.yml b/test/monitoring/config-grafana/provisioning/datasources/prometheus.yml new file mode 100644 index 00000000000..3ad5d908d67 --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/datasources/prometheus.yml @@ -0,0 +1,9 @@ +# Connect Grafana to Prometheus through a Grafana datasource. Hostname is derived from the docker name. +apiVersion: 1 +datasources: + - name: prometheus + uid: prometheus + type: prometheus + url: http://prometheus:9090 + is_default: true + editable: true diff --git a/test/monitoring/config-grafana/provisioning/notifiers/.placeholder b/test/monitoring/config-grafana/provisioning/notifiers/.placeholder new file mode 100644 index 00000000000..bf4aeaf198d --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/notifiers/.placeholder @@ -0,0 +1 @@ +Placeholder so the Grafana log does not complain about missing folders. diff --git a/test/monitoring/config-grafana/provisioning/plugins/.placeholder b/test/monitoring/config-grafana/provisioning/plugins/.placeholder new file mode 100644 index 00000000000..bf4aeaf198d --- /dev/null +++ b/test/monitoring/config-grafana/provisioning/plugins/.placeholder @@ -0,0 +1 @@ +Placeholder so the Grafana log does not complain about missing folders. diff --git a/test/monitoring/config-prometheus/prometheus.yml b/test/monitoring/config-prometheus/prometheus.yml new file mode 100644 index 00000000000..0070b82bac2 --- /dev/null +++ b/test/monitoring/config-prometheus/prometheus.yml @@ -0,0 +1,30 @@ +# my global config +global: + scrape_interval: 10s + evaluation_interval: 15s + +scrape_configs: + - job_name: 'host' + static_configs: + - targets: ['node-exporter:9100'] + scrape_interval: 5s + + - job_name: 'node0' + static_configs: + - targets: ['host.docker.internal:26670'] + scrape_interval: 5s + + - job_name: 'node1' + static_configs: + - targets: ['host.docker.internal:26671'] + scrape_interval: 5s + + - job_name: 'node2' + static_configs: + - targets: ['host.docker.internal:26672'] + scrape_interval: 5s + + - job_name: 'node3' + static_configs: + - targets: ['host.docker.internal:26673'] + scrape_interval: 5s diff --git a/tests.mk b/tests.mk index ec461eb69de..ee8fed36359 100644 --- a/tests.mk +++ b/tests.mk @@ -35,14 +35,12 @@ test_abci_cli: test_integrations: make build_docker_test_image - make tools make install make install_abci make test_cover make test_apps make test_abci_apps make test_abci_cli - make test_libs .PHONY: test_integrations test_release: @@ -53,15 +51,10 @@ test100: @for i in {1..100}; do make test; done .PHONY: test100 -vagrant_test: - vagrant up - vagrant ssh -c 'make test_integrations' -.PHONY: vagrant_test - ### go tests test: @echo "--> Running go test" - @go test -p 1 $(PACKAGES) -tags deadlock + @go test -p 1 $(PACKAGES) -tags deadlock,bls12381 .PHONY: test test_race: @@ -71,5 +64,5 @@ test_race: test_deadlock: @echo "--> Running go test --deadlock" - @go test -p 1 -v $(PACKAGES) -tags deadlock + @go test -p 1 -v $(PACKAGES) -tags deadlock .PHONY: test_race diff --git a/tools/README.md b/tools/README.md deleted file mode 100644 index 98e36c86887..00000000000 --- a/tools/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# tools - -Tools for working with CometBFT and associated technologies. -Documentation for these tools can be found online in the -[CometBFT tools documentation](https://docs.cometbft.com/main/tools/). diff --git a/tools/proto/Dockerfile b/tools/proto/Dockerfile deleted file mode 100644 index bd2d486a33f..00000000000 --- a/tools/proto/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM bufbuild/buf:latest as buf - -FROM golang:1.14-alpine3.11 as builder - -RUN apk add --update --no-cache build-base curl git upx && \ - rm -rf /var/cache/apk/* - -ENV GOLANG_PROTOBUF_VERSION=1.3.1 \ - GOGOPROTO_VERSION=1.4.1 - -RUN GO111MODULE=on go get \ - github.com/golang/protobuf/protoc-gen-go@v${GOLANG_PROTOBUF_VERSION} \ - github.com/cosmos/gogoproto/protoc-gen-gogo@v${GOGOPROTO_VERSION} \ - github.com/cosmos/gogoproto/protoc-gen-gogofaster@v${GOGOPROTO_VERSION} && \ - mv /go/bin/protoc-gen-go* /usr/local/bin/ - - -FROM alpine:edge - -WORKDIR /work - -RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories && \ - apk add --update --no-cache clang && \ - rm -rf /var/cache/apk/* - -COPY --from=builder /usr/local/bin /usr/local/bin -COPY --from=buf /usr/local/bin /usr/local/bin diff --git a/tools/tools.go b/tools/tools.go deleted file mode 100644 index 23d2366bb99..00000000000 --- a/tools/tools.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build tools - -// This file uses the recommended method for tracking developer tools in a go module. -// -// https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module - -package tools - -import ( - _ "github.com/bufbuild/buf/cmd/buf" - _ "github.com/golangci/golangci-lint/cmd/golangci-lint" - _ "github.com/pointlander/peg" - _ "github.com/vektra/mockery/v2" -) diff --git a/types/block.go b/types/block.go index 0dadd571b9f..d8fd5d3d4b0 100644 --- a/types/block.go +++ b/types/block.go @@ -10,22 +10,23 @@ import ( "github.com/cosmos/gogoproto/proto" gogotypes "github.com/cosmos/gogoproto/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/merkle" "github.com/cometbft/cometbft/crypto/tmhash" - "github.com/cometbft/cometbft/libs/bits" + "github.com/cometbft/cometbft/internal/bits" + cmtsync "github.com/cometbft/cometbft/internal/sync" cmtbytes "github.com/cometbft/cometbft/libs/bytes" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtsync "github.com/cometbft/cometbft/libs/sync" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" + cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) const ( // MaxHeaderBytes is a maximum header size. // NOTE: Because app hash can be of arbitrary size, the header is therefore not - // capped in size and thus this number should be seen as a soft max + // capped in size and thus this number should be seen as a soft max. MaxHeaderBytes int64 = 626 // MaxOverheadForBlock - maximum overhead to encode a block (up to @@ -35,7 +36,7 @@ const ( // Uvarint length of MaxBlockSizeBytes: 4 bytes // 2 fields (2 embedded): 2 bytes // Uvarint length of Data.Txs: 4 bytes - // Data.Txs field: 1 byte + // Data.Txs field: 1 byte. MaxOverheadForBlock int64 = 11 ) @@ -69,7 +70,7 @@ func (b *Block) ValidateBasic() error { return errors.New("nil LastCommit") } if err := b.LastCommit.ValidateBasic(); err != nil { - return fmt.Errorf("wrong LastCommit: %v", err) + return fmt.Errorf("wrong LastCommit: %w", err) } if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) { @@ -91,7 +92,7 @@ func (b *Block) ValidateBasic() error { // NOTE: b.Evidence.Evidence may be nil, but we're just looping. for i, ev := range b.Evidence.Evidence { if err := ev.ValidateBasic(); err != nil { - return fmt.Errorf("invalid evidence (#%d): %v", i, err) + return fmt.Errorf("invalid evidence (#%d): %w", i, err) } } @@ -105,7 +106,7 @@ func (b *Block) ValidateBasic() error { return nil } -// fillHeader fills in any remaining header fields that are a function of the block data +// fillHeader fills in any remaining header fields that are a function of the block data. func (b *Block) fillHeader() { if b.LastCommitHash == nil { b.LastCommitHash = b.LastCommit.Hash() @@ -190,7 +191,7 @@ func (b *Block) String() string { // Data // Evidence // LastCommit -// Hash +// Hash. func (b *Block) StringIndented(indent string) string { if b == nil { return "nil-Block" @@ -216,7 +217,7 @@ func (b *Block) StringShort() string { return fmt.Sprintf("Block#%X", b.Hash()) } -// ToProto converts Block to protobuf +// ToProto converts Block to protobuf. func (b *Block) ToProto() (*cmtproto.Block, error) { if b == nil { return nil, errors.New("nil Block") @@ -237,7 +238,7 @@ func (b *Block) ToProto() (*cmtproto.Block, error) { return pb, nil } -// FromProto sets a protobuf Block to the given pointer. +// BlockFromProto sets a protobuf Block to the given pointer. // It returns an error if the block is invalid. func BlockFromProto(bp *cmtproto.Block) (*Block, error) { if bp == nil { @@ -270,7 +271,7 @@ func BlockFromProto(bp *cmtproto.Block) (*Block, error) { return b, b.ValidateBasic() } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // MaxDataBytes returns the maximum size of block's data. // @@ -294,8 +295,7 @@ func MaxDataBytes(maxBytes, evidenceBytes int64, valsCount int) int64 { } // MaxDataBytesNoEvidence returns the maximum size of block's data when -// evidence count is unknown. MaxEvidencePerBlock will be used for the size -// of evidence. +// evidence count is unknown (will be assumed to be 0). // // XXX: Panics on negative result. func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 { @@ -306,7 +306,7 @@ func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 { if maxDataBytes < 0 { panic(fmt.Sprintf( - "Negative MaxDataBytesUnknownEvidence. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d", + "Negative MaxDataBytesNoEvidence. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d", maxBytes, -(maxDataBytes - maxBytes), )) @@ -315,7 +315,7 @@ func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 { return maxDataBytes } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Header defines the structure of a CometBFT block header. // NOTE: changes to the Header should be duplicated in: @@ -342,7 +342,7 @@ type Header struct { ConsensusHash cmtbytes.HexBytes `json:"consensus_hash"` // consensus params for current block AppHash cmtbytes.HexBytes `json:"app_hash"` // state after txs from the previous block // root hash of all results from the txs from the previous block - // see `deterministicExecTxResult` to understand which parts of a tx is hashed into here + // see `DeterministicExecTxResult` to understand which parts of a tx is hashed into here LastResultsHash cmtbytes.HexBytes `json:"last_results_hash"` // consensus info @@ -394,15 +394,15 @@ func (h Header) ValidateBasic() error { } if err := ValidateHash(h.LastCommitHash); err != nil { - return fmt.Errorf("wrong LastCommitHash: %v", err) + return fmt.Errorf("wrong LastCommitHash: %w", err) } if err := ValidateHash(h.DataHash); err != nil { - return fmt.Errorf("wrong DataHash: %v", err) + return fmt.Errorf("wrong DataHash: %w", err) } if err := ValidateHash(h.EvidenceHash); err != nil { - return fmt.Errorf("wrong EvidenceHash: %v", err) + return fmt.Errorf("wrong EvidenceHash: %w", err) } if len(h.ProposerAddress) != crypto.AddressSize { @@ -415,17 +415,17 @@ func (h Header) ValidateBasic() error { // Basic validation of hashes related to application data. // Will validate fully against state in state#ValidateBlock. if err := ValidateHash(h.ValidatorsHash); err != nil { - return fmt.Errorf("wrong ValidatorsHash: %v", err) + return fmt.Errorf("wrong ValidatorsHash: %w", err) } if err := ValidateHash(h.NextValidatorsHash); err != nil { - return fmt.Errorf("wrong NextValidatorsHash: %v", err) + return fmt.Errorf("wrong NextValidatorsHash: %w", err) } if err := ValidateHash(h.ConsensusHash); err != nil { - return fmt.Errorf("wrong ConsensusHash: %v", err) + return fmt.Errorf("wrong ConsensusHash: %w", err) } // NOTE: AppHash is arbitrary length if err := ValidateHash(h.LastResultsHash); err != nil { - return fmt.Errorf("wrong LastResultsHash: %v", err) + return fmt.Errorf("wrong LastResultsHash: %w", err) } return nil @@ -513,7 +513,7 @@ func (h *Header) StringIndented(indent string) string { ) } -// ToProto converts Header to protobuf +// ToProto converts Header to protobuf. func (h *Header) ToProto() *cmtproto.Header { if h == nil { return nil @@ -537,7 +537,7 @@ func (h *Header) ToProto() *cmtproto.Header { } } -// FromProto sets a protobuf Header to the given pointer. +// HeaderFromProto sets a protobuf Header to the given pointer. // It returns an error if the header is invalid. func HeaderFromProto(ph *cmtproto.Header) (Header, error) { if ph == nil { @@ -570,7 +570,7 @@ func HeaderFromProto(ph *cmtproto.Header) (Header, error) { return *h, h.ValidateBasic() } -//------------------------------------- +// ------------------------------------- // BlockIDFlag indicates which BlockID the signature is for. type BlockIDFlag byte @@ -587,9 +587,9 @@ const ( const ( // Max size of commit without any commitSigs -> 82 for BlockID, 8 for Height, 4 for Round. MaxCommitOverheadBytes int64 = 94 - // Commit sig size is made up of 64 bytes for the signature, 20 bytes for the address, - // 1 byte for the flag and 14 bytes for the timestamp - MaxCommitSigBytes int64 = 109 + // Commit sig size is made up of 96 bytes for the signature, 20 bytes for the address, + // 1 byte for the flag and 14 bytes for the timestamp. + MaxCommitSigBytes int64 = 131 + 10 // where's the 10 from? ) // CommitSig is a part of the Vote included in a Commit. @@ -601,8 +601,9 @@ type CommitSig struct { } func MaxCommitBytes(valCount int) int64 { + // protoEncodingOverhead represents the overhead in bytes when encoding a protocol buffer message. + const protoEncodingOverhead int64 = 3 // From the repeated commit sig field - var protoEncodingOverhead int64 = 2 return MaxCommitOverheadBytes + ((MaxCommitSigBytes + protoEncodingOverhead) * int64(valCount)) } @@ -614,12 +615,12 @@ func NewCommitSigAbsent() CommitSig { } } -// CommitSig returns a string representation of CommitSig. +// String returns a string representation of CommitSig. // // 1. first 6 bytes of signature // 2. first 6 bytes of validator address // 3. block ID flag -// 4. timestamp +// 4. timestamp. func (cs CommitSig) String() string { return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}", cmtbytes.Fingerprint(cs.Signature), @@ -685,7 +686,7 @@ func (cs CommitSig) ValidateBasic() error { return nil } -// ToProto converts CommitSig to protobuf +// ToProto converts CommitSig to protobuf. func (cs *CommitSig) ToProto() *cmtproto.CommitSig { if cs == nil { return nil @@ -710,7 +711,7 @@ func (cs *CommitSig) FromProto(csp cmtproto.CommitSig) error { return cs.ValidateBasic() } -//------------------------------------- +// ------------------------------------- // ExtendedCommitSig contains a commit signature along with its corresponding // vote extension and vote extension signature. @@ -730,7 +731,7 @@ func NewExtendedCommitSigAbsent() ExtendedCommitSig { // // 1. commit sig // 2. first 6 bytes of vote extension -// 3. first 6 bytes of vote extension signature +// 3. first 6 bytes of vote extension signature. func (ecs ExtendedCommitSig) String() string { return fmt.Sprintf("ExtendedCommitSig{%s with %X %X}", ecs.CommitSig, @@ -761,7 +762,7 @@ func (ecs ExtendedCommitSig) ValidateBasic() error { return nil } -// EnsureExtensions validates that a vote extensions signature is present for +// EnsureExtension validates that a vote extensions signature is present for // this ExtendedCommitSig. func (ecs ExtendedCommitSig) EnsureExtension(extEnabled bool) error { if extEnabled { @@ -830,7 +831,7 @@ func (ecs *ExtendedCommitSig) FromProto(ecsp cmtproto.ExtendedCommitSig) error { return ecs.ValidateBasic() } -//------------------------------------- +// ------------------------------------- // Commit contains the evidence that a block was committed by a set of validators. // NOTE: Commit is empty for height 1, but never nil. @@ -858,7 +859,7 @@ type Commit struct { func (commit *Commit) GetVote(valIdx int32) *Vote { commitSig := commit.Signatures[valIdx] return &Vote{ - Type: cmtproto.PrecommitType, + Type: PrecommitType, Height: commit.Height, Round: commit.Round, BlockID: commitSig.BlockID(commit.BlockID), @@ -877,7 +878,7 @@ func (commit *Commit) GetVote(valIdx int32) *Vote { // // Panics if valIdx >= commit.Size(). // -// See VoteSignBytes +// See VoteSignBytes. func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte { v := commit.GetVote(valIdx).ToProto() return VoteSignBytes(chainID, v) @@ -902,7 +903,7 @@ func (commit *Commit) ValidateBasic() error { } if commit.Height >= 1 { - if commit.BlockID.IsZero() { + if commit.BlockID.IsNil() { return errors.New("commit cannot be for nil block") } @@ -911,14 +912,40 @@ func (commit *Commit) ValidateBasic() error { } for i, commitSig := range commit.Signatures { if err := commitSig.ValidateBasic(); err != nil { - return fmt.Errorf("wrong CommitSig #%d: %v", i, err) + return fmt.Errorf("wrong CommitSig #%d: %w", i, err) } } } return nil } -// Hash returns the hash of the commit +// MedianTime computes the median time for a Commit based on the associated validator set. +// The median time is the weighted median of the Timestamp fields of the commit votes, +// with heights defined by the validator's voting powers. +// The BFT Time algorithm ensures that the computed median time is always picked among +// the timestamps produced by honest processes, i.e., faulty processes cannot arbitrarily +// increase or decrease the median time. +// See: https://github.com/cometbft/cometbft/blob/main/spec/consensus/bft-time.md +func (commit *Commit) MedianTime(validators *ValidatorSet) time.Time { + weightedTimes := make([]*cmttime.WeightedTime, len(commit.Signatures)) + totalVotingPower := int64(0) + + for i, commitSig := range commit.Signatures { + if commitSig.BlockIDFlag == BlockIDFlagAbsent { + continue + } + _, validator := validators.GetByAddress(commitSig.ValidatorAddress) + // If there's no condition, TestValidateBlockCommit panics; not needed normally. + if validator != nil { + totalVotingPower += validator.VotingPower + weightedTimes[i] = cmttime.NewWeightedTime(commitSig.Timestamp, validator.VotingPower) + } + } + + return cmttime.WeightedMedian(weightedTimes, totalVotingPower) +} + +// Hash returns the hash of the commit. func (commit *Commit) Hash() cmtbytes.HexBytes { if commit == nil { return nil @@ -983,7 +1010,7 @@ func (commit *Commit) StringIndented(indent string) string { indent, commit.hash) } -// ToProto converts Commit to protobuf +// ToProto converts Commit to protobuf. func (commit *Commit) ToProto() *cmtproto.Commit { if commit == nil { return nil @@ -1003,16 +1030,14 @@ func (commit *Commit) ToProto() *cmtproto.Commit { return c } -// FromProto sets a protobuf Commit to the given pointer. +// CommitFromProto sets a protobuf Commit to the given pointer. // It returns an error if the commit is invalid. func CommitFromProto(cp *cmtproto.Commit) (*Commit, error) { if cp == nil { return nil, errors.New("nil Commit") } - var ( - commit = new(Commit) - ) + commit := new(Commit) bi, err := BlockIDFromProto(&cp.BlockID) if err != nil { @@ -1034,7 +1059,7 @@ func CommitFromProto(cp *cmtproto.Commit) (*Commit, error) { return commit, commit.ValidateBasic() } -//------------------------------------- +// ------------------------------------- // ExtendedCommit is similar to Commit, except that its signatures also retain // their corresponding vote extensions and vote extension signatures. @@ -1061,7 +1086,7 @@ func (ec *ExtendedCommit) Clone() *ExtendedCommit { // Panics if any of the votes have invalid or absent vote extension data. // Inverse of VoteSet.MakeExtendedCommit(). func (ec *ExtendedCommit) ToExtendedVoteSet(chainID string, vals *ValidatorSet) *VoteSet { - voteSet := NewExtendedVoteSet(chainID, ec.Height, ec.Round, cmtproto.PrecommitType, vals) + voteSet := NewExtendedVoteSet(chainID, ec.Height, ec.Round, PrecommitType, vals) ec.addSigsToVoteSet(voteSet) return voteSet } @@ -1087,7 +1112,7 @@ func (ec *ExtendedCommit) addSigsToVoteSet(voteSet *VoteSet) { // Panics if signatures from the commit can't be added to the voteset. // Inverse of VoteSet.MakeCommit(). func (commit *Commit) ToVoteSet(chainID string, vals *ValidatorSet) *VoteSet { - voteSet := NewVoteSet(chainID, commit.Height, commit.Round, cmtproto.PrecommitType, vals) + voteSet := NewVoteSet(chainID, commit.Height, commit.Round, PrecommitType, vals) for idx, cs := range commit.Signatures { if cs.BlockIDFlag == BlockIDFlagAbsent { continue // OK, some precommits can be missing. @@ -1136,7 +1161,7 @@ func (ec *ExtendedCommit) ToCommit() *Commit { func (ec *ExtendedCommit) GetExtendedVote(valIndex int32) *Vote { ecs := ec.ExtendedSignatures[valIndex] return &Vote{ - Type: cmtproto.PrecommitType, + Type: PrecommitType, Height: ec.Height, Round: ec.Round, BlockID: ecs.BlockID(ec.BlockID), @@ -1152,7 +1177,7 @@ func (ec *ExtendedCommit) GetExtendedVote(valIndex int32) *Vote { // Type returns the vote type of the extended commit, which is always // VoteTypePrecommit // Implements VoteSetReader. -func (ec *ExtendedCommit) Type() byte { return byte(cmtproto.PrecommitType) } +func (*ExtendedCommit) Type() byte { return byte(PrecommitType) } // GetHeight returns height of the extended commit. // Implements VoteSetReader. @@ -1210,7 +1235,7 @@ func (ec *ExtendedCommit) ValidateBasic() error { } if ec.Height >= 1 { - if ec.BlockID.IsZero() { + if ec.BlockID.IsNil() { return errors.New("extended commit cannot be for nil block") } @@ -1219,14 +1244,14 @@ func (ec *ExtendedCommit) ValidateBasic() error { } for i, extCommitSig := range ec.ExtendedSignatures { if err := extCommitSig.ValidateBasic(); err != nil { - return fmt.Errorf("wrong ExtendedCommitSig #%d: %v", i, err) + return fmt.Errorf("wrong ExtendedCommitSig #%d: %w", i, err) } } } return nil } -// ToProto converts ExtendedCommit to protobuf +// ToProto converts ExtendedCommit to protobuf. func (ec *ExtendedCommit) ToProto() *cmtproto.ExtendedCommit { if ec == nil { return nil @@ -1274,11 +1299,10 @@ func ExtendedCommitFromProto(ecp *cmtproto.ExtendedCommit) (*ExtendedCommit, err return extCommit, extCommit.ValidateBasic() } -//------------------------------------- +// ------------------------------------- -// Data contains the set of transactions included in the block +// Data contains the set of transactions included in the block. type Data struct { - // Txs that will be applied by state @ block.Height+1. // NOTE: not all txs here are valid. We're just agreeing on the order first. // This means that block.AppHash does not include these txs. @@ -1288,7 +1312,7 @@ type Data struct { hash cmtbytes.HexBytes } -// Hash returns the hash of the data +// Hash returns the hash of the data. func (data *Data) Hash() cmtbytes.HexBytes { if data == nil { return (Txs{}).Hash() @@ -1319,7 +1343,7 @@ func (data *Data) StringIndented(indent string) string { indent, data.hash) } -// ToProto converts Data to protobuf +// ToProto converts Data to protobuf. func (data *Data) ToProto() cmtproto.Data { tp := new(cmtproto.Data) @@ -1355,9 +1379,9 @@ func DataFromProto(dp *cmtproto.Data) (Data, error) { return *data, nil } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- -// EvidenceData contains any evidence of malicious wrong-doing by validators +// EvidenceData contains any evidence of malicious wrong-doing by validators. type EvidenceData struct { Evidence EvidenceList `json:"evidence"` @@ -1374,7 +1398,7 @@ func (data *EvidenceData) Hash() cmtbytes.HexBytes { return data.hash } -// ByteSize returns the total byte size of all the evidence +// ByteSize returns the total byte size of all the evidence. func (data *EvidenceData) ByteSize() int64 { if data.byteSize == 0 && len(data.Evidence) != 0 { pb, err := data.ToProto() @@ -1406,7 +1430,7 @@ func (data *EvidenceData) StringIndented(indent string) string { indent, data.hash) } -// ToProto converts EvidenceData to protobuf +// ToProto converts EvidenceData to protobuf. func (data *EvidenceData) ToProto() (*cmtproto.EvidenceList, error) { if data == nil { return nil, errors.New("nil evidence data") @@ -1446,21 +1470,21 @@ func (data *EvidenceData) FromProto(eviData *cmtproto.EvidenceList) error { return nil } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- -// BlockID +// BlockID. type BlockID struct { Hash cmtbytes.HexBytes `json:"hash"` PartSetHeader PartSetHeader `json:"parts"` } -// Equals returns true if the BlockID matches the given BlockID +// Equals returns true if the BlockID matches the given BlockID. func (blockID BlockID) Equals(other BlockID) bool { return bytes.Equal(blockID.Hash, other.Hash) && blockID.PartSetHeader.Equals(other.PartSetHeader) } -// Key returns a machine-readable string representation of the BlockID +// Key returns a machine-readable string representation of the BlockID. func (blockID BlockID) Key() string { pbph := blockID.PartSetHeader.ToProto() bz, err := pbph.Marshal() @@ -1475,16 +1499,16 @@ func (blockID BlockID) Key() string { func (blockID BlockID) ValidateBasic() error { // Hash can be empty in case of POLBlockID in Proposal. if err := ValidateHash(blockID.Hash); err != nil { - return fmt.Errorf("wrong Hash") + return errors.New("wrong Hash") } if err := blockID.PartSetHeader.ValidateBasic(); err != nil { - return fmt.Errorf("wrong PartSetHeader: %v", err) + return fmt.Errorf("wrong PartSetHeader: %w", err) } return nil } -// IsZero returns true if this is the BlockID of a nil block. -func (blockID BlockID) IsZero() bool { +// IsNil returns true if this is the BlockID of a nil block. +func (blockID BlockID) IsNil() bool { return len(blockID.Hash) == 0 && blockID.PartSetHeader.IsZero() } @@ -1501,12 +1525,12 @@ func (blockID BlockID) IsComplete() bool { // 1. hash // 2. part set header // -// See PartSetHeader#String +// See PartSetHeader#String. func (blockID BlockID) String() string { return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartSetHeader) } -// ToProto converts BlockID to protobuf +// ToProto converts BlockID to protobuf. func (blockID *BlockID) ToProto() cmtproto.BlockID { if blockID == nil { return cmtproto.BlockID{} @@ -1518,7 +1542,7 @@ func (blockID *BlockID) ToProto() cmtproto.BlockID { } } -// FromProto sets a protobuf BlockID to the given pointer. +// BlockIDFromProto sets a protobuf BlockID to the given pointer. // It returns an error if the block id is invalid. func BlockIDFromProto(bID *cmtproto.BlockID) (*BlockID, error) { if bID == nil { diff --git a/types/block_meta.go b/types/block_meta.go index d66cc8f36cd..ed3bff6ee76 100644 --- a/types/block_meta.go +++ b/types/block_meta.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" ) // BlockMeta contains meta information. diff --git a/types/block_meta_test.go b/types/block_meta_test.go index b557f284a50..4c08878d592 100644 --- a/types/block_meta_test.go +++ b/types/block_meta_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/crypto/tmhash" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) func TestBlockMeta_ToProto(t *testing.T) { @@ -49,10 +49,14 @@ func TestBlockMeta_ToProto(t *testing.T) { func TestBlockMeta_ValidateBasic(t *testing.T) { h := makeRandHeader() bi := BlockID{Hash: h.Hash(), PartSetHeader: PartSetHeader{Total: 123, Hash: cmtrand.Bytes(tmhash.Size)}} - bi2 := BlockID{Hash: cmtrand.Bytes(tmhash.Size), - PartSetHeader: PartSetHeader{Total: 123, Hash: cmtrand.Bytes(tmhash.Size)}} - bi3 := BlockID{Hash: []byte("incorrect hash"), - PartSetHeader: PartSetHeader{Total: 123, Hash: []byte("incorrect hash")}} + bi2 := BlockID{ + Hash: cmtrand.Bytes(tmhash.Size), + PartSetHeader: PartSetHeader{Total: 123, Hash: cmtrand.Bytes(tmhash.Size)}, + } + bi3 := BlockID{ + Hash: []byte("incorrect hash"), + PartSetHeader: PartSetHeader{Total: 123, Hash: []byte("incorrect hash")}, + } bm := &BlockMeta{ BlockID: bi, diff --git a/types/block_test.go b/types/block_test.go index f9c97a7e840..981ef37833e 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -1,9 +1,6 @@ package types import ( - // it is ok to use math/rand here: we do not need a cryptographically secure random - // number generator here and we can run the tests a bit faster - "crypto/rand" "encoding/hex" "math" @@ -16,14 +13,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/merkle" "github.com/cometbft/cometbft/crypto/tmhash" - "github.com/cometbft/cometbft/libs/bits" + "github.com/cometbft/cometbft/internal/bits" + cmtrand "github.com/cometbft/cometbft/internal/rand" "github.com/cometbft/cometbft/libs/bytes" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) @@ -38,17 +34,17 @@ func TestBlockAddEvidence(t *testing.T) { lastID := makeBlockIDRandom() h := int64(3) - voteSet, _, vals := randVoteSet(h-1, 1, cmtproto.PrecommitType, 10, 1, false) - extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, time.Now(), false) + voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1, false) + extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, cmttime.Now(), false) require.NoError(t, err) - ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, cmttime.Now(), vals[0], "block-test-chain") require.NoError(t, err) evList := []Evidence{ev} block := MakeBlock(h, txs, extCommit.ToCommit(), evList) require.NotNil(t, block) - require.Equal(t, 1, len(block.Evidence.Evidence)) + require.Len(t, block.Evidence.Evidence, 1) require.NotNil(t, block.EvidenceHash) } @@ -59,12 +55,12 @@ func TestBlockValidateBasic(t *testing.T) { lastID := makeBlockIDRandom() h := int64(3) - voteSet, valSet, vals := randVoteSet(h-1, 1, cmtproto.PrecommitType, 10, 1, false) - extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, time.Now(), false) + voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1, false) + extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, cmttime.Now(), false) require.NoError(t, err) commit := extCommit.ToCommit() - ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, cmttime.Now(), vals[0], "block-test-chain") require.NoError(t, err) evList := []Evidence{ev} @@ -73,17 +69,17 @@ func TestBlockValidateBasic(t *testing.T) { malleateBlock func(*Block) expErr bool }{ - {"Make Block", func(blk *Block) {}, false}, + {"Make Block", func(_ *Block) {}, false}, {"Make Block w/ proposer Addr", func(blk *Block) { blk.ProposerAddress = valSet.GetProposer().Address }, false}, {"Negative Height", func(blk *Block) { blk.Height = -1 }, true}, {"Remove 1/2 the commits", func(blk *Block) { blk.LastCommit.Signatures = commit.Signatures[:commit.Size()/2] - blk.LastCommit.hash = nil // clear hash or change wont be noticed + blk.LastCommit.hash = nil // clear hash or change won't be noticed }, true}, {"Remove LastCommitHash", func(blk *Block) { blk.LastCommitHash = []byte("something else") }, true}, {"Tampered Data", func(blk *Block) { blk.Data.Txs[0] = Tx("something else") - blk.Data.hash = nil // clear hash or change wont be noticed + blk.Data.hash = nil // clear hash or change won't be noticed }, true}, {"Tampered DataHash", func(blk *Block) { blk.DataHash = cmtrand.Bytes(len(blk.DataHash)) @@ -115,7 +111,7 @@ func TestBlockHash(t *testing.T) { func TestBlockMakePartSet(t *testing.T) { bps, err := (*Block)(nil).MakePartSet(2) - assert.Error(t, err) + require.Error(t, err) assert.Nil(t, bps) partSet, err := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).MakePartSet(1024) @@ -126,17 +122,17 @@ func TestBlockMakePartSet(t *testing.T) { func TestBlockMakePartSetWithEvidence(t *testing.T) { bps, err := (*Block)(nil).MakePartSet(2) - assert.Error(t, err) + require.Error(t, err) assert.Nil(t, bps) lastID := makeBlockIDRandom() h := int64(3) - voteSet, _, vals := randVoteSet(h-1, 1, cmtproto.PrecommitType, 10, 1, false) - extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, time.Now(), false) + voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1, false) + extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, cmttime.Now(), false) require.NoError(t, err) - ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, cmttime.Now(), vals[0], "block-test-chain") require.NoError(t, err) evList := []Evidence{ev} @@ -152,11 +148,11 @@ func TestBlockHashesTo(t *testing.T) { lastID := makeBlockIDRandom() h := int64(3) - voteSet, valSet, vals := randVoteSet(h-1, 1, cmtproto.PrecommitType, 10, 1, false) - extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, time.Now(), false) + voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1, false) + extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, cmttime.Now(), false) require.NoError(t, err) - ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, time.Now(), vals[0], "block-test-chain") + ev, err := NewMockDuplicateVoteEvidenceWithValidator(h, cmttime.Now(), vals[0], "block-test-chain") require.NoError(t, err) evList := []Evidence{ev} @@ -213,10 +209,12 @@ func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) BlockID { var nilBytes []byte -// This follows RFC-6962, i.e. `echo -n ” | sha256sum` -var emptyBytes = []byte{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, +// This follows RFC-6962, i.e. `echo -n ” | sha256sum`. +var emptyBytes = []byte{ + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, - 0x78, 0x52, 0xb8, 0x55} + 0x78, 0x52, 0xb8, 0x55, +} func TestNilHeaderHashDoesntCrash(t *testing.T) { assert.Equal(t, nilBytes, []byte((*Header)(nil).Hash())) @@ -231,13 +229,13 @@ func TestNilDataHashDoesntCrash(t *testing.T) { func TestCommit(t *testing.T) { lastID := makeBlockIDRandom() h := int64(3) - voteSet, _, vals := randVoteSet(h-1, 1, cmtproto.PrecommitType, 10, 1, true) - extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, time.Now(), true) + voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1, true) + extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, cmttime.Now(), true) require.NoError(t, err) assert.Equal(t, h-1, extCommit.Height) assert.EqualValues(t, 1, extCommit.Round) - assert.Equal(t, cmtproto.PrecommitType, cmtproto.SignedMsgType(extCommit.Type())) + assert.Equal(t, PrecommitType, SignedMsgType(extCommit.Type())) if extCommit.Size() <= 0 { t.Fatalf("commit %v has a zero or negative size: %d", extCommit, extCommit.Size()) } @@ -255,7 +253,7 @@ func TestCommitValidateBasic(t *testing.T) { malleateCommit func(*Commit) expectErr bool }{ - {"Random Commit", func(com *Commit) {}, false}, + {"Random Commit", func(_ *Commit) {}, false}, {"Incorrect signature", func(com *Commit) { com.Signatures[0].Signature = []byte{0} }, false}, {"Incorrect height", func(com *Commit) { com.Height = int64(-100) }, true}, {"Incorrect round", func(com *Commit) { com.Round = -100 }, true}, @@ -263,7 +261,7 @@ func TestCommitValidateBasic(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { - com := randCommit(time.Now()) + com := randCommit(cmttime.Now()) tc.malleateCommit(com) assert.Equal(t, tc.expectErr, com.ValidateBasic() != nil, "Validate Basic had an unexpected result") }) @@ -312,7 +310,6 @@ func TestMaxCommitBytes(t *testing.T) { pb = commit.ToProto() assert.EqualValues(t, MaxCommitBytes(MaxVotesCount), int64(pb.Size())) - } func TestHeaderHash(t *testing.T) { @@ -439,7 +436,7 @@ func TestMaxHeaderBytes(t *testing.T) { func randCommit(now time.Time) *Commit { lastID := makeBlockIDRandom() h := int64(3) - voteSet, _, vals := randVoteSet(h-1, 1, cmtproto.PrecommitType, 10, 1, false) + voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1, false) extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, now, false) if err != nil { panic(err) @@ -466,10 +463,9 @@ func TestBlockMaxDataBytes(t *testing.T) { 0: {-10, 1, 0, true, 0}, 1: {10, 1, 0, true, 0}, 2: {841, 1, 0, true, 0}, - 3: {842, 1, 0, false, 0}, - 4: {843, 1, 0, false, 1}, - 5: {954, 2, 0, false, 1}, - 6: {1053, 2, 100, false, 0}, + 3: {875, 1, 0, false, 0}, + 4: {876, 1, 0, false, 1}, + 5: {1019, 2, 0, false, 0}, } for i, tc := range testCases { @@ -497,8 +493,8 @@ func TestBlockMaxDataBytesNoEvidence(t *testing.T) { 0: {-10, 1, true, 0}, 1: {10, 1, true, 0}, 2: {841, 1, true, 0}, - 3: {842, 1, false, 0}, - 4: {843, 1, false, 1}, + 3: {875, 1, false, 0}, + 4: {876, 1, false, 1}, } for i, tc := range testCases { @@ -534,16 +530,15 @@ func TestVoteSetToExtendedCommit(t *testing.T) { includeExtension: true, }, } { - t.Run(testCase.name, func(t *testing.T) { blockID := makeBlockIDRandom() valSet, vals := RandValidatorSet(10, 1) var voteSet *VoteSet if testCase.includeExtension { - voteSet = NewExtendedVoteSet("test_chain_id", 3, 1, cmtproto.PrecommitType, valSet) + voteSet = NewExtendedVoteSet("test_chain_id", 3, 1, PrecommitType, valSet) } else { - voteSet = NewVoteSet("test_chain_id", 3, 1, cmtproto.PrecommitType, valSet) + voteSet = NewVoteSet("test_chain_id", 3, 1, PrecommitType, valSet) } for i := 0; i < len(vals); i++ { pubKey, err := vals[i].GetPubKey() @@ -553,12 +548,12 @@ func TestVoteSetToExtendedCommit(t *testing.T) { ValidatorIndex: int32(i), Height: 3, Round: 1, - Type: cmtproto.PrecommitType, + Type: PrecommitType, BlockID: blockID, - Timestamp: time.Now(), + Timestamp: cmttime.Now(), } v := vote.ToProto() - err = vals[i].SignVote(voteSet.ChainID(), v) + err = vals[i].SignVote(voteSet.ChainID(), v, true) require.NoError(t, err) vote.Signature = v.Signature if testCase.includeExtension { @@ -568,11 +563,11 @@ func TestVoteSetToExtendedCommit(t *testing.T) { require.NoError(t, err) require.True(t, added) } - var veHeight int64 + p := DefaultFeatureParams() if testCase.includeExtension { - veHeight = 1 + p.VoteExtensionsEnableHeight = 1 } - ec := voteSet.MakeExtendedCommit(ABCIParams{VoteExtensionsEnableHeight: veHeight}) + ec := voteSet.MakeExtendedCommit(p) for i := int32(0); int(i) < len(vals); i++ { vote1 := voteSet.GetByIndex(i) @@ -592,7 +587,7 @@ func TestVoteSetToExtendedCommit(t *testing.T) { // Panics if signatures from the ExtendedCommit can't be added to the voteset. // Inverse of VoteSet.MakeExtendedCommit(). func toVoteSet(ec *ExtendedCommit, chainID string, vals *ValidatorSet) *VoteSet { - voteSet := NewVoteSet(chainID, ec.Height, ec.Round, cmtproto.PrecommitType, vals) + voteSet := NewVoteSet(chainID, ec.Height, ec.Round, PrecommitType, vals) ec.addSigsToVoteSet(voteSet) return voteSet } @@ -619,9 +614,9 @@ func TestExtendedCommitToVoteSet(t *testing.T) { lastID := makeBlockIDRandom() h := int64(3) - voteSet, valSet, vals := randVoteSet(h-1, 1, cmtproto.PrecommitType, 10, 1, true) - extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, time.Now(), true) - assert.NoError(t, err) + voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1, true) + extCommit, err := MakeExtCommit(lastID, h-1, 1, voteSet, vals, cmttime.Now(), true) + require.NoError(t, err) if !testCase.includeExtension { for i := 0; i < len(vals); i++ { @@ -679,7 +674,7 @@ func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) { } for _, tc := range testCases { - voteSet, valSet, vals := randVoteSet(height-1, round, cmtproto.PrecommitType, tc.numValidators, 1, false) + voteSet, valSet, vals := randVoteSet(height-1, round, PrecommitType, tc.numValidators, 1, false) vi := int32(0) for n := range tc.blockIDs { @@ -691,25 +686,26 @@ func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) { ValidatorIndex: vi, Height: height - 1, Round: round, - Type: cmtproto.PrecommitType, + Type: PrecommitType, BlockID: tc.blockIDs[n], Timestamp: cmttime.Now(), } added, err := signAddVote(vals[vi], vote, voteSet) - assert.NoError(t, err) + require.NoError(t, err) assert.True(t, added) vi++ } } - veHeightParam := ABCIParams{VoteExtensionsEnableHeight: 0} + veHeightParam := DefaultFeatureParams() + veHeightParam.VoteExtensionsEnableHeight = 0 if tc.valid { extCommit := voteSet.MakeExtendedCommit(veHeightParam) // panics without > 2/3 valid votes assert.NotNil(t, extCommit) err := valSet.VerifyCommit(voteSet.ChainID(), blockID, height-1, extCommit.ToCommit()) - assert.Nil(t, err) + require.NoError(t, err) } else { assert.Panics(t, func() { voteSet.MakeExtendedCommit(veHeightParam) }) } @@ -758,7 +754,7 @@ func TestBlockIDValidateBasic(t *testing.T) { func TestBlockProtoBuf(t *testing.T) { h := cmtrand.Int63() - c1 := randCommit(time.Now()) + c1 := randCommit(cmttime.Now()) b1 := MakeBlock(h, []Tx{Tx([]byte{1})}, &Commit{Signatures: []CommitSig{}}, []Evidence{}) b1.ProposerAddress = cmtrand.Bytes(crypto.AddressSize) @@ -830,7 +826,7 @@ func TestDataProtoBuf(t *testing.T) { // TestEvidenceDataProtoBuf ensures parity in converting to and from proto. func TestEvidenceDataProtoBuf(t *testing.T) { const chainID = "mychain" - ev, err := NewMockDuplicateVoteEvidence(math.MaxInt64, time.Now(), chainID) + ev, err := NewMockDuplicateVoteEvidence(math.MaxInt64, cmttime.Now(), chainID) require.NoError(t, err) data := &EvidenceData{Evidence: EvidenceList{ev}} _ = data.ByteSize() @@ -866,7 +862,7 @@ func TestEvidenceDataProtoBuf(t *testing.T) { func makeRandHeader() Header { chainID := "test" - t := time.Now() + t := cmttime.Now() height := cmtrand.Int63() randBytes := cmtrand.Bytes(tmhash.Size) randAddress := cmtrand.Bytes(crypto.AddressSize) @@ -914,7 +910,6 @@ func TestHeaderProto(t *testing.T) { } else { require.Error(t, err, tt.msg) } - }) } } @@ -944,7 +939,7 @@ func TestBlockIDProtoBuf(t *testing.T) { } func TestSignedHeaderProtoBuf(t *testing.T) { - commit := randCommit(time.Now()) + commit := randCommit(cmttime.Now()) h := makeRandHeader() sh := SignedHeader{Header: &h, Commit: commit} diff --git a/types/canonical.go b/types/canonical.go index 64f4bac2b04..d98608cfa17 100644 --- a/types/canonical.go +++ b/types/canonical.go @@ -3,16 +3,16 @@ package types import ( "time" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" cmttime "github.com/cometbft/cometbft/types/time" ) // Canonical* wraps the structs in types for amino encoding them for use in SignBytes / the Signable interface. -// TimeFormat is used for generating the sigs +// TimeFormat is used for generating the sigs. const TimeFormat = time.RFC3339Nano -//----------------------------------- +// ----------------------------------- // Canonicalize the structs func CanonicalizeBlockID(bid cmtproto.BlockID) *cmtproto.CanonicalBlockID { @@ -21,7 +21,7 @@ func CanonicalizeBlockID(bid cmtproto.BlockID) *cmtproto.CanonicalBlockID { panic(err) } var cbid *cmtproto.CanonicalBlockID - if rbid == nil || rbid.IsZero() { + if rbid == nil || rbid.IsNil() { cbid = nil } else { cbid = &cmtproto.CanonicalBlockID{ @@ -33,18 +33,18 @@ func CanonicalizeBlockID(bid cmtproto.BlockID) *cmtproto.CanonicalBlockID { return cbid } -// CanonicalizeVote transforms the given PartSetHeader to a CanonicalPartSetHeader. +// CanonicalizePartSetHeader transforms the given PartSetHeader to a CanonicalPartSetHeader. func CanonicalizePartSetHeader(psh cmtproto.PartSetHeader) cmtproto.CanonicalPartSetHeader { return cmtproto.CanonicalPartSetHeader(psh) } -// CanonicalizeVote transforms the given Proposal to a CanonicalProposal. +// CanonicalizeProposal transforms the given Proposal to a CanonicalProposal. func CanonicalizeProposal(chainID string, proposal *cmtproto.Proposal) cmtproto.CanonicalProposal { return cmtproto.CanonicalProposal{ - Type: cmtproto.ProposalType, - Height: proposal.Height, // encoded as sfixed64 - Round: int64(proposal.Round), // encoded as sfixed64 - POLRound: int64(proposal.PolRound), + Type: ProposalType, + Height: proposal.Height, // encoded as sfixed64 + Round: int64(proposal.Round), // encoded as sfixed64 + POLRound: int64(proposal.PolRound), // FIXME: not matching BlockID: CanonicalizeBlockID(proposal.BlockID), Timestamp: proposal.Timestamp, ChainID: chainID, diff --git a/types/canonical_test.go b/types/canonical_test.go index 1dc439f5856..8ca3094d47e 100644 --- a/types/canonical_test.go +++ b/types/canonical_test.go @@ -4,21 +4,29 @@ import ( "reflect" "testing" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto/tmhash" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) func TestCanonicalizeBlockID(t *testing.T) { randhash := cmtrand.Bytes(tmhash.Size) - block1 := cmtproto.BlockID{Hash: randhash, - PartSetHeader: cmtproto.PartSetHeader{Total: 5, Hash: randhash}} - block2 := cmtproto.BlockID{Hash: randhash, - PartSetHeader: cmtproto.PartSetHeader{Total: 10, Hash: randhash}} - cblock1 := cmtproto.CanonicalBlockID{Hash: randhash, - PartSetHeader: cmtproto.CanonicalPartSetHeader{Total: 5, Hash: randhash}} - cblock2 := cmtproto.CanonicalBlockID{Hash: randhash, - PartSetHeader: cmtproto.CanonicalPartSetHeader{Total: 10, Hash: randhash}} + block1 := cmtproto.BlockID{ + Hash: randhash, + PartSetHeader: cmtproto.PartSetHeader{Total: 5, Hash: randhash}, + } + block2 := cmtproto.BlockID{ + Hash: randhash, + PartSetHeader: cmtproto.PartSetHeader{Total: 10, Hash: randhash}, + } + cblock1 := cmtproto.CanonicalBlockID{ + Hash: randhash, + PartSetHeader: cmtproto.CanonicalPartSetHeader{Total: 5, Hash: randhash}, + } + cblock2 := cmtproto.CanonicalBlockID{ + Hash: randhash, + PartSetHeader: cmtproto.CanonicalPartSetHeader{Total: 10, Hash: randhash}, + } tests := []struct { name string diff --git a/types/encoding_helper.go b/types/encoding_helper.go index 3590ac9a252..85366d952b4 100644 --- a/types/encoding_helper.go +++ b/types/encoding_helper.go @@ -7,8 +7,8 @@ import ( ) // cdcEncode returns nil if the input is nil, otherwise returns -// proto.Marshal(Value{Value: item}) -func cdcEncode(item interface{}) []byte { +// proto.Marshal(Value{Value: item}). +func cdcEncode(item any) []byte { if item != nil && !isTypedNil(item) && !isEmpty(item) { switch item := item.(type) { case string: diff --git a/types/errors.go b/types/errors/errors.go similarity index 98% rename from types/errors.go rename to types/errors/errors.go index d828f638759..6192cb21a10 100644 --- a/types/errors.go +++ b/types/errors/errors.go @@ -1,4 +1,4 @@ -package types +package errors import "fmt" diff --git a/types/errors/proto.go b/types/errors/proto.go new file mode 100644 index 00000000000..8c707dc3c38 --- /dev/null +++ b/types/errors/proto.go @@ -0,0 +1,31 @@ +package errors + +import ( + "fmt" +) + +type ErrMsgToProto struct { + MessageName string + Err error +} + +func (e ErrMsgToProto) Error() string { + return fmt.Sprintf("%s to proto error: %s", e.MessageName, e.Err.Error()) +} + +func (e ErrMsgToProto) Unwrap() error { + return e.Err +} + +type ErrMsgFromProto struct { + MessageName string + Err error +} + +func (e ErrMsgFromProto) Error() string { + return fmt.Sprintf("%s msg from proto error: %s", e.MessageName, e.Err.Error()) +} + +func (e ErrMsgFromProto) Unwrap() error { + return e.Err +} diff --git a/types/errors/sanity.go b/types/errors/sanity.go new file mode 100644 index 00000000000..bec8afba93b --- /dev/null +++ b/types/errors/sanity.go @@ -0,0 +1,43 @@ +package errors + +import "fmt" + +type ( + // ErrNegativeField is returned every time some field which should be non-negative turns out negative. + ErrNegativeField struct { + Field string + } + + // ErrRequiredField is returned every time a required field is not provided. + ErrRequiredField struct { + Field string + } + + // ErrInvalidField is returned every time a value does not pass a validity check. + ErrInvalidField struct { + Field string + Reason string + } + + // ErrWrongField is returned every time a value does not pass a validaty check, accompanied with error. + ErrWrongField struct { + Field string + Err error + } +) + +func (e ErrNegativeField) Error() string { + return e.Field + " can't be negative" +} + +func (e ErrRequiredField) Error() string { + return e.Field + " is required" +} + +func (e ErrInvalidField) Error() string { + return fmt.Sprintf("invalid field %s %s", e.Field, e.Reason) +} + +func (e ErrWrongField) Error() string { + return fmt.Sprintf("wrong %s: %v", e.Field, e.Err) +} diff --git a/types/event_bus.go b/types/event_bus.go index 8ed23ab8005..12c2000f7f8 100644 --- a/types/event_bus.go +++ b/types/event_bus.go @@ -3,11 +3,12 @@ package types import ( "context" "fmt" + "strconv" "github.com/cometbft/cometbft/abci/types" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + "github.com/cometbft/cometbft/internal/service" "github.com/cometbft/cometbft/libs/log" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - "github.com/cometbft/cometbft/libs/service" ) const defaultCapacity = 0 @@ -81,8 +82,8 @@ func (b *EventBus) Subscribe( return b.pubsub.Subscribe(ctx, subscriber, query, outCapacity...) } -// This method can be used for a local consensus explorer and synchronous -// testing. Do not use for for public facing / untrusted subscriptions! +// SubscribeUnbuffered can be used for a local consensus explorer and synchronous +// testing. Do not use for public facing / untrusted subscriptions! func (b *EventBus) SubscribeUnbuffered( ctx context.Context, subscriber string, @@ -109,7 +110,7 @@ func (b *EventBus) Publish(eventType string, eventData TMEventData) error { // map of stringified events where each key is composed of the event // type and each of the event's attributes keys in the form of // "{event.Type}.{attribute.Key}" and the value is each attribute's value. -func (b *EventBus) validateAndStringifyEvents(events []types.Event, logger log.Logger) map[string][]string { +func (*EventBus) validateAndStringifyEvents(events []types.Event, logger log.Logger) map[string][]string { result := make(map[string][]string) for _, event := range events { if len(event.Type) == 0 { @@ -183,7 +184,7 @@ func (b *EventBus) PublishEventTx(data EventDataTx) error { // add predefined compositeKeys events[EventTypeKey] = append(events[EventTypeKey], EventTx) events[TxHashKey] = append(events[TxHashKey], fmt.Sprintf("%X", Tx(data.Tx).Hash())) - events[TxHeightKey] = append(events[TxHeightKey], fmt.Sprintf("%d", data.Height)) + events[TxHeightKey] = append(events[TxHeightKey], strconv.FormatInt(data.Height, 10)) return b.pubsub.PublishWithEvents(ctx, data, events) } @@ -212,10 +213,6 @@ func (b *EventBus) PublishEventPolka(data EventDataRoundState) error { return b.Publish(EventPolka, data) } -func (b *EventBus) PublishEventUnlock(data EventDataRoundState) error { - return b.Publish(EventUnlock, data) -} - func (b *EventBus) PublishEventRelock(data EventDataRoundState) error { return b.Publish(EventRelock, data) } @@ -228,86 +225,82 @@ func (b *EventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpd return b.Publish(EventValidatorSetUpdates, data) } -// ----------------------------------------------------------------------------- +// -----------------------------------------------------------------------------. type NopEventBus struct{} func (NopEventBus) Subscribe( - ctx context.Context, - subscriber string, - query cmtpubsub.Query, - out chan<- interface{}, + context.Context, + string, + cmtpubsub.Query, + chan<- any, ) error { return nil } -func (NopEventBus) Unsubscribe(ctx context.Context, subscriber string, query cmtpubsub.Query) error { - return nil -} - -func (NopEventBus) UnsubscribeAll(ctx context.Context, subscriber string) error { +func (NopEventBus) Unsubscribe(context.Context, string, cmtpubsub.Query) error { return nil } -func (NopEventBus) PublishEventNewBlock(data EventDataNewBlock) error { +func (NopEventBus) UnsubscribeAll(context.Context, string) error { return nil } -func (NopEventBus) PublishEventNewBlockHeader(data EventDataNewBlockHeader) error { +func (NopEventBus) PublishEventNewBlock(EventDataNewBlock) error { return nil } -func (NopEventBus) PublishEventNewBlockEvents(data EventDataNewBlockEvents) error { +func (NopEventBus) PublishEventNewBlockHeader(EventDataNewBlockHeader) error { return nil } -func (NopEventBus) PublishEventNewEvidence(evidence EventDataNewEvidence) error { +func (NopEventBus) PublishEventNewBlockEvents(EventDataNewBlockEvents) error { return nil } -func (NopEventBus) PublishEventVote(data EventDataVote) error { +func (NopEventBus) PublishEventNewEvidence(EventDataNewEvidence) error { return nil } -func (NopEventBus) PublishEventTx(data EventDataTx) error { +func (NopEventBus) PublishEventVote(EventDataVote) error { return nil } -func (NopEventBus) PublishEventNewRoundStep(data EventDataRoundState) error { +func (NopEventBus) PublishEventTx(EventDataTx) error { return nil } -func (NopEventBus) PublishEventTimeoutPropose(data EventDataRoundState) error { +func (NopEventBus) PublishEventNewRoundStep(EventDataRoundState) error { return nil } -func (NopEventBus) PublishEventTimeoutWait(data EventDataRoundState) error { +func (NopEventBus) PublishEventTimeoutPropose(EventDataRoundState) error { return nil } -func (NopEventBus) PublishEventNewRound(data EventDataRoundState) error { +func (NopEventBus) PublishEventTimeoutWait(EventDataRoundState) error { return nil } -func (NopEventBus) PublishEventCompleteProposal(data EventDataRoundState) error { +func (NopEventBus) PublishEventNewRound(EventDataRoundState) error { return nil } -func (NopEventBus) PublishEventPolka(data EventDataRoundState) error { +func (NopEventBus) PublishEventCompleteProposal(EventDataRoundState) error { return nil } -func (NopEventBus) PublishEventUnlock(data EventDataRoundState) error { +func (NopEventBus) PublishEventPolka(EventDataRoundState) error { return nil } -func (NopEventBus) PublishEventRelock(data EventDataRoundState) error { +func (NopEventBus) PublishEventRelock(EventDataRoundState) error { return nil } -func (NopEventBus) PublishEventLock(data EventDataRoundState) error { +func (NopEventBus) PublishEventLock(EventDataRoundState) error { return nil } -func (NopEventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpdates) error { +func (NopEventBus) PublishEventValidatorSetUpdates(EventDataValidatorSetUpdates) error { return nil } diff --git a/types/event_bus_test.go b/types/event_bus_test.go index 3058a80d402..d1a84252f99 100644 --- a/types/event_bus_test.go +++ b/types/event_bus_test.go @@ -11,8 +11,9 @@ import ( "github.com/stretchr/testify/require" abci "github.com/cometbft/cometbft/abci/types" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - cmtquery "github.com/cometbft/cometbft/libs/pubsub/query" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + cmtquery "github.com/cometbft/cometbft/internal/pubsub/query" + cmttime "github.com/cometbft/cometbft/types/time" ) func TestEventBusPublishEventTx(t *testing.T) { @@ -55,7 +56,7 @@ func TestEventBusPublishEventTx(t *testing.T) { Tx: tx, Result: result, }}) - assert.NoError(t, err) + require.NoError(t, err) select { case <-done: @@ -75,7 +76,7 @@ func TestEventBusPublishEventNewBlock(t *testing.T) { }) block := MakeBlock(0, []Tx{}, nil, []Evidence{}) - resultFinalizeBlock := abci.ResponseFinalizeBlock{ + resultFinalizeBlock := abci.FinalizeBlockResponse{ Events: []abci.Event{ {Type: "testType", Attributes: []abci.EventAttribute{{Key: "baz", Value: "1"}}}, }, @@ -96,7 +97,7 @@ func TestEventBusPublishEventNewBlock(t *testing.T) { }() var ps *PartSet - ps, err = block.MakePartSet(MaxBlockSizeBytes) + ps, err = block.MakePartSet(BlockPartSizeBytes) require.NoError(t, err) err = eventBus.PublishEventNewBlock(EventDataNewBlock{ @@ -107,7 +108,7 @@ func TestEventBusPublishEventNewBlock(t *testing.T) { }, ResultFinalizeBlock: resultFinalizeBlock, }) - assert.NoError(t, err) + require.NoError(t, err) select { case <-done: @@ -209,7 +210,7 @@ func TestEventBusPublishEventTxDuplicateKeys(t *testing.T) { Tx: tx, Result: result, }}) - assert.NoError(t, err) + require.NoError(t, err) select { case <-done: @@ -251,7 +252,7 @@ func TestEventBusPublishEventNewBlockHeader(t *testing.T) { err = eventBus.PublishEventNewBlockHeader(EventDataNewBlockHeader{ Header: block.Header, }) - assert.NoError(t, err) + require.NoError(t, err) select { case <-done: @@ -293,7 +294,7 @@ func TestEventBusPublishEventNewBlockEvents(t *testing.T) { }}, }}, }) - assert.NoError(t, err) + require.NoError(t, err) select { case <-done: @@ -312,7 +313,7 @@ func TestEventBusPublishEventNewEvidence(t *testing.T) { } }) - ev, err := NewMockDuplicateVoteEvidence(1, time.Now(), "test-chain-id") + ev, err := NewMockDuplicateVoteEvidence(1, cmttime.Now(), "test-chain-id") require.NoError(t, err) query := "tm.event='NewEvidence'" @@ -332,7 +333,7 @@ func TestEventBusPublishEventNewEvidence(t *testing.T) { Evidence: ev, Height: 4, }) - assert.NoError(t, err) + require.NoError(t, err) select { case <-done: @@ -351,7 +352,7 @@ func TestEventBusPublish(t *testing.T) { } }) - const numEventsExpected = 15 + const numEventsExpected = 14 sub, err := eventBus.Subscribe(context.Background(), "test", cmtquery.All, numEventsExpected) require.NoError(t, err) @@ -390,8 +391,6 @@ func TestEventBusPublish(t *testing.T) { require.NoError(t, err) err = eventBus.PublishEventPolka(EventDataRoundState{}) require.NoError(t, err) - err = eventBus.PublishEventUnlock(EventDataRoundState{}) - require.NoError(t, err) err = eventBus.PublishEventRelock(EventDataRoundState{}) require.NoError(t, err) err = eventBus.PublishEventLock(EventDataRoundState{}) @@ -433,14 +432,15 @@ func BenchmarkEventBus(b *testing.B) { for _, bm := range benchmarks { bm := bm b.Run(bm.name, func(b *testing.B) { - benchmarkEventBus(bm.numClients, bm.randQueries, bm.randEvents, b) + benchmarkEventBus(b, bm.numClients, bm.randQueries, bm.randEvents) }) } } -func benchmarkEventBus(numClients int, randQueries bool, randEvents bool, b *testing.B) { +func benchmarkEventBus(b *testing.B, numClients int, randQueries bool, randEvents bool) { + b.Helper() // for random* functions - rnd := rand.New(rand.NewSource(time.Now().Unix())) + rnd := rand.New(rand.NewSource(cmttime.Now().Unix())) eventBus := NewEventBusWithBufferCapacity(0) // set buffer capacity to 0 so we are not testing cache err := eventBus.Start() @@ -500,7 +500,6 @@ var events = []string{ EventTimeoutPropose, EventCompleteProposal, EventPolka, - EventUnlock, EventLock, EventRelock, EventTimeoutWait, @@ -520,7 +519,6 @@ var queries = []cmtpubsub.Query{ EventQueryTimeoutPropose, EventQueryCompleteProposal, EventQueryPolka, - EventQueryUnlock, EventQueryLock, EventQueryRelock, EventQueryTimeoutWait, diff --git a/types/events.go b/types/events.go index 3dbf9a78db6..5591145959d 100644 --- a/types/events.go +++ b/types/events.go @@ -4,9 +4,9 @@ import ( "fmt" abci "github.com/cometbft/cometbft/abci/types" + cmtpubsub "github.com/cometbft/cometbft/internal/pubsub" + cmtquery "github.com/cometbft/cometbft/internal/pubsub/query" cmtjson "github.com/cometbft/cometbft/libs/json" - cmtpubsub "github.com/cometbft/cometbft/libs/pubsub" - cmtquery "github.com/cometbft/cometbft/libs/pubsub/query" ) // Reserved event types (alphabetically sorted). @@ -26,23 +26,23 @@ const ( // Internal consensus events. // These are used for testing the consensus state machine. // They can also be used to build real-time consensus visualizers. - EventCompleteProposal = "CompleteProposal" - EventLock = "Lock" - EventNewRound = "NewRound" - EventNewRoundStep = "NewRoundStep" - EventPolka = "Polka" - EventRelock = "Relock" - EventTimeoutPropose = "TimeoutPropose" - EventTimeoutWait = "TimeoutWait" - EventUnlock = "Unlock" - EventValidBlock = "ValidBlock" - EventVote = "Vote" + EventCompleteProposal = "CompleteProposal" + EventLock = "Lock" + EventNewRound = "NewRound" + EventNewRoundStep = "NewRoundStep" + EventPolka = "Polka" + EventRelock = "Relock" + EventTimeoutPropose = "TimeoutPropose" + EventTimeoutWait = "TimeoutWait" + EventValidBlock = "ValidBlock" + EventVote = "Vote" + EventProposalBlockPart = "ProposalBlockPart" ) // ENCODING / DECODING // TMEventData implements events.EventData. -type TMEventData interface { +type TMEventData interface { //nolint:revive // this empty interface angers the linter // empty interface } @@ -66,7 +66,7 @@ func init() { type EventDataNewBlock struct { Block *Block `json:"block"` BlockID BlockID `json:"block_id"` - ResultFinalizeBlock abci.ResponseFinalizeBlock `json:"result_finalize_block"` + ResultFinalizeBlock abci.FinalizeBlockResponse `json:"result_finalize_block"` } type EventDataNewBlockHeader struct { @@ -84,12 +84,12 @@ type EventDataNewEvidence struct { Evidence Evidence `json:"evidence"` } -// All txs fire EventDataTx +// All txs fire EventDataTx. type EventDataTx struct { abci.TxResult } -// NOTE: This goes into the replay WAL +// NOTE: This goes into the replay WAL. type EventDataRoundState struct { Height int64 `json:"height"` Round int32 `json:"round"` @@ -134,11 +134,11 @@ const ( EventTypeKey = "tm.event" // TxHashKey is a reserved key, used to specify transaction's hash. - // see EventBus#PublishEventTx + // see EventBus#PublishEventTx. TxHashKey = "tx.hash" // TxHeightKey is a reserved key, used to specify transaction block's height. - // see EventBus#PublishEventTx + // see EventBus#PublishEventTx. TxHeightKey = "tx.height" // BlockHeightKey is a reserved key used for indexing FinalizeBlock events. @@ -159,7 +159,6 @@ var ( EventQueryTimeoutPropose = QueryForEvent(EventTimeoutPropose) EventQueryTimeoutWait = QueryForEvent(EventTimeoutWait) EventQueryTx = QueryForEvent(EventTx) - EventQueryUnlock = QueryForEvent(EventUnlock) EventQueryValidatorSetUpdates = QueryForEvent(EventValidatorSetUpdates) EventQueryValidBlock = QueryForEvent(EventValidBlock) EventQueryVote = QueryForEvent(EventVote) @@ -173,16 +172,16 @@ func QueryForEvent(eventType string) cmtpubsub.Query { return cmtquery.MustCompile(fmt.Sprintf("%s='%s'", EventTypeKey, eventType)) } -// BlockEventPublisher publishes all block related events +// BlockEventPublisher publishes all block related events. type BlockEventPublisher interface { PublishEventNewBlock(block EventDataNewBlock) error PublishEventNewBlockHeader(header EventDataNewBlockHeader) error PublishEventNewBlockEvents(events EventDataNewBlockEvents) error PublishEventNewEvidence(evidence EventDataNewEvidence) error - PublishEventTx(EventDataTx) error - PublishEventValidatorSetUpdates(EventDataValidatorSetUpdates) error + PublishEventTx(tx EventDataTx) error + PublishEventValidatorSetUpdates(updates EventDataValidatorSetUpdates) error } type TxEventPublisher interface { - PublishEventTx(EventDataTx) error + PublishEventTx(tx EventDataTx) error } diff --git a/types/evidence.go b/types/evidence.go index c849b3ecbe3..bcd0e477fec 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -10,11 +10,12 @@ import ( "time" abci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto/merkle" "github.com/cometbft/cometbft/crypto/tmhash" + cmtrand "github.com/cometbft/cometbft/internal/rand" cmtjson "github.com/cometbft/cometbft/libs/json" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmterrors "github.com/cometbft/cometbft/types/errors" ) // Evidence represents any provable malicious activity by a validator. @@ -29,7 +30,7 @@ type Evidence interface { ValidateBasic() error // basic consistency check } -//-------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- // DuplicateVoteEvidence contains evidence of a single validator signing two conflicting votes. type DuplicateVoteEvidence struct { @@ -46,7 +47,7 @@ var _ Evidence = &DuplicateVoteEvidence{} // NewDuplicateVoteEvidence creates DuplicateVoteEvidence with right ordering given // two conflicting votes. If either of the votes is nil, the val set is nil or the voter is -// not in the val set, an error is returned +// not in the val set, an error is returned. func NewDuplicateVoteEvidence(vote1, vote2 *Vote, blockTime time.Time, valSet *ValidatorSet, ) (*DuplicateVoteEvidence, error) { var voteA, voteB *Vote @@ -77,10 +78,10 @@ func NewDuplicateVoteEvidence(vote1, vote2 *Vote, blockTime time.Time, valSet *V }, nil } -// ABCI returns the application relevant representation of the evidence +// ABCI returns the application relevant representation of the evidence. func (dve *DuplicateVoteEvidence) ABCI() []abci.Misbehavior { return []abci.Misbehavior{{ - Type: abci.MisbehaviorType_DUPLICATE_VOTE, + Type: abci.MISBEHAVIOR_TYPE_DUPLICATE_VOTE, Validator: abci.Validator{ Address: dve.VoteA.ValidatorAddress, Power: dve.ValidatorPower, @@ -107,7 +108,7 @@ func (dve *DuplicateVoteEvidence) Hash() []byte { return tmhash.Sum(dve.Bytes()) } -// Height returns the height of the infraction +// Height returns the height of the infraction. func (dve *DuplicateVoteEvidence) Height() int64 { return dve.VoteA.Height } @@ -117,7 +118,7 @@ func (dve *DuplicateVoteEvidence) String() string { return fmt.Sprintf("DuplicateVoteEvidence{VoteA: %v, VoteB: %v}", dve.VoteA, dve.VoteB) } -// Time returns the time of the infraction +// Time returns the time of the infraction. func (dve *DuplicateVoteEvidence) Time() time.Time { return dve.Timestamp } @@ -125,7 +126,7 @@ func (dve *DuplicateVoteEvidence) Time() time.Time { // ValidateBasic performs basic validation. func (dve *DuplicateVoteEvidence) ValidateBasic() error { if dve == nil { - return errors.New("empty duplicate vote evidence") + return cmterrors.ErrRequiredField{Field: "duplicate_vote_evidence"} } if dve.VoteA == nil || dve.VoteB == nil { @@ -144,7 +145,7 @@ func (dve *DuplicateVoteEvidence) ValidateBasic() error { return nil } -// ToProto encodes DuplicateVoteEvidence to protobuf +// ToProto encodes DuplicateVoteEvidence to protobuf. func (dve *DuplicateVoteEvidence) ToProto() *cmtproto.DuplicateVoteEvidence { voteB := dve.VoteB.ToProto() voteA := dve.VoteA.ToProto() @@ -158,7 +159,7 @@ func (dve *DuplicateVoteEvidence) ToProto() *cmtproto.DuplicateVoteEvidence { return &tp } -// DuplicateVoteEvidenceFromProto decodes protobuf into DuplicateVoteEvidence +// DuplicateVoteEvidenceFromProto decodes protobuf into DuplicateVoteEvidence. func DuplicateVoteEvidenceFromProto(pb *cmtproto.DuplicateVoteEvidence) (*DuplicateVoteEvidence, error) { if pb == nil { return nil, errors.New("nil duplicate vote evidence") @@ -199,13 +200,13 @@ func DuplicateVoteEvidenceFromProto(pb *cmtproto.DuplicateVoteEvidence) (*Duplic return dve, dve.ValidateBasic() } -//------------------------------------ LIGHT EVIDENCE -------------------------------------- +// ------------------------------------ LIGHT EVIDENCE -------------------------------------- // LightClientAttackEvidence is a generalized evidence that captures all forms of known attacks on // a light client such that a full node can verify, propose and commit the evidence on-chain for // punishment of the malicious validators. There are three forms of attacks: Lunatic, Equivocation // and Amnesia. These attacks are exhaustive. You can find a more detailed overview of this at -// cometbft/docs/architecture/adr-047-handling-evidence-from-light-client.md +// cometbft/docs/architecture/tendermint-core/adr-047-handling-evidence-from-light-client.md. type LightClientAttackEvidence struct { ConflictingBlock *LightBlock CommonHeight int64 @@ -218,12 +219,12 @@ type LightClientAttackEvidence struct { var _ Evidence = &LightClientAttackEvidence{} -// ABCI forms an array of abci.Misbehavior for each byzantine validator +// ABCI forms an array of abci.Misbehavior for each byzantine validator. func (l *LightClientAttackEvidence) ABCI() []abci.Misbehavior { abciEv := make([]abci.Misbehavior, len(l.ByzantineValidators)) for idx, val := range l.ByzantineValidators { abciEv[idx] = abci.Misbehavior{ - Type: abci.MisbehaviorType_LIGHT_CLIENT_ATTACK, + Type: abci.MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK, Validator: TM2PB.Validator(val), Height: l.Height(), Time: l.Timestamp, @@ -233,7 +234,7 @@ func (l *LightClientAttackEvidence) ABCI() []abci.Misbehavior { return abciEv } -// Bytes returns the proto-encoded evidence as a byte array +// Bytes returns the proto-encoded evidence as a byte array. func (l *LightClientAttackEvidence) Bytes() []byte { pbe, err := l.ToProto() if err != nil { @@ -248,9 +249,10 @@ func (l *LightClientAttackEvidence) Bytes() []byte { // GetByzantineValidators finds out what style of attack LightClientAttackEvidence was and then works out who // the malicious validators were and returns them. This is used both for forming the ByzantineValidators -// field and for validating that it is correct. Validators are ordered based on validator power +// field and for validating that it is correct. Validators are ordered based on validator power. func (l *LightClientAttackEvidence) GetByzantineValidators(commonVals *ValidatorSet, - trusted *SignedHeader) []*Validator { + trusted *SignedHeader, +) []*Validator { var validators []*Validator // First check if the header is invalid. This means that it is a lunatic attack and therefore we take the // validators who are in the commonVals and voted for the lunatic header @@ -297,7 +299,7 @@ func (l *LightClientAttackEvidence) GetByzantineValidators(commonVals *Validator return validators } -// ConflictingHeaderIsInvalid takes a trusted header and matches it againt a conflicting header +// ConflictingHeaderIsInvalid takes a trusted header and matches it against a conflicting header // to determine whether the conflicting header was the product of a valid state transition // or not. If it is then all the deterministic fields of the header should be the same. // If not, it is an invalid header and constitutes a lunatic attack. @@ -307,7 +309,6 @@ func (l *LightClientAttackEvidence) ConflictingHeaderIsInvalid(trustedHeader *He !bytes.Equal(trustedHeader.ConsensusHash, l.ConflictingBlock.ConsensusHash) || !bytes.Equal(trustedHeader.AppHash, l.ConflictingBlock.AppHash) || !bytes.Equal(trustedHeader.LastResultsHash, l.ConflictingBlock.LastResultsHash) - } // Hash returns the hash of the header and the commonHeight. This is designed to cause hash collisions @@ -317,7 +318,7 @@ func (l *LightClientAttackEvidence) ConflictingHeaderIsInvalid(trustedHeader *He // most commit signatures (captures the most byzantine validators) but anything greater than 1/3 is // sufficient. // TODO: We should change the hash to include the commit, header, total voting power, byzantine -// validators and timestamp +// validators and timestamp. func (l *LightClientAttackEvidence) Hash() []byte { buf := make([]byte, binary.MaxVarintLen64) n := binary.PutVarint(buf, l.CommonHeight) @@ -329,18 +330,18 @@ func (l *LightClientAttackEvidence) Hash() []byte { // Height returns the last height at which the primary provider and witness provider had the same header. // We use this as the height of the infraction rather than the actual conflicting header because we know -// that the malicious validators were bonded at this height which is important for evidence expiry +// that the malicious validators were bonded at this height which is important for evidence expiry. func (l *LightClientAttackEvidence) Height() int64 { return l.CommonHeight } -// String returns a string representation of LightClientAttackEvidence +// String returns a string representation of LightClientAttackEvidence. func (l *LightClientAttackEvidence) String() string { return fmt.Sprintf(`LightClientAttackEvidence{ - ConflictingBlock: %v, - CommonHeight: %d, - ByzatineValidators: %v, - TotalVotingPower: %d, + ConflictingBlock: %v, + CommonHeight: %d, + ByzatineValidators: %v, + TotalVotingPower: %d, Timestamp: %v}#%X`, l.ConflictingBlock.String(), l.CommonHeight, l.ByzantineValidators, l.TotalVotingPower, l.Timestamp, l.Hash()) @@ -385,7 +386,7 @@ func (l *LightClientAttackEvidence) ValidateBasic() error { return nil } -// ToProto encodes LightClientAttackEvidence to protobuf +// ToProto encodes LightClientAttackEvidence to protobuf. func (l *LightClientAttackEvidence) ToProto() (*cmtproto.LightClientAttackEvidence, error) { conflictingBlock, err := l.ConflictingBlock.ToProto() if err != nil { @@ -410,10 +411,10 @@ func (l *LightClientAttackEvidence) ToProto() (*cmtproto.LightClientAttackEviden }, nil } -// LightClientAttackEvidenceFromProto decodes protobuf +// LightClientAttackEvidenceFromProto decodes protobuf. func LightClientAttackEvidenceFromProto(lpb *cmtproto.LightClientAttackEvidence) (*LightClientAttackEvidence, error) { if lpb == nil { - return nil, errors.New("empty light client attack evidence") + return nil, cmterrors.ErrRequiredField{Field: "light_client_attack_evidence"} } conflictingBlock, err := LightBlockFromProto(lpb.ConflictingBlock) @@ -441,7 +442,7 @@ func LightClientAttackEvidenceFromProto(lpb *cmtproto.LightClientAttackEvidence) return l, l.ValidateBasic() } -//------------------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------------------ // EvidenceList is a list of Evidence. Evidences is not a word. type EvidenceList []Evidence @@ -488,10 +489,10 @@ func (evl EvidenceList) ToABCI() []abci.Misbehavior { return el } -//------------------------------------------ PROTO -------------------------------------- +// ------------------------------------------ PROTO -------------------------------------- // EvidenceToProto is a generalized function for encoding evidence that conforms to the -// evidence interface to protobuf +// evidence interface to protobuf. func EvidenceToProto(evidence Evidence) (*cmtproto.Evidence, error) { if evidence == nil { return nil, errors.New("nil evidence") @@ -523,7 +524,7 @@ func EvidenceToProto(evidence Evidence) (*cmtproto.Evidence, error) { } // EvidenceFromProto is a generalized function for decoding protobuf into the -// evidence interface +// evidence interface. func EvidenceFromProto(evidence *cmtproto.Evidence) (Evidence, error) { if evidence == nil { return nil, errors.New("nil evidence") @@ -544,7 +545,7 @@ func init() { cmtjson.RegisterType(&LightClientAttackEvidence{}, "tendermint/LightClientAttackEvidence") } -//-------------------------------------------- ERRORS -------------------------------------- +// -------------------------------------------- ERRORS -------------------------------------- // ErrInvalidEvidence wraps a piece of evidence and the error denoting how or why it is invalid. type ErrInvalidEvidence struct { @@ -578,19 +579,22 @@ func (err *ErrEvidenceOverflow) Error() string { return fmt.Sprintf("Too much evidence: Max %d, got %d", err.Max, err.Got) } -//-------------------------------------------- MOCKING -------------------------------------- +// -------------------------------------------- MOCKING -------------------------------------- // unstable - use only for testing -// assumes the round to be 0 and the validator index to be 0 +// NewMockDuplicateVoteEvidence assumes the round to be 0 and the validator +// index to be 0. func NewMockDuplicateVoteEvidence(height int64, time time.Time, chainID string) (*DuplicateVoteEvidence, error) { val := NewMockPV() return NewMockDuplicateVoteEvidenceWithValidator(height, time, val, chainID) } -// assumes voting power to be 10 and validator to be the only one in the set +// NewMockDuplicateVoteEvidenceWithValidator assumes voting power to be 10 +// and validator to be the only one in the set. func NewMockDuplicateVoteEvidenceWithValidator(height int64, time time.Time, - pv PrivValidator, chainID string) (*DuplicateVoteEvidence, error) { + pv PrivValidator, chainID string, +) (*DuplicateVoteEvidence, error) { pubKey, err := pv.GetPubKey() if err != nil { return nil, err @@ -598,14 +602,14 @@ func NewMockDuplicateVoteEvidenceWithValidator(height int64, time time.Time, val := NewValidator(pubKey, 10) voteA := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) vA := voteA.ToProto() - err = pv.SignVote(chainID, vA) + err = pv.SignVote(chainID, vA, false) if err != nil { return nil, err } voteA.Signature = vA.Signature voteB := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) vB := voteB.ToProto() - err = pv.SignVote(chainID, vB) + err = pv.SignVote(chainID, vB, false) if err != nil { return nil, err } @@ -614,9 +618,10 @@ func NewMockDuplicateVoteEvidenceWithValidator(height int64, time time.Time, } func makeMockVote(height int64, round, index int32, addr Address, - blockID BlockID, time time.Time) *Vote { + blockID BlockID, time time.Time, +) *Vote { return &Vote{ - Type: cmtproto.SignedMsgType(2), + Type: SignedMsgType(2), Height: height, Round: round, BlockID: blockID, diff --git a/types/evidence_test.go b/types/evidence_test.go index 89968c248eb..bb0ae60406f 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -8,11 +8,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/tmhash" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" + cmtrand "github.com/cometbft/cometbft/internal/rand" + cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) @@ -28,6 +28,7 @@ func TestEvidenceList(t *testing.T) { } func randomDuplicateVoteEvidence(t *testing.T) *DuplicateVoteEvidence { + t.Helper() val := NewMockPV() blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash")) @@ -43,11 +44,11 @@ func randomDuplicateVoteEvidence(t *testing.T) *DuplicateVoteEvidence { func TestDuplicateVoteEvidence(t *testing.T) { const height = int64(13) - ev, err := NewMockDuplicateVoteEvidence(height, time.Now(), "mock-chain-id") + ev, err := NewMockDuplicateVoteEvidence(height, cmttime.Now(), "mock-chain-id") require.NoError(t, err) assert.Equal(t, ev.Hash(), tmhash.Sum(ev.Bytes())) assert.NotNil(t, ev.String()) - assert.Equal(t, ev.Height(), height) + assert.Equal(t, height, ev.Height()) } func TestDuplicateVoteEvidenceValidation(t *testing.T) { @@ -61,7 +62,7 @@ func TestDuplicateVoteEvidenceValidation(t *testing.T) { malleateEvidence func(*DuplicateVoteEvidence) expectErr bool }{ - {"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false}, + {"Good DuplicateVoteEvidence", func(_ *DuplicateVoteEvidence) {}, false}, {"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true}, {"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true}, {"Nil votes", func(ev *DuplicateVoteEvidence) { @@ -95,7 +96,7 @@ func TestLightClientAttackEvidenceBasic(t *testing.T) { height := int64(5) commonHeight := height - 1 nValidators := 10 - voteSet, valSet, privVals := randVoteSet(height, 1, cmtproto.PrecommitType, nValidators, 1, false) + voteSet, valSet, privVals := randVoteSet(height, 1, PrecommitType, nValidators, 1, false) header := makeHeaderRandom() header.Height = height blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) @@ -156,12 +157,12 @@ func TestLightClientAttackEvidenceValidation(t *testing.T) { height := int64(5) commonHeight := height - 1 nValidators := 10 - voteSet, valSet, privVals := randVoteSet(height, 1, cmtproto.PrecommitType, nValidators, 1, false) + voteSet, valSet, privVals := randVoteSet(height, 1, PrecommitType, nValidators, 1, false) header := makeHeaderRandom() header.Height = height header.ValidatorsHash = valSet.Hash() blockID := makeBlockID(header.Hash(), math.MaxInt32, tmhash.Sum([]byte("partshash"))) - extCommit, err := MakeExtCommit(blockID, height, 1, voteSet, privVals, time.Now(), false) + extCommit, err := MakeExtCommit(blockID, height, 1, voteSet, privVals, cmttime.Now(), false) require.NoError(t, err) commit := extCommit.ToCommit() @@ -178,14 +179,14 @@ func TestLightClientAttackEvidenceValidation(t *testing.T) { Timestamp: header.Time, ByzantineValidators: valSet.Validators[:nValidators/2], } - assert.NoError(t, lcae.ValidateBasic()) + require.NoError(t, lcae.ValidateBasic()) testCases := []struct { testName string malleateEvidence func(*LightClientAttackEvidence) expectErr bool }{ - {"Good LightClientAttackEvidence", func(ev *LightClientAttackEvidence) {}, false}, + {"Good LightClientAttackEvidence", func(_ *LightClientAttackEvidence) {}, false}, {"Negative height", func(ev *LightClientAttackEvidence) { ev.CommonHeight = -10 }, true}, {"Height is greater than divergent block", func(ev *LightClientAttackEvidence) { ev.CommonHeight = height + 1 @@ -220,19 +221,18 @@ func TestLightClientAttackEvidenceValidation(t *testing.T) { } tc.malleateEvidence(lcae) if tc.expectErr { - assert.Error(t, lcae.ValidateBasic(), tc.testName) + require.Error(t, lcae.ValidateBasic(), tc.testName) } else { - assert.NoError(t, lcae.ValidateBasic(), tc.testName) + require.NoError(t, lcae.ValidateBasic(), tc.testName) } }) } - } func TestMockEvidenceValidateBasic(t *testing.T) { - goodEvidence, err := NewMockDuplicateVoteEvidence(int64(1), time.Now(), "mock-chain-id") + goodEvidence, err := NewMockDuplicateVoteEvidence(int64(1), cmttime.Now(), "mock-chain-id") require.NoError(t, err) - assert.Nil(t, goodEvidence.ValidateBasic()) + require.NoError(t, goodEvidence.ValidateBasic()) } func makeHeaderRandom() *Header { @@ -240,7 +240,7 @@ func makeHeaderRandom() *Header { Version: cmtversion.Consensus{Block: version.BlockProtocol, App: 1}, ChainID: cmtrand.Str(12), Height: int64(cmtrand.Uint16()) + 1, - Time: time.Now(), + Time: cmttime.Now(), LastBlockID: makeBlockIDRandom(), LastCommitHash: crypto.CRandBytes(tmhash.Size), DataHash: crypto.CRandBytes(tmhash.Size), @@ -296,14 +296,14 @@ func TestEvidenceProto(t *testing.T) { t.Run(tt.testName, func(t *testing.T) { pb, err := EvidenceToProto(tt.evidence) if tt.toProtoErr { - assert.Error(t, err, tt.testName) + require.Error(t, err, tt.testName) return } - assert.NoError(t, err, tt.testName) + require.NoError(t, err, tt.testName) evi, err := EvidenceFromProto(pb) if tt.fromProtoErr { - assert.Error(t, err, tt.testName) + require.Error(t, err, tt.testName) return } require.Equal(t, tt.evidence, evi, tt.testName) diff --git a/types/genesis.go b/types/genesis.go index d6d0b2afaa4..1a38d26435a 100644 --- a/types/genesis.go +++ b/types/genesis.go @@ -9,9 +9,9 @@ import ( "time" "github.com/cometbft/cometbft/crypto" + cmtos "github.com/cometbft/cometbft/internal/os" cmtbytes "github.com/cometbft/cometbft/libs/bytes" cmtjson "github.com/cometbft/cometbft/libs/json" - cmtos "github.com/cometbft/cometbft/libs/os" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -20,7 +20,7 @@ const ( MaxChainIDLen = 50 ) -//------------------------------------------------------------ +// ------------------------------------------------------------ // core types for a genesis definition // NOTE: any changes to the genesis definition should // be reflected in the documentation: @@ -51,10 +51,10 @@ func (genDoc *GenesisDoc) SaveAs(file string) error { if err != nil { return err } - return cmtos.WriteFile(file, genDocBytes, 0644) + return cmtos.WriteFile(file, genDocBytes, 0o644) } -// ValidatorHash returns the hash of the validator set contained in the GenesisDoc +// ValidatorHash returns the hash of the validator set contained in the GenesisDoc. func (genDoc *GenesisDoc) ValidatorHash() []byte { vals := make([]*Validator, len(genDoc.Validators)) for i, v := range genDoc.Validators { @@ -65,7 +65,7 @@ func (genDoc *GenesisDoc) ValidatorHash() []byte { } // ValidateAndComplete checks that all necessary fields are present -// and fills in defaults for optional fields left empty +// and fills in defaults for optional fields left empty. func (genDoc *GenesisDoc) ValidateAndComplete() error { if genDoc.ChainID == "" { return errors.New("genesis doc must include non-empty chain_id") @@ -105,7 +105,7 @@ func (genDoc *GenesisDoc) ValidateAndComplete() error { return nil } -//------------------------------------------------------------ +// ------------------------------------------------------------ // Make genesis state from file // GenesisDocFromJSON unmarshalls JSON data into a GenesisDoc. diff --git a/types/genesis_test.go b/types/genesis_test.go index 65dcf0bc44e..fa6609448d3 100644 --- a/types/genesis_test.go +++ b/types/genesis_test.go @@ -52,29 +52,36 @@ func TestGenesisBad(t *testing.T) { for _, testCase := range testCases { _, err := GenesisDocFromJSON(testCase) - assert.Error(t, err, "expected error for empty genDoc json") + require.Error(t, err, "expected error for empty genDoc json") } } -func TestGenesisGood(t *testing.T) { +func TestBasicGenesisDoc(t *testing.T) { // test a good one by raw json genDocBytes := []byte( `{ "genesis_time": "0001-01-01T00:00:00Z", "chain_id": "test-chain-QDKdJr", "initial_height": "1000", - "consensus_params": null, "validators": [{ "pub_key":{"type":"tendermint/PubKeyEd25519","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="}, "power":"10", "name":"" }], "app_hash":"", - "app_state":{"account_owner": "Bob"} + "app_state":{"account_owner": "Bob"}, + "consensus_params": { + "synchrony": {"precision": "1", "message_delay": "10"}, + "validator": {"pub_key_types":["ed25519"]}, + "block": {"max_bytes": "100"}, + "evidence": {"max_age_num_blocks": "100", "max_age_duration": "10"}, + "feature": {"vote_extension_enable_height": "0", "pbts_enable_height": "0"} + } }`, ) + _, err := GenesisDocFromJSON(genDocBytes) - assert.NoError(t, err, "expected no error for good genDoc json") + require.NoError(t, err, "expected no error for good genDoc json") pubkey := ed25519.GenPrivKey().PubKey() // create a base gendoc from struct @@ -83,11 +90,11 @@ func TestGenesisGood(t *testing.T) { Validators: []GenesisValidator{{pubkey.Address(), pubkey, 10, "myval"}}, } genDocBytes, err = cmtjson.Marshal(baseGenDoc) - assert.NoError(t, err, "error marshaling genDoc") + require.NoError(t, err, "error marshaling genDoc") // test base gendoc and check consensus params were filled genDoc, err := GenesisDocFromJSON(genDocBytes) - assert.NoError(t, err, "expected no error for valid genDoc json") + require.NoError(t, err, "expected no error for valid genDoc json") assert.NotNil(t, genDoc.ConsensusParams, "expected consensus params to be filled in") // check validator's address is filled @@ -95,16 +102,16 @@ func TestGenesisGood(t *testing.T) { // create json with consensus params filled genDocBytes, err = cmtjson.Marshal(genDoc) - assert.NoError(t, err, "error marshaling genDoc") + require.NoError(t, err, "error marshaling genDoc") genDoc, err = GenesisDocFromJSON(genDocBytes) - assert.NoError(t, err, "expected no error for valid genDoc json") + require.NoError(t, err, "expected no error for valid genDoc json") // test with invalid consensus params genDoc.ConsensusParams.Block.MaxBytes = 0 genDocBytes, err = cmtjson.Marshal(genDoc) - assert.NoError(t, err, "error marshaling genDoc") + require.NoError(t, err, "error marshaling genDoc") _, err = GenesisDocFromJSON(genDocBytes) - assert.Error(t, err, "expected error for genDoc json with block size of 0") + require.Error(t, err, "expected error for genDoc json with block size of 0") // Genesis doc from raw json missingValidatorsTestCases := [][]byte{ @@ -116,7 +123,7 @@ func TestGenesisGood(t *testing.T) { for _, tc := range missingValidatorsTestCases { _, err := GenesisDocFromJSON(tc) - assert.NoError(t, err) + require.NoError(t, err) } } diff --git a/types/keys.go b/types/keys.go index 941e82b65b0..cb1161bf579 100644 --- a/types/keys.go +++ b/types/keys.go @@ -1,6 +1,6 @@ package types -// UNSTABLE +// UNSTABLE. var ( PeerStateKey = "ConsensusReactor.peerState" ) diff --git a/types/light.go b/types/light.go index 31fdc620f94..946ca9d8e26 100644 --- a/types/light.go +++ b/types/light.go @@ -5,11 +5,11 @@ import ( "errors" "fmt" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" ) // LightBlock is a SignedHeader and a ValidatorSet. -// It is the basis of the light client +// It is the basis of the light client. type LightBlock struct { *SignedHeader `json:"signed_header"` ValidatorSet *ValidatorSet `json:"validator_set"` @@ -17,7 +17,7 @@ type LightBlock struct { // ValidateBasic checks that the data is correct and consistent // -// This does no verification of the signatures +// This does no verification of the signatures. func (lb LightBlock) ValidateBasic(chainID string) error { if lb.SignedHeader == nil { return errors.New("missing signed header") @@ -43,7 +43,7 @@ func (lb LightBlock) ValidateBasic(chainID string) error { return nil } -// String returns a string representation of the LightBlock +// String returns a string representation of the LightBlock. func (lb LightBlock) String() string { return lb.StringIndented("") } @@ -51,7 +51,7 @@ func (lb LightBlock) String() string { // StringIndented returns an indented string representation of the LightBlock // // SignedHeader -// ValidatorSet +// ValidatorSet. func (lb LightBlock) StringIndented(indent string) string { return fmt.Sprintf(`LightBlock{ %s %v @@ -62,7 +62,7 @@ func (lb LightBlock) StringIndented(indent string) string { indent) } -// ToProto converts the LightBlock to protobuf +// ToProto converts the LightBlock to protobuf. func (lb *LightBlock) ToProto() (*cmtproto.LightBlock, error) { if lb == nil { return nil, nil @@ -84,7 +84,7 @@ func (lb *LightBlock) ToProto() (*cmtproto.LightBlock, error) { } // LightBlockFromProto converts from protobuf back into the Lightblock. -// An error is returned if either the validator set or signed header are invalid +// An error is returned if either the validator set or signed header are invalid. func LightBlockFromProto(pb *cmtproto.LightBlock) (*LightBlock, error) { if pb == nil { return nil, errors.New("nil light block") @@ -111,7 +111,7 @@ func LightBlockFromProto(pb *cmtproto.LightBlock) (*LightBlock, error) { return lb, nil } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // SignedHeader is a header along with the commits that prove it. type SignedHeader struct { @@ -120,6 +120,11 @@ type SignedHeader struct { Commit *Commit `json:"commit"` } +// IsEmpty returns true if both the header and commit are nil. +func (sh SignedHeader) IsEmpty() bool { + return sh.Header == nil && sh.Commit == nil +} + // ValidateBasic does basic consistency checks and makes sure the header // and commit are consistent. // @@ -164,7 +169,7 @@ func (sh SignedHeader) String() string { // StringIndented returns an indented string representation of SignedHeader. // // Header -// Commit +// Commit. func (sh SignedHeader) StringIndented(indent string) string { return fmt.Sprintf(`SignedHeader{ %s %v @@ -175,7 +180,7 @@ func (sh SignedHeader) StringIndented(indent string) string { indent) } -// ToProto converts SignedHeader to protobuf +// ToProto converts SignedHeader to protobuf. func (sh *SignedHeader) ToProto() *cmtproto.SignedHeader { if sh == nil { return nil @@ -192,7 +197,7 @@ func (sh *SignedHeader) ToProto() *cmtproto.SignedHeader { return psh } -// FromProto sets a protobuf SignedHeader to the given pointer. +// SignedHeaderFromProto sets a protobuf SignedHeader to the given pointer. // It returns an error if the header or the commit is invalid. func SignedHeaderFromProto(shp *cmtproto.SignedHeader) (*SignedHeader, error) { if shp == nil { diff --git a/types/light_test.go b/types/light_test.go index 82af25277f1..29c4b821e58 100644 --- a/types/light_test.go +++ b/types/light_test.go @@ -6,15 +6,17 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" "github.com/cometbft/cometbft/crypto" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" + cmttime "github.com/cometbft/cometbft/types/time" "github.com/cometbft/cometbft/version" ) func TestLightBlockValidateBasic(t *testing.T) { header := makeRandHeader() - commit := randCommit(time.Now()) + commit := randCommit(cmttime.Now()) vals, _ := RandValidatorSet(5, 1) header.Height = commit.Height header.LastBlockID = commit.BlockID @@ -39,7 +41,7 @@ func TestLightBlockValidateBasic(t *testing.T) { {"valid light block", sh, vals, false}, {"hashes don't match", sh, vals2, true}, {"invalid validator set", sh, vals3, true}, - {"invalid signed header", &SignedHeader{Header: &header, Commit: randCommit(time.Now())}, vals, true}, + {"invalid signed header", &SignedHeader{Header: &header, Commit: randCommit(cmttime.Now())}, vals, true}, } for _, tc := range testCases { @@ -49,17 +51,16 @@ func TestLightBlockValidateBasic(t *testing.T) { } err := lightBlock.ValidateBasic(header.ChainID) if tc.expectErr { - assert.Error(t, err, tc.name) + require.Error(t, err, tc.name) } else { - assert.NoError(t, err, tc.name) + require.NoError(t, err, tc.name) } } - } func TestLightBlockProtobuf(t *testing.T) { header := makeRandHeader() - commit := randCommit(time.Now()) + commit := randCommit(cmttime.Now()) vals, _ := RandValidatorSet(5, 1) header.Height = commit.Height header.LastBlockID = commit.BlockID @@ -94,24 +95,23 @@ func TestLightBlockProtobuf(t *testing.T) { } lbp, err := lightBlock.ToProto() if tc.toProtoErr { - assert.Error(t, err, tc.name) + require.Error(t, err, tc.name) } else { - assert.NoError(t, err, tc.name) + require.NoError(t, err, tc.name) } lb, err := LightBlockFromProto(lbp) if tc.toBlockErr { - assert.Error(t, err, tc.name) + require.Error(t, err, tc.name) } else { - assert.NoError(t, err, tc.name) + require.NoError(t, err, tc.name) assert.Equal(t, lightBlock, lb) } } - } func TestSignedHeaderValidateBasic(t *testing.T) { - commit := randCommit(time.Now()) + commit := randCommit(cmttime.Now()) chainID := "𠜎" timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) h := Header{ diff --git a/types/params.go b/types/params.go index d12503ae0e0..799512b43d5 100644 --- a/types/params.go +++ b/types/params.go @@ -3,17 +3,21 @@ package types import ( "errors" "fmt" + "math" "time" + gogo "github.com/cosmos/gogoproto/types" + + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/crypto/bls12381" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/crypto/secp256k1" "github.com/cometbft/cometbft/crypto/tmhash" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) const ( // MaxBlockSizeBytes is the maximum permitted size of the blocks. - MaxBlockSizeBytes = 104857600 // 100MB + MaxBlockSizeBytes = 100 * 1024 * 1024 // BlockPartSizeBytes is the size of one block part. BlockPartSizeBytes uint32 = 65536 // 64kB @@ -23,6 +27,7 @@ const ( ABCIPubKeyTypeEd25519 = ed25519.KeyType ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType + ABCIPubKeyTypeBls12381 = bls12381.KeyType ) var ABCIPubKeyTypesToNames = map[string]string{ @@ -30,6 +35,12 @@ var ABCIPubKeyTypesToNames = map[string]string{ ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName, } +func init() { + if bls12381.Enabled { + ABCIPubKeyTypesToNames[ABCIPubKeyTypeBls12381] = bls12381.PubKeyName + } +} + // ConsensusParams contains consensus critical parameters that determine the // validity of blocks. type ConsensusParams struct { @@ -37,17 +48,17 @@ type ConsensusParams struct { Evidence EvidenceParams `json:"evidence"` Validator ValidatorParams `json:"validator"` Version VersionParams `json:"version"` - ABCI ABCIParams `json:"abci"` + Synchrony SynchronyParams `json:"synchrony"` + Feature FeatureParams `json:"feature"` } -// BlockParams define limits on the block size and gas plus minimum time -// between blocks. +// BlockParams define limits on the block size and gas. type BlockParams struct { MaxBytes int64 `json:"max_bytes"` MaxGas int64 `json:"max_gas"` } -// EvidenceParams determine how we handle evidence of malfeasance. +// EvidenceParams determine the validity of evidences of Byzantine behavior. type EvidenceParams struct { MaxAgeNumBlocks int64 `json:"max_age_num_blocks"` // only accept new evidence more recent than this MaxAgeDuration time.Duration `json:"max_age_duration"` @@ -60,26 +71,72 @@ type ValidatorParams struct { PubKeyTypes []string `json:"pub_key_types"` } +// VersionParams contain the version of specific components of CometBFT. type VersionParams struct { App uint64 `json:"app"` } -// ABCIParams configure ABCI functionality specific to the Application Blockchain -// Interface. -type ABCIParams struct { +// FeatureParams configure the height from which features of CometBFT are enabled. +type FeatureParams struct { VoteExtensionsEnableHeight int64 `json:"vote_extensions_enable_height"` + PbtsEnableHeight int64 `json:"pbts_enable_height"` } // VoteExtensionsEnabled returns true if vote extensions are enabled at height h // and false otherwise. -func (a ABCIParams) VoteExtensionsEnabled(h int64) bool { - if h < 1 { - panic(fmt.Errorf("cannot check if vote extensions enabled for height %d (< 1)", h)) +func (p FeatureParams) VoteExtensionsEnabled(h int64) bool { + enabledHeight := p.VoteExtensionsEnableHeight + + return featureEnabled(enabledHeight, h, "Vote Extensions") +} + +// PbtsEnabled returns true if PBTS is enabled at height h and false otherwise. +func (p FeatureParams) PbtsEnabled(h int64) bool { + enabledHeight := p.PbtsEnableHeight + + return featureEnabled(enabledHeight, h, "PBTS") +} + +// featureEnabled returns true if `enabledHeight` points to a height that is smaller than `currentHeight“. +func featureEnabled(enableHeight int64, currentHeight int64, f string) bool { + if currentHeight < 1 { + panic(fmt.Errorf("cannot check if %s is enabled for height %d (< 1)", f, currentHeight)) } - if a.VoteExtensionsEnableHeight == 0 { + + if enableHeight <= 0 { return false } - return a.VoteExtensionsEnableHeight <= h + + return enableHeight <= currentHeight +} + +// SynchronyParams determine the validity of block timestamps. +// +// These parameters are part of the Proposer-Based Timestamps (PBTS) algorithm. +// For more information on the relationship of the synchrony parameters to +// block timestamps validity, refer to the PBTS specification: +// // https://github.com/cometbft/cometbft/tree/main/spec/consensus/proposer-based-timestamp +type SynchronyParams struct { + Precision time.Duration `json:"precision,string"` + MessageDelay time.Duration `json:"message_delay,string"` +} + +// InRound ensures an exponential back-off of SynchronyParams.MessageDelay for +// block timestamps validation, as the associated proposal rounds increase. +// +// The adaptation is achieve by increasing MessageDelay by a factor of 10% each +// subsequent round a proposal's timeliness is calculated, namely: +// +// MessageDelay(round) == MessageDelay * (1.1)^round +// +// The goal is facilitate the progression of consensus when improper synchrony +// parameters are set or become insufficient to preserve liveness. Refer to +// https://github.com/cometbft/cometbft/issues/2184 for more details. +func (sp SynchronyParams) InRound(round int32) SynchronyParams { + return SynchronyParams{ + Precision: sp.Precision, + MessageDelay: time.Duration(math.Pow(1.1, float64(round)) * float64(sp.MessageDelay)), + } } // DefaultConsensusParams returns a default ConsensusParams. @@ -89,15 +146,16 @@ func DefaultConsensusParams() *ConsensusParams { Evidence: DefaultEvidenceParams(), Validator: DefaultValidatorParams(), Version: DefaultVersionParams(), - ABCI: DefaultABCIParams(), + Feature: DefaultFeatureParams(), + Synchrony: DefaultSynchronyParams(), } } // DefaultBlockParams returns a default BlockParams. func DefaultBlockParams() BlockParams { return BlockParams{ - MaxBytes: 22020096, // 21MB - MaxGas: -1, + MaxBytes: 4194304, // four megabytes + MaxGas: 10000000, // ten million } } @@ -124,10 +182,20 @@ func DefaultVersionParams() VersionParams { } } -func DefaultABCIParams() ABCIParams { - return ABCIParams{ - // When set to 0, vote extensions are not required. +// Disabled by default. +func DefaultFeatureParams() FeatureParams { + return FeatureParams{ VoteExtensionsEnableHeight: 0, + PbtsEnableHeight: 0, + } +} + +func DefaultSynchronyParams() SynchronyParams { + // Default values determined based on experimental results and on + // https://github.com/tendermint/tendermint/issues/7202 + return SynchronyParams{ + Precision: 500 * time.Millisecond, + MessageDelay: 2 * time.Second, } } @@ -140,11 +208,15 @@ func IsValidPubkeyType(params ValidatorParams, pubkeyType string) bool { return false } -// Validate validates the ConsensusParams to ensure all values are within their +// ValidateBasic validates the ConsensusParams to ensure **all** values are within their // allowed limits, and returns an error if they are not. func (params ConsensusParams) ValidateBasic() error { - if params.Block.MaxBytes <= 0 { - return fmt.Errorf("block.MaxBytes must be greater than 0. Got %d", + if params.Block.MaxBytes == 0 { + return errors.New("block.MaxBytes cannot be 0") + } + if params.Block.MaxBytes < -1 { + return fmt.Errorf("block.MaxBytes must be -1 or greater than 0. Got %d", + params.Block.MaxBytes) } if params.Block.MaxBytes > MaxBlockSizeBytes { @@ -163,11 +235,15 @@ func (params ConsensusParams) ValidateBasic() error { } if params.Evidence.MaxAgeDuration <= 0 { - return fmt.Errorf("evidence.MaxAgeDuration must be grater than 0 if provided, Got %v", + return fmt.Errorf("evidence.MaxAgeDuration must be greater than 0 if provided, Got %v", params.Evidence.MaxAgeDuration) } - if params.Evidence.MaxBytes > params.Block.MaxBytes { + maxBytes := params.Block.MaxBytes + if maxBytes == -1 { + maxBytes = int64(MaxBlockSizeBytes) + } + if params.Evidence.MaxBytes > maxBytes { return fmt.Errorf("evidence.MaxBytesEvidence is greater than upper bound, %d > %d", params.Evidence.MaxBytes, params.Block.MaxBytes) } @@ -176,9 +252,24 @@ func (params ConsensusParams) ValidateBasic() error { return fmt.Errorf("evidence.MaxBytes must be non negative. Got: %d", params.Evidence.MaxBytes) } + if params.Feature.VoteExtensionsEnableHeight < 0 { + return fmt.Errorf("Feature.VoteExtensionsEnabledHeight cannot be negative. Got: %d", params.Feature.VoteExtensionsEnableHeight) + } - if params.ABCI.VoteExtensionsEnableHeight < 0 { - return fmt.Errorf("ABCI.VoteExtensionsEnableHeight cannot be negative. Got: %d", params.ABCI.VoteExtensionsEnableHeight) + if params.Feature.PbtsEnableHeight < 0 { + return fmt.Errorf("Feature.PbtsEnableHeight cannot be negative. Got: %d", params.Feature.PbtsEnableHeight) + } + + // Synchrony params are only relevant when PBTS is enabled + if params.Feature.PbtsEnableHeight > 0 { + if params.Synchrony.MessageDelay <= 0 { + return fmt.Errorf("synchrony.MessageDelay must be greater than 0. Got: %d", + params.Synchrony.MessageDelay) + } + if params.Synchrony.Precision <= 0 { + return fmt.Errorf("synchrony.Precision must be greater than 0. Got: %d", + params.Synchrony.Precision) + } } if len(params.Validator.PubKeyTypes) == 0 { @@ -197,27 +288,91 @@ func (params ConsensusParams) ValidateBasic() error { return nil } +// ValidateUpdate validates the updated Consensus Params +// if updated == nil, then pass. func (params ConsensusParams) ValidateUpdate(updated *cmtproto.ConsensusParams, h int64) error { - if updated.Abci == nil { + if updated == nil { return nil } - if params.ABCI.VoteExtensionsEnableHeight == updated.Abci.VoteExtensionsEnableHeight { + + var err error + // Validate feature update parameters. + if updated.Feature != nil { + err = validateUpdateFeatures(params.Feature, *updated.Feature, h) + } + return err +} + +// validateUpdateFeatures validates the updated PBTSEnableHeight. +// | r | params...EnableHeight | updated...EnableHeight | result (nil == pass) +// | 2 | * | < 0 | EnableHeight must be positive +// | 3 | <=0 | 0 | nil +// | 4 | X | X (>=0) | nil +// | 5 | > 0; <=height | 0 | Feature cannot be disabled once enabled +// | 6 | > 0; > height | 0 | nil (disable a previous proposal) +// | 7 | * | <=height | Feature cannot be updated to a past height +// | 8 | <=0 | > height (*) | nil +// | 9 | (> 0) <=height | > height (*) | Feature cannot be modified once enabled +// | 10 | (> 0) > height | > height (*) | nil +// The table above reflects all cases covered. +func validateUpdateFeatures(params FeatureParams, updated cmtproto.FeatureParams, h int64) error { + if updated.VoteExtensionsEnableHeight != nil { + err := validateUpdateFeatureEnableHeight(params.VoteExtensionsEnableHeight, updated.VoteExtensionsEnableHeight.Value, h, "Vote Extensions") + if err != nil { + return err + } + } + + if updated.PbtsEnableHeight != nil { + err := validateUpdateFeatureEnableHeight(params.PbtsEnableHeight, updated.PbtsEnableHeight.Value, h, "PBTS") + if err != nil { + return err + } + } + return nil +} + +func validateUpdateFeatureEnableHeight(param int64, updated int64, h int64, featureName string) error { + // 2 + if updated < 0 { + return fmt.Errorf("%s EnableHeight must be positive", featureName) + } + // 3 + if param <= 0 && updated == 0 { return nil } - if params.ABCI.VoteExtensionsEnableHeight != 0 && updated.Abci.VoteExtensionsEnableHeight == 0 { - return errors.New("vote extensions cannot be disabled once enabled") + // 4 (implicit: updated >= 0) + if param == updated { + return nil } - if updated.Abci.VoteExtensionsEnableHeight <= h { - return fmt.Errorf("VoteExtensionsEnableHeight cannot be updated to a past height, "+ - "initial height: %d, current height %d", - params.ABCI.VoteExtensionsEnableHeight, h) + // 5 & 6 + if param > 0 && updated == 0 { + // 5 + if param <= h { + return fmt.Errorf("%s cannot be disabled once enabled"+ + "enabled height: %d, current height: %d", + featureName, param, h) + } + // 6 + return nil } - if params.ABCI.VoteExtensionsEnableHeight <= h { - return fmt.Errorf("VoteExtensionsEnableHeight cannot be modified once"+ - "the initial height has occurred, "+ - "initial height: %d, current height %d", - params.ABCI.VoteExtensionsEnableHeight, h) + // 7 (implicit: updated > 0) + if updated <= h { + return fmt.Errorf("%s cannot be updated to a past or current height, "+ + "enabled height: %d, enable height: %d, current height %d", + featureName, param, updated, h) } + // 8 (implicit: updated > h) + if param <= 0 { + return nil + } + // 9 (implicit: param > 0 && updated > h) + if param <= h { + return fmt.Errorf("%s cannot be modified once enabled"+ + "enabled height: %d, current height: %d", + featureName, param, h) + } + // 10 (implicit: param > h && updated > h) return nil } @@ -246,7 +401,7 @@ func (params ConsensusParams) Hash() []byte { } // Update returns a copy of the params with updates from the non-zero fields of p2. -// NOTE: note: must not modify the original +// NOTE: note: must not modify the original. func (params ConsensusParams) Update(params2 *cmtproto.ConsensusParams) ConsensusParams { res := params // explicit copy @@ -272,9 +427,24 @@ func (params ConsensusParams) Update(params2 *cmtproto.ConsensusParams) Consensu if params2.Version != nil { res.Version.App = params2.Version.App } - if params2.Abci != nil { - res.ABCI.VoteExtensionsEnableHeight = params2.Abci.GetVoteExtensionsEnableHeight() + if params2.Feature != nil { + if params2.Feature.VoteExtensionsEnableHeight != nil { + res.Feature.VoteExtensionsEnableHeight = params2.Feature.GetVoteExtensionsEnableHeight().Value + } + + if params2.Feature.PbtsEnableHeight != nil { + res.Feature.PbtsEnableHeight = params2.Feature.GetPbtsEnableHeight().Value + } + } + if params2.Synchrony != nil { + if params2.Synchrony.MessageDelay != nil { + res.Synchrony.MessageDelay = *params2.Synchrony.GetMessageDelay() + } + if params2.Synchrony.Precision != nil { + res.Synchrony.Precision = *params2.Synchrony.GetPrecision() + } } + return res } @@ -295,8 +465,13 @@ func (params *ConsensusParams) ToProto() cmtproto.ConsensusParams { Version: &cmtproto.VersionParams{ App: params.Version.App, }, - Abci: &cmtproto.ABCIParams{ - VoteExtensionsEnableHeight: params.ABCI.VoteExtensionsEnableHeight, + Feature: &cmtproto.FeatureParams{ + PbtsEnableHeight: &gogo.Int64Value{Value: params.Feature.PbtsEnableHeight}, + VoteExtensionsEnableHeight: &gogo.Int64Value{Value: params.Feature.VoteExtensionsEnableHeight}, + }, + Synchrony: &cmtproto.SynchronyParams{ + MessageDelay: ¶ms.Synchrony.MessageDelay, + Precision: ¶ms.Synchrony.Precision, }, } } @@ -318,9 +493,24 @@ func ConsensusParamsFromProto(pbParams cmtproto.ConsensusParams) ConsensusParams Version: VersionParams{ App: pbParams.Version.App, }, + Feature: FeatureParams{ + VoteExtensionsEnableHeight: pbParams.GetFeature().GetVoteExtensionsEnableHeight().GetValue(), + PbtsEnableHeight: pbParams.GetFeature().GetPbtsEnableHeight().GetValue(), + }, } - if pbParams.Abci != nil { - c.ABCI.VoteExtensionsEnableHeight = pbParams.Abci.GetVoteExtensionsEnableHeight() + if pbParams.GetSynchrony().GetMessageDelay() != nil { + c.Synchrony.MessageDelay = *pbParams.GetSynchrony().GetMessageDelay() + } + if pbParams.GetSynchrony().GetPrecision() != nil { + c.Synchrony.Precision = *pbParams.GetSynchrony().GetPrecision() + } + if pbParams.GetAbci().GetVoteExtensionsEnableHeight() > 0 { //nolint: staticcheck + // Value set before the upgrade to V1. We can safely overwrite here because + // ABCIParams and FeatureParams being set is mutually exclusive (=V1). + if pbParams.GetFeature().GetVoteExtensionsEnableHeight().GetValue() > 0 { + panic("vote_extension_enable_height is set in two different places") + } + c.Feature.VoteExtensionsEnableHeight = pbParams.Abci.VoteExtensionsEnableHeight } return c } diff --git a/types/params_test.go b/types/params_test.go index 4311945d558..eb331c8548c 100644 --- a/types/params_test.go +++ b/types/params_test.go @@ -6,10 +6,11 @@ import ( "testing" "time" + "github.com/cosmos/gogoproto/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" ) var ( @@ -19,72 +20,337 @@ var ( func TestConsensusParamsValidation(t *testing.T) { testCases := []struct { + name string params ConsensusParams valid bool }{ - // test block params - 0: {makeParams(1, 0, 2, 0, valEd25519, 0), true}, - 1: {makeParams(0, 0, 2, 0, valEd25519, 0), false}, - 2: {makeParams(47*1024*1024, 0, 2, 0, valEd25519, 0), true}, - 3: {makeParams(10, 0, 2, 0, valEd25519, 0), true}, - 4: {makeParams(100*1024*1024, 0, 2, 0, valEd25519, 0), true}, - 5: {makeParams(101*1024*1024, 0, 2, 0, valEd25519, 0), false}, - 6: {makeParams(1024*1024*1024, 0, 2, 0, valEd25519, 0), false}, - // test evidence params - 7: {makeParams(1, 0, 0, 0, valEd25519, 0), false}, - 8: {makeParams(1, 0, 2, 2, valEd25519, 0), false}, - 9: {makeParams(1000, 0, 2, 1, valEd25519, 0), true}, - 10: {makeParams(1, 0, -1, 0, valEd25519, 0), false}, - // test no pubkey type provided - 11: {makeParams(1, 0, 2, 0, []string{}, 0), false}, - // test invalid pubkey type provided - 12: {makeParams(1, 0, 2, 0, []string{"potatoes make good pubkeys"}, 0), false}, - } - for i, tc := range testCases { + // valid params + { + name: "minimal setup", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + }), + valid: true, + }, + { + name: "minimal setup, pbts enabled", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: time.Nanosecond, + messageDelay: time.Nanosecond, + pbtsHeight: 1, + }), + valid: true, + }, + { + name: "minimal setup, pbts disabled", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + // Invalid Synchrony params, but this is ok + // since PBTS is disabled. + precision: 0, + messageDelay: 0, + }), + valid: true, + }, + // block params + { + name: "blockBytes se to 0", + params: makeParams(makeParamsArgs{ + blockBytes: 0, + evidenceAge: 2, + }), + valid: false, + }, + { + name: "blockBytes set to a big valid value", + params: makeParams(makeParamsArgs{ + blockBytes: 47 * 1024 * 1024, + evidenceAge: 2, + }), + valid: true, + }, + { + name: "blockBytes set to a small valid value", + params: makeParams(makeParamsArgs{ + blockBytes: 10, + evidenceAge: 2, + }), + valid: true, + }, + { + name: "blockBytes set to the biggest valid value", + params: makeParams(makeParamsArgs{ + blockBytes: 100 * 1024 * 1024, + evidenceAge: 2, + }), + valid: true, + }, + { + name: "blockBytes, biggest valid value, off-by-1", + params: makeParams(makeParamsArgs{ + blockBytes: 100*1024*1024 + 1, + evidenceAge: 2, + }), + valid: false, + }, + { + name: "blockBytes, biggest valid value, off-by-1MB", + params: makeParams(makeParamsArgs{ + blockBytes: 101 * 1024 * 1024, + evidenceAge: 2, + }), + valid: false, + }, + { + name: "blockBytes, value set to 1GB (too big)", + params: makeParams(makeParamsArgs{ + blockBytes: 1024 * 1024 * 1024, + evidenceAge: 2, + }), + valid: false, + }, + // blockBytes can be -1 + { + name: "blockBytes -1", + params: makeParams(makeParamsArgs{ + blockBytes: -1, + evidenceAge: 2, + }), + valid: true, + }, + { + name: "blockBytes -2", + params: makeParams(makeParamsArgs{ + blockBytes: -2, + evidenceAge: 2, + }), + valid: false, + }, + // evidence params + { + name: "evidenceAge 0", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 0, + maxEvidenceBytes: 0, + }), + valid: false, + }, + { + name: "evidenceAge negative", + params: makeParams(makeParamsArgs{ + blockBytes: 1 * 1024 * 1024, + evidenceAge: -1, + }), + valid: false, + }, + { + name: "maxEvidenceBytes not less than blockBytes", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + maxEvidenceBytes: 2, + }), + valid: false, + }, + { + name: "maxEvidenceBytes less than blockBytes", + params: makeParams(makeParamsArgs{ + blockBytes: 1000, + evidenceAge: 2, + maxEvidenceBytes: 1, + }), + valid: true, + }, + { + name: "maxEvidenceBytes 0", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 1, + maxEvidenceBytes: 0, + }), + valid: true, + }, + // pubkey params + { + name: "empty pubkeyTypes", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + pubkeyTypes: []string{}, + }), + valid: false, + }, + { + name: "bad pubkeyTypes", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + pubkeyTypes: []string{"potatoes make good pubkeys"}, + }), + valid: false, + }, + // pbts enabled, invalid synchrony params + { + name: "messageDelay 0", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: time.Nanosecond, + messageDelay: 0, + pbtsHeight: 1, + }), + valid: false, + }, + { + name: "messageDelay negative", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: time.Nanosecond, + messageDelay: -1, + pbtsHeight: 1, + }), + valid: false, + }, + { + name: "precision 0", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: 0, + messageDelay: time.Nanosecond, + pbtsHeight: 1, + }), + valid: false, + }, + { + name: "precision negative", + params: makeParams(makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: -1, + messageDelay: time.Nanosecond, + pbtsHeight: 1, + }), + valid: false, + }, + // pbts enable height + { + name: "pbts height -1", + params: makeParams( + makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: time.Nanosecond, + messageDelay: time.Nanosecond, + pbtsHeight: -1, + }), + valid: false, + }, + { + name: "pbts disabled", + params: makeParams( + makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: time.Nanosecond, + messageDelay: time.Nanosecond, + pbtsHeight: 0, + }), + valid: true, + }, + { + name: "pbts enabled", + params: makeParams( + makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: time.Nanosecond, + messageDelay: time.Nanosecond, + pbtsHeight: 1, + }), + valid: true, + }, + { + name: "pbts from height 100", + params: makeParams( + makeParamsArgs{ + blockBytes: 1, + evidenceAge: 2, + precision: time.Nanosecond, + messageDelay: time.Nanosecond, + pbtsHeight: 100, + }), + valid: true, + }, + } + for _, tc := range testCases { if tc.valid { - assert.NoErrorf(t, tc.params.ValidateBasic(), "expected no error for valid params (#%d)", i) + require.NoErrorf(t, tc.params.ValidateBasic(), + "expected no error for valid params, test: '%s'", tc.name) } else { - assert.Errorf(t, tc.params.ValidateBasic(), "expected error for non valid params (#%d)", i) + require.Errorf(t, tc.params.ValidateBasic(), + "expected error for non valid params, test: '%s'", tc.name) } } } -func makeParams( - blockBytes, blockGas int64, - evidenceAge int64, - maxEvidenceBytes int64, - pubkeyTypes []string, - abciExtensionHeight int64, -) ConsensusParams { +type makeParamsArgs struct { + blockBytes int64 + blockGas int64 + evidenceAge int64 + maxEvidenceBytes int64 + pubkeyTypes []string + voteExtensionHeight int64 + pbtsHeight int64 + precision time.Duration + messageDelay time.Duration +} + +func makeParams(args makeParamsArgs) ConsensusParams { + if args.pubkeyTypes == nil { + args.pubkeyTypes = valEd25519 + } + return ConsensusParams{ Block: BlockParams{ - MaxBytes: blockBytes, - MaxGas: blockGas, + MaxBytes: args.blockBytes, + MaxGas: args.blockGas, }, Evidence: EvidenceParams{ - MaxAgeNumBlocks: evidenceAge, - MaxAgeDuration: time.Duration(evidenceAge), - MaxBytes: maxEvidenceBytes, + MaxAgeNumBlocks: args.evidenceAge, + MaxAgeDuration: time.Duration(args.evidenceAge), + MaxBytes: args.maxEvidenceBytes, }, Validator: ValidatorParams{ - PubKeyTypes: pubkeyTypes, + PubKeyTypes: args.pubkeyTypes, + }, + Synchrony: SynchronyParams{ + Precision: args.precision, + MessageDelay: args.messageDelay, }, - ABCI: ABCIParams{ - VoteExtensionsEnableHeight: abciExtensionHeight, + Feature: FeatureParams{ + VoteExtensionsEnableHeight: args.voteExtensionHeight, + PbtsEnableHeight: args.pbtsHeight, }, } } func TestConsensusParamsHash(t *testing.T) { params := []ConsensusParams{ - makeParams(4, 2, 3, 1, valEd25519, 0), - makeParams(1, 4, 3, 1, valEd25519, 0), - makeParams(1, 2, 4, 1, valEd25519, 0), - makeParams(2, 5, 7, 1, valEd25519, 0), - makeParams(1, 7, 6, 1, valEd25519, 0), - makeParams(9, 5, 4, 1, valEd25519, 0), - makeParams(7, 8, 9, 1, valEd25519, 0), - makeParams(4, 6, 5, 1, valEd25519, 0), + makeParams(makeParamsArgs{blockBytes: 4, blockGas: 2, evidenceAge: 3, maxEvidenceBytes: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 4, evidenceAge: 3, maxEvidenceBytes: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 4, maxEvidenceBytes: 1}), + makeParams(makeParamsArgs{blockBytes: 2, blockGas: 5, evidenceAge: 7, maxEvidenceBytes: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 7, evidenceAge: 6, maxEvidenceBytes: 1}), + makeParams(makeParamsArgs{blockBytes: 9, blockGas: 5, evidenceAge: 4, maxEvidenceBytes: 1}), + makeParams(makeParamsArgs{blockBytes: 7, blockGas: 8, evidenceAge: 9, maxEvidenceBytes: 1}), + makeParams(makeParamsArgs{blockBytes: 4, blockGas: 6, evidenceAge: 5, maxEvidenceBytes: 1}), } hashes := make([][]byte, len(params)) @@ -104,20 +370,91 @@ func TestConsensusParamsHash(t *testing.T) { func TestConsensusParamsUpdate(t *testing.T) { testCases := []struct { - params ConsensusParams + intialParams ConsensusParams updates *cmtproto.ConsensusParams updatedParams ConsensusParams }{ // empty updates { - makeParams(1, 2, 3, 0, valEd25519, 0), - &cmtproto.ConsensusParams{}, - makeParams(1, 2, 3, 0, valEd25519, 0), + intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}), + updates: &cmtproto.ConsensusParams{}, + updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}), + }, + { + // update synchrony params + intialParams: makeParams(makeParamsArgs{evidenceAge: 3, precision: time.Second, messageDelay: 3 * time.Second}), + updates: &cmtproto.ConsensusParams{ + Synchrony: &cmtproto.SynchronyParams{ + Precision: durationPtr(time.Second * 2), + MessageDelay: durationPtr(time.Second * 4), + }, + }, + updatedParams: makeParams(makeParamsArgs{evidenceAge: 3, precision: 2 * time.Second, messageDelay: 4 * time.Second}), }, + // update enable vote extensions only + { + intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}), + updates: &cmtproto.ConsensusParams{ + Feature: &cmtproto.FeatureParams{ + VoteExtensionsEnableHeight: &types.Int64Value{Value: 1}, + }, + }, + updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, voteExtensionHeight: 1}), + }, + { + intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, voteExtensionHeight: 1, pbtsHeight: 4}), + updates: &cmtproto.ConsensusParams{ + Feature: &cmtproto.FeatureParams{ + VoteExtensionsEnableHeight: &types.Int64Value{Value: 10}, + }, + }, + updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, voteExtensionHeight: 10, pbtsHeight: 4}), + }, + // update enabled pbts only + { + intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}), + updates: &cmtproto.ConsensusParams{ + Feature: &cmtproto.FeatureParams{ + PbtsEnableHeight: &types.Int64Value{Value: 1}, + }, + }, + updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, pbtsHeight: 1}), + }, + { + intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, voteExtensionHeight: 4, pbtsHeight: 1}), + updates: &cmtproto.ConsensusParams{ + Feature: &cmtproto.FeatureParams{ + PbtsEnableHeight: &types.Int64Value{Value: 100}, + }, + }, + updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, pbtsHeight: 100, voteExtensionHeight: 4}), + }, + // update both pbts and vote extensions enable heights + { + intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}), + updates: &cmtproto.ConsensusParams{ + Feature: &cmtproto.FeatureParams{ + VoteExtensionsEnableHeight: &types.Int64Value{Value: 1}, + PbtsEnableHeight: &types.Int64Value{Value: 1}, + }, + }, + updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, voteExtensionHeight: 1, pbtsHeight: 1}), + }, + { + intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, voteExtensionHeight: 1, pbtsHeight: 1}), + updates: &cmtproto.ConsensusParams{ + Feature: &cmtproto.FeatureParams{ + VoteExtensionsEnableHeight: &types.Int64Value{Value: 10}, + PbtsEnableHeight: &types.Int64Value{Value: 100}, + }, + }, + updatedParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3, voteExtensionHeight: 10, pbtsHeight: 100}), + }, + // fine updates { - makeParams(1, 2, 3, 0, valEd25519, 0), - &cmtproto.ConsensusParams{ + intialParams: makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}), + updates: &cmtproto.ConsensusParams{ Block: &cmtproto.BlockParams{ MaxBytes: 100, MaxGas: 200, @@ -131,17 +468,22 @@ func TestConsensusParamsUpdate(t *testing.T) { PubKeyTypes: valSecp256k1, }, }, - makeParams(100, 200, 300, 50, valSecp256k1, 0), + updatedParams: makeParams(makeParamsArgs{ + blockBytes: 100, blockGas: 200, + evidenceAge: 300, + maxEvidenceBytes: 50, + pubkeyTypes: valSecp256k1, + }), }, } for _, tc := range testCases { - assert.Equal(t, tc.updatedParams, tc.params.Update(tc.updates)) + assert.Equal(t, tc.updatedParams, tc.intialParams.Update(tc.updates)) } } func TestConsensusParamsUpdate_AppVersion(t *testing.T) { - params := makeParams(1, 2, 3, 0, valEd25519, 0) + params := makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 3}) assert.EqualValues(t, 0, params.Version.App) @@ -151,84 +493,207 @@ func TestConsensusParamsUpdate_AppVersion(t *testing.T) { assert.EqualValues(t, 1, updated.Version.App) } -func TestConsensusParamsUpdate_VoteExtensionsEnableHeight(t *testing.T) { - t.Run("set to height but initial height already run", func(*testing.T) { - initialParams := makeParams(1, 0, 2, 0, valEd25519, 1) - update := &cmtproto.ConsensusParams{ - Abci: &cmtproto.ABCIParams{ - VoteExtensionsEnableHeight: 10, - }, - } - require.Error(t, initialParams.ValidateUpdate(update, 1)) - require.Error(t, initialParams.ValidateUpdate(update, 5)) - }) - t.Run("reset to 0", func(t *testing.T) { - initialParams := makeParams(1, 0, 2, 0, valEd25519, 1) - update := &cmtproto.ConsensusParams{ - Abci: &cmtproto.ABCIParams{ - VoteExtensionsEnableHeight: 0, - }, - } - require.Error(t, initialParams.ValidateUpdate(update, 1)) - }) - t.Run("set to height before current height run", func(*testing.T) { - initialParams := makeParams(1, 0, 2, 0, valEd25519, 100) - update := &cmtproto.ConsensusParams{ - Abci: &cmtproto.ABCIParams{ - VoteExtensionsEnableHeight: 10, - }, - } - require.Error(t, initialParams.ValidateUpdate(update, 11)) - require.Error(t, initialParams.ValidateUpdate(update, 99)) - }) - t.Run("set to height after current height run", func(*testing.T) { - initialParams := makeParams(1, 0, 2, 0, valEd25519, 300) - update := &cmtproto.ConsensusParams{ - Abci: &cmtproto.ABCIParams{ - VoteExtensionsEnableHeight: 99, - }, - } - require.NoError(t, initialParams.ValidateUpdate(update, 11)) - require.NoError(t, initialParams.ValidateUpdate(update, 98)) - }) - t.Run("no error when unchanged", func(*testing.T) { - initialParams := makeParams(1, 0, 2, 0, valEd25519, 100) - update := &cmtproto.ConsensusParams{ - Abci: &cmtproto.ABCIParams{ - VoteExtensionsEnableHeight: 100, - }, - } - require.NoError(t, initialParams.ValidateUpdate(update, 500)) - }) - t.Run("updated from 0 to 0", func(t *testing.T) { - initialParams := makeParams(1, 0, 2, 0, valEd25519, 0) - update := &cmtproto.ConsensusParams{ - Abci: &cmtproto.ABCIParams{ - VoteExtensionsEnableHeight: 0, - }, - } - require.NoError(t, initialParams.ValidateUpdate(update, 100)) - }) +func TestConsensusParamsUpdate_EnableHeight(t *testing.T) { + const nilTest = -10000000 + testCases := []struct { + name string + current int64 + from int64 + to int64 + expectedErr bool + }{ + {"no change: 3, 0 -> 0", 3, 0, 0, false}, + {"no change: 3, 100 -> 100, ", 3, 100, 100, false}, + {"no change: 100, 100 -> 100, ", 100, 100, 100, false}, + {"no change: 300, 100 -> 100, ", 300, 100, 100, false}, + {"first time: 4, 0 -> 5, ", 4, 0, 5, false}, + {"first time: 3, 0 -> 5, ", 3, 0, 5, false}, + {"first time: 5, 0 -> 5, ", 5, 0, 5, true}, + {"first time: 6, 0 -> 5, ", 6, 0, 5, true}, + {"first time: 50, 0 -> 5, ", 50, 0, 5, true}, + {"reset to 0: 4, 5 -> 0, ", 4, 5, 0, false}, + {"reset to 0: 5, 5 -> 0, ", 5, 5, 0, true}, + {"reset to 0: 6, 5 -> 0, ", 6, 5, 0, true}, + {"reset to 0: 10, 5 -> 0, ", 10, 5, 0, true}, + {"modify backwards: 1, 10 -> 5, ", 1, 10, 5, false}, + {"modify backwards: 4, 10 -> 5, ", 4, 10, 5, false}, + {"modify backwards: 5, 10 -> 5, ", 5, 10, 5, true}, + {"modify backwards: 6, 10 -> 5, ", 6, 10, 5, true}, + {"modify backwards: 9, 10 -> 5, ", 9, 10, 5, true}, + {"modify backwards: 10, 10 -> 5, ", 10, 10, 5, true}, + {"modify backwards: 11, 10 -> 5, ", 11, 10, 5, true}, + {"modify backwards: 100, 10 -> 5, ", 100, 10, 5, true}, + {"modify forward: 3, 10 -> 15, ", 3, 10, 15, false}, + {"modify forward: 9, 10 -> 15, ", 9, 10, 15, false}, + {"modify forward: 10, 10 -> 15, ", 10, 10, 15, true}, + {"modify forward: 11, 10 -> 15, ", 11, 10, 15, true}, + {"modify forward: 14, 10 -> 15, ", 14, 10, 15, true}, + {"modify forward: 15, 10 -> 15, ", 15, 10, 15, true}, + {"modify forward: 16, 10 -> 15, ", 16, 10, 15, true}, + {"modify forward: 100, 10 -> 15, ", 100, 10, 15, true}, + {"set to negative value: 3, 0 -> -5", 3, 0, -5, true}, + {"set to negative value: 3, -5 -> 100, ", 3, -5, 100, false}, + {"set to negative value: 3, -10 -> 3, ", 3, -10, 3, true}, + {"set to negative value: 3, -3 -> -3", 3, -3, -3, true}, + {"set to negative value: 100, -8 -> -9, ", 100, -8, -9, true}, + {"set to negative value: 300, -10 -> -8, ", 300, -10, -8, true}, + {"nil: 300, 400 -> nil, ", 300, 400, nilTest, false}, + {"nil: 300, 200 -> nil, ", 300, 200, nilTest, false}, + } + + // Test VoteExtensions enabling + for _, tc := range testCases { + t.Run(tc.name+" VE", func(*testing.T) { + initialParams := makeParams(makeParamsArgs{ + voteExtensionHeight: tc.from, + }) + update := &cmtproto.ConsensusParams{Feature: &cmtproto.FeatureParams{}} + if tc.to == nilTest { + update.Feature.VoteExtensionsEnableHeight = nil + } else { + update.Feature = &cmtproto.FeatureParams{ + VoteExtensionsEnableHeight: &types.Int64Value{Value: tc.to}, + } + } + if tc.expectedErr { + require.Error(t, initialParams.ValidateUpdate(update, tc.current)) + } else { + require.NoError(t, initialParams.ValidateUpdate(update, tc.current)) + } + }) + } + + // Test PBTS enabling + for _, tc := range testCases { + t.Run(tc.name+" PBTS", func(*testing.T) { + initialParams := makeParams(makeParamsArgs{ + pbtsHeight: tc.from, + }) + update := &cmtproto.ConsensusParams{Feature: &cmtproto.FeatureParams{}} + if tc.to == nilTest { + update.Feature.PbtsEnableHeight = nil + } else { + update.Feature = &cmtproto.FeatureParams{ + PbtsEnableHeight: &types.Int64Value{Value: tc.to}, + } + } + if tc.expectedErr { + require.Error(t, initialParams.ValidateUpdate(update, tc.current)) + } else { + require.NoError(t, initialParams.ValidateUpdate(update, tc.current)) + } + }) + } + + // Test PBTS and VE enabling + for _, tc := range testCases { + t.Run(tc.name+"VE PBTS", func(*testing.T) { + initialParams := makeParams(makeParamsArgs{ + voteExtensionHeight: tc.from, + pbtsHeight: tc.from, + }) + update := &cmtproto.ConsensusParams{Feature: &cmtproto.FeatureParams{}} + if tc.to == nilTest { + update.Feature.VoteExtensionsEnableHeight = nil + update.Feature.PbtsEnableHeight = nil + } else { + update.Feature = &cmtproto.FeatureParams{ + VoteExtensionsEnableHeight: &types.Int64Value{Value: tc.to}, + PbtsEnableHeight: &types.Int64Value{Value: tc.to}, + } + } + if tc.expectedErr { + require.Error(t, initialParams.ValidateUpdate(update, tc.current)) + } else { + require.NoError(t, initialParams.ValidateUpdate(update, tc.current)) + } + }) + } +} + +func consensusParamsForTestProto() []ConsensusParams { + return []ConsensusParams{ + makeParams(makeParamsArgs{blockBytes: 4, blockGas: 2, evidenceAge: 3, maxEvidenceBytes: 1, voteExtensionHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 4, blockGas: 2, evidenceAge: 3, maxEvidenceBytes: 1, pbtsHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 4, blockGas: 2, evidenceAge: 3, maxEvidenceBytes: 1, voteExtensionHeight: 1, pbtsHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 4, evidenceAge: 3, maxEvidenceBytes: 1, voteExtensionHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 4, evidenceAge: 3, maxEvidenceBytes: 1, pbtsHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 4, evidenceAge: 3, maxEvidenceBytes: 1, voteExtensionHeight: 1, pbtsHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 4, maxEvidenceBytes: 1, voteExtensionHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 4, maxEvidenceBytes: 1, pbtsHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 2, evidenceAge: 4, maxEvidenceBytes: 1, voteExtensionHeight: 1, pbtsHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 2, blockGas: 5, evidenceAge: 7, maxEvidenceBytes: 1, voteExtensionHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 1, blockGas: 7, evidenceAge: 6, maxEvidenceBytes: 1, voteExtensionHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 9, blockGas: 5, evidenceAge: 4, maxEvidenceBytes: 1, voteExtensionHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 7, blockGas: 8, evidenceAge: 9, maxEvidenceBytes: 1, voteExtensionHeight: 1}), + makeParams(makeParamsArgs{blockBytes: 4, blockGas: 6, evidenceAge: 5, maxEvidenceBytes: 1, voteExtensionHeight: 1}), + makeParams(makeParamsArgs{precision: time.Second, messageDelay: time.Minute}), + makeParams(makeParamsArgs{precision: time.Nanosecond, messageDelay: time.Millisecond}), + makeParams(makeParamsArgs{voteExtensionHeight: 100}), + makeParams(makeParamsArgs{pbtsHeight: 100}), + makeParams(makeParamsArgs{voteExtensionHeight: 100, pbtsHeight: 42}), + makeParams(makeParamsArgs{pbtsHeight: 100}), + } } func TestProto(t *testing.T) { - params := []ConsensusParams{ - makeParams(4, 2, 3, 1, valEd25519, 1), - makeParams(1, 4, 3, 1, valEd25519, 1), - makeParams(1, 2, 4, 1, valEd25519, 1), - makeParams(2, 5, 7, 1, valEd25519, 1), - makeParams(1, 7, 6, 1, valEd25519, 1), - makeParams(9, 5, 4, 1, valEd25519, 1), - makeParams(7, 8, 9, 1, valEd25519, 1), - makeParams(4, 6, 5, 1, valEd25519, 1), + params := consensusParamsForTestProto() + + for i := range params { + pbParams := params[i].ToProto() + + oriParams := ConsensusParamsFromProto(pbParams) + + assert.Equal(t, params[i], oriParams) } +} + +func TestProtoUpgrade(t *testing.T) { + params := consensusParamsForTestProto() for i := range params { pbParams := params[i].ToProto() + // Downgrade + if pbParams.GetFeature().GetVoteExtensionsEnableHeight().GetValue() > 0 { + pbParams.Abci = &cmtproto.ABCIParams{VoteExtensionsEnableHeight: pbParams.GetFeature().GetVoteExtensionsEnableHeight().GetValue()} //nolint: staticcheck + pbParams.Feature.VoteExtensionsEnableHeight = nil + } + oriParams := ConsensusParamsFromProto(pbParams) assert.Equal(t, params[i], oriParams) + } +} + +func durationPtr(t time.Duration) *time.Duration { + return &t +} +func TestParamsAdaptiveSynchronyParams(t *testing.T) { + originalSP := DefaultSynchronyParams() + assert.Equal(t, originalSP, originalSP.InRound(0), + "SynchronyParams(0) must be equal to SynchronyParams") + + lastSP := originalSP + for round := int32(1); round <= 10; round++ { + adaptedSP := originalSP.InRound(round) + assert.NotEqual(t, adaptedSP, lastSP) + assert.Equal(t, adaptedSP.Precision, lastSP.Precision, + "Precision must not change over rounds") + assert.Greater(t, adaptedSP.MessageDelay, lastSP.MessageDelay, + "MessageDelay must increase over rounds") + + // It should not increase a lot per round, say more than 25% + maxMessageDelay := lastSP.MessageDelay + lastSP.MessageDelay*25/100 + assert.LessOrEqual(t, adaptedSP.MessageDelay, maxMessageDelay, + "MessageDelay should not increase by more than 25% per round") + + lastSP = adaptedSP } + + assert.GreaterOrEqual(t, lastSP.MessageDelay, originalSP.MessageDelay*2, + "MessageDelay must at least double after 10 rounds") + assert.LessOrEqual(t, lastSP.MessageDelay, originalSP.MessageDelay*10, + "MessageDelay must not increase by more than 10 times after 10 rounds") } diff --git a/types/part_set.go b/types/part_set.go index cd110bfcec7..69a281526c8 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -6,18 +6,20 @@ import ( "fmt" "io" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto/merkle" - "github.com/cometbft/cometbft/libs/bits" + "github.com/cometbft/cometbft/internal/bits" + cmtsync "github.com/cometbft/cometbft/internal/sync" cmtbytes "github.com/cometbft/cometbft/libs/bytes" cmtjson "github.com/cometbft/cometbft/libs/json" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtsync "github.com/cometbft/cometbft/libs/sync" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) var ( ErrPartSetUnexpectedIndex = errors.New("error part set unexpected index") ErrPartSetInvalidProof = errors.New("error part set invalid proof") + ErrPartTooBig = errors.New("error part size too big") + ErrPartInvalidSize = errors.New("error inner part with invalid size") ) type Part struct { @@ -29,7 +31,11 @@ type Part struct { // ValidateBasic performs basic validation. func (part *Part) ValidateBasic() error { if len(part.Bytes) > int(BlockPartSizeBytes) { - return fmt.Errorf("too big: %d bytes, max: %d", len(part.Bytes), BlockPartSizeBytes) + return ErrPartTooBig + } + // All parts except the last one should have the same constant size. + if int64(part.Index) < part.Proof.Total-1 && len(part.Bytes) != int(BlockPartSizeBytes) { + return ErrPartInvalidSize } if err := part.Proof.ValidateBasic(); err != nil { return fmt.Errorf("wrong Proof: %w", err) @@ -46,7 +52,7 @@ func (part *Part) String() string { // StringIndented returns an indented Part. // -// See merkle.Proof#StringIndented +// See merkle.Proof#StringIndented. func (part *Part) StringIndented(indent string) string { return fmt.Sprintf(`Part{#%v %s Bytes: %X... @@ -89,7 +95,7 @@ func PartFromProto(pb *cmtproto.Part) (*Part, error) { return part, part.ValidateBasic() } -//------------------------------------- +// ------------------------------------- type PartSetHeader struct { Total uint32 `json:"total"` @@ -99,7 +105,7 @@ type PartSetHeader struct { // String returns a string representation of PartSetHeader. // // 1. total number of parts -// 2. first 6 bytes of the hash +// 2. first 6 bytes of the hash. func (psh PartSetHeader) String() string { return fmt.Sprintf("%v:%X", psh.Total, cmtbytes.Fingerprint(psh.Hash)) } @@ -121,7 +127,7 @@ func (psh PartSetHeader) ValidateBasic() error { return nil } -// ToProto converts PartSetHeader to protobuf +// ToProto converts PartSetHeader to protobuf. func (psh *PartSetHeader) ToProto() cmtproto.PartSetHeader { if psh == nil { return cmtproto.PartSetHeader{} @@ -133,7 +139,7 @@ func (psh *PartSetHeader) ToProto() cmtproto.PartSetHeader { } } -// FromProto sets a protobuf PartSetHeader to the given pointer +// PartSetHeaderFromProto sets a protobuf PartSetHeader to the given pointer. func PartSetHeaderFromProto(ppsh *cmtproto.PartSetHeader) (*PartSetHeader, error) { if ppsh == nil { return nil, errors.New("nil PartSetHeader") @@ -151,7 +157,7 @@ func ProtoPartSetHeaderIsZero(ppsh *cmtproto.PartSetHeader) bool { return ppsh.Total == 0 && len(ppsh.Hash) == 0 } -//------------------------------------- +// ------------------------------------- type PartSet struct { total uint32 @@ -166,11 +172,11 @@ type PartSet struct { byteSize int64 } -// Returns an immutable, full PartSet from the data bytes. +// NewPartSetFromData returns an immutable, full PartSet from the data bytes. // The data bytes are split into "partSize" chunks, and merkle tree computed. // CONTRACT: partSize is greater than zero. func NewPartSetFromData(data []byte, partSize uint32) *PartSet { - // divide data into 4kb parts. + // divide data into parts of size `partSize` total := (uint32(len(data)) + partSize - 1) / partSize parts := make([]*Part, total) partsBytes := make([][]byte, total) @@ -199,7 +205,7 @@ func NewPartSetFromData(data []byte, partSize uint32) *PartSet { } } -// Returns an empty PartSet ready to be populated. +// NewPartSetFromHeader returns an empty PartSet ready to be populated. func NewPartSetFromHeader(header PartSetHeader) *PartSet { return &PartSet{ total: header.Total, @@ -270,9 +276,12 @@ func (ps *PartSet) Total() uint32 { } func (ps *PartSet) AddPart(part *Part) (bool, error) { + // TODO: remove this? would be preferable if this only returned (false, nil) + // when its a duplicate block part if ps == nil { return false, nil } + ps.mtx.Lock() defer ps.mtx.Unlock() @@ -286,6 +295,11 @@ func (ps *PartSet) AddPart(part *Part) (bool, error) { return false, nil } + // The proof should be compatible with the number of parts. + if part.Proof.Total != int64(ps.total) { + return false, ErrPartSetInvalidProof + } + // Check hash proof if part.Proof.Verify(ps.Hash(), part.Bytes) != nil { return false, ErrPartSetInvalidProof @@ -353,7 +367,7 @@ func (psr *PartSetReader) Read(p []byte) (n int, err error) { // StringShort returns a short version of String. // -// (Count of Total) +// (Count of Total). func (ps *PartSet) StringShort() string { if ps == nil { return "nil-PartSet" diff --git a/types/part_set_test.go b/types/part_set_test.go index c1f885260cd..311edae4875 100644 --- a/types/part_set_test.go +++ b/types/part_set_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/crypto/merkle" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) const ( @@ -44,11 +44,11 @@ func TestBasicPartSet(t *testing.T) { // adding part with invalid index added, err := partSet2.AddPart(&Part{Index: 10000}) assert.False(t, added) - assert.Error(t, err) + require.Error(t, err) // adding existing part added, err = partSet2.AddPart(partSet2.GetPart(0)) assert.False(t, added) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, partSet.Hash(), partSet2.Hash()) assert.EqualValues(t, nParts, partSet2.Total()) @@ -86,6 +86,22 @@ func TestWrongProof(t *testing.T) { if added || err == nil { t.Errorf("expected to fail adding a part with bad bytes.") } + + // Test adding a part with wrong proof index. + part = partSet.GetPart(2) + part.Proof.Index = 1 + added, err = partSet2.AddPart(part) + if added || err == nil { + t.Errorf("expected to fail adding a part with bad proof index.") + } + + // Test adding a part with wrong proof total. + part = partSet.GetPart(3) + part.Proof.Total = int64(partSet.Total() - 1) + added, err = partSet2.AddPart(part) + if added || err == nil { + t.Errorf("expected to fail adding a part with bad proof total.") + } } func TestPartSetHeaderValidateBasic(t *testing.T) { @@ -94,7 +110,7 @@ func TestPartSetHeaderValidateBasic(t *testing.T) { malleatePartSetHeader func(*PartSetHeader) expectErr bool }{ - {"Good PartSet", func(psHeader *PartSetHeader) {}, false}, + {"Good PartSet", func(_ *PartSetHeader) {}, false}, {"Invalid Hash", func(psHeader *PartSetHeader) { psHeader.Hash = make([]byte, 1) }, true}, } for _, tc := range testCases { @@ -115,11 +131,21 @@ func TestPartValidateBasic(t *testing.T) { malleatePart func(*Part) expectErr bool }{ - {"Good Part", func(pt *Part) {}, false}, + {"Good Part", func(_ *Part) {}, false}, {"Too big part", func(pt *Part) { pt.Bytes = make([]byte, BlockPartSizeBytes+1) }, true}, + {"Good small last part", func(pt *Part) { + pt.Index = 1 + pt.Bytes = make([]byte, BlockPartSizeBytes-1) + pt.Proof.Total = 2 + }, false}, + {"Too small inner part", func(pt *Part) { + pt.Index = 0 + pt.Bytes = make([]byte, BlockPartSizeBytes-1) + pt.Proof.Total = 2 + }, true}, {"Too big proof", func(pt *Part) { pt.Proof = merkle.Proof{ - Total: 1, + Total: 2, Index: 1, LeafHash: make([]byte, 1024*1024), } @@ -145,8 +171,10 @@ func TestParSetHeaderProtoBuf(t *testing.T) { expPass bool }{ {"success empty", &PartSetHeader{}, true}, - {"success", - &PartSetHeader{Total: 1, Hash: []byte("hash")}, true}, + { + "success", + &PartSetHeader{Total: 1, Hash: []byte("hash")}, true, + }, } for _, tc := range testCases { @@ -162,7 +190,6 @@ func TestParSetHeaderProtoBuf(t *testing.T) { } func TestPartProtoBuf(t *testing.T) { - proof := merkle.Proof{ Total: 1, Index: 1, @@ -175,8 +202,10 @@ func TestPartProtoBuf(t *testing.T) { }{ {"failure empty", &Part{}, false}, {"failure nil", nil, false}, - {"success", - &Part{Index: 1, Bytes: cmtrand.Bytes(32), Proof: proof}, true}, + { + "success", + &Part{Index: 1, Bytes: cmtrand.Bytes(32), Proof: proof}, true, + }, } for _, tc := range testCases { diff --git a/types/priv_validator.go b/types/priv_validator.go index b12dd6e6765..91f2bff25b7 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -5,18 +5,28 @@ import ( "errors" "fmt" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) // PrivValidator defines the functionality of a local CometBFT validator // that signs votes and proposals, and never double signs. type PrivValidator interface { + // GetPubKey returns the public key of the validator. GetPubKey() (crypto.PubKey, error) - SignVote(chainID string, vote *cmtproto.Vote) error + // FIXME: should use the domain types defined in this package, not the proto types + + // SignVote signs a canonical representation of the vote. If signExtension is + // true, it also signs the vote extension. + SignVote(chainID string, vote *cmtproto.Vote, signExtension bool) error + + // SignProposal signs a canonical representation of the proposal. SignProposal(chainID string, proposal *cmtproto.Proposal) error + + // SignBytes signs an arbitrary array of bytes. + SignBytes(bytes []byte) ([]byte, error) } type PrivValidatorsByAddress []PrivValidator @@ -42,7 +52,7 @@ func (pvs PrivValidatorsByAddress) Swap(i, j int) { pvs[i], pvs[j] = pvs[j], pvs[i] } -//---------------------------------------- +// ---------------------------------------- // MockPV // MockPV implements PrivValidator without any safety or persistence. @@ -64,13 +74,13 @@ func NewMockPVWithParams(privKey crypto.PrivKey, breakProposalSigning, breakVote return MockPV{privKey, breakProposalSigning, breakVoteSigning} } -// Implements PrivValidator. +// GetPubKey implements PrivValidator. func (pv MockPV) GetPubKey() (crypto.PubKey, error) { return pv.PrivKey.PubKey(), nil } -// Implements PrivValidator. -func (pv MockPV) SignVote(chainID string, vote *cmtproto.Vote) error { +// SignVote implements PrivValidator. +func (pv MockPV) SignVote(chainID string, vote *cmtproto.Vote, signExtension bool) error { useChainID := chainID if pv.breakVoteSigning { useChainID = "incorrect-chain-id" @@ -83,22 +93,24 @@ func (pv MockPV) SignVote(chainID string, vote *cmtproto.Vote) error { } vote.Signature = sig - var extSig []byte - // We only sign vote extensions for non-nil precommits - if vote.Type == cmtproto.PrecommitType && !ProtoBlockIDIsNil(&vote.BlockID) { - extSignBytes := VoteExtensionSignBytes(useChainID, vote) - extSig, err = pv.PrivKey.Sign(extSignBytes) - if err != nil { - return err + if signExtension { + var extSig []byte + // We only sign vote extensions for non-nil precommits + if vote.Type == PrecommitType && !ProtoBlockIDIsNil(&vote.BlockID) { + extSignBytes := VoteExtensionSignBytes(useChainID, vote) + extSig, err = pv.PrivKey.Sign(extSignBytes) + if err != nil { + return err + } + } else if len(vote.Extension) > 0 { + return errors.New("unexpected vote extension - vote extensions are only allowed in non-nil precommits") } - } else if len(vote.Extension) > 0 { - return errors.New("unexpected vote extension - vote extensions are only allowed in non-nil precommits") + vote.ExtensionSignature = extSig } - vote.ExtensionSignature = extSig return nil } -// Implements PrivValidator. +// SignProposal implements PrivValidator. func (pv MockPV) SignProposal(chainID string, proposal *cmtproto.Proposal) error { useChainID := chainID if pv.breakProposalSigning { @@ -114,6 +126,11 @@ func (pv MockPV) SignProposal(chainID string, proposal *cmtproto.Proposal) error return nil } +// SignBytes implements PrivValidator. +func (pv MockPV) SignBytes(bytes []byte) ([]byte, error) { + return pv.PrivKey.Sign(bytes) +} + func (pv MockPV) ExtractIntoValidator(votingPower int64) *Validator { pubKey, _ := pv.GetPubKey() return &Validator{ @@ -130,7 +147,7 @@ func (pv MockPV) String() string { } // XXX: Implement. -func (pv MockPV) DisableChecks() { +func (MockPV) DisableChecks() { // Currently this does nothing, // as MockPV has no safety checks at all. } @@ -141,13 +158,13 @@ type ErroringMockPV struct { var ErroringMockPVErr = errors.New("erroringMockPV always returns an error") -// Implements PrivValidator. -func (pv *ErroringMockPV) SignVote(chainID string, vote *cmtproto.Vote) error { +// SignVote implements PrivValidator. +func (*ErroringMockPV) SignVote(string, *cmtproto.Vote, bool) error { return ErroringMockPVErr } -// Implements PrivValidator. -func (pv *ErroringMockPV) SignProposal(chainID string, proposal *cmtproto.Proposal) error { +// SignProposal implements PrivValidator. +func (*ErroringMockPV) SignProposal(string, *cmtproto.Proposal) error { return ErroringMockPVErr } diff --git a/types/proposal.go b/types/proposal.go index 9bae5e4efa4..ad727bd4c2d 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -5,9 +5,9 @@ import ( "fmt" "time" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + "github.com/cometbft/cometbft/internal/protoio" cmtbytes "github.com/cometbft/cometbft/libs/bytes" - "github.com/cometbft/cometbft/libs/protoio" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" cmttime "github.com/cometbft/cometbft/types/time" ) @@ -23,7 +23,7 @@ var ( // a so-called Proof-of-Lock (POL) round, as noted in the POLRound. // If POLRound >= 0, then BlockID corresponds to the block that is locked in POLRound. type Proposal struct { - Type cmtproto.SignedMsgType + Type SignedMsgType Height int64 `json:"height"` Round int32 `json:"round"` // there can not be greater than 2_147_483_647 rounds POLRound int32 `json:"pol_round"` // -1 if null. @@ -34,24 +34,24 @@ type Proposal struct { // NewProposal returns a new Proposal. // If there is no POLRound, polRound should be -1. -func NewProposal(height int64, round int32, polRound int32, blockID BlockID) *Proposal { +func NewProposal(height int64, round int32, polRound int32, blockID BlockID, ts time.Time) *Proposal { return &Proposal{ - Type: cmtproto.ProposalType, + Type: ProposalType, Height: height, Round: round, BlockID: blockID, POLRound: polRound, - Timestamp: cmttime.Now(), + Timestamp: cmttime.Canonical(ts), } } // ValidateBasic performs basic validation. func (p *Proposal) ValidateBasic() error { - if p.Type != cmtproto.ProposalType { + if p.Type != ProposalType { return errors.New("invalid Type") } - if p.Height < 0 { - return errors.New("negative Height") + if p.Height <= 0 { + return errors.New("non positive Height") } if p.Round < 0 { return errors.New("negative Round") @@ -59,26 +59,53 @@ func (p *Proposal) ValidateBasic() error { if p.POLRound < -1 { return errors.New("negative POLRound (exception: -1)") } + if p.POLRound >= p.Round { + return errors.New("POLRound >= Round") + } if err := p.BlockID.ValidateBasic(); err != nil { - return fmt.Errorf("wrong BlockID: %v", err) + return fmt.Errorf("wrong BlockID: %w", err) } // ValidateBasic above would pass even if the BlockID was empty: if !p.BlockID.IsComplete() { return fmt.Errorf("expected a complete, non-empty BlockID, got: %v", p.BlockID) } - - // NOTE: Timestamp validation is subtle and handled elsewhere. - + // Times must be canonical + if cmttime.Canonical(p.Timestamp) != p.Timestamp { + return fmt.Errorf("expected a canonical timestamp, got: %v", p.Timestamp) + } if len(p.Signature) == 0 { return errors.New("signature is missing") } - if len(p.Signature) > MaxSignatureSize { return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) } return nil } +// IsTimely validates that the proposal timestamp is 'timely' according to the +// proposer-based timestamp algorithm. To evaluate if a proposal is timely, its +// timestamp is compared to the local time of the validator when it receives +// the proposal along with the configured Precision and MessageDelay +// parameters. Specifically, a proposed proposal timestamp is considered timely +// if it is satisfies the following inequalities: +// +// proposalReceiveTime >= proposalTimestamp - Precision +// proposalReceiveTime <= proposalTimestamp + MessageDelay + Precision +// +// For more information on the meaning of 'timely', refer to the specification: +// https://github.com/cometbft/cometbft/tree/main/spec/consensus/proposer-based-timestamp +func (p *Proposal) IsTimely(recvTime time.Time, sp SynchronyParams) bool { + // lhs is `proposalTimestamp - Precision` in the first inequality + lhs := p.Timestamp.Add(-sp.Precision) + // rhs is `proposalTimestamp + MessageDelay + Precision` in the second inequality + rhs := p.Timestamp.Add(sp.MessageDelay).Add(sp.Precision) + + if recvTime.Before(lhs) || recvTime.After(rhs) { + return false + } + return true +} + // String returns a string representation of the Proposal. // // 1. height @@ -106,7 +133,7 @@ func (p *Proposal) String() string { // for backwards-compatibility with the Amino encoding, due to e.g. hardware // devices that rely on this encoding. // -// See CanonicalizeProposal +// See CanonicalizeProposal. func ProposalSignBytes(chainID string, p *cmtproto.Proposal) []byte { pb := CanonicalizeProposal(chainID, p) bz, err := protoio.MarshalDelimited(&pb) @@ -117,7 +144,7 @@ func ProposalSignBytes(chainID string, p *cmtproto.Proposal) []byte { return bz } -// ToProto converts Proposal to protobuf +// ToProto converts Proposal to protobuf. func (p *Proposal) ToProto() *cmtproto.Proposal { if p == nil { return &cmtproto.Proposal{} @@ -128,14 +155,14 @@ func (p *Proposal) ToProto() *cmtproto.Proposal { pb.Type = p.Type pb.Height = p.Height pb.Round = p.Round - pb.PolRound = p.POLRound + pb.PolRound = p.POLRound // FIXME: names do not match pb.Timestamp = p.Timestamp pb.Signature = p.Signature return pb } -// FromProto sets a protobuf Proposal to the given pointer. +// ProposalFromProto sets a protobuf Proposal to the given pointer. // It returns an error if the proposal is invalid. func ProposalFromProto(pp *cmtproto.Proposal) (*Proposal, error) { if pp == nil { @@ -153,7 +180,7 @@ func ProposalFromProto(pp *cmtproto.Proposal) (*Proposal, error) { p.Type = pp.Type p.Height = pp.Height p.Round = pp.Round - p.POLRound = pp.PolRound + p.POLRound = pp.PolRound // FIXME: names do not match p.Timestamp = pp.Timestamp p.Signature = pp.Signature diff --git a/types/proposal_test.go b/types/proposal_test.go index 0e7f574c4ac..97b4f7e03a2 100644 --- a/types/proposal_test.go +++ b/types/proposal_test.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "math" "testing" "time" @@ -9,27 +10,34 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto/tmhash" - "github.com/cometbft/cometbft/libs/protoio" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cometbft/cometbft/internal/protoio" + cmtrand "github.com/cometbft/cometbft/internal/rand" + cmttime "github.com/cometbft/cometbft/types/time" ) var ( testProposal *Proposal + testBlockID BlockID pbp *cmtproto.Proposal ) func init() { - var stamp, err = time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z") + stamp, err := time.Parse(TimeFormat, "2018-02-11T07:09:22.765Z") if err != nil { panic(err) } + + testBlockID = BlockID{ + Hash: []byte("--June_15_2020_amino_was_removed"), + PartSetHeader: PartSetHeader{Total: 111, Hash: []byte("--June_15_2020_amino_was_removed")}, + } testProposal = &Proposal{ - Height: 12345, - Round: 23456, - BlockID: BlockID{Hash: []byte("--June_15_2020_amino_was_removed"), - PartSetHeader: PartSetHeader{Total: 111, Hash: []byte("--June_15_2020_amino_was_removed")}}, + Type: ProposalType, + Height: 12345, + Round: 23456, + BlockID: testBlockID, POLRound: -1, Timestamp: stamp, } @@ -60,8 +68,8 @@ func TestProposalVerifySignature(t *testing.T) { require.NoError(t, err) prop := NewProposal( - 4, 2, 2, - BlockID{cmtrand.Bytes(tmhash.Size), PartSetHeader{777, cmtrand.Bytes(tmhash.Size)}}) + 4, 2, 1, + BlockID{cmtrand.Bytes(tmhash.Size), PartSetHeader{777, cmtrand.Bytes(tmhash.Size)}}, cmttime.Now()) p := prop.ToProto() signBytes := ProposalSignBytes("test_chain_id", p) @@ -123,50 +131,73 @@ func BenchmarkProposalVerifySignature(b *testing.B) { } func TestProposalValidateBasic(t *testing.T) { - privVal := NewMockPV() + blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) + location, err := time.LoadLocation("CET") + require.NoError(t, err) + testCases := []struct { testName string malleateProposal func(*Proposal) expectErr bool }{ - {"Good Proposal", func(p *Proposal) {}, false}, - {"Invalid Type", func(p *Proposal) { p.Type = cmtproto.PrecommitType }, true}, + {"Good Proposal", func(*Proposal) {}, false}, + {"Test Proposal", func(p *Proposal) { + p.Type = testProposal.Type + p.Height = testProposal.Height + p.Round = testProposal.Round + p.BlockID = testProposal.BlockID + p.POLRound = testProposal.POLRound + p.Timestamp = testProposal.Timestamp + }, false}, + {"Invalid Type", func(p *Proposal) { p.Type = PrecommitType }, true}, {"Invalid Height", func(p *Proposal) { p.Height = -1 }, true}, + {"Zero Height", func(p *Proposal) { p.Height = 0 }, true}, {"Invalid Round", func(p *Proposal) { p.Round = -1 }, true}, {"Invalid POLRound", func(p *Proposal) { p.POLRound = -2 }, true}, + {"POLRound == Round", func(p *Proposal) { p.POLRound = p.Round }, true}, {"Invalid BlockId", func(p *Proposal) { p.BlockID = BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}} }, true}, {"Invalid Signature", func(p *Proposal) { p.Signature = make([]byte, 0) }, true}, + {"Small Signature", func(p *Proposal) { + p.Signature = make([]byte, MaxSignatureSize-1) + }, false}, {"Too big Signature", func(p *Proposal) { p.Signature = make([]byte, MaxSignatureSize+1) }, true}, + {"Non canonical time", func(p *Proposal) { + p.Timestamp = time.Now().In(location) + }, true}, + {"Not rounded time", func(p *Proposal) { + p.Timestamp = time.Now() + }, true}, } - blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) - for _, tc := range testCases { tc := tc t.Run(tc.testName, func(t *testing.T) { prop := NewProposal( - 4, 2, 2, - blockID) + 4, 2, 1, + blockID, cmttime.Now()) p := prop.ToProto() err := privVal.SignProposal("test_chain_id", p) prop.Signature = p.Signature require.NoError(t, err) + tc.malleateProposal(prop) - assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result") + err = prop.ValidateBasic() + errMessage := fmt.Sprintf("Validate Basic had an unexpected error: %v", err) + assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, errMessage) }) } } func TestProposalProtoBuf(t *testing.T) { - proposal := NewProposal(1, 2, 3, makeBlockID([]byte("hash"), 2, []byte("part_set_hash"))) + proposal := NewProposal(1, 2, 1, makeBlockID([]byte("hash"), 2, []byte("part_set_hash")), cmttime.Now()) proposal.Signature = []byte("sig") - proposal2 := NewProposal(1, 2, 3, BlockID{}) + proposal2 := NewProposal(1, 2, 1, BlockID{}, cmttime.Now()) testCases := []struct { msg string @@ -190,3 +221,69 @@ func TestProposalProtoBuf(t *testing.T) { } } } + +func TestProposalIsTimely(t *testing.T) { + timestamp, err := time.Parse(time.RFC3339, "2019-03-13T23:00:00Z") + sp := SynchronyParams{ + Precision: time.Nanosecond, + MessageDelay: 2 * time.Nanosecond, + } + require.NoError(t, err) + testCases := []struct { + name string + proposalHeight int64 + proposalTimestamp time.Time + proposalReceiveTime time.Time + expectTimely bool + }{ + // Timely requirements: + // proposalReceiveTime >= proposalTimestamp - PRECISION + // proposalReceiveTime <= proposalTimestamp + MSGDELAY + PRECISION + { + name: "timestamp in the past", + proposalHeight: 2, + proposalTimestamp: timestamp, + proposalReceiveTime: timestamp.Add(sp.Precision + sp.MessageDelay), + expectTimely: true, + }, + { + name: "timestamp far in the past", + proposalHeight: 2, + proposalTimestamp: timestamp, + proposalReceiveTime: timestamp.Add(sp.Precision + sp.MessageDelay + 1), + expectTimely: false, + }, + { + name: "timestamp in the future", + proposalHeight: 2, + proposalTimestamp: timestamp.Add(sp.Precision), + proposalReceiveTime: timestamp, + expectTimely: true, + }, + { + name: "timestamp far in the future", + proposalHeight: 2, + proposalTimestamp: timestamp.Add(sp.Precision + 1), + proposalReceiveTime: timestamp, + expectTimely: false, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + p := Proposal{ + Type: ProposalType, + Height: testCase.proposalHeight, + Timestamp: testCase.proposalTimestamp, + Round: 0, + POLRound: -1, + BlockID: testBlockID, + Signature: []byte{1}, + } + require.NoError(t, p.ValidateBasic()) + + ti := p.IsTimely(testCase.proposalReceiveTime, sp) + assert.Equal(t, testCase.expectTimely, ti) + }) + } +} diff --git a/types/protobuf.go b/types/protobuf.go index 4393f571c6e..1c8d22a6e93 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -2,15 +2,15 @@ package types import ( abci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" cryptoenc "github.com/cometbft/cometbft/crypto/encoding" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) -//------------------------------------------------------- +// ------------------------------------------------------- // TM2PB is used for converting CometBFT ABCI to protobuf ABCI. -// UNSTABLE +// UNSTABLE. var TM2PB = tm2pb{} type tm2pb struct{} @@ -59,7 +59,7 @@ func (tm2pb) PartSetHeader(header PartSetHeader) cmtproto.PartSetHeader { } } -// XXX: panics on unknown pubkey type +// XXX: panics on unknown pubkey type. func (tm2pb) ValidatorUpdate(val *Validator) abci.ValidatorUpdate { pk, err := cryptoenc.PubKeyToProto(val.PubKey) if err != nil { @@ -71,7 +71,7 @@ func (tm2pb) ValidatorUpdate(val *Validator) abci.ValidatorUpdate { } } -// XXX: panics on nil or unknown pubkey type +// XXX: panics on nil or unknown pubkey type. func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate { validators := make([]abci.ValidatorUpdate, vals.Size()) for i, val := range vals.Validators { @@ -80,7 +80,7 @@ func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate { return validators } -// XXX: panics on nil or unknown pubkey type +// XXX: panics on nil or unknown pubkey type. func (tm2pb) NewValidatorUpdate(pubkey crypto.PubKey, power int64) abci.ValidatorUpdate { pubkeyABCI, err := cryptoenc.PubKeyToProto(pubkey) if err != nil { @@ -92,10 +92,10 @@ func (tm2pb) NewValidatorUpdate(pubkey crypto.PubKey, power int64) abci.Validato } } -//---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // PB2TM is used for converting protobuf ABCI to CometBFT ABCI. -// UNSTABLE +// UNSTABLE. var PB2TM = pb2tm{} type pb2tm struct{} diff --git a/types/protobuf_test.go b/types/protobuf_test.go index 375b304d282..3a822b52f5d 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -14,17 +14,16 @@ import ( func TestABCIPubKey(t *testing.T) { pkEd := ed25519.GenPrivKey().PubKey() - err := testABCIPubKey(t, pkEd, ABCIPubKeyTypeEd25519) - assert.NoError(t, err) + testABCIPubKey(t, pkEd) } -func testABCIPubKey(t *testing.T, pk crypto.PubKey, typeStr string) error { +func testABCIPubKey(t *testing.T, pk crypto.PubKey) { + t.Helper() abciPubKey, err := cryptoenc.PubKeyToProto(pk) require.NoError(t, err) pk2, err := cryptoenc.PubKeyFromProto(abciPubKey) require.NoError(t, err) require.Equal(t, pk, pk2) - return nil } func TestABCIValidators(t *testing.T) { @@ -37,7 +36,7 @@ func TestABCIValidators(t *testing.T) { abciVal := TM2PB.ValidatorUpdate(cmtVal) cmtVals, err := PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{abciVal}) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, cmtValExpected, cmtVals[0]) abciVals := TM2PB.ValidatorUpdates(NewValidatorSet(cmtVals)) @@ -48,18 +47,18 @@ func TestABCIValidators(t *testing.T) { abciVal = TM2PB.ValidatorUpdate(cmtVal) cmtVals, err = PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{abciVal}) - assert.Nil(t, err) + require.NoError(t, err) assert.Equal(t, cmtValExpected, cmtVals[0]) } type pubKeyEddie struct{} -func (pubKeyEddie) Address() Address { return []byte{} } -func (pubKeyEddie) Bytes() []byte { return []byte{} } -func (pubKeyEddie) VerifySignature(msg []byte, sig []byte) bool { return false } -func (pubKeyEddie) Equals(crypto.PubKey) bool { return false } -func (pubKeyEddie) String() string { return "" } -func (pubKeyEddie) Type() string { return "pubKeyEddie" } +func (pubKeyEddie) Address() Address { return []byte{} } +func (pubKeyEddie) Bytes() []byte { return []byte{} } +func (pubKeyEddie) VerifySignature([]byte, []byte) bool { return false } +func (pubKeyEddie) Equals(crypto.PubKey) bool { return false } +func (pubKeyEddie) String() string { return "" } +func (pubKeyEddie) Type() string { return "pubKeyEddie" } func TestABCIValidatorFromPubKeyAndPower(t *testing.T) { pubkey := ed25519.GenPrivKey().PubKey() diff --git a/types/results.go b/types/results.go index 2c6728a6d3e..abf42f6f760 100644 --- a/types/results.go +++ b/types/results.go @@ -13,7 +13,7 @@ type ABCIResults []*abci.ExecTxResult func NewResults(responses []*abci.ExecTxResult) ABCIResults { res := make(ABCIResults, len(responses)) for i, d := range responses { - res[i] = deterministicExecTxResult(d) + res[i] = abci.DeterministicExecTxResult(d) } return res } @@ -23,7 +23,7 @@ func (a ABCIResults) Hash() []byte { return merkle.HashFromByteSlices(a.toByteSlices()) } -// ProveResult returns a merkle proof of one result from the set +// ProveResult returns a merkle proof of one result from the set. func (a ABCIResults) ProveResult(i int) merkle.Proof { _, proofs := merkle.ProofsFromByteSlices(a.toByteSlices()) return *proofs[i] @@ -41,14 +41,3 @@ func (a ABCIResults) toByteSlices() [][]byte { } return bzs } - -// deterministicExecTxResult strips non-deterministic fields from -// ExecTxResult and returns another ExecTxResult. -func deterministicExecTxResult(response *abci.ExecTxResult) *abci.ExecTxResult { - return &abci.ExecTxResult{ - Code: response.Code, - Data: response.Data, - GasWanted: response.GasWanted, - GasUsed: response.GasUsed, - } -} diff --git a/types/results_test.go b/types/results_test.go index bf3db01ecaa..e08c67185d3 100644 --- a/types/results_test.go +++ b/types/results_test.go @@ -49,6 +49,6 @@ func TestABCIResults(t *testing.T) { proof := results.ProveResult(i) valid := proof.Verify(root, bz) - assert.NoError(t, valid, "%d", i) + require.NoError(t, valid, "%d", i) } } diff --git a/types/signable.go b/types/signable.go index 8ba2e6599a1..3f3453a62d0 100644 --- a/types/signable.go +++ b/types/signable.go @@ -1,16 +1,15 @@ package types import ( + "github.com/cometbft/cometbft/crypto/bls12381" "github.com/cometbft/cometbft/crypto/ed25519" cmtmath "github.com/cometbft/cometbft/libs/math" ) -var ( - // MaxSignatureSize is a maximum allowed signature size for the Proposal - // and Vote. - // XXX: secp256k1 does not have Size nor MaxSize defined. - MaxSignatureSize = cmtmath.MaxInt(ed25519.SignatureSize, 64) -) +// MaxSignatureSize is a maximum allowed signature size for the Proposal +// and Vote. +// XXX: secp256k1 does not have Size nor MaxSize defined. +var MaxSignatureSize = cmtmath.MaxInt(ed25519.SignatureSize, cmtmath.MaxInt(bls12381.SignatureLength, 64)) // Signable is an interface for all signable things. // It typically removes signatures before serializing. diff --git a/types/signed_msg_type.go b/types/signed_msg_type.go index e8daccbb1b3..f879d4a4439 100644 --- a/types/signed_msg_type.go +++ b/types/signed_msg_type.go @@ -1,11 +1,20 @@ package types -import cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" +import cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + +type SignedMsgType = cmtproto.SignedMsgType + +const ( + UnknownType SignedMsgType = cmtproto.UnknownType + PrevoteType SignedMsgType = cmtproto.PrevoteType + PrecommitType SignedMsgType = cmtproto.PrecommitType + ProposalType SignedMsgType = cmtproto.ProposalType +) // IsVoteTypeValid returns true if t is a valid vote type. -func IsVoteTypeValid(t cmtproto.SignedMsgType) bool { +func IsVoteTypeValid(t SignedMsgType) bool { switch t { - case cmtproto.PrevoteType, cmtproto.PrecommitType: + case PrevoteType, PrecommitType: return true default: return false diff --git a/types/test_util.go b/types/test_util.go index 8f94e6d91be..2a959ef3af9 100644 --- a/types/test_util.go +++ b/types/test_util.go @@ -5,15 +5,15 @@ import ( "testing" "time" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmtversion "github.com/cometbft/cometbft/proto/tendermint/version" - "github.com/cometbft/cometbft/version" "github.com/stretchr/testify/require" + + cmtversion "github.com/cometbft/cometbft/api/cometbft/version/v1" + "github.com/cometbft/cometbft/version" ) func MakeExtCommit(blockID BlockID, height int64, round int32, - voteSet *VoteSet, validators []PrivValidator, now time.Time, extEnabled bool) (*ExtendedCommit, error) { - + voteSet *VoteSet, validators []PrivValidator, now time.Time, extEnabled bool, +) (*ExtendedCommit, error) { // all sign for i := 0; i < len(validators); i++ { pubKey, err := validators[i].GetPubKey() @@ -25,7 +25,7 @@ func MakeExtCommit(blockID BlockID, height int64, round int32, ValidatorIndex: int32(i), Height: height, Round: round, - Type: cmtproto.PrecommitType, + Type: PrecommitType, BlockID: blockID, Timestamp: now, } @@ -36,12 +36,12 @@ func MakeExtCommit(blockID BlockID, height int64, round int32, } } - var enableHeight int64 + p := DefaultFeatureParams() if extEnabled { - enableHeight = height + p.VoteExtensionsEnableHeight = height } - return voteSet.MakeExtendedCommit(ABCIParams{VoteExtensionsEnableHeight: enableHeight}), nil + return voteSet.MakeExtendedCommit(p), nil } func signAddVote(privVal PrivValidator, vote *Vote, voteSet *VoteSet) (bool, error) { @@ -60,9 +60,9 @@ func MakeVote( valIndex int32, height int64, round int32, - step cmtproto.SignedMsgType, + step SignedMsgType, blockID BlockID, - time time.Time, + votetime time.Time, ) (*Vote, error) { pubKey, err := val.GetPubKey() if err != nil { @@ -76,10 +76,10 @@ func MakeVote( Round: round, Type: step, BlockID: blockID, - Timestamp: time, + Timestamp: votetime, } - extensionsEnabled := step == cmtproto.PrecommitType + extensionsEnabled := step == PrecommitType if _, err := SignAndCheckVote(vote, val, chainID, extensionsEnabled); err != nil { return nil, err } @@ -94,10 +94,12 @@ func MakeVoteNoError( valIndex int32, height int64, round int32, - step cmtproto.SignedMsgType, + step SignedMsgType, blockID BlockID, time time.Time, ) *Vote { + t.Helper() + vote, err := MakeVote(val, chainID, valIndex, height, round, step, blockID, time) require.NoError(t, err) return vote diff --git a/types/time/mocks/source.go b/types/time/mocks/source.go new file mode 100644 index 00000000000..85a0e0af2af --- /dev/null +++ b/types/time/mocks/source.go @@ -0,0 +1,46 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + time "time" + + mock "github.com/stretchr/testify/mock" +) + +// Source is an autogenerated mock type for the Source type +type Source struct { + mock.Mock +} + +// Now provides a mock function with given fields: +func (_m *Source) Now() time.Time { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Now") + } + + var r0 time.Time + if rf, ok := ret.Get(0).(func() time.Time); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(time.Time) + } + + return r0 +} + +// NewSource creates a new instance of Source. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSource(t interface { + mock.TestingT + Cleanup(func()) +}) *Source { + mock := &Source{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/types/time/now.go b/types/time/now.go new file mode 100644 index 00000000000..abea9a18d7b --- /dev/null +++ b/types/time/now.go @@ -0,0 +1,13 @@ +//go:build !clock_skew +// +build !clock_skew + +package time + +import ( + "time" +) + +// Now returns the current time in UTC with no monotonic component. +func Now() time.Time { + return Canonical(time.Now()) +} diff --git a/types/time/now_skew.go b/types/time/now_skew.go new file mode 100644 index 00000000000..8a975f8c649 --- /dev/null +++ b/types/time/now_skew.go @@ -0,0 +1,29 @@ +//go:build clock_skew +// +build clock_skew + +package time + +import ( + "fmt" + "os" + "time" +) + +var clockSkew time.Duration + +// Now returns the current time in UTC with no monotonic component. +func Now() time.Time { + return Canonical(time.Now().Add(clockSkew)) +} + +func init() { + skewStr := os.Getenv("COMETBFT_CLOCK_SKEW") + if len(skewStr) == 0 { + return + } + skew, err := time.ParseDuration(skewStr) + if err != nil { + panic(fmt.Sprintf("contents of env variable COMETBFT_CLOCK_SKEW (%q) must be empty or a duration expression", skewStr)) + } + clockSkew = skew +} diff --git a/types/time/time.go b/types/time/time.go index 022bdf574f8..1077aa1ebe7 100644 --- a/types/time/time.go +++ b/types/time/time.go @@ -5,11 +5,6 @@ import ( "time" ) -// Now returns the current time in UTC with no monotonic component. -func Now() time.Time { - return Canonical(time.Now()) -} - // Canonical returns UTC time with no monotonic component. // Stripping the monotonic component is for time equality. // See https://github.com/tendermint/tendermint/pull/2203#discussion_r215064334 @@ -17,6 +12,33 @@ func Canonical(t time.Time) time.Time { return t.Round(0).UTC() } +//go:generate ../../scripts/mockery_generate.sh Source + +// Source is an interface that defines a way to fetch the current time. +type Source interface { + Now() time.Time +} + +// Until returns the duration until t. +// It is shorthand for t.Sub(time.Now()). +func Until(t time.Time) time.Duration { + return t.Sub(Now()) +} + +// Since returns the time elapsed since t. +// It is shorthand for time.Now().Sub(t). +func Since(t time.Time) time.Duration { + return Now().Sub(t) +} + +// DefaultSource implements the Source interface using the system clock provided by the standard library. +type DefaultSource struct{} + +func (DefaultSource) Now() time.Time { + return Now() +} + +// TODO: find which commit removed this and make sure it's in our list // WeightedTime for computing a median. type WeightedTime struct { Time time.Time @@ -54,5 +76,5 @@ func WeightedMedian(weightedTimes []*WeightedTime, totalVotingPower int64) (res median -= weightedTime.Weight } } - return + return res } diff --git a/types/time/time_test.go b/types/time/time_test.go index 1b1a30e5058..93982c5301e 100644 --- a/types/time/time_test.go +++ b/types/time/time_test.go @@ -22,7 +22,7 @@ func TestWeightedMedian(t *testing.T) { median := WeightedMedian(m, totalVotingPower) assert.Equal(t, t2, median) // median always returns value between values of correct processes - assert.Equal(t, true, (median.After(t1) || median.Equal(t1)) && + assert.True(t, true, (median.After(t1) || median.Equal(t1)) && (median.Before(t3) || median.Equal(t3))) m[1] = NewWeightedTime(t1, 40) // correct processes @@ -33,7 +33,7 @@ func TestWeightedMedian(t *testing.T) { median = WeightedMedian(m, totalVotingPower) assert.Equal(t, t2, median) // median always returns value between values of correct processes - assert.Equal(t, true, (median.After(t1) || median.Equal(t1)) && + assert.True(t, true, (median.After(t1) || median.Equal(t1)) && (median.Before(t2) || median.Equal(t2))) m = make([]*WeightedTime, 8) @@ -51,6 +51,6 @@ func TestWeightedMedian(t *testing.T) { median = WeightedMedian(m, totalVotingPower) assert.Equal(t, t3, median) // median always returns value between values of correct processes - assert.Equal(t, true, (median.After(t1) || median.Equal(t1)) && + assert.True(t, (median.After(t1) || median.Equal(t1)) && (median.Before(t4) || median.Equal(t4))) } diff --git a/types/tx.go b/types/tx.go index 0ba14dbadd0..fa6930a56e6 100644 --- a/types/tx.go +++ b/types/tx.go @@ -6,13 +6,13 @@ import ( "errors" "fmt" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto/merkle" "github.com/cometbft/cometbft/crypto/tmhash" cmtbytes "github.com/cometbft/cometbft/libs/bytes" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) -// TxKeySize is the size of the transaction key index +// TxKeySize is the size of the transaction key index. const TxKeySize = sha256.Size type ( @@ -49,7 +49,7 @@ func (txs Txs) Hash() []byte { return merkle.HashFromByteSlices(hl) } -// Index returns the index of this transaction in the list, or -1 if not found +// Index returns the index of this transaction in the list, or -1 if not found. func (txs Txs) Index(tx Tx) int { for i := range txs { if bytes.Equal(txs[i], tx) { @@ -59,7 +59,7 @@ func (txs Txs) Index(tx Tx) int { return -1 } -// IndexByHash returns the index of this transaction hash in the list, or -1 if not found +// IndexByHash returns the index of this transaction hash in the list, or -1 if not found. func (txs Txs) IndexByHash(hash []byte) int { for i := range txs { if bytes.Equal(txs[i].Hash(), hash) { @@ -90,6 +90,7 @@ func (txs Txs) hashList() [][]byte { // Txs is a slice of transactions. Sorting a Txs value orders the transactions // lexicographically. + func (txs Txs) Len() int { return len(txs) } func (txs Txs) Swap(i, j int) { txs[i], txs[j] = txs[j], txs[i] } func (txs Txs) Less(i, j int) bool { @@ -107,7 +108,7 @@ func ToTxs(txl [][]byte) Txs { func (txs Txs) Validate(maxSizeBytes int64) error { var size int64 for _, tx := range txs { - size += int64(len(tx)) + size += ComputeProtoSizeForTxs([]Tx{tx}) if size > maxSizeBytes { return fmt.Errorf("transaction data size exceeds maximum %d", maxSizeBytes) } @@ -156,7 +157,6 @@ func (tp TxProof) Validate(dataHash []byte) error { } func (tp TxProof) ToProto() cmtproto.TxProof { - pbProof := tp.Proof.ToProto() pbtp := cmtproto.TxProof{ @@ -167,8 +167,8 @@ func (tp TxProof) ToProto() cmtproto.TxProof { return pbtp } -func TxProofFromProto(pb cmtproto.TxProof) (TxProof, error) { +func TxProofFromProto(pb cmtproto.TxProof) (TxProof, error) { pbProof, err := merkle.ProofFromProto(pb.Proof) if err != nil { return TxProof{}, err diff --git a/types/tx_test.go b/types/tx_test.go index f5de93ae276..9bd8c3c89af 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -8,9 +8,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - cmtrand "github.com/cometbft/cometbft/libs/rand" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + cmtrand "github.com/cometbft/cometbft/internal/rand" ctest "github.com/cometbft/cometbft/libs/test" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) func makeTxs(cnt, size int) Txs { @@ -71,8 +71,8 @@ func TestValidTxProof(t *testing.T) { assert.EqualValues(t, root, proof.RootHash, "%d: %d", h, i) assert.EqualValues(t, tx, proof.Data, "%d: %d", h, i) assert.EqualValues(t, txs[i].Hash(), proof.Leaf(), "%d: %d", h, i) - assert.Nil(t, proof.Validate(root), "%d: %d", h, i) - assert.NotNil(t, proof.Validate([]byte("foobar")), "%d: %d", h, i) + require.NoError(t, proof.Validate(root), "%d: %d", h, i) + require.Error(t, proof.Validate([]byte("foobar")), "%d: %d", h, i) // read-write must also work var ( @@ -87,8 +87,8 @@ func TestValidTxProof(t *testing.T) { require.NoError(t, err) p2, err = TxProofFromProto(pb2) - if assert.Nil(t, err, "%d: %d: %+v", h, i, err) { - assert.Nil(t, p2.Validate(root), "%d: %d", h, i) + if assert.NoError(t, err, "%d: %d: %+v", h, i, err) { //nolint:testifylint // require.Error doesn't work with the conditional here + require.NoError(t, p2.Validate(root), "%d: %d", h, i) } } } @@ -102,6 +102,7 @@ func TestTxProofUnchangable(t *testing.T) { } func testTxProofUnchangable(t *testing.T) { + t.Helper() // make some proof txs := makeTxs(randInt(2, 100), randInt(16, 128)) root := txs.Hash() @@ -109,7 +110,7 @@ func testTxProofUnchangable(t *testing.T) { proof := txs.Proof(i) // make sure it is valid to start with - assert.Nil(t, proof.Validate(root)) + require.NoError(t, proof.Validate(root)) pbProof := proof.ToProto() bin, err := pbProof.Marshal() require.NoError(t, err) @@ -123,9 +124,9 @@ func testTxProofUnchangable(t *testing.T) { } } -// This makes sure that the proof doesn't deserialize into something valid. +// assertBadProof makes sure that the proof doesn't deserialize into something valid. func assertBadProof(t *testing.T, root []byte, bad []byte, good TxProof) { - + t.Helper() var ( proof TxProof pbProof cmtproto.TxProof diff --git a/types/utils.go b/types/utils.go index 60e82fe3fd7..94942fea695 100644 --- a/types/utils.go +++ b/types/utils.go @@ -7,7 +7,7 @@ import "reflect" // - https://dave.cheney.net/2017/08/09/typed-nils-in-go-2 // - https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I/discussion // - https://github.com/golang/go/issues/21538 -func isTypedNil(o interface{}) bool { +func isTypedNil(o any) bool { rv := reflect.ValueOf(o) switch rv.Kind() { case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice: @@ -17,8 +17,8 @@ func isTypedNil(o interface{}) bool { } } -// Returns true if it has zero length. -func isEmpty(o interface{}) bool { +// isEmpty returns true if it has zero length. +func isEmpty(o any) bool { rv := reflect.ValueOf(o) switch rv.Kind() { case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String: diff --git a/types/validation.go b/types/validation.go index ad3a13690c5..f170fc3b0b8 100644 --- a/types/validation.go +++ b/types/validation.go @@ -7,6 +7,7 @@ import ( "github.com/cometbft/cometbft/crypto/batch" "github.com/cometbft/cometbft/crypto/tmhash" cmtmath "github.com/cometbft/cometbft/libs/math" + cmterrors "github.com/cometbft/cometbft/types/errors" ) const batchVerifyThreshold = 2 @@ -23,7 +24,8 @@ func shouldBatchVerify(vals *ValidatorSet, commit *Commit) bool { // includes which validators signed. For instance, Gaia incentivizes proposers // with a bonus for including more than +2/3 of the signatures. func VerifyCommit(chainID string, vals *ValidatorSet, blockID BlockID, - height int64, commit *Commit) error { + height int64, commit *Commit, +) error { // run a basic validation of the arguments if err := verifyBasicValsAndCommit(vals, commit, height, blockID); err != nil { return err @@ -54,10 +56,39 @@ func VerifyCommit(chainID string, vals *ValidatorSet, blockID BlockID, // VerifyCommitLight verifies +2/3 of the set had signed the given commit. // -// This method is primarily used by the light client and does not check all the +// This method is primarily used by the light client and does NOT check all the // signatures. -func VerifyCommitLight(chainID string, vals *ValidatorSet, blockID BlockID, - height int64, commit *Commit) error { +func VerifyCommitLight( + chainID string, + vals *ValidatorSet, + blockID BlockID, + height int64, + commit *Commit, +) error { + return verifyCommitLightInternal(chainID, vals, blockID, height, commit, false) +} + +// VerifyCommitLightAllSignatures verifies +2/3 of the set had signed the given commit. +// +// This method DOES check all the signatures. +func VerifyCommitLightAllSignatures( + chainID string, + vals *ValidatorSet, + blockID BlockID, + height int64, + commit *Commit, +) error { + return verifyCommitLightInternal(chainID, vals, blockID, height, commit, true) +} + +func verifyCommitLightInternal( + chainID string, + vals *ValidatorSet, + blockID BlockID, + height int64, + commit *Commit, + countAllSignatures bool, +) error { // run a basic validation of the arguments if err := verifyBasicValsAndCommit(vals, commit, height, blockID); err != nil { return err @@ -70,28 +101,63 @@ func VerifyCommitLight(chainID string, vals *ValidatorSet, blockID BlockID, ignore := func(c CommitSig) bool { return c.BlockIDFlag != BlockIDFlagCommit } // count all the remaining signatures - count := func(c CommitSig) bool { return true } + count := func(_ CommitSig) bool { return true } // attempt to batch verify if shouldBatchVerify(vals, commit) { return verifyCommitBatch(chainID, vals, commit, - votingPowerNeeded, ignore, count, false, true) + votingPowerNeeded, ignore, count, countAllSignatures, true) } // if verification failed or is not supported then fallback to single verification return verifyCommitSingle(chainID, vals, commit, votingPowerNeeded, - ignore, count, false, true) + ignore, count, countAllSignatures, true) } // VerifyCommitLightTrusting verifies that trustLevel of the validator set signed -// this commit. +// this commit. "Trusting" means that we trust the validator set to be correct. // // NOTE the given validators do not necessarily correspond to the validator set // for this commit, but there may be some intersection. // -// This method is primarily used by the light client and does not check all the +// This method is primarily used by the light client and does NOT check all the // signatures. -func VerifyCommitLightTrusting(chainID string, vals *ValidatorSet, commit *Commit, trustLevel cmtmath.Fraction) error { +// +// CONTRACT: must run ValidateBasic() on commit before verifying. +func VerifyCommitLightTrusting( + chainID string, + vals *ValidatorSet, + commit *Commit, + trustLevel cmtmath.Fraction, +) error { + return verifyCommitLightTrustingInternal(chainID, vals, commit, trustLevel, false) +} + +// VerifyCommitLightTrustingAllSignatures verifies that trustLevel of the validator +// set signed this commit. "Trusting" means that we trust the validator set to be correct. +// +// NOTE the given validators do not necessarily correspond to the validator set +// for this commit, but there may be some intersection. +// +// This method DOES check all the signatures. +// +// CONTRACT: must run ValidateBasic() on commit before verifying. +func VerifyCommitLightTrustingAllSignatures( + chainID string, + vals *ValidatorSet, + commit *Commit, + trustLevel cmtmath.Fraction, +) error { + return verifyCommitLightTrustingInternal(chainID, vals, commit, trustLevel, true) +} + +func verifyCommitLightTrustingInternal( + chainID string, + vals *ValidatorSet, + commit *Commit, + trustLevel cmtmath.Fraction, + countAllSignatures bool, +) error { // sanity checks if vals == nil { return errors.New("nil validator set") @@ -114,19 +180,19 @@ func VerifyCommitLightTrusting(chainID string, vals *ValidatorSet, commit *Commi ignore := func(c CommitSig) bool { return c.BlockIDFlag != BlockIDFlagCommit } // count all the remaining signatures - count := func(c CommitSig) bool { return true } + count := func(_ CommitSig) bool { return true } // attempt to batch verify commit. As the validator set doesn't necessarily // correspond with the validator set that signed the block we need to look // up by address rather than index. if shouldBatchVerify(vals, commit) { return verifyCommitBatch(chainID, vals, commit, - votingPowerNeeded, ignore, count, false, false) + votingPowerNeeded, ignore, count, countAllSignatures, false) } // attempt with single verification return verifyCommitSingle(chainID, vals, commit, votingPowerNeeded, - ignore, count, false, false) + ignore, count, countAllSignatures, false) } // ValidateHash returns an error if the hash is not empty, but its @@ -171,7 +237,7 @@ func verifyCommitBatch( // re-check if batch verification is supported if !ok || len(commit.Signatures) < batchVerifyThreshold { // This should *NEVER* happen. - return fmt.Errorf("unsupported signature algorithm or insufficient signatures for batch verification") + return errors.New("unsupported signature algorithm or insufficient signatures for batch verification") } for idx, commitSig := range commit.Signatures { @@ -180,7 +246,7 @@ func verifyCommitBatch( continue } - // If the vals and commit have a 1-to-1 correspondance we can retrieve + // If the vals and commit have a 1-to-1 correspondence we can retrieve // them by index else we need to retrieve them by address if lookUpByIndex { val = vals.Validators[idx] @@ -252,7 +318,7 @@ func verifyCommitBatch( // happened: // * non-zero tallied voting power, empty batch (impossible?) // * bv.Verify() returned `false, []bool{true, ..., true}` (BUG) - return fmt.Errorf("BUG: batch verification failed with no invalid signatures") + return errors.New("BUG: batch verification failed with no invalid signatures") } // Single Verification @@ -261,7 +327,7 @@ func verifyCommitBatch( // If a key does not support batch verification, or batch verification fails this will be used // This method is used to check all the signatures included in a commit. // It is used in consensus for validating a block LastCommit. -// CONTRACT: both commit and validator set should have passed validate basic +// CONTRACT: both commit and validator set should have passed validate basic. func verifyCommitSingle( chainID string, vals *ValidatorSet, @@ -284,7 +350,11 @@ func verifyCommitSingle( continue } - // If the vals and commit have a 1-to-1 correspondance we can retrieve + if commitSig.ValidateBasic() != nil { + return fmt.Errorf("invalid signatures from %v at index %d", val, idx) + } + + // If the vals and commit have a 1-to-1 correspondence we can retrieve // them by index else we need to retrieve them by address if lookUpByIndex { val = vals.Validators[idx] @@ -306,6 +376,10 @@ func verifyCommitSingle( seenVals[valIdx] = idx } + if val.PubKey == nil { + return fmt.Errorf("validator %v has a nil PubKey at index %d", val, idx) + } + voteSignBytes = commit.VoteSignBytes(chainID, int32(idx)) if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { @@ -341,12 +415,12 @@ func verifyBasicValsAndCommit(vals *ValidatorSet, commit *Commit, height int64, } if vals.Size() != len(commit.Signatures) { - return NewErrInvalidCommitSignatures(vals.Size(), len(commit.Signatures)) + return cmterrors.NewErrInvalidCommitSignatures(vals.Size(), len(commit.Signatures)) } // Validate Height and BlockID. if height != commit.Height { - return NewErrInvalidCommitHeight(height, commit.Height) + return cmterrors.NewErrInvalidCommitHeight(height, commit.Height) } if !blockID.Equals(commit.BlockID) { return fmt.Errorf("invalid commit -- wrong block ID: want %v, got %v", diff --git a/types/validation_test.go b/types/validation_test.go index a6cdf818c3e..373f584e6a1 100644 --- a/types/validation_test.go +++ b/types/validation_test.go @@ -1,14 +1,14 @@ package types import ( + "strconv" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmttime "github.com/cometbft/cometbft/types/time" ) // Check VerifyCommit, VerifyCommitLight and VerifyCommitLightTrusting basic @@ -24,7 +24,7 @@ func TestValidatorSet_VerifyCommit_All(t *testing.T) { ) testCases := []struct { - description string + description, description2 string // description2, if not empty, is checked against VerifyCommitLightTrusting // vote chainID chainID string // vote blockID @@ -41,25 +41,28 @@ func TestValidatorSet_VerifyCommit_All(t *testing.T) { expErr bool }{ - {"good (batch verification)", chainID, blockID, 3, height, 3, 0, 0, false}, - {"good (single verification)", chainID, blockID, 1, height, 1, 0, 0, false}, + {"good (batch verification)", "", chainID, blockID, 3, height, 3, 0, 0, false}, + {"good (single verification)", "", chainID, blockID, 1, height, 1, 0, 0, false}, - {"wrong signature (#0)", "EpsilonEridani", blockID, 2, height, 2, 0, 0, true}, - {"wrong block ID", chainID, makeBlockIDRandom(), 2, height, 2, 0, 0, true}, - {"wrong height", chainID, blockID, 1, height - 1, 1, 0, 0, true}, + {"wrong signature (#0)", "", "EpsilonEridani", blockID, 2, height, 2, 0, 0, true}, + {"wrong block ID", "", chainID, makeBlockIDRandom(), 2, height, 2, 0, 0, true}, + {"wrong height", "", chainID, blockID, 1, height - 1, 1, 0, 0, true}, - {"wrong set size: 4 vs 3", chainID, blockID, 4, height, 3, 0, 0, true}, - {"wrong set size: 1 vs 2", chainID, blockID, 1, height, 2, 0, 0, true}, + {"wrong set size: 4 vs 3", "", chainID, blockID, 4, height, 3, 0, 0, true}, + {"wrong set size: 1 vs 2", "double vote from Validator", chainID, blockID, 1, height, 2, 0, 0, true}, - {"insufficient voting power: got 30, needed more than 66", chainID, blockID, 10, height, 3, 2, 5, true}, - {"insufficient voting power: got 0, needed more than 6", chainID, blockID, 1, height, 0, 0, 1, true}, - {"insufficient voting power: got 60, needed more than 60", chainID, blockID, 9, height, 6, 3, 0, true}, + {"insufficient voting power: got 30, needed more than 66", "", chainID, blockID, 10, height, 3, 2, 5, true}, + {"insufficient voting power: got 0, needed more than 6", "", chainID, blockID, 1, height, 0, 0, 1, true}, // absent + {"insufficient voting power: got 0, needed more than 6", "", chainID, blockID, 1, height, 0, 1, 0, true}, // nil + {"insufficient voting power: got 60, needed more than 60", "", chainID, blockID, 9, height, 6, 3, 0, true}, } for _, tc := range testCases { tc := tc - t.Run(tc.description, func(t *testing.T) { - _, valSet, vals := randVoteSet(tc.height, round, cmtproto.PrecommitType, tc.valSize, 10, false) + countAllSignatures := false + f := func(t *testing.T) { + t.Helper() + _, valSet, vals := randVoteSet(tc.height, round, PrecommitType, tc.valSize, 10, false) totalVotes := tc.blockVotes + tc.absentVotes + tc.nilVotes sigs := make([]CommitSig, totalVotes) vi := 0 @@ -69,7 +72,6 @@ func TestValidatorSet_VerifyCommit_All(t *testing.T) { vi++ } for i := 0; i < tc.blockVotes+tc.nilVotes; i++ { - pubKey, err := vals[vi%len(vals)].GetPubKey() require.NoError(t, err) vote := &Vote{ @@ -77,9 +79,9 @@ func TestValidatorSet_VerifyCommit_All(t *testing.T) { ValidatorIndex: int32(vi), Height: tc.height, Round: round, - Type: cmtproto.PrecommitType, + Type: PrecommitType, BlockID: tc.blockID, - Timestamp: time.Now(), + Timestamp: cmttime.Now(), } if i >= tc.blockVotes { vote.BlockID = BlockID{} @@ -87,7 +89,7 @@ func TestValidatorSet_VerifyCommit_All(t *testing.T) { v := vote.ToProto() - require.NoError(t, vals[vi%len(vals)].SignVote(tc.chainID, v)) + require.NoError(t, vals[vi%len(vals)].SignVote(tc.chainID, v, false)) vote.Signature = v.Signature sigs[vi] = vote.CommitSig() @@ -103,35 +105,51 @@ func TestValidatorSet_VerifyCommit_All(t *testing.T) { err := valSet.VerifyCommit(chainID, blockID, height, commit) if tc.expErr { - if assert.Error(t, err, "VerifyCommit") { + if assert.Error(t, err, "VerifyCommit") { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Contains(t, err.Error(), tc.description, "VerifyCommit") } } else { - assert.NoError(t, err, "VerifyCommit") + require.NoError(t, err, "VerifyCommit") } - err = valSet.VerifyCommitLight(chainID, blockID, height, commit) + if countAllSignatures { + err = valSet.VerifyCommitLightAllSignatures(chainID, blockID, height, commit) + } else { + err = valSet.VerifyCommitLight(chainID, blockID, height, commit) + } if tc.expErr { - if assert.Error(t, err, "VerifyCommitLight") { + if assert.Error(t, err, "VerifyCommitLight") { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Contains(t, err.Error(), tc.description, "VerifyCommitLight") } } else { - assert.NoError(t, err, "VerifyCommitLight") + require.NoError(t, err, "VerifyCommitLight") } // only a subsection of the tests apply to VerifyCommitLightTrusting - if totalVotes != tc.valSize || !tc.blockID.Equals(blockID) || tc.height != height { - tc.expErr = false + expErr := tc.expErr + if (!countAllSignatures && totalVotes != tc.valSize) || totalVotes < tc.valSize || !tc.blockID.Equals(blockID) || tc.height != height { + expErr = false } - err = valSet.VerifyCommitLightTrusting(chainID, commit, trustLevel) - if tc.expErr { - if assert.Error(t, err, "VerifyCommitLightTrusting") { - assert.Contains(t, err.Error(), tc.description, "VerifyCommitLightTrusting") + if countAllSignatures { + err = valSet.VerifyCommitLightTrustingAllSignatures(chainID, commit, trustLevel) + } else { + err = valSet.VerifyCommitLightTrusting(chainID, commit, trustLevel) + } + if expErr { + if assert.Error(t, err, "VerifyCommitLightTrusting") { //nolint:testifylint // require.Error doesn't work with the conditional here + errStr := tc.description2 + if len(errStr) == 0 { + errStr = tc.description + } + assert.Contains(t, err.Error(), errStr, "VerifyCommitLightTrusting") } } else { - assert.NoError(t, err, "VerifyCommitLightTrusting") + require.NoError(t, err, "VerifyCommitLightTrusting") } - }) + } + t.Run(tc.description+"/"+strconv.FormatBool(countAllSignatures), f) + countAllSignatures = true + t.Run(tc.description+"/"+strconv.FormatBool(countAllSignatures), f) } } @@ -142,8 +160,8 @@ func TestValidatorSet_VerifyCommit_CheckAllSignatures(t *testing.T) { blockID = makeBlockIDRandom() ) - voteSet, valSet, vals := randVoteSet(h, 0, cmtproto.PrecommitType, 4, 10, false) - extCommit, err := MakeExtCommit(blockID, h, 0, voteSet, vals, time.Now(), false) + voteSet, valSet, vals := randVoteSet(h, 0, PrecommitType, 4, 10, false) + extCommit, err := MakeExtCommit(blockID, h, 0, voteSet, vals, cmttime.Now(), false) require.NoError(t, err) commit := extCommit.ToCommit() require.NoError(t, valSet.VerifyCommit(chainID, blockID, h, commit)) @@ -151,75 +169,93 @@ func TestValidatorSet_VerifyCommit_CheckAllSignatures(t *testing.T) { // malleate 4th signature vote := voteSet.GetByIndex(3) v := vote.ToProto() - err = vals[3].SignVote("CentaurusA", v) + err = vals[3].SignVote("CentaurusA", v, true) require.NoError(t, err) vote.Signature = v.Signature vote.ExtensionSignature = v.ExtensionSignature commit.Signatures[3] = vote.CommitSig() err = valSet.VerifyCommit(chainID, blockID, h, commit) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Contains(t, err.Error(), "wrong signature (#3)") } } -func TestValidatorSet_VerifyCommitLight_ReturnsAsSoonAsMajorityOfVotingPowerSigned(t *testing.T) { +func TestValidatorSet_VerifyCommitLight_ReturnsAsSoonAsMajOfVotingPowerSignedIffNotAllSigs(t *testing.T) { var ( chainID = "test_chain_id" h = int64(3) blockID = makeBlockIDRandom() ) - voteSet, valSet, vals := randVoteSet(h, 0, cmtproto.PrecommitType, 4, 10, false) - extCommit, err := MakeExtCommit(blockID, h, 0, voteSet, vals, time.Now(), false) + voteSet, valSet, vals := randVoteSet(h, 0, PrecommitType, 4, 10, false) + extCommit, err := MakeExtCommit(blockID, h, 0, voteSet, vals, cmttime.Now(), false) require.NoError(t, err) commit := extCommit.ToCommit() require.NoError(t, valSet.VerifyCommit(chainID, blockID, h, commit)) + err = valSet.VerifyCommitLightAllSignatures(chainID, blockID, h, commit) + require.NoError(t, err) + // malleate 4th signature (3 signatures are enough for 2/3+) vote := voteSet.GetByIndex(3) v := vote.ToProto() - err = vals[3].SignVote("CentaurusA", v) + err = vals[3].SignVote("CentaurusA", v, true) require.NoError(t, err) vote.Signature = v.Signature vote.ExtensionSignature = v.ExtensionSignature commit.Signatures[3] = vote.CommitSig() err = valSet.VerifyCommitLight(chainID, blockID, h, commit) - assert.NoError(t, err) + require.NoError(t, err) + err = valSet.VerifyCommitLightAllSignatures(chainID, blockID, h, commit) + require.Error(t, err) // counting all signatures detects the malleated signature } -func TestValidatorSet_VerifyCommitLightTrusting_ReturnsAsSoonAsTrustLevelOfVotingPowerSigned(t *testing.T) { +func TestValidatorSet_VerifyCommitLightTrusting_ReturnsAsSoonAsTrustLevelSignedIffNotAllSigs(t *testing.T) { var ( chainID = "test_chain_id" h = int64(3) blockID = makeBlockIDRandom() ) - voteSet, valSet, vals := randVoteSet(h, 0, cmtproto.PrecommitType, 4, 10, false) - extCommit, err := MakeExtCommit(blockID, h, 0, voteSet, vals, time.Now(), false) + voteSet, valSet, vals := randVoteSet(h, 0, PrecommitType, 4, 10, false) + extCommit, err := MakeExtCommit(blockID, h, 0, voteSet, vals, cmttime.Now(), false) require.NoError(t, err) commit := extCommit.ToCommit() require.NoError(t, valSet.VerifyCommit(chainID, blockID, h, commit)) + err = valSet.VerifyCommitLightTrustingAllSignatures( + chainID, + commit, + cmtmath.Fraction{Numerator: 1, Denominator: 3}, + ) + require.NoError(t, err) + // malleate 3rd signature (2 signatures are enough for 1/3+ trust level) vote := voteSet.GetByIndex(2) v := vote.ToProto() - err = vals[2].SignVote("CentaurusA", v) + err = vals[2].SignVote("CentaurusA", v, true) require.NoError(t, err) vote.Signature = v.Signature vote.ExtensionSignature = v.ExtensionSignature commit.Signatures[2] = vote.CommitSig() err = valSet.VerifyCommitLightTrusting(chainID, commit, cmtmath.Fraction{Numerator: 1, Denominator: 3}) - assert.NoError(t, err) + require.NoError(t, err) + err = valSet.VerifyCommitLightTrustingAllSignatures( + chainID, + commit, + cmtmath.Fraction{Numerator: 1, Denominator: 3}, + ) + require.Error(t, err) // counting all signatures detects the malleated signature } func TestValidatorSet_VerifyCommitLightTrusting(t *testing.T) { var ( blockID = makeBlockIDRandom() - voteSet, originalValset, vals = randVoteSet(1, 1, cmtproto.PrecommitType, 6, 1, false) - extCommit, err = MakeExtCommit(blockID, 1, 1, voteSet, vals, time.Now(), false) + voteSet, originalValset, vals = randVoteSet(1, 1, PrecommitType, 6, 1, false) + extCommit, err = MakeExtCommit(blockID, 1, 1, voteSet, vals, cmttime.Now(), false) newValSet, _ = RandValidatorSet(2, 1) ) require.NoError(t, err) @@ -250,9 +286,9 @@ func TestValidatorSet_VerifyCommitLightTrusting(t *testing.T) { err = tc.valSet.VerifyCommitLightTrusting("test_chain_id", commit, cmtmath.Fraction{Numerator: 1, Denominator: 3}) if tc.err { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } } } @@ -260,14 +296,14 @@ func TestValidatorSet_VerifyCommitLightTrusting(t *testing.T) { func TestValidatorSet_VerifyCommitLightTrustingErrorsOnOverflow(t *testing.T) { var ( blockID = makeBlockIDRandom() - voteSet, valSet, vals = randVoteSet(1, 1, cmtproto.PrecommitType, 1, MaxTotalVotingPower, false) - extCommit, err = MakeExtCommit(blockID, 1, 1, voteSet, vals, time.Now(), false) + voteSet, valSet, vals = randVoteSet(1, 1, PrecommitType, 1, MaxTotalVotingPower, false) + extCommit, err = MakeExtCommit(blockID, 1, 1, voteSet, vals, cmttime.Now(), false) ) require.NoError(t, err) err = valSet.VerifyCommitLightTrusting("test_chain_id", extCommit.ToCommit(), cmtmath.Fraction{Numerator: 25, Denominator: 55}) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Contains(t, err.Error(), "int64 overflow") } } diff --git a/types/validator.go b/types/validator.go index 886b32756d8..120944c9c0c 100644 --- a/types/validator.go +++ b/types/validator.go @@ -6,15 +6,15 @@ import ( "fmt" "strings" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" ce "github.com/cometbft/cometbft/crypto/encoding" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtrand "github.com/cometbft/cometbft/internal/rand" ) // Volatile state for each Validator // NOTE: The ProposerPriority is not included in Validator.Hash(); -// make sure to update that method if changes are made here +// make sure to update that method if changes are made here. type Validator struct { Address Address `json:"address"` PubKey crypto.PubKey `json:"pub_key"` @@ -46,21 +46,22 @@ func (v *Validator) ValidateBasic() error { return errors.New("validator has negative voting power") } - if len(v.Address) != crypto.AddressSize { - return fmt.Errorf("validator address is the wrong size: %v", v.Address) + addr := v.PubKey.Address() + if !bytes.Equal(v.Address, addr) { + return fmt.Errorf("validator address is incorrectly derived from pubkey. Exp: %v, got %v", addr, v.Address) } return nil } -// Creates a new copy of the validator so we can mutate ProposerPriority. +// Copy creates a new copy of the validator so we can mutate ProposerPriority. // Panics if the validator is nil. func (v *Validator) Copy() *Validator { vCopy := *v return &vCopy } -// Returns the one with higher ProposerPriority. +// CompareProposerPriority returns the one with higher ProposerPriority. func (v *Validator) CompareProposerPriority(other *Validator) *Validator { if v == nil { return other @@ -88,7 +89,7 @@ func (v *Validator) CompareProposerPriority(other *Validator) *Validator { // 1. address // 2. public key // 3. voting power -// 4. proposer priority +// 4. proposer priority. func (v *Validator) String() string { if v == nil { return "nil-Validator" @@ -132,7 +133,7 @@ func (v *Validator) Bytes() []byte { return bz } -// ToProto converts Valiator to protobuf +// ToProto converts Validator to protobuf. func (v *Validator) ToProto() (*cmtproto.Validator, error) { if v == nil { return nil, errors.New("nil validator") @@ -153,7 +154,7 @@ func (v *Validator) ToProto() (*cmtproto.Validator, error) { return &vp, nil } -// FromProto sets a protobuf Validator to the given pointer. +// ValidatorFromProto sets a protobuf Validator to the given pointer. // It returns an error if the public key is invalid. func ValidatorFromProto(vp *cmtproto.Validator) (*Validator, error) { if vp == nil { @@ -173,11 +174,11 @@ func ValidatorFromProto(vp *cmtproto.Validator) (*Validator, error) { return v, nil } -//---------------------------------------- +// ---------------------------------------- // RandValidator // RandValidator returns a randomized validator, useful for testing. -// UNSTABLE +// UNSTABLE. func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator) { privVal := NewMockPV() votePower := minPower diff --git a/types/validator_set.go b/types/validator_set.go index 4b509d605a1..14a05ea8fdf 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -9,9 +9,9 @@ import ( "sort" "strings" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto/merkle" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) const ( @@ -105,9 +105,9 @@ func (vals *ValidatorSet) IsNilOrEmpty() bool { // CopyIncrementProposerPriority increments ProposerPriority and updates the // proposer on a copy, and returns it. func (vals *ValidatorSet) CopyIncrementProposerPriority(times int32) *ValidatorSet { - copy := vals.Copy() - copy.IncrementProposerPriority(times) - return copy + cp := vals.Copy() + cp.IncrementProposerPriority(times) + return cp } // IncrementProposerPriority increments ProposerPriority of each validator and @@ -177,7 +177,7 @@ func (vals *ValidatorSet) incrementProposerPriority() *Validator { return mostest } -// Should not be called on an empty validator set. +// computeAvgProposerPriority should not be called on an empty validator set. func (vals *ValidatorSet) computeAvgProposerPriority() int64 { n := int64(len(vals.Validators)) sum := big.NewInt(0) @@ -193,7 +193,8 @@ func (vals *ValidatorSet) computeAvgProposerPriority() int64 { panic(fmt.Sprintf("Cannot represent avg ProposerPriority as an int64 %v", avg)) } -// Compute the difference between the max and min ProposerPriority of that set. +// computeMaxMinPriorityDiff computes the difference between the max and min +// ProposerPriority of that set. func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 { if vals.IsNilOrEmpty() { panic("empty validator set") @@ -233,7 +234,7 @@ func (vals *ValidatorSet) shiftByAvgProposerPriority() { } } -// Makes a copy of the validator list. +// validatorListCopy makes a copy of the validator list. func validatorListCopy(valsList []*Validator) []*Validator { if valsList == nil { return nil @@ -293,7 +294,7 @@ func (vals *ValidatorSet) Size() int { return len(vals.Validators) } -// Forces recalculation of the set's total voting power. +// updateTotalVotingPower forces recalculation of the set's total voting power. // Panics if total voting power is bigger than MaxTotalVotingPower. func (vals *ValidatorSet) updateTotalVotingPower() { sum := int64(0) @@ -362,7 +363,8 @@ func (vals *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) { } } -// Checks changes against duplicates, splits the changes in updates and +// processChanges checks changes against duplicates, +// splits the changes in updates and // removals, sorts them by address. // // Returns: @@ -423,13 +425,12 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e // Note that this will be < 2 * MaxTotalVotingPower in case high power validators are removed and // validators are added/ updated with high power values. // -// err - non-nil if the maximum allowed total voting power would be exceeded +// err - non-nil if the maximum allowed total voting power would be exceeded. func verifyUpdates( updates []*Validator, vals *ValidatorSet, removedPower int64, ) (tvpAfterUpdatesBeforeRemovals int64, err error) { - delta := func(update *Validator, vals *ValidatorSet) int64 { _, val := vals.GetByAddress(update.Address) if val != nil { @@ -493,7 +494,6 @@ func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotal valUpdate.ProposerPriority = val.ProposerPriority } } - } // Merges the vals' validator list with the updates list. @@ -537,7 +537,8 @@ func (vals *ValidatorSet) applyUpdates(updates []*Validator) { vals.Validators = merged[:i] } -// Checks that the validators to be removed are part of the validator set. +// verifyRemovals checks that the validators to be removed are part of the +// validator set. // No changes are made to the validator set 'vals'. func verifyRemovals(deletes []*Validator, vals *ValidatorSet) (votingPower int64, err error) { removedVotingPower := int64(0) @@ -555,7 +556,8 @@ func verifyRemovals(deletes []*Validator, vals *ValidatorSet) (votingPower int64 return removedVotingPower, nil } -// Removes the validators specified in 'deletes' from validator set 'vals'. +// applyRemovals removes the validators specified in 'deletes' from validator +// set 'vals'. // Should not fail as verification has been done before. // Expects vals to be sorted by address (done by applyUpdates). func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { @@ -584,7 +586,8 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { vals.Validators = merged[:i] } -// Main function used by UpdateWithChangeSet() and NewValidatorSet(). +// updateWithChangeSet is the main function used by UpdateWithChangeSet( +// ) and NewValidatorSet(). // If 'allowDeletes' is false then delete operations (identified by validators with voting power 0) // are not allowed and will trigger an error if present in 'changes'. // The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet(). @@ -658,26 +661,55 @@ func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error { } // VerifyCommit verifies +2/3 of the set had signed the given commit and all -// other signatures are valid +// other signatures are valid. func (vals *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, - height int64, commit *Commit) error { + height int64, commit *Commit, +) error { return VerifyCommit(chainID, vals, blockID, height, commit) } // LIGHT CLIENT VERIFICATION METHODS // VerifyCommitLight verifies +2/3 of the set had signed the given commit. +// It does NOT count all signatures. func (vals *ValidatorSet) VerifyCommitLight(chainID string, blockID BlockID, - height int64, commit *Commit) error { + height int64, commit *Commit, +) error { return VerifyCommitLight(chainID, vals, blockID, height, commit) } +// VerifyCommitLight verifies +2/3 of the set had signed the given commit. +// It DOES count all signatures. +func (vals *ValidatorSet) VerifyCommitLightAllSignatures(chainID string, blockID BlockID, + height int64, commit *Commit, +) error { + return VerifyCommitLightAllSignatures(chainID, vals, blockID, height, commit) +} + // VerifyCommitLightTrusting verifies that trustLevel of the validator set signed // this commit. -func (vals *ValidatorSet) VerifyCommitLightTrusting(chainID string, commit *Commit, trustLevel cmtmath.Fraction) error { +// It does NOT count all signatures. +// CONTRACT: must run ValidateBasic() on commit before verifying. +func (vals *ValidatorSet) VerifyCommitLightTrusting( + chainID string, + commit *Commit, + trustLevel cmtmath.Fraction, +) error { return VerifyCommitLightTrusting(chainID, vals, commit, trustLevel) } +// VerifyCommitLightTrusting verifies that trustLevel of the validator set signed +// this commit. +// It DOES count all signatures. +// CONTRACT: must run ValidateBasic() on commit before verifying. +func (vals *ValidatorSet) VerifyCommitLightTrustingAllSignatures( + chainID string, + commit *Commit, + trustLevel cmtmath.Fraction, +) error { + return VerifyCommitLightTrustingAllSignatures(chainID, vals, commit, trustLevel) +} + // findPreviousProposer reverses the compare proposer priority function to find the validator // with the lowest proposer priority which would have been the previous proposer. // @@ -696,7 +728,7 @@ func (vals *ValidatorSet) findPreviousProposer() *Validator { return previousProposer } -//----------------- +// ----------------- // IsErrNotEnoughVotingPowerSigned returns true if err is // ErrNotEnoughVotingPowerSigned. @@ -715,7 +747,7 @@ func (e ErrNotEnoughVotingPowerSigned) Error() string { return fmt.Sprintf("invalid commit -- insufficient voting power: got %d, needed more than %d", e.Got, e.Needed) } -//---------------- +// ---------------- // String returns a string representation of ValidatorSet. // @@ -732,7 +764,7 @@ func (vals *ValidatorSet) StringIndented(indent string) string { return "nil-ValidatorSet" } var valStrings []string - vals.Iterate(func(index int, val *Validator) bool { + vals.Iterate(func(_ int, val *Validator) bool { valStrings = append(valStrings, val.String()) return false }) @@ -745,10 +777,9 @@ func (vals *ValidatorSet) StringIndented(indent string) string { indent, indent, strings.Join(valStrings, "\n"+indent+" "), indent) - } -//------------------------------------- +// ------------------------------------- // ValidatorsByVotingPower implements sort.Interface for []*Validator based on // the VotingPower and Address fields. @@ -781,7 +812,7 @@ func (valz ValidatorsByAddress) Swap(i, j int) { valz[i], valz[j] = valz[j], valz[i] } -// ToProto converts ValidatorSet to protobuf +// ToProto converts ValidatorSet to protobuf. func (vals *ValidatorSet) ToProto() (*cmtproto.ValidatorSet, error) { if vals.IsNilOrEmpty() { return &cmtproto.ValidatorSet{}, nil // validator set should never be nil @@ -813,7 +844,7 @@ func (vals *ValidatorSet) ToProto() (*cmtproto.ValidatorSet, error) { // ValidatorSetFromProto sets a protobuf ValidatorSet to the given pointer. // It returns an error if any of the validators from the set or the proposer -// is invalid +// is invalid. func ValidatorSetFromProto(vp *cmtproto.ValidatorSet) (*ValidatorSet, error) { if vp == nil { return nil, errors.New("nil validator set") // validator set should never be nil, bigger issues are at play if empty @@ -871,7 +902,7 @@ func ValidatorSetFromExistingValidators(valz []*Validator) (*ValidatorSet, error return vals, nil } -//---------------------------------------- +// ---------------------------------------- // RandValidatorSet returns a randomized validator set (size: +numValidators+), // where each validator has a voting power of +votingPower+. diff --git a/types/validator_set_test.go b/types/validator_set_test.go index 11f1ab24834..18285bb4a85 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -12,11 +12,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" + cmtrand "github.com/cometbft/cometbft/internal/rand" cmtmath "github.com/cometbft/cometbft/libs/math" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) func TestValidatorSetBasic(t *testing.T) { @@ -45,12 +45,14 @@ func TestValidatorSetBasic(t *testing.T) { assert.Zero(t, vset.Size()) assert.Equal(t, int64(0), vset.TotalVotingPower()) assert.Nil(t, vset.GetProposer()) - assert.Equal(t, []byte{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, + assert.Equal(t, []byte{ + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, - 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}, vset.Hash()) + 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, + }, vset.Hash()) // add val = randValidator(vset.TotalVotingPower()) - assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) + require.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) assert.True(t, vset.HasAddress(val.Address)) idx, _ = vset.GetByAddress(val.Address) @@ -65,16 +67,15 @@ func TestValidatorSetBasic(t *testing.T) { // update val = randValidator(vset.TotalVotingPower()) - assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) + require.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) _, val = vset.GetByAddress(val.Address) val.VotingPower += 100 proposerPriority := val.ProposerPriority val.ProposerPriority = 0 - assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) + require.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) _, val = vset.GetByAddress(val.Address) assert.Equal(t, proposerPriority, val.ProposerPriority) - } func TestValidatorSetValidateBasic(t *testing.T) { @@ -125,14 +126,13 @@ func TestValidatorSetValidateBasic(t *testing.T) { for _, tc := range testCases { err := tc.vals.ValidateBasic() if tc.err { - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, tc.msg, err.Error()) } } else { - assert.NoError(t, err) + require.NoError(t, err) } } - } func TestCopy(t *testing.T) { @@ -182,7 +182,7 @@ func BenchmarkValidatorSetCopy(b *testing.B) { } } -//------------------------------------------------------------------- +// ------------------------------------------------------------------- func TestProposerSelection1(t *testing.T) { vset := NewValidatorSet([]*Validator{ @@ -261,56 +261,60 @@ func TestProposerSelection2(t *testing.T) { valList = []*Validator{val0, val1, val2} propCount := make([]int, 3) vals = NewValidatorSet(valList) - N := 1 - for i := 0; i < 120*N; i++ { + n := 1 + for i := 0; i < 120*n; i++ { prop := vals.GetProposer() ii := prop.Address[19] propCount[ii]++ vals.IncrementProposerPriority(1) } - if propCount[0] != 40*N { + if propCount[0] != 40*n { t.Fatalf( "Expected prop count for validator with 4/12 of voting power to be %d/%d. Got %d/%d", - 40*N, - 120*N, + 40*n, + 120*n, propCount[0], - 120*N, + 120*n, ) } - if propCount[1] != 50*N { + if propCount[1] != 50*n { t.Fatalf( "Expected prop count for validator with 5/12 of voting power to be %d/%d. Got %d/%d", - 50*N, - 120*N, + 50*n, + 120*n, propCount[1], - 120*N, + 120*n, ) } - if propCount[2] != 30*N { + if propCount[2] != 30*n { t.Fatalf( "Expected prop count for validator with 3/12 of voting power to be %d/%d. Got %d/%d", - 30*N, - 120*N, + 30*n, + 120*n, propCount[2], - 120*N, + 120*n, ) } } func TestProposerSelection3(t *testing.T) { - vset := NewValidatorSet([]*Validator{ + vals := []*Validator{ newValidator([]byte("avalidator_address12"), 1), newValidator([]byte("bvalidator_address12"), 1), newValidator([]byte("cvalidator_address12"), 1), newValidator([]byte("dvalidator_address12"), 1), - }) + } - proposerOrder := make([]*Validator, 4) for i := 0; i < 4; i++ { - // need to give all validators to have keys pk := ed25519.GenPrivKey().PubKey() - vset.Validators[i].PubKey = pk + vals[i].PubKey = pk + vals[i].Address = pk.Address() + } + sort.Sort(ValidatorsByAddress(vals)) + vset := NewValidatorSet(vals) + proposerOrder := make([]*Validator, 4) + for i := 0; i < 4; i++ { proposerOrder[i] = vset.GetProposer() vset.IncrementProposerPriority(1) } @@ -403,7 +407,7 @@ func (vals *ValidatorSet) toBytes() []byte { return bz } -func (vals *ValidatorSet) fromBytes(b []byte) *ValidatorSet { +func (*ValidatorSet) fromBytes(b []byte) *ValidatorSet { pbvs := new(cmtproto.ValidatorSet) err := pbvs.Unmarshal(b) if err != nil { @@ -419,7 +423,7 @@ func (vals *ValidatorSet) fromBytes(b []byte) *ValidatorSet { return vs } -//------------------------------------------------------------------- +// ------------------------------------------------------------------- func TestValidatorSetTotalVotingPowerPanicsOnOverflow(t *testing.T) { // NewValidatorSet calls IncrementProposerPriority which calls TotalVotingPower() @@ -478,28 +482,39 @@ func TestAveragingInIncrementProposerPriority(t *testing.T) { times int32 avg int64 }{ - 0: {ValidatorSet{ - Validators: []*Validator{ - {Address: []byte("a"), ProposerPriority: 1}, - {Address: []byte("b"), ProposerPriority: 2}, - {Address: []byte("c"), ProposerPriority: 3}}}, - 1, 2}, - 1: {ValidatorSet{ - Validators: []*Validator{ - {Address: []byte("a"), ProposerPriority: 10}, - {Address: []byte("b"), ProposerPriority: -10}, - {Address: []byte("c"), ProposerPriority: 1}}}, + 0: { + ValidatorSet{ + Validators: []*Validator{ + {Address: []byte("a"), ProposerPriority: 1}, + {Address: []byte("b"), ProposerPriority: 2}, + {Address: []byte("c"), ProposerPriority: 3}, + }, + }, + 1, 2, + }, + 1: { + ValidatorSet{ + Validators: []*Validator{ + {Address: []byte("a"), ProposerPriority: 10}, + {Address: []byte("b"), ProposerPriority: -10}, + {Address: []byte("c"), ProposerPriority: 1}, + }, + }, // this should average twice but the average should be 0 after the first iteration // (voting power is 0 -> no changes) 11, 0, // 1 / 3 }, - 2: {ValidatorSet{ - Validators: []*Validator{ - {Address: []byte("a"), ProposerPriority: 100}, - {Address: []byte("b"), ProposerPriority: -10}, - {Address: []byte("c"), ProposerPriority: 1}}}, - 1, 91 / 3}, + 2: { + ValidatorSet{ + Validators: []*Validator{ + {Address: []byte("a"), ProposerPriority: 100}, + {Address: []byte("b"), ProposerPriority: -10}, + {Address: []byte("c"), ProposerPriority: 1}, + }, + }, + 1, 91 / 3, + }, } for i, tc := range tcs { // work on copy to have the old ProposerPriorities: @@ -523,103 +538,125 @@ func TestAveragingInIncrementProposerPriorityWithVotingPower(t *testing.T) { vals := ValidatorSet{Validators: []*Validator{ {Address: []byte{0}, ProposerPriority: 0, VotingPower: vp0}, {Address: []byte{1}, ProposerPriority: 0, VotingPower: vp1}, - {Address: []byte{2}, ProposerPriority: 0, VotingPower: vp2}}} + {Address: []byte{2}, ProposerPriority: 0, VotingPower: vp2}, + }} tcs := []struct { vals *ValidatorSet wantProposerPrioritys []int64 times int32 wantProposer *Validator }{ - 0: { vals.Copy(), []int64{ // Acumm+VotingPower-Avg: 0 + vp0 - total - avg, // mostest will be subtracted by total voting power (12) 0 + vp1, - 0 + vp2}, + 0 + vp2, + }, 1, - vals.Validators[0]}, + vals.Validators[0], + }, 1: { vals.Copy(), []int64{ (0 + vp0 - total) + vp0 - total - avg, // this will be mostest on 2nd iter, too (0 + vp1) + vp1, - (0 + vp2) + vp2}, + (0 + vp2) + vp2, + }, 2, - vals.Validators[0]}, // increment twice -> expect average to be subtracted twice + vals.Validators[0], + }, // increment twice -> expect average to be subtracted twice 2: { vals.Copy(), []int64{ 0 + 3*(vp0-total) - avg, // still mostest 0 + 3*vp1, - 0 + 3*vp2}, + 0 + 3*vp2, + }, 3, - vals.Validators[0]}, + vals.Validators[0], + }, 3: { vals.Copy(), []int64{ 0 + 4*(vp0-total), // still mostest 0 + 4*vp1, - 0 + 4*vp2}, + 0 + 4*vp2, + }, 4, - vals.Validators[0]}, + vals.Validators[0], + }, 4: { vals.Copy(), []int64{ 0 + 4*(vp0-total) + vp0, // 4 iters was mostest 0 + 5*vp1 - total, // now this val is mostest for the 1st time (hence -12==totalVotingPower) - 0 + 5*vp2}, + 0 + 5*vp2, + }, 5, - vals.Validators[1]}, + vals.Validators[1], + }, 5: { vals.Copy(), []int64{ 0 + 6*vp0 - 5*total, // mostest again 0 + 6*vp1 - total, // mostest once up to here - 0 + 6*vp2}, + 0 + 6*vp2, + }, 6, - vals.Validators[0]}, + vals.Validators[0], + }, 6: { vals.Copy(), []int64{ 0 + 7*vp0 - 6*total, // in 7 iters this val is mostest 6 times 0 + 7*vp1 - total, // in 7 iters this val is mostest 1 time - 0 + 7*vp2}, + 0 + 7*vp2, + }, 7, - vals.Validators[0]}, + vals.Validators[0], + }, 7: { vals.Copy(), []int64{ 0 + 8*vp0 - 7*total, // mostest again 0 + 8*vp1 - total, - 0 + 8*vp2}, + 0 + 8*vp2, + }, 8, - vals.Validators[0]}, + vals.Validators[0], + }, 8: { vals.Copy(), []int64{ 0 + 9*vp0 - 7*total, 0 + 9*vp1 - total, - 0 + 9*vp2 - total}, // mostest + 0 + 9*vp2 - total, + }, // mostest 9, - vals.Validators[2]}, + vals.Validators[2], + }, 9: { vals.Copy(), []int64{ 0 + 10*vp0 - 8*total, // after 10 iters this is mostest again 0 + 10*vp1 - total, // after 6 iters this val is "mostest" once and not in between - 0 + 10*vp2 - total}, // in between 10 iters this val is "mostest" once + 0 + 10*vp2 - total, + }, // in between 10 iters this val is "mostest" once 10, - vals.Validators[0]}, + vals.Validators[0], + }, 10: { vals.Copy(), []int64{ 0 + 11*vp0 - 9*total, - 0 + 11*vp1 - total, // after 6 iters this val is "mostest" once and not in between - 0 + 11*vp2 - total}, // after 10 iters this val is "mostest" once + 0 + 11*vp1 - total, // after 6 iters this val is "mostest" once and not in between + 0 + 11*vp2 - total, + }, // after 10 iters this val is "mostest" once 11, - vals.Validators[0]}, + vals.Validators[0], + }, } for i, tc := range tcs { tc.vals.IncrementProposerPriority(tc.times) @@ -662,10 +699,9 @@ func TestSafeSubClip(t *testing.T) { assert.EqualValues(t, math.MaxInt64, safeSubClip(math.MaxInt64, -10)) } -//------------------------------------------------------------------- +// ------------------------------------------------------------------- func TestEmptySet(t *testing.T) { - var valList []*Validator valSet := NewValidatorSet(valList) assert.Panics(t, func() { valSet.IncrementProposerPriority(1) }) @@ -678,22 +714,20 @@ func TestEmptySet(t *testing.T) { v1 := newValidator([]byte("v1"), 100) v2 := newValidator([]byte("v2"), 100) valList = []*Validator{v1, v2} - assert.NoError(t, valSet.UpdateWithChangeSet(valList)) + require.NoError(t, valSet.UpdateWithChangeSet(valList)) verifyValidatorSet(t, valSet) // Delete all validators from set v1 = newValidator([]byte("v1"), 0) v2 = newValidator([]byte("v2"), 0) delList := []*Validator{v1, v2} - assert.Error(t, valSet.UpdateWithChangeSet(delList)) + require.Error(t, valSet.UpdateWithChangeSet(delList)) // Attempt delete from empty set - assert.Error(t, valSet.UpdateWithChangeSet(delList)) - + require.Error(t, valSet.UpdateWithChangeSet(delList)) } func TestUpdatesForNewValidatorSet(t *testing.T) { - v1 := newValidator([]byte("v1"), 100) v2 := newValidator([]byte("v2"), 100) valList := []*Validator{v1, v2} @@ -720,7 +754,6 @@ func TestUpdatesForNewValidatorSet(t *testing.T) { v3 = newValidator([]byte("v3"), 30) valList = []*Validator{v1, v2, v3} assert.Panics(t, func() { NewValidatorSet(valList) }) - } type testVal struct { @@ -762,8 +795,9 @@ func valSetTotalProposerPriority(valSet *ValidatorSet) int64 { } func verifyValidatorSet(t *testing.T, valSet *ValidatorSet) { + t.Helper() // verify that the capacity and length of validators is the same - assert.Equal(t, len(valSet.Validators), cap(valSet.Validators)) + assert.Len(t, valSet.Validators, cap(valSet.Validators)) // verify that the set's total voting power has been updated tvp := valSet.totalVotingPower @@ -780,7 +814,7 @@ func verifyValidatorSet(t *testing.T, valSet *ValidatorSet) { // verify that priorities are scaled dist := computeMaxMinPriorityDiff(valSet) - assert.True(t, dist <= PriorityWindowSizeFactor*tvp, + assert.LessOrEqual(t, dist, PriorityWindowSizeFactor*tvp, "expected priority distance < %d. Got %d", PriorityWindowSizeFactor*tvp, dist) } @@ -807,6 +841,7 @@ type valSetErrTestCase struct { } func executeValSetErrTestCase(t *testing.T, idx int, tt valSetErrTestCase) { + t.Helper() // create a new set and apply updates, keeping copies for the checks valSet := createNewValidatorSet(tt.startVals) valSetCopy := valSet.Copy() @@ -815,7 +850,7 @@ func executeValSetErrTestCase(t *testing.T, idx int, tt valSetErrTestCase) { err := valSet.UpdateWithChangeSet(valList) // for errors check the validator set has not been changed - assert.Error(t, err, "test %d", idx) + require.Error(t, err, "test %d", idx) assert.Equal(t, valSet, valSetCopy, "test %v", idx) // check the parameter list has not changed @@ -981,7 +1016,7 @@ func TestValSetUpdatesBasicTestsExecute(t *testing.T) { valSet := createNewValidatorSet(tt.startVals) valList := createNewValidatorList(tt.updateVals) err := valSet.UpdateWithChangeSet(valList) - assert.NoError(t, err, "test %d", i) + require.NoError(t, err, "test %d", i) valListCopy := validatorListCopy(valSet.Validators) // check that the voting power in the set's validators is not changing if the voting power @@ -990,7 +1025,6 @@ func TestValSetUpdatesBasicTestsExecute(t *testing.T) { if len(valList) > 0 { valList[0].VotingPower++ assert.Equal(t, toTestValList(valListCopy), toTestValList(valSet.Validators), "test %v", i) - } // check the final validator list is as expected and the set is properly scaled and centered. @@ -1010,19 +1044,23 @@ func TestValSetUpdatesOrderIndependenceTestsExecute(t *testing.T) { }{ 0: { // order of changes should not matter, the final validator sets should be the same []testVal{{"v4", 40}, {"v3", 30}, {"v2", 10}, {"v1", 10}}, - []testVal{{"v4", 44}, {"v3", 33}, {"v2", 22}, {"v1", 11}}}, + []testVal{{"v4", 44}, {"v3", 33}, {"v2", 22}, {"v1", 11}}, + }, 1: { // order of additions should not matter []testVal{{"v2", 20}, {"v1", 10}}, - []testVal{{"v3", 30}, {"v4", 40}, {"v5", 50}, {"v6", 60}}}, + []testVal{{"v3", 30}, {"v4", 40}, {"v5", 50}, {"v6", 60}}, + }, 2: { // order of removals should not matter []testVal{{"v4", 40}, {"v3", 30}, {"v2", 20}, {"v1", 10}}, - []testVal{{"v1", 0}, {"v3", 0}, {"v4", 0}}}, + []testVal{{"v1", 0}, {"v3", 0}, {"v4", 0}}, + }, 3: { // order of mixed operations should not matter []testVal{{"v4", 40}, {"v3", 30}, {"v2", 20}, {"v1", 10}}, - []testVal{{"v1", 0}, {"v3", 0}, {"v2", 22}, {"v5", 50}, {"v4", 44}}}, + []testVal{{"v1", 0}, {"v3", 0}, {"v2", 22}, {"v5", 50}, {"v4", 44}}, + }, } for i, tt := range valSetUpdatesOrderTests { @@ -1030,7 +1068,7 @@ func TestValSetUpdatesOrderIndependenceTestsExecute(t *testing.T) { valSet := createNewValidatorSet(tt.startVals) valSetCopy := valSet.Copy() valList := createNewValidatorList(tt.updateVals) - assert.NoError(t, valSetCopy.UpdateWithChangeSet(valList)) + require.NoError(t, valSetCopy.UpdateWithChangeSet(valList)) // save the result as expected for next updates valSetExp := valSetCopy.Copy() @@ -1044,19 +1082,19 @@ func TestValSetUpdatesOrderIndependenceTestsExecute(t *testing.T) { valList := createNewValidatorList(permutation(tt.updateVals)) // check there was no error and the set is properly scaled and centered. - assert.NoError(t, valSetCopy.UpdateWithChangeSet(valList), + require.NoError(t, valSetCopy.UpdateWithChangeSet(valList), "test %v failed for permutation %v", i, valList) verifyValidatorSet(t, valSetCopy) // verify the resulting test is same as the expected - assert.Equal(t, valSetCopy, valSetExp, + assert.Equal(t, valSetExp, valSetCopy, "test %v failed for permutation %v", i, valList) } } } // This tests the private function validator_set.go:applyUpdates() function, used only for additions and changes. -// Should perform a proper merge of updatedVals and startVals +// Should perform a proper merge of updatedVals and startVals. func TestValSetApplyUpdatesTestsExecute(t *testing.T) { valSetUpdatesBasicTests := []struct { startVals []testVal @@ -1067,41 +1105,50 @@ func TestValSetApplyUpdatesTestsExecute(t *testing.T) { 0: { // prepend []testVal{{"v4", 44}, {"v5", 55}}, []testVal{{"v1", 11}}, - []testVal{{"v1", 11}, {"v4", 44}, {"v5", 55}}}, + []testVal{{"v1", 11}, {"v4", 44}, {"v5", 55}}, + }, 1: { // append []testVal{{"v4", 44}, {"v5", 55}}, []testVal{{"v6", 66}}, - []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}}}, + []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}}, + }, 2: { // insert []testVal{{"v4", 44}, {"v6", 66}}, []testVal{{"v5", 55}}, - []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}}}, + []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}}, + }, 3: { // insert multi []testVal{{"v4", 44}, {"v6", 66}, {"v9", 99}}, []testVal{{"v5", 55}, {"v7", 77}, {"v8", 88}}, - []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}, {"v7", 77}, {"v8", 88}, {"v9", 99}}}, + []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}, {"v7", 77}, {"v8", 88}, {"v9", 99}}, + }, // changes 4: { // head []testVal{{"v1", 111}, {"v2", 22}}, []testVal{{"v1", 11}}, - []testVal{{"v1", 11}, {"v2", 22}}}, + []testVal{{"v1", 11}, {"v2", 22}}, + }, 5: { // tail []testVal{{"v1", 11}, {"v2", 222}}, []testVal{{"v2", 22}}, - []testVal{{"v1", 11}, {"v2", 22}}}, + []testVal{{"v1", 11}, {"v2", 22}}, + }, 6: { // middle []testVal{{"v1", 11}, {"v2", 222}, {"v3", 33}}, []testVal{{"v2", 22}}, - []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}}, + []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}, + }, 7: { // multi []testVal{{"v1", 111}, {"v2", 222}, {"v3", 333}}, []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}, - []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}}, + []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}, + }, // additions and changes 8: { []testVal{{"v1", 111}, {"v2", 22}}, []testVal{{"v1", 11}, {"v3", 33}, {"v4", 44}}, - []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}, {"v4", 44}}}, + []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}, {"v4", 44}}, + }, } for i, tt := range valSetUpdatesBasicTests { @@ -1113,7 +1160,7 @@ func TestValSetApplyUpdatesTestsExecute(t *testing.T) { valSet.applyUpdates(valList) // check the new list of validators for proper merge - assert.Equal(t, toTestValList(valSet.Validators), tt.expectedVals, "test %v", i) + assert.Equal(t, tt.expectedVals, toTestValList(valSet.Validators), "test %v", i) } } @@ -1127,7 +1174,7 @@ type testVSetCfg struct { expErr error } -func randTestVSetCfg(t *testing.T, nBase, nAddMax int) testVSetCfg { +func randTestVSetCfg(nBase, nAddMax int) testVSetCfg { if nBase <= 0 || nAddMax < 0 { panic(fmt.Sprintf("bad parameters %v %v", nBase, nAddMax)) } @@ -1179,10 +1226,10 @@ func randTestVSetCfg(t *testing.T, nBase, nAddMax int) testVSetCfg { sort.Sort(testValsByVotingPower(cfg.expectedVals)) return cfg - } func applyChangesToValSet(t *testing.T, expErr error, valSet *ValidatorSet, valsLists ...[]testVal) { + t.Helper() changes := make([]testVal, 0) for _, valsList := range valsLists { changes = append(changes, valsList...) @@ -1192,7 +1239,7 @@ func applyChangesToValSet(t *testing.T, expErr error, valSet *ValidatorSet, vals if expErr != nil { assert.Equal(t, expErr, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } } @@ -1225,19 +1272,18 @@ func TestValSetUpdatePriorityOrderTests(t *testing.T) { // generate a configuration with 100 validators, // randomly select validators for updates and deletes, and // generate 10 new validators to be added - 3: randTestVSetCfg(t, 100, 10), + 3: randTestVSetCfg(100, 10), - 4: randTestVSetCfg(t, 1000, 100), + 4: randTestVSetCfg(1000, 100), - 5: randTestVSetCfg(t, 10, 100), + 5: randTestVSetCfg(10, 100), - 6: randTestVSetCfg(t, 100, 1000), + 6: randTestVSetCfg(100, 1000), - 7: randTestVSetCfg(t, 1000, 1000), + 7: randTestVSetCfg(1000, 1000), } for _, cfg := range testCases { - // create a new validator set valSet := createNewValidatorSet(cfg.startVals) verifyValidatorSet(t, valSet) @@ -1248,6 +1294,7 @@ func TestValSetUpdatePriorityOrderTests(t *testing.T) { } func verifyValSetUpdatePriorityOrder(t *testing.T, valSet *ValidatorSet, cfg testVSetCfg, nMaxElections int32) { + t.Helper() // Run election up to nMaxElections times, sort validators by priorities valSet.IncrementProposerPriority(cmtrand.Int31()%nMaxElections + 1) @@ -1291,7 +1338,7 @@ func TestNewValidatorSetFromExistingValidators(t *testing.T) { assert.NotEqual(t, valSet, newValSet) existingValSet, err := ValidatorSetFromExistingValidators(valSet.Validators) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, valSet, existingValSet) assert.Equal(t, valSet.CopyIncrementProposerPriority(3), existingValSet.CopyIncrementProposerPriority(3)) } @@ -1325,28 +1372,56 @@ func TestValSetUpdateOverflowRelated(t *testing.T) { { name: "4 no false overflow error messages for adds, updates and deletes", startVals: []testVal{ - {"v1", MaxTotalVotingPower / 4}, {"v2", MaxTotalVotingPower / 4}, - {"v3", MaxTotalVotingPower / 4}, {"v4", MaxTotalVotingPower / 4}}, + {"v1", MaxTotalVotingPower / 4}, + {"v2", MaxTotalVotingPower / 4}, + {"v3", MaxTotalVotingPower / 4}, + {"v4", MaxTotalVotingPower / 4}, + }, deletedVals: []testVal{{"v2", 0}}, updatedVals: []testVal{ - {"v1", MaxTotalVotingPower/2 - 2}, {"v3", MaxTotalVotingPower/2 - 3}, {"v4", 2}}, + {"v1", MaxTotalVotingPower/2 - 2}, {"v3", MaxTotalVotingPower/2 - 3}, {"v4", 2}, + }, addedVals: []testVal{{"v5", 3}}, expectedVals: []testVal{ - {"v1", MaxTotalVotingPower/2 - 2}, {"v3", MaxTotalVotingPower/2 - 3}, {"v5", 3}, {"v4", 2}}, + {"v1", MaxTotalVotingPower/2 - 2}, {"v3", MaxTotalVotingPower/2 - 3}, {"v5", 3}, {"v4", 2}, + }, expErr: nil, }, { name: "5 check panic on overflow is prevented: update 8 validators with power int64(math.MaxInt64)/8", startVals: []testVal{ - {"v1", 1}, {"v2", 1}, {"v3", 1}, {"v4", 1}, {"v5", 1}, - {"v6", 1}, {"v7", 1}, {"v8", 1}, {"v9", 1}}, + {"v1", 1}, + {"v2", 1}, + {"v3", 1}, + {"v4", 1}, + {"v5", 1}, + {"v6", 1}, + {"v7", 1}, + {"v8", 1}, + {"v9", 1}, + }, updatedVals: []testVal{ - {"v1", MaxTotalVotingPower}, {"v2", MaxTotalVotingPower}, {"v3", MaxTotalVotingPower}, - {"v4", MaxTotalVotingPower}, {"v5", MaxTotalVotingPower}, {"v6", MaxTotalVotingPower}, - {"v7", MaxTotalVotingPower}, {"v8", MaxTotalVotingPower}, {"v9", 8}}, + {"v1", MaxTotalVotingPower}, + {"v2", MaxTotalVotingPower}, + {"v3", MaxTotalVotingPower}, + {"v4", MaxTotalVotingPower}, + {"v5", MaxTotalVotingPower}, + {"v6", MaxTotalVotingPower}, + {"v7", MaxTotalVotingPower}, + {"v8", MaxTotalVotingPower}, + {"v9", 8}, + }, expectedVals: []testVal{ - {"v1", 1}, {"v2", 1}, {"v3", 1}, {"v4", 1}, {"v5", 1}, - {"v6", 1}, {"v7", 1}, {"v8", 1}, {"v9", 1}}, + {"v1", 1}, + {"v2", 1}, + {"v3", 1}, + {"v4", 1}, + {"v5", 1}, + {"v6", 1}, + {"v7", 1}, + {"v8", 1}, + {"v9", 1}, + }, expErr: ErrTotalVotingPowerOverflow, }, } @@ -1436,7 +1511,7 @@ func TestValidatorSetProtoBuf(t *testing.T) { } // --------------------- -// Sort validators by priority and address +// Sort validators by priority and address. type validatorsByPriority []*Validator func (valz validatorsByPriority) Len() int { @@ -1457,7 +1532,7 @@ func (valz validatorsByPriority) Swap(i, j int) { valz[i], valz[j] = valz[j], valz[i] } -//------------------------------------- +// ------------------------------------- type testValsByVotingPower []testVal @@ -1467,7 +1542,7 @@ func (tvals testValsByVotingPower) Len() int { func (tvals testValsByVotingPower) Less(i, j int) bool { if tvals[i].power == tvals[j].power { - return bytes.Compare([]byte(tvals[i].name), []byte(tvals[j].name)) == -1 + return strings.Compare(tvals[i].name, tvals[j].name) == -1 } return tvals[i].power > tvals[j].power } @@ -1477,7 +1552,7 @@ func (tvals testValsByVotingPower) Swap(i, j int) { } // ------------------------------------- -// Benchmark tests +// Benchmark tests. func BenchmarkUpdates(b *testing.B) { const ( n = 100 @@ -1501,6 +1576,41 @@ func BenchmarkUpdates(b *testing.B) { for i := 0; i < b.N; i++ { // Add m validators to valSetCopy valSetCopy := valSet.Copy() - assert.NoError(b, valSetCopy.UpdateWithChangeSet(newValList)) + require.NoError(b, valSetCopy.UpdateWithChangeSet(newValList)) + } +} + +func TestVerifyCommitWithInvalidProposerKey(t *testing.T) { + vs := &ValidatorSet{ + Validators: []*Validator{{}, {}}, + } + commit := &Commit{ + Height: 100, + Signatures: []CommitSig{{}, {}}, + } + var bid BlockID + cid := "" + err := vs.VerifyCommit(cid, bid, 100, commit) + require.Error(t, err) +} + +func TestVerifyCommitSingleWithInvalidSignatures(t *testing.T) { + vs := &ValidatorSet{ + Validators: []*Validator{{}, {}}, + } + commit := &Commit{ + Height: 100, + Signatures: []CommitSig{{}, {}}, } + cid := "" + votingPowerNeeded := vs.TotalVotingPower() * 2 / 3 + + // ignore all absent signatures + ignore := func(c CommitSig) bool { return c.BlockIDFlag == BlockIDFlagAbsent } + + // only count the signatures that are for the block + count := func(c CommitSig) bool { return c.BlockIDFlag == BlockIDFlagCommit } + + err := verifyCommitSingle(cid, vs, commit, votingPowerNeeded, ignore, count, true, true) + require.Error(t, err) } diff --git a/types/validator_test.go b/types/validator_test.go index 5eb2ed7bf1c..7ae067f8222 100644 --- a/types/validator_test.go +++ b/types/validator_test.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "testing" "github.com/stretchr/testify/assert" @@ -74,7 +75,7 @@ func TestValidatorValidateBasic(t *testing.T) { Address: nil, }, err: true, - msg: "validator address is the wrong size: ", + msg: fmt.Sprintf("validator address is incorrectly derived from pubkey. Exp: %v, got ", pubKey.Address()), }, { val: &Validator{ @@ -82,18 +83,18 @@ func TestValidatorValidateBasic(t *testing.T) { Address: []byte{'a'}, }, err: true, - msg: "validator address is the wrong size: 61", + msg: fmt.Sprintf("validator address is incorrectly derived from pubkey. Exp: %v, got 61", pubKey.Address()), }, } for _, tc := range testCases { err := tc.val.ValidateBasic() if tc.err { - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, tc.msg, err.Error()) } } else { - assert.NoError(t, err) + require.NoError(t, err) } } } diff --git a/types/vote.go b/types/vote.go index 660b538d178..a14a3c089aa 100644 --- a/types/vote.go +++ b/types/vote.go @@ -6,10 +6,11 @@ import ( "fmt" "time" + cmtcons "github.com/cometbft/cometbft/api/cometbft/consensus/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" + "github.com/cometbft/cometbft/internal/protoio" cmtbytes "github.com/cometbft/cometbft/libs/bytes" - "github.com/cometbft/cometbft/libs/protoio" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) const ( @@ -24,6 +25,7 @@ var ( ErrVoteInvalidValidatorIndex = errors.New("invalid validator index") ErrVoteInvalidValidatorAddress = errors.New("invalid validator address") ErrVoteInvalidSignature = errors.New("invalid signature") + ErrVoteNoSignature = errors.New("no signature") ErrVoteInvalidBlockHash = errors.New("invalid block hash") ErrVoteNonDeterministicSignature = errors.New("non-deterministic signature") ErrVoteNil = errors.New("nil vote") @@ -47,22 +49,31 @@ func NewConflictingVoteError(vote1, vote2 *Vote) *ErrVoteConflictingVotes { } } +// The vote extension is only valid for non-nil precommits. +type ErrVoteExtensionInvalid struct { + ExtSignature []byte +} + +func (err *ErrVoteExtensionInvalid) Error() string { + return fmt.Sprintf("extensions must be present IFF vote is a non-nil Precommit; extension signature: %X", err.ExtSignature) +} + // Address is hex bytes. type Address = crypto.Address // Vote represents a prevote, precommit, or commit vote from validators for // consensus. type Vote struct { - Type cmtproto.SignedMsgType `json:"type"` - Height int64 `json:"height"` - Round int32 `json:"round"` // assume there will not be greater than 2_147_483_647 rounds - BlockID BlockID `json:"block_id"` // zero if vote is nil. - Timestamp time.Time `json:"timestamp"` - ValidatorAddress Address `json:"validator_address"` - ValidatorIndex int32 `json:"validator_index"` - Signature []byte `json:"signature"` - Extension []byte `json:"extension"` - ExtensionSignature []byte `json:"extension_signature"` + Type SignedMsgType `json:"type"` + Height int64 `json:"height"` + Round int32 `json:"round"` // assume there will not be greater than 2_147_483_647 rounds + BlockID BlockID `json:"block_id"` // zero if vote is nil. + Timestamp time.Time `json:"timestamp"` + ValidatorAddress Address `json:"validator_address"` + ValidatorIndex int32 `json:"validator_index"` + Signature []byte `json:"signature"` + Extension []byte `json:"extension"` + ExtensionSignature []byte `json:"extension_signature"` } // VoteFromProto attempts to convert the given serialization (Protobuf) type to @@ -99,7 +110,7 @@ func (vote *Vote) CommitSig() CommitSig { switch { case vote.BlockID.IsComplete(): blockIDFlag = BlockIDFlagCommit - case vote.BlockID.IsZero(): + case vote.BlockID.IsNil(): blockIDFlag = BlockIDFlagNil default: panic(fmt.Sprintf("Invalid vote %v - expected BlockID to be either empty or complete", vote)) @@ -135,7 +146,7 @@ func (vote *Vote) ExtendedCommitSig() ExtendedCommitSig { // for backwards-compatibility with the Amino encoding, due to e.g. hardware // devices that rely on this encoding. // -// See CanonicalizeVote +// See CanonicalizeVote. func VoteSignBytes(chainID string, vote *cmtproto.Vote) []byte { pb := CanonicalizeVote(chainID, vote) bz, err := protoio.MarshalDelimited(&pb) @@ -177,7 +188,7 @@ func (vote *Vote) Copy() *Vote { // 7. first 6 bytes of block hash // 8. first 6 bytes of signature // 9. first 6 bytes of vote extension -// 10. timestamp +// 10. timestamp. func (vote *Vote) String() string { if vote == nil { return nilVoteStr @@ -185,9 +196,9 @@ func (vote *Vote) String() string { var typeString string switch vote.Type { - case cmtproto.PrevoteType: + case PrevoteType: typeString = "Prevote" - case cmtproto.PrecommitType: + case PrecommitType: typeString = "Precommit" default: panic("Unknown vote type") @@ -236,9 +247,9 @@ func (vote *Vote) VerifyVoteAndExtension(chainID string, pubKey crypto.PubKey) e return err } // We only verify vote extension signatures for non-nil precommits. - if vote.Type == cmtproto.PrecommitType && !ProtoBlockIDIsNil(&v.BlockID) { + if vote.Type == PrecommitType && !ProtoBlockIDIsNil(&v.BlockID) { if len(vote.ExtensionSignature) == 0 { - return errors.New("expected vote extension signature") + return ErrVoteNoSignature } extSignBytes := VoteExtensionSignBytes(chainID, v) @@ -252,11 +263,14 @@ func (vote *Vote) VerifyVoteAndExtension(chainID string, pubKey crypto.PubKey) e // VerifyExtension checks whether the vote extension signature corresponds to the // given chain ID and public key. func (vote *Vote) VerifyExtension(chainID string, pubKey crypto.PubKey) error { - if vote.Type != cmtproto.PrecommitType || vote.BlockID.IsZero() { + if vote.Type != PrecommitType || vote.BlockID.IsNil() { return nil } v := vote.ToProto() extSignBytes := VoteExtensionSignBytes(chainID, v) + if len(vote.ExtensionSignature) == 0 { + return ErrVoteNoSignature + } if !pubKey.VerifySignature(extSignBytes, vote.ExtensionSignature) { return ErrVoteInvalidSignature } @@ -282,12 +296,12 @@ func (vote *Vote) ValidateBasic() error { // NOTE: Timestamp validation is subtle and handled elsewhere. if err := vote.BlockID.ValidateBasic(); err != nil { - return fmt.Errorf("wrong BlockID: %v", err) + return fmt.Errorf("wrong BlockID: %w", err) } // BlockID.ValidateBasic would not err if we for instance have an empty hash but a // non-empty PartsSetHeader: - if !vote.BlockID.IsZero() && !vote.BlockID.IsComplete() { + if !vote.BlockID.IsNil() && !vote.BlockID.IsComplete() { return fmt.Errorf("blockID must be either empty or complete, got: %v", vote.BlockID) } @@ -311,11 +325,11 @@ func (vote *Vote) ValidateBasic() error { // We should only ever see vote extensions in non-nil precommits, otherwise // this is a violation of the specification. // https://github.com/tendermint/tendermint/issues/8487 - if vote.Type != cmtproto.PrecommitType || vote.BlockID.IsZero() { + if vote.Type != PrecommitType || vote.BlockID.IsNil() { if len(vote.Extension) > 0 { return fmt.Errorf( "unexpected vote extension; vote type %d, isNil %t", - vote.Type, vote.BlockID.IsZero(), + vote.Type, vote.BlockID.IsNil(), ) } if len(vote.ExtensionSignature) > 0 { @@ -323,7 +337,7 @@ func (vote *Vote) ValidateBasic() error { } } - if vote.Type == cmtproto.PrecommitType && !vote.BlockID.IsZero() { + if vote.Type == PrecommitType && !vote.BlockID.IsNil() { // It's possible that this vote has vote extensions but // they could also be disabled and thus not present thus // we can't do all checks @@ -332,11 +346,11 @@ func (vote *Vote) ValidateBasic() error { } // NOTE: extended votes should have a signature regardless of - // of whether there is any data in the extension or not however + // whether there is any data in the extension or not however // we don't know if extensions are enabled so we can only // enforce the signature when extension size is not nil if len(vote.ExtensionSignature) == 0 && len(vote.Extension) != 0 { - return fmt.Errorf("vote extension signature absent on vote with extension") + return ErrVoteNoSignature } } @@ -347,10 +361,10 @@ func (vote *Vote) ValidateBasic() error { // on precommit vote types. func (vote *Vote) EnsureExtension() error { // We should always see vote extension signatures in non-nil precommits - if vote.Type != cmtproto.PrecommitType { + if vote.Type != PrecommitType { return nil } - if vote.BlockID.IsZero() { + if vote.BlockID.IsNil() { return nil } if len(vote.ExtensionSignature) > 0 { @@ -360,7 +374,7 @@ func (vote *Vote) EnsureExtension() error { } // ToProto converts the handwritten type to proto generated type -// return type, nil if everything converts safely, otherwise nil, error +// return type, nil if everything converts safely, otherwise nil, error. func (vote *Vote) ToProto() *cmtproto.Vote { if vote == nil { return nil @@ -396,6 +410,9 @@ func VotesToProto(votes []*Vote) []*cmtproto.Vote { return res } +// SignAndCheckVote signs the vote with the given privVal and checks the vote. +// It returns an error if the vote is invalid and a boolean indicating if the +// error is recoverable or not. func SignAndCheckVote( vote *Vote, privVal PrivValidator, @@ -403,35 +420,34 @@ func SignAndCheckVote( extensionsEnabled bool, ) (bool, error) { v := vote.ToProto() - if err := privVal.SignVote(chainID, v); err != nil { - // Failing to sign a vote has always been a recoverable error, this function keeps it that way - return true, err // true = recoverable + if err := privVal.SignVote(chainID, v, extensionsEnabled); err != nil { + // Failing to sign a vote has always been a recoverable error, this + // function keeps it that way. + return true, err } vote.Signature = v.Signature - isPrecommit := vote.Type == cmtproto.PrecommitType + isPrecommit := vote.Type == PrecommitType if !isPrecommit && extensionsEnabled { // Non-recoverable because the caller passed parameters that don't make sense - return false, fmt.Errorf("only Precommit votes may have extensions enabled; vote type: %d", vote.Type) - } - - isNil := vote.BlockID.IsZero() - extSignature := (len(v.ExtensionSignature) > 0) - if extSignature == (!isPrecommit || isNil) { - // Non-recoverable because the vote is malformed - return false, fmt.Errorf( - "extensions must be present IFF vote is a non-nil Precommit; present %t, vote type %d, is nil %t", - extSignature, - vote.Type, - isNil, - ) + return false, &ErrVoteExtensionInvalid{ExtSignature: v.ExtensionSignature} } vote.ExtensionSignature = nil if extensionsEnabled { + isNil := vote.BlockID.IsNil() + extSignature := (len(v.ExtensionSignature) > 0) + if extSignature == (!isPrecommit || isNil) { + // Non-recoverable because the vote is malformed + return false, &ErrVoteExtensionInvalid{ExtSignature: v.ExtensionSignature} + } + vote.ExtensionSignature = v.ExtensionSignature } + vote.Timestamp = v.Timestamp return true, nil } + +var _ Wrapper = &cmtcons.Vote{} diff --git a/types/vote_set.go b/types/vote_set.go index effcb16d2d3..4ecffba290a 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -5,10 +5,9 @@ import ( "fmt" "strings" - "github.com/cometbft/cometbft/libs/bits" + "github.com/cometbft/cometbft/internal/bits" + cmtsync "github.com/cometbft/cometbft/internal/sync" cmtjson "github.com/cometbft/cometbft/libs/json" - cmtsync "github.com/cometbft/cometbft/libs/sync" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" ) const ( @@ -62,7 +61,7 @@ type VoteSet struct { chainID string height int64 round int32 - signedMsgType cmtproto.SignedMsgType + signedMsgType SignedMsgType valSet *ValidatorSet extensionsEnabled bool @@ -78,7 +77,8 @@ type VoteSet struct { // NewVoteSet instantiates all fields of a new vote set. This constructor requires // that no vote extension data be present on the votes that are added to the set. func NewVoteSet(chainID string, height int64, round int32, - signedMsgType cmtproto.SignedMsgType, valSet *ValidatorSet) *VoteSet { + signedMsgType SignedMsgType, valSet *ValidatorSet, +) *VoteSet { if height == 0 { panic("Cannot make VoteSet for height == 0, doesn't make sense.") } @@ -101,7 +101,8 @@ func NewVoteSet(chainID string, height int64, round int32, // The VoteSet constructed with NewExtendedVoteSet verifies the vote extension // data for every vote added to the set. func NewExtendedVoteSet(chainID string, height int64, round int32, - signedMsgType cmtproto.SignedMsgType, valSet *ValidatorSet) *VoteSet { + signedMsgType SignedMsgType, valSet *ValidatorSet, +) *VoteSet { vs := NewVoteSet(chainID, height, round, signedMsgType, valSet) vs.extensionsEnabled = true return vs @@ -111,7 +112,7 @@ func (voteSet *VoteSet) ChainID() string { return voteSet.chainID } -// Implements VoteSetReader. +// GetHeight implements VoteSetReader. func (voteSet *VoteSet) GetHeight() int64 { if voteSet == nil { return 0 @@ -119,7 +120,7 @@ func (voteSet *VoteSet) GetHeight() int64 { return voteSet.height } -// Implements VoteSetReader. +// GetRound implements VoteSetReader. func (voteSet *VoteSet) GetRound() int32 { if voteSet == nil { return -1 @@ -127,7 +128,7 @@ func (voteSet *VoteSet) GetRound() int32 { return voteSet.round } -// Implements VoteSetReader. +// Type implements VoteSetReader. func (voteSet *VoteSet) Type() byte { if voteSet == nil { return 0x00 @@ -135,7 +136,7 @@ func (voteSet *VoteSet) Type() byte { return byte(voteSet.signedMsgType) } -// Implements VoteSetReader. +// Size implements VoteSetReader. func (voteSet *VoteSet) Size() int { if voteSet == nil { return 0 @@ -143,7 +144,7 @@ func (voteSet *VoteSet) Size() int { return voteSet.valSet.Size() } -// Returns added=true if vote is valid and new. +// AddVote returns added=true if vote is valid and new. // Otherwise returns err=ErrVote[ // // UnexpectedStep | InvalidIndex | InvalidAddress | @@ -153,7 +154,7 @@ func (voteSet *VoteSet) Size() int { // Conflicting votes return added=*, err=ErrVoteConflictingVotes. // NOTE: vote should not be mutated after adding. // NOTE: VoteSet must not be nil -// NOTE: Vote must not be nil +// NOTE: Vote must not be nil. func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error) { if voteSet == nil { panic("AddVote() on nil VoteSet") @@ -241,7 +242,7 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) { return added, nil } -// Returns (vote, true) if vote exists for valIndex and blockKey. +// getVote returns (vote, true) if vote exists for valIndex and blockKey. func (voteSet *VoteSet) getVote(valIndex int32, blockKey string) (vote *Vote, ok bool) { if existing := voteSet.votes[valIndex]; existing != nil && existing.BlockID.Key() == blockKey { return existing, true @@ -252,7 +253,7 @@ func (voteSet *VoteSet) getVote(valIndex int32, blockKey string) (vote *Vote, ok return nil, false } -// Assumes signature is valid. +// addVerifiedVote assumes signature is valid. // If conflicting vote exists, returns it. func (voteSet *VoteSet) addVerifiedVote( vote *Vote, @@ -265,9 +266,8 @@ func (voteSet *VoteSet) addVerifiedVote( if existing := voteSet.votes[valIndex]; existing != nil { if existing.BlockID.Equals(vote.BlockID) { panic("addVerifiedVote does not expect duplicate votes") - } else { - conflicting = existing } + conflicting = existing // Replace vote if blockKey matches voteSet.maj23. if voteSet.maj23 != nil && voteSet.maj23.Key() == blockKey { voteSet.votes[valIndex] = vote @@ -331,7 +331,7 @@ func (voteSet *VoteSet) addVerifiedVote( // NOTE: if there are too many peers, or too much peer churn, // this can cause memory issues. // TODO: implement ability to remove peers too -// NOTE: VoteSet must not be nil +// NOTE: VoteSet must not be nil. func (voteSet *VoteSet) SetPeerMaj23(peerID P2PID, blockID BlockID) error { if voteSet == nil { panic("SetPeerMaj23() on nil VoteSet") @@ -367,7 +367,7 @@ func (voteSet *VoteSet) SetPeerMaj23(peerID P2PID, blockID BlockID) error { return nil } -// Implements VoteSetReader. +// BitArray implements VoteSetReader. func (voteSet *VoteSet) BitArray() *bits.BitArray { if voteSet == nil { return nil @@ -437,12 +437,12 @@ func (voteSet *VoteSet) HasTwoThirdsMajority() bool { return voteSet.maj23 != nil } -// Implements VoteSetReader. +// IsCommit implements VoteSetReader. func (voteSet *VoteSet) IsCommit() bool { if voteSet == nil { return false } - if voteSet.signedMsgType != cmtproto.PrecommitType { + if voteSet.signedMsgType != PrecommitType { return false } voteSet.mtx.Lock() @@ -482,7 +482,7 @@ func (voteSet *VoteSet) TwoThirdsMajority() (blockID BlockID, ok bool) { return BlockID{}, false } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- // Strings and JSON const nilVoteSetString = "nil-VoteSet" @@ -530,7 +530,7 @@ func (voteSet *VoteSet) StringIndented(indent string) string { indent) } -// Marshal the VoteSet to JSON. Same as String(), just in JSON, +// MarshalJSON marshals the VoteSet to JSON. Same as String(), just in JSON, // and without the height/round/signedMsgType (since its already included in the votes). func (voteSet *VoteSet) MarshalJSON() ([]byte, error) { voteSet.mtx.Lock() @@ -544,16 +544,16 @@ func (voteSet *VoteSet) MarshalJSON() ([]byte, error) { // More human readable JSON of the vote set // NOTE: insufficient for unmarshalling from (compressed votes) -// TODO: make the peerMaj23s nicer to read (eg just the block hash) +// TODO: make the peerMaj23s nicer to read (eg just the block hash). type VoteSetJSON struct { Votes []string `json:"votes"` VotesBitArray string `json:"votes_bit_array"` PeerMaj23s map[P2PID]BlockID `json:"peer_maj_23s"` } -// Return the bit-array of votes including +// BitArrayString returns the bit-array of votes including // the fraction of power that has voted like: -// "BA{29:xx__x__x_x___x__x_______xxx__} 856/1304 = 0.66" +// "BA{29:xx__x__x_x___x__x_______xxx__} 856/1304 = 0.66". func (voteSet *VoteSet) BitArrayString() string { voteSet.mtx.Lock() defer voteSet.mtx.Unlock() @@ -566,7 +566,7 @@ func (voteSet *VoteSet) bitArrayString() string { return fmt.Sprintf("%s %d/%d = %.2f", bAString, voted, total, fracVoted) } -// Returns a list of votes compressed to more readable strings. +// VoteStrings returns a list of votes compressed to more readable strings. func (voteSet *VoteSet) VoteStrings() []string { voteSet.mtx.Lock() defer voteSet.mtx.Unlock() @@ -593,7 +593,7 @@ func (voteSet *VoteSet) voteStrings() []string { // 4. first 2/3+ majority // 5. fraction of voted power // 6. votes bit array -// 7. 2/3+ majority for each peer +// 7. 2/3+ majority for each peer. func (voteSet *VoteSet) StringShort() string { if voteSet == nil { return nilVoteSetString @@ -618,14 +618,14 @@ func (voteSet *VoteSet) LogString() string { return fmt.Sprintf("Votes:%d/%d(%.3f)", voted, total, frac) } -// return the power voted, the total, and the fraction -func (voteSet *VoteSet) sumTotalFrac() (int64, int64, float64) { - voted, total := voteSet.sum, voteSet.valSet.TotalVotingPower() - fracVoted := float64(voted) / float64(total) +// sumTotalFrac returns the power voted, the total, and the fraction. +func (voteSet *VoteSet) sumTotalFrac() (voted, total int64, fracVoted float64) { + voted, total = voteSet.sum, voteSet.valSet.TotalVotingPower() + fracVoted = float64(voted) / float64(total) return voted, total, fracVoted } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- // Commit // MakeExtendedCommit constructs a Commit from the VoteSet. It only includes @@ -633,11 +633,11 @@ func (voteSet *VoteSet) sumTotalFrac() (int64, int64, float64) { // // Panics if the vote type is not PrecommitType or if there's no +2/3 votes for // a single block. -func (voteSet *VoteSet) MakeExtendedCommit(ap ABCIParams) *ExtendedCommit { +func (voteSet *VoteSet) MakeExtendedCommit(fp FeatureParams) *ExtendedCommit { voteSet.mtx.Lock() defer voteSet.mtx.Unlock() - if voteSet.signedMsgType != cmtproto.PrecommitType { + if voteSet.signedMsgType != PrecommitType { panic("Cannot MakeExtendCommit() unless VoteSet.Type is PrecommitType") } @@ -664,20 +664,20 @@ func (voteSet *VoteSet) MakeExtendedCommit(ap ABCIParams) *ExtendedCommit { BlockID: *voteSet.maj23, ExtendedSignatures: sigs, } - if err := ec.EnsureExtensions(ap.VoteExtensionsEnabled(ec.Height)); err != nil { + if err := ec.EnsureExtensions(fp.VoteExtensionsEnabled(ec.Height)); err != nil { panic(fmt.Errorf("problem with vote extension data when making extended commit of height %d; %w", ec.Height, err)) } return ec } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- /* Votes for a particular block There are two ways a *blockVotes gets created for a blockKey. 1. first (non-conflicting) vote of a validator w/ blockKey (peerMaj23=false) -2. A peer claims to have a 2/3 majority w/ blockKey (peerMaj23=true) +2. A peer claims to have a 2/3 majority w/ blockKey (peerMaj23=true). */ type blockVotes struct { peerMaj23 bool // peer claims to have maj23 @@ -711,15 +711,15 @@ func (vs *blockVotes) getByIndex(index int32) *Vote { return vs.votes[index] } -//-------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- -// Common interface between *consensus.VoteSet and types.Commit +// Common interface between *consensus.VoteSet and types.Commit. type VoteSetReader interface { GetHeight() int64 GetRound() int32 Type() byte Size() int BitArray() *bits.BitArray - GetByIndex(int32) *Vote + GetByIndex(idx int32) *Vote IsCommit() bool } diff --git a/types/vote_set_test.go b/types/vote_set_test.go index bfd7ac49248..169dc50b234 100644 --- a/types/vote_set_test.go +++ b/types/vote_set_test.go @@ -8,14 +8,13 @@ import ( "github.com/stretchr/testify/require" "github.com/cometbft/cometbft/crypto" - cmtrand "github.com/cometbft/cometbft/libs/rand" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + cmtrand "github.com/cometbft/cometbft/internal/rand" cmttime "github.com/cometbft/cometbft/types/time" ) func TestVoteSet_AddVote_Good(t *testing.T) { height, round := int64(1), int32(0) - voteSet, _, privValidators := randVoteSet(height, round, cmtproto.PrevoteType, 10, 1, false) + voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1, false) val0 := privValidators[0] val0p, err := val0.GetPubKey() @@ -25,14 +24,14 @@ func TestVoteSet_AddVote_Good(t *testing.T) { assert.Nil(t, voteSet.GetByAddress(val0Addr)) assert.False(t, voteSet.BitArray().GetIndex(0)) blockID, ok := voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), "there should be no 2/3 majority") + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority") vote := &Vote{ ValidatorAddress: val0Addr, ValidatorIndex: 0, // since privValidators are in order Height: height, Round: round, - Type: cmtproto.PrevoteType, + Type: PrevoteType, Timestamp: cmttime.Now(), BlockID: BlockID{nil, PartSetHeader{}}, } @@ -42,12 +41,12 @@ func TestVoteSet_AddVote_Good(t *testing.T) { assert.NotNil(t, voteSet.GetByAddress(val0Addr)) assert.True(t, voteSet.BitArray().GetIndex(0)) blockID, ok = voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), "there should be no 2/3 majority") + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority") } func TestVoteSet_AddVote_Bad(t *testing.T) { height, round := int64(1), int32(0) - voteSet, _, privValidators := randVoteSet(height, round, cmtproto.PrevoteType, 10, 1, false) + voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1, false) voteProto := &Vote{ ValidatorAddress: nil, @@ -55,7 +54,7 @@ func TestVoteSet_AddVote_Bad(t *testing.T) { Height: height, Round: round, Timestamp: cmttime.Now(), - Type: cmtproto.PrevoteType, + Type: PrevoteType, BlockID: BlockID{nil, PartSetHeader{}}, } @@ -113,24 +112,23 @@ func TestVoteSet_AddVote_Bad(t *testing.T) { require.NoError(t, err) addr := pubKey.Address() vote := withValidator(voteProto, addr, 3) - added, err := signAddVote(privValidators[3], withType(vote, byte(cmtproto.PrecommitType)), voteSet) + added, err := signAddVote(privValidators[3], withType(vote, byte(PrecommitType)), voteSet) if added || err == nil { t.Errorf("expected VoteSet.Add to fail, wrong type") } } - } func TestVoteSet_2_3Majority(t *testing.T) { height, round := int64(1), int32(0) - voteSet, _, privValidators := randVoteSet(height, round, cmtproto.PrevoteType, 10, 1, false) + voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1, false) voteProto := &Vote{ ValidatorAddress: nil, // NOTE: must fill in ValidatorIndex: -1, // NOTE: must fill in Height: height, Round: round, - Type: cmtproto.PrevoteType, + Type: PrevoteType, Timestamp: cmttime.Now(), BlockID: BlockID{nil, PartSetHeader{}}, } @@ -144,7 +142,7 @@ func TestVoteSet_2_3Majority(t *testing.T) { require.NoError(t, err) } blockID, ok := voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), "there should be no 2/3 majority") + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority") // 7th validator voted for some blockhash { @@ -155,7 +153,7 @@ func TestVoteSet_2_3Majority(t *testing.T) { _, err = signAddVote(privValidators[6], withBlockHash(vote, cmtrand.Bytes(32)), voteSet) require.NoError(t, err) blockID, ok = voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), "there should be no 2/3 majority") + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority") } // 8th validator voted for nil. @@ -167,13 +165,13 @@ func TestVoteSet_2_3Majority(t *testing.T) { _, err = signAddVote(privValidators[7], vote, voteSet) require.NoError(t, err) blockID, ok = voteSet.TwoThirdsMajority() - assert.True(t, ok || blockID.IsZero(), "there should be 2/3 majority for nil") + assert.True(t, ok && blockID.IsNil(), "there should be 2/3 majority for nil") } } func TestVoteSet_2_3MajorityRedux(t *testing.T) { height, round := int64(1), int32(0) - voteSet, _, privValidators := randVoteSet(height, round, cmtproto.PrevoteType, 100, 1, false) + voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 100, 1, false) blockHash := crypto.CRandBytes(32) blockPartsTotal := uint32(123) @@ -185,11 +183,11 @@ func TestVoteSet_2_3MajorityRedux(t *testing.T) { Height: height, Round: round, Timestamp: cmttime.Now(), - Type: cmtproto.PrevoteType, + Type: PrevoteType, BlockID: BlockID{blockHash, blockPartSetHeader}, } - // 66 out of 100 voted for nil. + // 66 out of 100 voted for blockHash. for i := int32(0); i < 66; i++ { pubKey, err := privValidators[i].GetPubKey() require.NoError(t, err) @@ -199,7 +197,7 @@ func TestVoteSet_2_3MajorityRedux(t *testing.T) { require.NoError(t, err) } blockID, ok := voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority") // 67th validator voted for nil @@ -211,7 +209,7 @@ func TestVoteSet_2_3MajorityRedux(t *testing.T) { _, err = signAddVote(privValidators[66], withBlockHash(vote, nil), voteSet) require.NoError(t, err) blockID, ok = voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority: last vote added was nil") } @@ -225,7 +223,7 @@ func TestVoteSet_2_3MajorityRedux(t *testing.T) { _, err = signAddVote(privValidators[67], withBlockPartSetHeader(vote, blockPartsHeader), voteSet) require.NoError(t, err) blockID, ok = voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority: last vote added had different PartSetHeader Hash") } @@ -239,7 +237,7 @@ func TestVoteSet_2_3MajorityRedux(t *testing.T) { _, err = signAddVote(privValidators[68], withBlockPartSetHeader(vote, blockPartsHeader), voteSet) require.NoError(t, err) blockID, ok = voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority: last vote added had different PartSetHeader Total") } @@ -252,7 +250,7 @@ func TestVoteSet_2_3MajorityRedux(t *testing.T) { _, err = signAddVote(privValidators[69], withBlockHash(vote, cmtrand.Bytes(32)), voteSet) require.NoError(t, err) blockID, ok = voteSet.TwoThirdsMajority() - assert.False(t, ok || !blockID.IsZero(), + assert.False(t, ok || !blockID.IsNil(), "there should be no 2/3 majority: last vote added had different BlockHash") } @@ -272,7 +270,7 @@ func TestVoteSet_2_3MajorityRedux(t *testing.T) { func TestVoteSet_Conflicts(t *testing.T) { height, round := int64(1), int32(0) - voteSet, _, privValidators := randVoteSet(height, round, cmtproto.PrevoteType, 4, 1, false) + voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 4, 1, false) blockHash1 := cmtrand.Bytes(32) blockHash2 := cmtrand.Bytes(32) @@ -282,7 +280,7 @@ func TestVoteSet_Conflicts(t *testing.T) { Height: height, Round: round, Timestamp: cmttime.Now(), - Type: cmtproto.PrevoteType, + Type: PrevoteType, BlockID: BlockID{nil, PartSetHeader{}}, } @@ -304,7 +302,7 @@ func TestVoteSet_Conflicts(t *testing.T) { vote := withValidator(voteProto, val0Addr, 0) added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash1), voteSet) assert.False(t, added, "conflicting vote") - assert.Error(t, err, "conflicting vote") + require.Error(t, err, "conflicting vote") } // start tracking blockHash1 @@ -316,7 +314,7 @@ func TestVoteSet_Conflicts(t *testing.T) { vote := withValidator(voteProto, val0Addr, 0) added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash1), voteSet) assert.True(t, added, "called SetPeerMaj23()") - assert.Error(t, err, "conflicting vote") + require.Error(t, err, "conflicting vote") } // attempt tracking blockHash2, should fail because already set for peerA. @@ -328,13 +326,13 @@ func TestVoteSet_Conflicts(t *testing.T) { vote := withValidator(voteProto, val0Addr, 0) added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash2), voteSet) assert.False(t, added, "duplicate SetPeerMaj23() from peerA") - assert.Error(t, err, "conflicting vote") + require.Error(t, err, "conflicting vote") } // val1 votes for blockHash1. { pv, err := privValidators[1].GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) addr := pv.Address() vote := withValidator(voteProto, addr, 1) added, err := signAddVote(privValidators[1], withBlockHash(vote, blockHash1), voteSet) @@ -354,7 +352,7 @@ func TestVoteSet_Conflicts(t *testing.T) { // val2 votes for blockHash2. { pv, err := privValidators[2].GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) addr := pv.Address() vote := withValidator(voteProto, addr, 2) added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash2), voteSet) @@ -378,30 +376,26 @@ func TestVoteSet_Conflicts(t *testing.T) { // val2 votes for blockHash1. { pv, err := privValidators[2].GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) addr := pv.Address() vote := withValidator(voteProto, addr, 2) added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash1), voteSet) assert.True(t, added) - assert.Error(t, err, "conflicting vote") + require.Error(t, err, "conflicting vote") } // check - if !voteSet.HasTwoThirdsMajority() { - t.Errorf("we should have 2/3 majority for blockHash1") - } - blockIDMaj23, _ := voteSet.TwoThirdsMajority() - if !bytes.Equal(blockIDMaj23.Hash, blockHash1) { - t.Errorf("got the wrong 2/3 majority blockhash") - } - if !voteSet.HasTwoThirdsAny() { - t.Errorf("we should have 2/3 if any votes") - } + require.True(t, voteSet.HasTwoThirdsMajority(), "we should have 2/3 majority for blockHash1") + + blockIDMaj23, ok := voteSet.TwoThirdsMajority() + require.True(t, ok) + require.True(t, bytes.Equal(blockIDMaj23.Hash, blockHash1), "got the wrong 2/3 majority blockhash") + require.True(t, voteSet.HasTwoThirdsAny(), "we should have 2/3 if any votes") } func TestVoteSet_MakeCommit(t *testing.T) { height, round := int64(1), int32(0) - voteSet, _, privValidators := randVoteSet(height, round, cmtproto.PrecommitType, 10, 1, true) + voteSet, _, privValidators := randVoteSet(height, round, PrecommitType, 10, 1, true) blockHash, blockPartSetHeader := crypto.CRandBytes(32), PartSetHeader{123, crypto.CRandBytes(32)} voteProto := &Vote{ @@ -410,14 +404,14 @@ func TestVoteSet_MakeCommit(t *testing.T) { Height: height, Round: round, Timestamp: cmttime.Now(), - Type: cmtproto.PrecommitType, + Type: PrecommitType, BlockID: BlockID{blockHash, blockPartSetHeader}, } // 6 out of 10 voted for some block. for i := int32(0); i < 6; i++ { pv, err := privValidators[i].GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) addr := pv.Address() vote := withValidator(voteProto, addr, i) _, err = signAddVote(privValidators[i], vote, voteSet) @@ -427,13 +421,14 @@ func TestVoteSet_MakeCommit(t *testing.T) { } // MakeCommit should fail. - veHeightParam := ABCIParams{VoteExtensionsEnableHeight: height} + veHeightParam := DefaultFeatureParams() + veHeightParam.VoteExtensionsEnableHeight = height assert.Panics(t, func() { voteSet.MakeExtendedCommit(veHeightParam) }, "Doesn't have +2/3 majority") // 7th voted for some other block. { pv, err := privValidators[6].GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) addr := pv.Address() vote := withValidator(voteProto, addr, 6) vote = withBlockHash(vote, cmtrand.Bytes(32)) @@ -446,7 +441,7 @@ func TestVoteSet_MakeCommit(t *testing.T) { // The 8th voted like everyone else. { pv, err := privValidators[7].GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) addr := pv.Address() vote := withValidator(voteProto, addr, 7) _, err = signAddVote(privValidators[7], vote, voteSet) @@ -456,7 +451,7 @@ func TestVoteSet_MakeCommit(t *testing.T) { // The 9th voted for nil. { pv, err := privValidators[8].GetPubKey() - assert.NoError(t, err) + require.NoError(t, err) addr := pv.Address() vote := withValidator(voteProto, addr, 8) vote.BlockID = BlockID{} @@ -468,7 +463,7 @@ func TestVoteSet_MakeCommit(t *testing.T) { extCommit := voteSet.MakeExtendedCommit(veHeightParam) // Commit should have 10 elements - assert.Equal(t, 10, len(extCommit.ExtendedSignatures)) + assert.Len(t, extCommit.ExtendedSignatures, 10) // Ensure that Commit is good. if err := extCommit.ValidateBasic(); err != nil { @@ -515,9 +510,9 @@ func TestVoteSet_VoteExtensionsEnabled(t *testing.T) { valSet, privValidators := RandValidatorSet(5, 10) var voteSet *VoteSet if tc.requireExtensions { - voteSet = NewExtendedVoteSet("test_chain_id", height, round, cmtproto.PrecommitType, valSet) + voteSet = NewExtendedVoteSet("test_chain_id", height, round, PrecommitType, valSet) } else { - voteSet = NewVoteSet("test_chain_id", height, round, cmtproto.PrecommitType, valSet) + voteSet = NewVoteSet("test_chain_id", height, round, PrecommitType, valSet) } val0 := privValidators[0] @@ -534,12 +529,12 @@ func TestVoteSet_VoteExtensionsEnabled(t *testing.T) { ValidatorIndex: 0, Height: height, Round: round, - Type: cmtproto.PrecommitType, + Type: PrecommitType, Timestamp: cmttime.Now(), BlockID: BlockID{blockHash, blockPartSetHeader}, } v := vote.ToProto() - err = val0.SignVote(voteSet.ChainID(), v) + err = val0.SignVote(voteSet.ChainID(), v, true) require.NoError(t, err) vote.Signature = v.Signature @@ -559,18 +554,18 @@ func TestVoteSet_VoteExtensionsEnabled(t *testing.T) { } } -// NOTE: privValidators are in order +// NOTE: privValidators are in order. func randVoteSet( height int64, round int32, - signedMsgType cmtproto.SignedMsgType, + signedMsgType SignedMsgType, numValidators int, votingPower int64, extEnabled bool, ) (*VoteSet, *ValidatorSet, []PrivValidator) { valSet, privValidators := RandValidatorSet(numValidators, votingPower) if extEnabled { - if signedMsgType != cmtproto.PrecommitType { + if signedMsgType != PrecommitType { return nil, nil, nil } return NewExtendedVoteSet("test_chain_id", height, round, signedMsgType, valSet), valSet, privValidators @@ -578,7 +573,7 @@ func randVoteSet( return NewVoteSet("test_chain_id", height, round, signedMsgType, valSet), valSet, privValidators } -// Convenience: Return new vote with different validator address/index +// Convenience: Return new vote with different validator address/index. func withValidator(vote *Vote, addr []byte, idx int32) *Vote { vote = vote.Copy() vote.ValidatorAddress = addr @@ -586,35 +581,35 @@ func withValidator(vote *Vote, addr []byte, idx int32) *Vote { return vote } -// Convenience: Return new vote with different height +// Convenience: Return new vote with different height. func withHeight(vote *Vote, height int64) *Vote { vote = vote.Copy() vote.Height = height return vote } -// Convenience: Return new vote with different round +// Convenience: Return new vote with different round. func withRound(vote *Vote, round int32) *Vote { vote = vote.Copy() vote.Round = round return vote } -// Convenience: Return new vote with different type +// Convenience: Return new vote with different type. func withType(vote *Vote, signedMsgType byte) *Vote { vote = vote.Copy() - vote.Type = cmtproto.SignedMsgType(signedMsgType) + vote.Type = SignedMsgType(signedMsgType) return vote } -// Convenience: Return new vote with different blockHash +// Convenience: Return new vote with different blockHash. func withBlockHash(vote *Vote, blockHash []byte) *Vote { vote = vote.Copy() vote.BlockID.Hash = blockHash return vote } -// Convenience: Return new vote with different blockParts +// Convenience: Return new vote with different blockParts. func withBlockPartSetHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote { vote = vote.Copy() vote.BlockID.PartSetHeader = blockPartsHeader diff --git a/types/vote_test.go b/types/vote_test.go index 9c7e8777f71..70e7b42f47f 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "testing" "time" @@ -8,32 +9,33 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" "github.com/cometbft/cometbft/crypto" "github.com/cometbft/cometbft/crypto/ed25519" "github.com/cometbft/cometbft/crypto/tmhash" - "github.com/cometbft/cometbft/libs/protoio" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cometbft/cometbft/internal/protoio" cmttime "github.com/cometbft/cometbft/types/time" ) func examplePrevote() *Vote { - return exampleVote(byte(cmtproto.PrevoteType)) + return exampleVote(byte(PrevoteType)) } func examplePrecommit() *Vote { - vote := exampleVote(byte(cmtproto.PrecommitType)) + vote := exampleVote(byte(PrecommitType)) + vote.Extension = []byte("extension") vote.ExtensionSignature = []byte("signature") return vote } func exampleVote(t byte) *Vote { - var stamp, err = time.Parse(TimeFormat, "2017-12-25T03:00:01.234Z") + stamp, err := time.Parse(TimeFormat, "2017-12-25T03:00:01.234Z") if err != nil { panic(err) } return &Vote{ - Type: cmtproto.SignedMsgType(t), + Type: SignedMsgType(t), Height: 12345, Round: 2, Timestamp: stamp, @@ -61,7 +63,6 @@ func TestVoteSignable(t *testing.T) { } func TestVoteSignBytesTestVectors(t *testing.T) { - tests := []struct { chainID string vote *Vote @@ -74,7 +75,7 @@ func TestVoteSignBytesTestVectors(t *testing.T) { }, // with proper (fixed size) height and round (PreCommit): 1: { - "", &Vote{Height: 1, Round: 1, Type: cmtproto.PrecommitType}, + "", &Vote{Height: 1, Round: 1, Type: PrecommitType}, []byte{ 0x21, // length 0x8, // (field_number << 3) | wire_type @@ -85,11 +86,12 @@ func TestVoteSignBytesTestVectors(t *testing.T) { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round 0x2a, // (field_number << 3) | wire_type // remaining fields (timestamp): - 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, + 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, + }, }, // with proper (fixed size) height and round (PreVote): 2: { - "", &Vote{Height: 1, Round: 1, Type: cmtproto.PrevoteType}, + "", &Vote{Height: 1, Round: 1, Type: PrevoteType}, []byte{ 0x21, // length 0x8, // (field_number << 3) | wire_type @@ -100,7 +102,8 @@ func TestVoteSignBytesTestVectors(t *testing.T) { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round 0x2a, // (field_number << 3) | wire_type // remaining fields (timestamp): - 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, + 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, + }, }, 3: { "", &Vote{Height: 1, Round: 1}, @@ -112,7 +115,8 @@ func TestVoteSignBytesTestVectors(t *testing.T) { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round // remaining fields (timestamp): 0x2a, - 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1}, + 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, + }, }, // containing non-empty chain_id: 4: { @@ -128,7 +132,8 @@ func TestVoteSignBytesTestVectors(t *testing.T) { 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, // timestamp // (field_number << 3) | wire_type 0x32, - 0xd, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64}, // chainID + 0xd, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, + }, // chainID }, // containing vote extension 5: { @@ -143,7 +148,7 @@ func TestVoteSignBytesTestVectors(t *testing.T) { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // height 0x19, // (field_number << 3) | wire_type 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // round - // remaning fields: + // remaining fields: 0x2a, // (field_number << 3) | wire_type 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, // timestamp // (field_number << 3) | wire_type @@ -180,7 +185,7 @@ func TestVoteVerifySignature(t *testing.T) { signBytes := VoteSignBytes("test_chain_id", v) // sign it - err = privVal.SignVote("test_chain_id", v) + err = privVal.SignVote("test_chain_id", v, false) require.NoError(t, err) // verify the same vote @@ -246,12 +251,12 @@ func TestVoteExtension(t *testing.T) { Height: height, Round: round, Timestamp: cmttime.Now(), - Type: cmtproto.PrecommitType, + Type: PrecommitType, BlockID: makeBlockIDRandom(), } v := vote.ToProto() - err = privVal.SignVote("test_chain_id", v) + err = privVal.SignVote("test_chain_id", v, true) require.NoError(t, err) vote.Signature = v.Signature if tc.includeSignature { @@ -270,17 +275,17 @@ func TestVoteExtension(t *testing.T) { func TestIsVoteTypeValid(t *testing.T) { tc := []struct { name string - in cmtproto.SignedMsgType + in SignedMsgType out bool }{ - {"Prevote", cmtproto.PrevoteType, true}, - {"Precommit", cmtproto.PrecommitType, true}, - {"InvalidType", cmtproto.SignedMsgType(0x3), false}, + {"Prevote", PrevoteType, true}, + {"Precommit", PrecommitType, true}, + {"InvalidType", SignedMsgType(0x3), false}, } for _, tt := range tc { tt := tt - t.Run(tt.name, func(st *testing.T) { + t.Run(tt.name, func(_ *testing.T) { if rs := IsVoteTypeValid(tt.in); rs != tt.out { t.Errorf("got unexpected Vote type. Expected:\n%v\nGot:\n%v", rs, tt.out) } @@ -297,19 +302,19 @@ func TestVoteVerify(t *testing.T) { vote.ValidatorAddress = pubkey.Address() err = vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey()) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, ErrVoteInvalidValidatorAddress, err) } err = vote.Verify("test_chain_id", pubkey) - if assert.Error(t, err) { + if assert.Error(t, err) { //nolint:testifylint // require.Error doesn't work with the conditional here assert.Equal(t, ErrVoteInvalidSignature, err) } } func TestVoteString(t *testing.T) { str := examplePrecommit().String() - expected := `Vote{56789:6AF1F4111082 12345/02/SIGNED_MSG_TYPE_PRECOMMIT(Precommit) 8B01023386C3 000000000000 000000000000 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests + expected := `Vote{56789:6AF1F4111082 12345/02/SIGNED_MSG_TYPE_PRECOMMIT(Precommit) 8B01023386C3 000000000000 657874656E73 @ 2017-12-25T03:00:01.234Z}` //nolint:lll //ignore line length for tests if str != expected { t.Errorf("got unexpected string for Vote. Expected:\n%v\nGot:\n%v", expected, str) } @@ -321,11 +326,12 @@ func TestVoteString(t *testing.T) { } } -func signVote(t *testing.T, pv PrivValidator, chainID string, vote *Vote) { +func signVote(t *testing.T, pv PrivValidator, vote *Vote) { t.Helper() + chainID := "test_chain_id" v := vote.ToProto() - require.NoError(t, pv.SignVote(chainID, v)) + require.NoError(t, pv.SignVote(chainID, v, true)) vote.Signature = v.Signature vote.ExtensionSignature = v.ExtensionSignature } @@ -338,12 +344,12 @@ func TestValidVotes(t *testing.T) { vote *Vote malleateVote func(*Vote) }{ - {"good prevote", examplePrevote(), func(v *Vote) {}}, + {"good prevote", examplePrevote(), func(_ *Vote) {}}, {"good precommit without vote extension", examplePrecommit(), func(v *Vote) { v.Extension = nil }}, {"good precommit with vote extension", examplePrecommit(), func(v *Vote) { v.Extension = []byte("extension") }}, } for _, tc := range testCases { - signVote(t, privVal, "test_chain_id", tc.vote) + signVote(t, privVal, tc.vote) tc.malleateVote(tc.vote) require.NoError(t, tc.vote.ValidateBasic(), "ValidateBasic for %s", tc.name) require.NoError(t, tc.vote.EnsureExtension(), "EnsureExtension for %s", tc.name) @@ -368,13 +374,13 @@ func TestInvalidVotes(t *testing.T) { } for _, tc := range testCases { prevote := examplePrevote() - signVote(t, privVal, "test_chain_id", prevote) + signVote(t, privVal, prevote) tc.malleateVote(prevote) require.Error(t, prevote.ValidateBasic(), "ValidateBasic for %s in invalid prevote", tc.name) require.NoError(t, prevote.EnsureExtension(), "EnsureExtension for %s in invalid prevote", tc.name) precommit := examplePrecommit() - signVote(t, privVal, "test_chain_id", precommit) + signVote(t, privVal, precommit) tc.malleateVote(precommit) require.Error(t, precommit.ValidateBasic(), "ValidateBasic for %s in invalid precommit", tc.name) require.NoError(t, precommit.EnsureExtension(), "EnsureExtension for %s in invalid precommit", tc.name) @@ -393,7 +399,7 @@ func TestInvalidPrevotes(t *testing.T) { } for _, tc := range testCases { prevote := examplePrevote() - signVote(t, privVal, "test_chain_id", prevote) + signVote(t, privVal, prevote) tc.malleateVote(prevote) require.Error(t, prevote.ValidateBasic(), "ValidateBasic for %s", tc.name) require.NoError(t, prevote.EnsureExtension(), "EnsureExtension for %s", tc.name) @@ -415,7 +421,7 @@ func TestInvalidPrecommitExtensions(t *testing.T) { } for _, tc := range testCases { precommit := examplePrecommit() - signVote(t, privVal, "test_chain_id", precommit) + signVote(t, privVal, precommit) tc.malleateVote(precommit) // ValidateBasic ensures that vote extensions, if present, are well formed require.Error(t, precommit.ValidateBasic(), "ValidateBasic for %s", tc.name) @@ -440,7 +446,7 @@ func TestEnsureVoteExtension(t *testing.T) { } for _, tc := range testCases { precommit := examplePrecommit() - signVote(t, privVal, "test_chain_id", precommit) + signVote(t, privVal, precommit) tc.malleateVote(precommit) if tc.expectError { require.Error(t, precommit.EnsureExtension(), "EnsureExtension for %s", tc.name) @@ -454,7 +460,7 @@ func TestVoteProtobuf(t *testing.T) { privVal := NewMockPV() vote := examplePrecommit() v := vote.ToProto() - err := privVal.SignVote("test_chain_id", v) + err := privVal.SignVote("test_chain_id", v, false) vote.Signature = v.Signature require.NoError(t, err) @@ -486,3 +492,110 @@ func TestVoteProtobuf(t *testing.T) { } } } + +func TestSignAndCheckVote(t *testing.T) { + privVal := NewMockPV() + + testCases := []struct { + name string + extensionsEnabled bool + vote *Vote + expectError bool + }{ + { + name: "precommit with extension signature", + extensionsEnabled: true, + vote: examplePrecommit(), + expectError: false, + }, + { + name: "precommit with extension signature", + extensionsEnabled: false, + vote: examplePrecommit(), + expectError: false, + }, + { + name: "precommit with extension signature for a nil block", + extensionsEnabled: true, + vote: func() *Vote { + v := examplePrecommit() + v.BlockID = BlockID{make([]byte, 0), PartSetHeader{0, make([]byte, 0)}} + return v + }(), + expectError: true, + }, + { + name: "precommit with extension signature for a nil block", + extensionsEnabled: false, + vote: func() *Vote { + v := examplePrecommit() + v.BlockID = BlockID{make([]byte, 0), PartSetHeader{0, make([]byte, 0)}} + return v + }(), + expectError: false, + }, + { + name: "precommit without extension", + extensionsEnabled: true, + vote: func() *Vote { + v := examplePrecommit() + v.Extension = make([]byte, 0) + return v + }(), + expectError: false, + }, + { + name: "precommit without extension", + extensionsEnabled: false, + vote: func() *Vote { + v := examplePrecommit() + v.Extension = make([]byte, 0) + return v + }(), + expectError: false, + }, + { + name: "prevote", + extensionsEnabled: true, + vote: examplePrevote(), + expectError: true, + }, + { + name: "prevote", + extensionsEnabled: false, + vote: examplePrevote(), + expectError: false, + }, + { + name: "prevote with extension", + extensionsEnabled: true, + vote: func() *Vote { + v := examplePrevote() + v.Extension = []byte("extension") + return v + }(), + expectError: true, + }, + { + name: "prevote with extension", + extensionsEnabled: false, + vote: func() *Vote { + v := examplePrevote() + v.Extension = []byte("extension") + return v + }(), + expectError: false, + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("%s (extensionsEnabled: %t) ", tc.name, tc.extensionsEnabled), func(t *testing.T) { + _, err := SignAndCheckVote(tc.vote, privVal, "test_chain_id", tc.extensionsEnabled) + if tc.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/types/wrapper.go b/types/wrapper.go new file mode 100644 index 00000000000..9d5b26a0411 --- /dev/null +++ b/types/wrapper.go @@ -0,0 +1,27 @@ +package types + +import ( + "github.com/cosmos/gogoproto/proto" +) + +// Unwrapper is a Protobuf message that can contain a variety of inner messages +// (e.g. via oneof fields). If a Channel's message type implements Unwrapper, the +// p2p layer will automatically unwrap inbound messages so that reactors do not have to do this themselves. +type Unwrapper interface { + proto.Message + + // Unwrap will unwrap the inner message contained in this message. + Unwrap() (proto.Message, error) +} + +// Wrapper is a companion type to Unwrapper. It is a Protobuf message that can contain a variety of inner messages. The p2p layer will automatically wrap outbound messages so that the reactors do not have to do it themselves. +type Wrapper interface { + proto.Message + + // Wrap will take the underlying message and wrap it in its wrapper type. + // + // NOTE: The consumer should only use the result to marshal the message into + // the wire format. Dynamic casts to any of the declared wrapper types + // may not produce the expected result. + Wrap() proto.Message +} diff --git a/version/version.go b/version/version.go index 049f13dfc34..06eec1e137a 100644 --- a/version/version.go +++ b/version/version.go @@ -1,23 +1,21 @@ package version const ( - // TMVersionDefault is the used as the fallback version of CometBFT - // when not using git describe. It is formatted with semantic versioning. - TMCoreSemVer = "0.38.0-dev" - // ABCISemVer is the semantic version of the ABCI protocol - ABCISemVer = "1.0.0" + // CMTSemVer is used as the fallback version of CometBFT + // when not using git describe. It uses semantic versioning format. + CMTSemVer = "1.0.0-dev" + // ABCISemVer is the semantic version of the ABCI protocol. + ABCISemVer = "2.0.0" ABCIVersion = ABCISemVer // P2PProtocol versions all p2p behavior and msgs. // This includes proposer selection. - P2PProtocol uint64 = 8 + P2PProtocol uint64 = 9 // BlockProtocol versions all block data structures and processing. // This includes validity of blocks and state updates. BlockProtocol uint64 = 11 ) -var ( - // TMGitCommitHash uses git rev-parse HEAD to find commit hash which is helpful - // for the engineering team when working with the cometbft binary. See Makefile - TMGitCommitHash = "" -) +// CMTGitCommitHash uses git rev-parse HEAD to find commit hash which is helpful +// for the engineering team when working with the cometbft binary. See Makefile. +var CMTGitCommitHash = ""